Ruby Configuration for Emacs
The following instructions create a modern, blinged-out setup for developing Ruby in Emacs.
Every Ruby instance is controlled by RVM. Install it, via:
curl -sSL https://get.rvm.io | bash -s stable
Next, install a Ruby version and set it to be used globally:
rvm install 1.9.3-p550 rvm use 1.9.3-p550
While the Ruby mode is supplied with Emacs, it needs to be associated with a few other file type extensions:
(use-package ruby-mode :ensure t :mode "\\.rb\\'" :mode "Rakefile\\'" :mode "Gemfile\\'" :mode "Berksfile\\'" :mode "Vagrantfile\\'" :interpreter "ruby" :init (setq ruby-indent-level 2 ruby-indent-tabs-mode nil) (add-hook 'ruby-mode 'superword-mode) :bind (([(meta down)] . ruby-forward-sexp) ([(meta up)] . ruby-backward-sexp) (("C-c C-e" . ruby-send-region)))) ;; Rebind since Rubocop uses C-c C-r
Being able to select code using expand-region, and then sending it to the Ruby REPL is often useful. But what does an s-expression mean in Ruby?
Other keystrokes to remember:
- Move to the beginning and end of a block
- Move to the beginning and end of a function
Use web-mode for dealing with ERB templates:
(use-package web-mode :ensure t :mode "\\.erb\\'")
Ruby Virtual Manager
Using RVM integration for Emacs:
(use-package rvm :ensure t :config (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).
Start with a default Gemset by placing the following in your local configuration:
(rvm-use "ruby-2.0.0" "p643")
Note: Run the following regularly:
rvm get latest
Ruby Functional Doc
The Yari project attempts to hook Ruby calls to the
(use-package yari :ensure t :init (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:
(use-package inf-ruby :ensure t :init (add-hook 'ruby-mode-hook 'inf-ruby-minor-mode))
To start eval-ing, do:
To run on a remote server:
(defun inf-ruby-remote (remote) "Run an inferior Ruby process on a remote server." (interactive "sHost: ") (let ((default-directory (format "/ssh:%s:" remote))) (inf-ruby)))
However, I need to specify a particular version, and I haven’t figured out how to call a particular Ruby implementation:
(defun inf-ruby-remote (remote) "Run an inferior Ruby process on a remote server." (interactive "sHost: ") (let ((default-directory (format "/ssh:%s:/opt/ruby2.0/embedded/bin" remote))) (run-ruby "/opt/ruby2.0/embedded/bin/irb" (format "%s:ruby" remote))))
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:
(use-package smartparens :ensure t :diminish (smartparens-mode . "()") :init (use-package smartparens-ruby) (add-hook 'ruby-mode-hook 'smartparens-strict-mode))
(use-package rubocop :ensure t :init (add-hook 'ruby-mode-hook 'rubocop-mode) :diminish rubocop-mode)
Install it with:
gem install rubocop
Let’s get Foodcritic working with Flycheck, but only if the file
is located in a
(use-package flycheck :no-require t :config (flycheck-define-checker chef-foodcritic "A Chef cookbooks syntax checker using Foodcritic. See URL `http://acrmp.github.io/foodcritic/'." :command ("foodcritic" source) :error-patterns ((error line-start (message) ": " (file-name) ":" line line-end)) :modes (enh-ruby-mode ruby-mode) :predicate (lambda () (let ((parent-dir (file-name-directory (buffer-file-name)))) (or ;; Chef CookBook ;; http://docs.opscode.com/chef/knife.html#id38 (locate-dominating-file parent-dir "recipes") ;; Knife Solo ;; http://matschaffer.github.io/knife-solo/#label-Init+command (locate-dominating-file parent-dir "cookbooks")))) :next-checkers ((warnings-only . ruby-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
And even then, it barely works.
Once started with
robe-start, we should get code completion:
(use-package robe :ensure t :bind ("C-M-." . robe-jump) :init (add-hook 'ruby-mode-hook 'robe-mode) :config (defadvice inf-ruby-console-auto (before activate-rvm-for-robe activate) (rvm-activate-corresponding-ruby)))
If we have installed Company for auto-complete, use robe for this purpose:
(use-package company :no-require t :config (push 'company-robe company-backends))
With a complex Ruby project, one should evaluate the entire Ruby
C-c C-l), and then run:
robe-jumpto go to the method’s definition
robe-askwill act like jump, but asks for the method first
robe-docdisplays the method documentation (doesn’t seem to be as useful as
However, it seldom works with any of the Ruby code that I use, so I currently have it turned off.
The little refactoring available with Ruby Tools looks interesting.
(use-package ruby-tools :ensure t :init (add-hook 'ruby-mode-hook 'ruby-tools-mode) :diminish 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 string
C-“converts the thing into a double-quoted string
C-:converts the thing into a symbol
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.
Before you can build this on a new system, make sure that you put
the cursor over any of these properties, and hit: