Ruby与emacs IDE,第一季

emacs安装后自带一个ruby模式,但是这个ruby mode功能弱的只能用敷衍来形容。与之相对c++和python就提供了完善的支持。不公平啊。所以不自己配置是肯定不行的。但是配置这货的过程充满了艰辛,就和我天天早起喝得叫人撞墙的中药一个味儿。现在想起来从一个小白起到能获得一个勉强能跑的emacs环境真是奇迹。问题在于相关的过程极度缺乏正规的文档化,有用的文章几乎都出自个人的摸索,分布于广大的互联网上各个blog里,很多是被封锁的,而且很大一部分都是用日文写成的,所幸的是这两点对我都不是问题。

ruby其实和emacs是很有渊源的。ruby的作者,松本行宏先生,在发布ruby前最有名的作品就是emacs的一个扩展。他的作业环境毫无疑问也是emacs。但是现在要设置emacs却如此麻烦。需要注意的是我配置的是ruby开发环境,而不是rails的,而且是1.9,很不成熟。首先是主模式,在ruby的源码包下misc目录里,有一堆el文件 ,这就是ruby在emacs中的基本。

ruby-mode.el 这是基本ruby-mode主模式。
inf-ruby.el 在ruby主模式里运行内置的irb
ruby-electric.el 一个加强副模式
rubydb3x.el 在emacs里调用debugger

要在emacs里使用这些文件需要把他们拷贝到执行路径中,我新建了名为myEmacsEl的文件夹并将其添加到执行路径中。我的.emacs如下:

