29 November 2010

Emacs Ruby Foo

Before worrying about Rails, you need to get Emacs to behave sanely with Ruby code. That means it should indent it automatically and syntax highlight the code.

Emacs 22.1

For most languages, Emacs will syntax highlight your source code right out of the box. It does this by switching into a language specific mode when you open files with certain extensions. Back in Emacs 22 days, Ruby Mode was not present out of the box, but adding support is trivial.

In the Ruby source distribution, under the misc directory, you will find several files. The one called ruby-mode.el is the one that adds Ruby syntax highlighting support to Emacs.

Download it and place it somewhere in your Emacs load path. On windows I created a directory called C:\emacs-22.1\includes and copied ruby-mode.el into it.

First ensure the 'includes directory' is in the emacs load path by defining it in your _emacs file (at or near the top as it needs to be declared before you use anything in it):

; directory to put various el files into
(add-to-list 'load-path "C:/emacs-22.1/includes")

Now add the following lines to your _emacs:

; loads ruby mode when a .rb file is opened.
(autoload 'ruby-mode "ruby-mode" "Major mode for editing ruby scripts." t)
(setq auto-mode-alist  (cons '(".rb$" . ruby-mode) auto-mode-alist))

Now when you open a file with an rb extension, ruby-mode will automatically activate.

Emacs 23.2

I don't know when it happened, but in some later version of Emacs, ruby-mode started being bundled by default, and you can skip the steps in the section above. If you open a file with a .rb extension, ruby-mode should start automatically.

Improving Ruby Mode

In both Emacs 23 and 22, if you set things up as above there are a few annoyances with ruby-mode. Mainly, it does not auto-indent the next line after you hit return, meaning you have to press tab each time. To fix it, add the following block to your _emacs file:

(add-hook 'ruby-mode-hook
      (lambda()
        (add-hook 'local-write-file-hooks
                  '(lambda()
                     (save-excursion
                       (untabify (point-min) (point-max))
                       (delete-trailing-whitespace)
                       )))
        (set (make-local-variable 'indent-tabs-mode) 'nil)
        (set (make-local-variable 'tab-width) 2)
        (imenu-add-to-menubar "IMENU")
        (define-key ruby-mode-map "\C-m" 'newline-and-indent) ;Not sure if this line is 100% right!
     ;   (require 'ruby-electric)
     ;   (ruby-electric-mode t)
        ))

This code makes ruby-mode much better, but I don't pretend to be an expert on it! Also note the two lines that are commented out for ruby-electric-mode, which I will next.

Adding Electric

Before saying anything more about ruby-mode, we may as well install ruby-electric mode. I started off using this, but eventually turned it off as it annoyed me more than it helped. Basically electric-mode defines 'electric keys'. For example, if you type a quote, the closing quote will automatically be inserted. Same for {, [, and (. Also typing 'def' will result in the corresponding 'end' being inserted too. Its easier if you play with it a little to see what I mean!

To install electric-mode, download the ruby-electric.el file from the Ruby misc directory into your include directory, and uncomment the two lines mentioning ruby-electric in the _emacs setting above.

Now, we have Ruby Syntax highlighting, electric keys, and auto-indenting, but we can do more ...

Messed Up Your Indentation?

If you let you code get into a bit of a twist, you can fix the indenting by press the TAB key while on the line – give it a try, moving over each line and pressing TAB on each to correct the indents!

Comment a block

If you want to comment out a large section of code, you can select it and the type ALT-x ruby-encomment-region and it will place a '#' symbol at the beginning of each line. ALT-x ruby-decomment-region does the opposite.

This is very specific to ruby-mode. A better way of commenting blocks is to highlight the region and use the ALT-; command (M-;). This will work in many language modes, and will either comment or uncomment the block as appropriate.

Compile and Run Code in Emacs

There are many ways to run code in Emacs. The easiest out-of-the-box way, is to type ALT-x compile. Emacs will prompt for a compile command, which by default is ‘make -k’. Replace this with:

ruby -w my_file_name.rb

The emacs window will split in two and the results of running the script will be in the new window.

If you are writing a text document that includes code snippets, and you want to ensure they are correct, you can select the region and type ALT-| to run it. Again, you need to enter the ruby command to run the code.

Smarter Compile?

All that typing ruby -w filename will start to annoy you after a while – the solution is mode-compile which has some brains built in. It can tell when you are editing a Ruby file (or many other types of file) and run it with the correct compiler/interpreter automatically. Download mode-compile.el and put it in your includes directory. As usual, add the following to your _emacs:

; Install mode-compile to give friendlier compiling support!
(autoload 'mode-compile "mode-compile"
"Command to compile current buffer file based on the major mode" t)
 (global-set-key "\\C-cc" 'mode-compile)
(autoload 'mode-compile-kill "mode-compile"
"Command to kill a compilation launched by `mode-compile'" t)
 (global-set-key "\\C-ck" 'mode-compile-kill)

Now you can compile/run code by typing CTRL-c c (and if your code enters a nasty infinite loop, you can kill it with CTRL-c k). The output will again appear in a new split window. If there are any compile errors in the output, you can move the cursor over them and hit return and emacs will jump to the offending line in your source file – pretty neat eh?

That is enough for this post – next time I will add some Rails specific config.

blog comments powered by Disqus