使用emacs而非普通ide的几个理由

轻便:emacs包括海量的文档也只有28M, 而eclipse一般是100多M,这就算轻便的了,visual studio是以G记的。而且emacs在启动时会占用更小的内存,更小的资源占用意味着更稳定,可以反复启动多次也不觉得浪费时间

支持:ide里eclipse只有对java和c++算是全功能,其他语言支持较少。visual studio因为是微软产品,除了对微软自家东西之外没有任何支持。而对python和ruby等开源语言或者clojure等新兴语言甚至是小众语言。这些ide要对一门新语言支持,等把。而emacs和vim等文本编辑器就好得多。

可定制性:在ide中想增加一个新功能,哪怕比较简单。提交bug报告然后等新版本吧,还不一定有。在emacs里你只要用lisp写新的代码然后hook到已有的模式,甚至直接改写已有模式就行了。

文本编辑功能:在emacs中即使在特定模式一般全局按键都是可用的,比如跳转到行首行尾,按词移动等。eclipse里也有类似特性但是emacs里更多。

因为ide能做的emacs大部分都能做到,而emacs能做的很多ide都无法实现,所以干嘛要用ide呢,无非是要付出时间去学习而已

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,读懂那些长长的代码,因为文档实在太少了,靠文档和别人的经验活下去,实在只能靠运气。

从官方安装RVM出现编译安装解释器出现错误的解决本办法

RVMRVM = ruby version manager,它本质上是一组shell脚本,通过从官方下载源码编译来获得ruby解释器,通过它可以让多个版本的解释器共存于一个环境下,这是很方便的。

使用rvm,有很多好处,你可以同时拥有多个ruby版本来运行不同的服务,而且每个解释器可以有自己的gems(第三方库)。而且由于是从官方下载源码编译,它可以第一时间拥有最新的解释器版本,而不用苦逼的等包管理器更新,实际上现在apt里也没有1.9.3版本的ruby。而且出于特殊目的用到老版本时,可以放心的安装而不会影响到现有服务。

从官方安装rvm,并且按照rvm requirement安装所有依赖后,编译安装解释器出现错误

Retrieving rubygems-
There is no checksum for 'http://production.cf.rubygems.org/rubygems/rubygems-.tgz' or 'rubygems-.tgz', it's not possible to validate it.
If you wish to continue with unverified download add '--verify-downloads 1' after the command.
There has been an error while trying to fetch the source. 
Halting the installation.

搜索后有人给出答案:
It looks like a bug, but it most likely is fixed already as I can not reproduce it, update RVM and try again:
rvm get stable
rvm rubygems current

升级rvm,然后重新安装rubygems,解释器出现错误的问题就解决了。

关于编程的一些感悟

这几天我在虚拟机里安装了ruby version manager,试图重写自己过去留下的几百行乱成一团的代码(虽然都还能用),并打算进个小步啥的,结果几天下来,一无所获。

于是我想:what the hell are you doing?

然后我试着又去搜索,看库文档,重新翻看编程书籍,但是感觉还是没什么进展。你没找到自己想要的。but why?我躺在床上一遍又一遍想这个问题,后来忽然有种悟的感觉:
那一切都他妈是扯淡。

当然,编程书籍是重要的,文档也是重要的。但是一本书并不能提供你的水平。我甚至购买了O’Reilly出版的ruby编程语言,结果呢,我懂得很多一般开发人员都不知道的细节和诀窍,但是我能独立开发一个web网站吗?显然不能。

书和文档,提供给你的只是零件,怎么把这些乱七八糟的齿轮组装成能用的机器则是你的问题,是人的问题,要解决这个问题,唯有学别人的样——读源代码。

因此一门好学的语言,当然语法简单也很重要,但更重要的是能不能找到好读的项目代码。ruby大部分的gem,都属于web开发领域,少数web无关的也都很陈旧,而他们往往依赖于其他gem,被依赖的gem很多已经升级换代导致api都不兼容了,所以这些web无关的玩意儿可能根本就跑不起来,本身都需要改写,谈不上再从中学习。(我感觉)python和perl就好一点。但更好学的,当然就是javascript,丫几乎无处不在,所有的web网站都有javascript,userscripts.org上有成堆的js脚本,firefox和chrome所有的扩展都用js写成并且可以拆开来看,要获取源码实在是太容易了!而且依赖google的v8引擎,js是现在几乎最快的可媲美c++的脚本语言,用node.js,可以脱离浏览器使用。

所以我将学javascript。其实api,库文档,书籍都不重要,那些标准,三年之后就全变了,干嘛要努力去记住呢?重要的是学习的速度,是结果