(set-default-font "DejaVu Sans Mono-14")
(set-fontset-font (frame-parameter nil 'font)
    'han'("WenQuanYi Micro Hei"))
(defun toggle-fullscreen()
  (interactive)
  (x-send-client-message
   nil 0 nil "_NET_WM_STATE" 32
   '(2 "_NET_WM_STATE_FULLSCREEN" 0))
)
(run-with-idle-timer 0.1 nil 'toggle-fullscreen)
(run-with-idle-timer 0.1 nil 'delete-other-windows)
(tool-bar-mode nil)

;;;;;;;;
;;ruby;;
;;;;;;;;
(setq ruby-program-name "/home/???/.rvm/rubies/ruby-1.9.3-p194/bin/irb --inf-ruby-mode")
;Allows syntax highlighting to work, among other things
(global-font-lock-mode 1)
; directory to put various el files into
(add-to-list 'load-path "/home/???/myEmacsEl/ruby")
; loads ruby mode when a .rb file is opened.
(autoload 'ruby-mode "ruby-mode"
  "Mode for editing ruby source files" t)
(setq auto-mode-alist
      (append '(("\\.rb$" . ruby-mode)) auto-mode-alist))
(setq interpreter-mode-alist (append '(("ruby" . ruby-mode))
                     interpreter-mode-alist))
; set to load inf-ruby and set inf-ruby key definition in ruby-mode.
(autoload 'run-ruby "inf-ruby"
  "Run an inferior Ruby process")
(autoload 'inf-ruby-keys "inf-ruby"
  "Set local key defs for inf-ruby in ruby-mode")
(add-hook 'ruby-mode-hook
          '(lambda ()
             (inf-ruby-keys)
         ))
; adding ruby electric
(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)
            (require 'ruby-electric)
            (ruby-electric-mode t)
            ))
;ruby debug
(autoload 'rubydb "rubydb3x" "run rubydb on program file in buffer" t)
;Auto-complete.el
(add-to-list 'load-path "/home/???/myEmacsEl/auto-complete")
(require 'auto-complete)
(global-auto-complete-mode t)
(add-to-list 'ac-dictionary-directories "/home/???/myEmacsEl/auto-complete/dict")
(require 'auto-complete-config)
(ac-config-default)
(add-to-list 'load-path "/home/???/.rvm/gems/ruby-1.9.3-p194/gems/rcodetools-0.8.5.0")
(require 'auto-complete-ruby)

从ruby标记往下是ruby的。

要注意的部分如下;
(setq ruby-program-name “/home/???/.rvm/rubies/ruby-1.9.3-p194/bin/irb –inf-ruby-mode”)
设置irb解释器的变量,务必要设定,否则inf-ruby内置解释器无法工作。因为我用的是rvm所以路径比较特殊。–inf-rubymode这个选项也是必须的,否则虽然可以用但是输出会很难看。这里用一个变量来确定irb的位置,我是很喜欢的,因为以后可以用pry之类的加强型irb替代。
(add-to-list ‘load-path “/home/???/myEmacsEl/ruby”)
追加路径

ruby-mode的主要功能就是tab的缩进功能被大幅在增强了,比如if或者循环可能嵌套很多层,按一下tab或者在回车时就可以正确缩进到当前应该缩进的位置,而不是仅仅插入一个制表符。
ruby-electric为ruby-mode提供一个副模式,其主要功能就是你在输入class或者def,while等等时会自动在下一行插入一个end,不要你手动去输了,而且双引号括号等等输入一个会自动出来一对,就跟eclipse一样。
inf-ruby自动hook到了ruby主模式上,按下C-c c-s会在emacs中出来一个irb,可以把buffer内的源代码分部分自动发到这个irb里去执行,方便的很。
rubydb3x.el这个就有点麻烦了,正确设定好.emacs后,按下M-x运行rubydb函数,在弹出来的minibuffer中输入当前ruby的全部路径和文件名才行,会自动在emacs里打开一个调试器,这实在说不上方便,我估计只是赋值一个变量的事儿,但是现在的我还做不到,而且ruby自带的调试器实在说不上好。

现在已经有了自动高亮,自动缩进,自动插入end和一个勉强可用的调试器

接下来是加入自动完成,可以自动输入代码中那些为了说明用途而长长的函数名还是很好的。

我用的是auto-complete.el,网址:http://www.cx4a.org/software/auto-complete/ 这货就叫这名字,是一个日本程序员的作品,令人不安的是从2010年后它就没有更新了,当然你也可以用yasppnet,或者其他自动完成后端。auto-complete提供了一个安装脚本,甚至还提供了一个Make文件,但是你读一遍就会发现它实际上就是把一些el文件放在安装的位置而已,所以你也可以手动做这些事,下载安装包,解压之后把所有的el文件和dict目录放在执行路径下,编辑.emacs文件。然后要再从这个作者的网站下载一个auto-complete-ruby.el文件放在路径下,因为auto-complete是一个泛用模式,它会给所有的主模式添加一个副模式,而auto-complete-ruby.el是为ruby特化,可是他需要require rodetools,这玩意儿从哪呢,gem install rcodetools.但是我就奇怪,你gem安装它和emacs有何关,能require到么?然后我在启动emacs时看到了一个warning,解决办法是你到rcodetools的目录下看看,那里面有很多el文件,把它的目录加入执行路径就没事了,这一点所有人都没提到。

悲剧的是auto-complete据我测试,似乎只按照预先定义好的字典和buffer里的上下文进行补全。就是说比如你导入一个第三方库,然后声明一个这个库里的对象,是没法补全他的方法的。因为ruby是动态语言,似乎也没法和java一样补全,因为在运行前无法确定对象的类型好像,我也不是很懂。这在技术上是毫无难度的,连我都可以想到,先运行补全位置之上的所有代码,之后对补全对象调用methods方法,然后根据出来的内容进行补全即可。但是没有必要:1.如果上面的代码有错误怎么办,这是很常见的 2.运行代码尤其当工程很大时要消耗大量时间,如果对这个进程进行优先级调度,则每次运行补全的结果会不一样。3 至少我是没见过ruby的库公共接口有java一样又臭又长的函数名

你可以用yas,但是我估计他和auto-complete没什么区别。Rsense是用java写的,不过按理只有速度上的提示而已。以后再努力尝试更多的补全插件。

我大致是按http://kimiboku.wordpress.com/2011/11/20/emacs-ruby/ 来的,中间也参考了无数其他网页,我看youtube一个视频里它只用了ruby-mode,yas,mate三个模式,mate我还没有尝试,但是基本的上面都有了,勉强也运行的起来。要进一步深入,我估计还是得学会emacs lisp,读懂那些长长的代码,因为文档实在太少了,靠文档和别人的经验活下去,实在只能靠运气。

发表评论

邮箱地址不会被公开。 必填项已用*标注