We begin by stealing a typical Ruby environment from Prelude.
I like having everything Ruby controlled by RVM:
curl -sSL https://get.rvm.io | bash -s stable
And then install a Ruby version and set it to be used globally:
rvm install 1.9.3-p550
rvm use 1.9.3-p550
See the Ruby Virtual Manager section below.
Starting to collect the Ruby packages that make the most sense for my work-flow and development style:
(packages-install '( ruby-tools
inf-ruby
rvm
yari
robe
rubocop
smartparens ))
Notice that I’m not using enh-ruby-mode, as I have found that the
updated ruby-mode
that is standard in Emacs 24.4 is quite good.
Many odd files need to associated with any Ruby mode:
(when (require 'ruby-mode nil t)
(add-to-list 'auto-mode-alist '("\\.rb$" . ruby-mode))
(add-to-list 'interpreter-mode-alist '("ruby" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.rake\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Rakefile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.gemspec\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.ru\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Gemfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Guardfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Capfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.thor\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.rabl\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Thorfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Vagrantfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.jbuilder\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Podfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("\\.podspec\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Puppetfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Berksfile\\'" . ruby-mode))
(add-to-list 'auto-mode-alist '("Appraisals\\'" . ruby-mode)))
Use web-mode for dealing with ERB templates:
(when (require 'web-mode nil t)
(add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode)))
Create a function that will set the default values for the
ruby-mode
, and tie that to the ruby-mode-hoook
:
(defun ha/ruby-mode-defaults ()
;; It hate subwords
(superword-mode +1)
(ruby-tools-mode +1)
(setq-default ruby-indent-level 2)
(setq-default ruby-indent-tabs-mode nil)
;; Using =expand-regions= and send a region to REPLs:
(local-set-key (kbd "C-c i") 'ruby-send-region))
(add-hook 'ruby-mode-hook 'ha/ruby-mode-defaults)
Each language that I use, I like to bind the sexp movement:
(define-key ruby-mode-map (kbd "M-<down>") 'ruby-forward-sexp)
(define-key ruby-mode-map (kbd "M-<up>") 'ruby-backward-sexp)
Other keystrokes to remember:
C-M-p
/C-M-n
- Move to the beginning and end of a block
C-M-a
/C-M-e
- Move to the beginning and end of a function
Using RVM integration for Emacs:
(when (require 'rvm nil t)
(rvm-use-default))
When jumping from project to project, need to run the command:
rvm-use
… which must be done before starting an Eshell (that
is, if you’re into that sort of thing).
The Yari project attempts to hook Ruby calls to the ri
project.
(when (require 'yari nil t)
(add-hook 'ruby-mode-hook
(lambda ()
(local-set-key [f1] 'yari))))
Now, place point on some function, and hit F1
to see the glory.
In order for this to work, we need to generate the missing docs:
gem rdoc --all --ri --no-rdoc
rvm docs generate all
And we may have to do this for every change to RVM. Seems that
dash-at-point
is more effective (C-c d
), however.
I am not sure I can learn a new language without a REPL connected to my editor, and for Ruby, this is inf-ruby:
(require 'inf-ruby)
(add-hook 'ruby-mode-hook 'inf-ruby-minor-mode)
To start eval-ing, do: M-x inf-ruby
… or: C-c C-s
Can I get the same wonder from paredit and Lisp in my Ruby using
smartparens? Not really, as it isn’t as pedantic as
paredit
. Still, it may be good enough for Ruby:
(when (require 'smartparens-config nil t)
(require 'smartparens-ruby)
(add-hook 'ruby-mode-hook 'smartparens-mode))
The lint-like style checker of choice for Ruby is Rubocop. The rubocop.el mode should just work with Flycheck.
(when (require 'rubocop nil t)
(add-hook 'ruby-mode-hook 'rubocop-mode))
Install it with: gem install rubocop
Robe is a “code assistance” tool, that pretty much only works with methods (and doesn’t seem to work well with direct functions). One must install the following before this will work:
gem install pry pry-doc
Once started with robe-start
, we should get code completion:
(when (require 'robe nil t)
(add-hook 'ruby-mode-hook 'robe-mode)
(eval-after-load 'company '(push 'company-robe company-backends))
;; Don't care to have to start up Ruby if I'm just jumping around
(define-key robe-mode-map (kbd "M-.") 'xref-find-definitions)
(define-key robe-mode-map (kbd "C-M-.") 'robe-jump)
(defadvice inf-ruby-console-auto (before activate-rvm-for-robe activate)
(rvm-activate-corresponding-ruby)))
With a complex Ruby project, one should evaluate the entire Ruby
file (C-c C-l
), and then run:
robe-jump
to go to the method’s definitionrobe-ask
will act like jump, but asks for the method firstrobe-doc
displays the method documentation (doesn’t seem to be as useful asdash-at-point
).
The little refactoring available with Ruby Tools looks interesting.
(when (require 'ruby-tools nil t)
(add-hook 'ruby-mode-hook 'ruby-tools-mode))
The primary key-bindings operate on the thing the cursor is on, e.g. a string, a symbol, etc.
C-‘
converts the thing into a single-quoted stringC-“
converts the thing into a double-quoted stringC-:
converts the thing into a symbol
Other options:
C-;
clears the string- Inside a string the
#
key will insert a variable interpolation if the string is double-quoted (this is actually what I use this package the most)
Make sure that we can simply require
this library.
(provide 'init-ruby)
Before you can build this on a new system, make sure that you put
the cursor over any of these properties, and hit: C-c C-c