Rails Emacs dired 模式在 rails 项目文件 navigation 中的应用

zw963 · 2012年02月25日 · 最后由 kzjeef 回复于 2014年06月05日 · 8226 次阅读

各位好~!

在下是个 Ruby 新人,确切的说,作为程序员 (虽然还没有找到程序员工作), 也是个新人. 在 Ruby-china 注册有一阵子了 (确切的说,2 月 14 号,哈哈。言外之意...), 但是还没有 发过帖子,正好最近小弟正在学习 Rails. 有感于大量的文件之间切换,好不麻烦,所 以尝试使用 Emacs dired-mode作为切换 (linux 的 mc).并且达到了一个不错的效果. 当然,使用 Emacs 最大的好处就是可以自由定制, Oh! Freedom.

本人平素较懒,甚少发帖,现在既然找到了组织, 以后一定要改正,多多发帖,多多请教。

闲言少叙,直接进入正题。先说下本人的开发环境:

Slackware13.37 64 位,桌面系统为 XFCE4.8, 平时基本上都是混在 Emacs 下 (deamon).

在使用 Dired 作为 navigation 之前,主要是使用 Emacs 的 ido-mode 和 find-file-in-project 作为项目切换. ido 可以在 find-file 或者 switch-buffer 的时候,通过输入关键字自动筛选结果。 `ffip 利用了 linux 下 find 命令,可以设定在 ido 中只显示指定项目目录下的某些特定类型的文件。 (ffip 通过.git 自动定位项目目录,打开 git 所在目录分支任意一个文件,即切换到该项目,也可以设定某个目录为例外,这里我关闭了自动定位,直接设定为~/work/depot)

虽然已经很不错了。不过我记性不好,对 rails 还不熟,郁闷的是使用 ido 关键字过滤, 总忘记输什么。之前使用过 rinari 和 emacs-rails, 不过前者实在是是太老了...后者 虽然功能强大,但是总觉得很多功能有些多余 (通过 CLI 更有效), 而且代码过老,总有 这样那样的问题。还得修改 lisp 源码,好麻烦,而我 elisp 水平说实话讲,是相当的差 劲 (仅限于满足 Emacs 的使用,有时间一定要恶补!!)

其间,也想过使用 speedbar-mode, 可能个人习惯原因,不爽!后来使用过程中,琢磨 来琢磨去,觉得 Dired-mode 其实不错,下面是具体的搭建步骤,道理很简单,希望起到 抛砖引玉的作用。

需要特别提及的是:提高效率一定是全方位的。我始终信奉 UINX 的 K.I.S.S 原则,每一 项特定的功能,都有它最擅长的工作方式。

我们会用到以下内容:

  • 需要修改.bashrc, 主要是添加 bash 的快捷键,别名,函数
  • 使用大量的 Emacs plugins(咱 Ruby 称作库), 需要通过 (require '符号名) 的方式加载, 它们可以在 emacs-wiki 上搜索得到。

dired 是 Emacs 内置功能,它同样具有常见的文件管理功能 (类似 nc), 但相比较其他工具,这个模式具有以下优势:

  1. 和 Emacs 无缝结合,同一个界面内快速打开文件。
  2. 作为一个方便的 file manager, 大量内置好用快捷功能 (多数为类似 vim 的单键,大概有几十个).
  3. 可自由定制,随你所好的添加所需的功能,使用所需的模式打开,修改习惯的快捷键,完全掌控.(需要了解 elisp)

下面简单的贴一下 dired 需要修改的代码:(复制以下代码到~/.emacs 或~/.emacs.d/init.el, 重启 Emacs daemon.)

;; ============================== 有关 dired-mode 设置 ==============================
;; 首先需要加载几个插件.

(require 'dired-isearch) ; isearch模式仅仅搜索文件名, 通过s打开isearch.
(require 'dired-x) ; dired开启omit模式. 可以通过dired-omit-files, 指定pattern来隐藏文件.
(set-default 'dired-omit-mode 1) ; 全局开启omit模式.

;; 全局设定一个快捷键, 在任何时候, 一键切入当前buffer所在的目录. 我使用了Control-f
(global-set-key [(control f)] '(lambda () (interactive) (dired ".")))

(add-hook 'dired-mode-hook
'(lambda ()
(define-key dired-mode-map [(tab)] 'dired-do-isearch-regexp) ; 在mark的文件中正则搜索, 我设为tab键
(define-key dired-mode-map "\e\t" 'dired-do-isearch) ; mark的文件中搜索, 设为Alt-tab (C-M-i)
(define-key dired-mode-map [(?\d)] 'dired-up-directory) ; 到上一层目录, 设为backspace键, 默认^不变.
(define-key dired-mode-map [(backspace)] 'dired-up-directory)
(define-key dired-mode-map  "z" 'dired-name-filter-only-show-matched-lines) ; 过滤文件名z, g重新显示
(define-key dired-mode-map [(s)] 'dired-isearch-forward) ; 按s从光标处向下搜索文件名
(define-key dired-mode-map [(r)] 'dired-isearch-backward); 按r从光标处向上搜索文件名
;; 下面的hotkey偷自XFCE4的Thunar文件管理器.
(define-key dired-mode-map [(\/)] (lambda () (interactive)
(dired "/"))) ; 按/返回根目录,
(define-key dired-mode-map [(\~)] (lambda () (interactive)
(dired "~/"))) ; 按~返回home.
;; 下面的快捷键打开rails项目目录对应目录, 仅供参考, 快捷键对应于c, v, b
(define-key dired-mode-map [(c)] (lambda () (interactive)
(dired (concat ffip-project-root "/app/controllers"))))
(define-key dired-mode-map [(v)] (lambda () (interactive)
(dired (concat ffip-project-root "/app/views"))))
(define-key dired-mode-map [(b)] (lambda () (interactive)
(dired (concat ffip-project-root "/app/models"))))
))

;; ============================== 有关 ido-mode 设置 ==============================
(require 'ido)

;; 在最近打开文件列表中打开文件.
(defun recentf-ido-find-file ()
"Find a recent file using ido."
(interactive)
(let ((file (ido-completing-read "Choose recent file: " recentf-list nil t)))
(when file
(find-file file))))

(global-set-key [(control x) (f)] 'recentf-ido-find-file) ; 快捷键C-x f

;; ============================== 有关 find-file-in-project 设置 ==============================

(require 'find-file-in-project) ; 加载库 (setq ffip-patterns '("*.html.erb" )) ; 查找文件的模板。假设我只打开.html.erb. (setq ffip-project-root "~/work/depot") ; 之前多次引用到这个变量,只需要修改这个,全部生效,是不是有点DRY? (global-set-key [(control c) (control f)] 'find-file-in-project) ; 快捷键 C-c C-f.

.bashrc 内需要编辑的代码。

function my_project_directory {
TMP=$(emacsclient -e "ffip-project-root")
PROJECT_DIRECTORY=$(echo $TMP |sed s#\"##g)
(command emacsclient -c "$PROJECT_DIRECTORY" &) &>/dev/null
}
alias ee='my_project_directory'

写了这么多还没说怎么用。

  1. 打开任意一个 Terminal, 键入 ee, 自动打开 emacsclient frame, 显示项目主目录。
  2. 回车键,进入目录,打开文件。修改完毕,C-f 返回 dired
  3. 通过 c, v, b 进入指定的目录,唯手熟而已。(也可以使用 Dired 内置的大量快捷键,例如批量查找,替换等.)
  4. 按下 s 或 r, 输入要查找的文件名的一部分。回车打开文件。

通过此种方式 (搭配强大的 ido 以及 ffip), 我可以在最多 2 秒钟内,访问 Rails 项目中任意一个文件或 buffer.

如果我直推 textmate,你会愤怒吗,哈哈,我喜欢可以直接拿来用的,最好 0 配置。曾经浪费太多生命在 vim 和 emacs、linux 上的人飘过。

#1 楼 @hhuai 有时玩玩 emacs 也是程序员的一种享受

#1 楼 @hhuai vim 配置熟了还行吧。。。。不至于浪费生命吧。。

@hhuai, 事实上,头一次使用 Emacs 会花费相当多的功夫,但是框架大体稳定后,几乎没什么改动了,不浪费什么青春,就我这篇文章内讲的内容,也就 10 分钟搞定,平常,Emacs 用到了才修改,都是两三分钟的事儿,但是改完后,感觉一下就不一样了,(不管是不是真的效率高), 顺手了。

不知道这样讲对不对,让你去适应键盘,比让键盘去适应你应该难得多。

@hhuai 你 vim,emacs 用了多长时间啊?

@zw963 把 emacs 的配置 github 共享一下啊,以后我玩 emacs 学学

话说 vim,我现在经常耗时间在折腾插件上,玩 emacs 最大的幸福就在于,IMHO,emacs 的插件语言是 lisp,比 vim 的插件语言舒服多了。。

@jinleileiking , 我 Emacs 大概用了有一年多点,没问题,等稍后,我会用了 github 我就共享啊。现在还一头雾水呢。我使用 Emacs 的方式,还有点像 Vim, 正常情况下,C-f, C-b 是左右,我拧是通过大量的 (全方位的) 修改快捷键,改成了 C-j 左,C-l 右。我记得 Vim 是 H 左,L 右吧。你要是 Emacser, 估计用我的键位会很难受,要是 Vim, 倒是好适应点。

http://www.cnblogs.com/zw963/ 有我以前写的一篇文章。讲如何改快捷键的。

说起编程用编辑器,建议早点换到 Emacs 或 textmate 喽。VIM 最大的优势就是做 Linux 维护, 你在任何一个电脑上,都具有唯一的操作方式。如果总是在那几台电脑上用,而且有 emacs daemon 的话,Vim 速度甚至比 Emacs 还慢一点。

另外可伸缩性,也是不可忽略的.Emacs 真是的可以称得上是上天入地,无所不能。

今天就是个活生生的例子。

上午发帖时,在网站上打字慢的要死,好难受,下午的时候,我已经在 chrome 浏览器内 双击输入表单,就弹出了一个 markdown 模式的 frame, 我可以很快乐的打字,留言. 使用 Emacs 的 Auto-complete 和 Yasnippet(据称来自于 textmate) 和其他大量插件, 最后一个快捷键提交。

我觉得这是一个 Vimer 支持的简单脚本语言,无法奢望做到的。

#7 楼 @zw963 你用 vim 多长时间了,听你一说。我也想切 emacs 了。

楼主很小众阿,emacs 在十年前就想学,始终没上手,有些遗憾

我也觉得 vim 比 emacs 用的多

@jinleileiking, 我没用过 vim 啊,确切地说,2011 年春节时,我才打算看看 vim(那时候我还不会 Emacs 呢), 不过折腾了半个月,愣是没折腾出感觉来。后来决定换 Emacs, 我想这两个编辑器,很快就上手了。我一致认为,Vim 和 Emacs 都是有灵魂的编辑器,他们会挑人的。例如,我觉得 Vim 看不上我,呵呵。它们是那么的不一样... 给人感觉是完全不同的。

说了半天给个建议:就像学习计算机语言一样,一定要都试试,自己做决定。

@fsword, 我也觉得自己挺小众的,不过,我觉得能来这里常发帖的哥们儿,姐们儿不都是挺小众的么?

用 emacs 作 rails 开发为何不用 emacs-rails 或者 rinari 呢?

#5 楼 @jinleileiking vim 和 emacs 来来回回用了几年,写 c 和 python 还过得去。最开始用了 2 年的 ue,换成了 eclipse+cdt。

#4 楼 @zw963 嗯,emacs 我也挺熟练的,有一段日子拿到键盘就喜欢按 ctrl+n p。用这种定制太强的编辑器有个问题是,会在写代码时打乱我的思路,容易把心思转到这上面去。记得当时在我写代码时,我发现其没有.h 和.cpp 互切的功能,就跑去学 lisp,再写这个功能,搞了很久时间,而这些功能 eclipse+cdt 上已实现得很好。 应该是我个人的注意力问题,太容易转移,所以我总结我不适合用这种太强的武器。让我回 win 平台再写 unixc,或许我还是会用 ue. 现在在 mac 下写 ios 软件,没有选择,只有 xcode,在 xcode 中我会全心写代码,不会想着给他来点什么快捷功能,因为 xcode 连插件概念都没有,我也没觉得他在编辑上浪费了我什么效率。写 ruby 代码我会直接用 textmate,都是一些啥也不用配的东东,拿上就开写。btw,textmate 配色我都不改的,直接用他的默认白底黑字。

逻里八索了这么多,不知道有人和我一样的感觉没。

@hhuai, 你说的我很有同感,尤其是下面这句话:

用这种定制太强的编辑器有个问题是,会在写代码时打乱我的思路,容易把心思转到这上面去。

的确是这样的。尤其是接触一个新的环境时,例如最近开始看 rails3.1(以前不懂 rails, 也没做过 web 开发), 照着书上的示例写代码,刚开始根本写不下去,因为我认为自己一行一行输入<#...#>类似代码实在是很丑陋,很无趣,然后就是写上几行,就改一段 Yasnippet.(从 textmate 移植过来的自动补全), 总之改完 html 改 ruby, 改完 ruby 改 css, 改了半天,代码没看太明白,输入速度的确快了。通常这种情况下,我都是改到自己基本满意为止,然后读过的东西也忘的差不多了 (之前老是被打断,没有条理), 只能从头再读了。

我了解自己的这种行为,跟我的个性有关,在某些方面,我是非常完美主义的。做事情,或者写代码,尤其讲究当时的状态以及 feeling, 事实上之前很多年,我都是很严重的强迫症患者。直到近几年,我才依靠自己的力量彻底克服。不过完美主义,理想主义,是改不了了。

话两头说:如果时间允许,这种牺牲是值得的。还拿自动补全说事,按照自己的特色改好后,下次再写代码,多练几次后,再写代码,就完全沉醉在代码之中,而丝毫不会受到诸如:"for 循环应该以 ->结尾而不是>结尾", "helper 方法绝对不应该使用 h() 方法", "而获取属性的值,基于安全考虑,一定要使用<#=h .... #>"以及输入 (相对于手指而言) 丑陋的<# ....#>符号。这些事情你不通过定制,是无法达到期望的。

对于我来说,在接触 Emacs 以前,只要一遇到反复困扰我的同一个问题,我就钻就牛角出不来,然后极度郁闷,最后放弃。自从使用 Emacs 后,钻牛角改了好多,不过,反复被一个问题困扰,即使暂时可以妥协,但绝对是不可以接受的,就如同你想切换 h 和 cpp 一样。

我也罗嗦说这么多,其实是想表达,Emacs 定制性太强,是优点也是缺点,不过,像你那样,换个系统,就换个编辑器,我觉得学习使用那些编辑器的时间花在 emacs 上 (当时坚持一下), 也许效果会更棒。

最后,那个白底黑字,实在不敢苟同,不管是保护眼睛也好,还是阅读方便也好,实在不是什么好的色调。尤其是编程,要使用俺色调,我用的是 zenburn, 自己做了少许修改,据说这个方案是从 Vim 上面偷来的。

@hhuai, 大概看了下你的配置,好古老,呵呵。看样子你的确很久不用 Emacs 了。而且插件实在太少了。话说 Emacs 这玩意儿,插件少了,那是相当不爽的。不说别的,就说在这里发帖,如果没有 Chrome 浏览器的支持的插件 edit-server 插件,让我在网页上打字发帖,不如杀了我. 我是设定在访问 ruby-china.org 这个网站时,双击文本表单,弹出一个新的 Emacs frame, 并且打开 markdown-mode. 发完贴,C-cC-c 提交。

#18 楼 @zw963 哈哈,看来是各有所爱了。哪天回到 emacs 了,向你请教。

@hhui,客气啦,等最近 rails 搞定,然后抽空琢磨下 github, 把我的配置发上去。你瞧瞧。

@siyang1982 ,嗨,你好。刚刚才注意到你的回复。谢谢你的提醒。 之前,我没有仔细看过 rinari. 今天试了下,的确不错。

我甚至耍了一点小小的技俩,下面的代码,我将 C-f 将映射到 C-c ; f (我只需要简单的按下 C-f, 等价于按下 C-c ; f), 现在使用 C-f 作为快捷键, 切换还是很爽的。原来的 Dired 模式,换成了 C-f C-f. 哈哈。

(define-key key-translation-map [(control f)] [(control c) (?\;) (f)])

我上你的 github 看了下,看得出来,你也是绝对是用心琢磨,配置出来的。因为 Emacs 里面的一些精品插件,我看到你都有使用。

你的 javascript 的 yasnippet, 我就直接收下了。(虽然目前我还不懂 javascript)

rsense 以前了解过,一直没用过。觉得他又太大用处。auto-complete 足够了。

下面有几个问题请教一下:

  1. anything 我实在没明白那个是什么玩意。你方便的话,给说下。

  2. yari 貌似不支持正则表达式查询吧?我都基本上很少上 web, 都是用 yari. 但是有时候有些方法名非常短,或者包括问号,你会怎么样做?

最后给你提个建议:nxhtml-mode, 貌似有点老,而且有问题。貌似很多专业功 能也用不到,推荐使用 html-mode 或 rhtml-mode 替代,这个模式就是从 rinari 分离 出来的。如果需要 mumamu 那样的多模式切换,可以考虑单独配置 html-mode 配合 multi-web-mode, 一样的效果。

如果你希望使用 xhtml 风格,只要在 html 模式的 hook 中添加下列语句即可。

(setq sgml-xml-mode t)

用 Emacs 做开发的人,实在是不多。以后要多多互相交流. 留个联系方式吧:[email protected]

#22 楼 @zw963 C-f 不是右移动的快捷键么,会有冲突吧? 我是将 C-c ; f 映射到 C-c,为了避免与其它插件冲突,只定义了需要的几个。

(add-to-list 'auto-mode-alist '("\\.html\\.erb\\'" . ruby-mode))
(global-set-key (kbd "C-c c") 'rinari-find-controller)  
(global-set-key (kbd "C-c m") 'rinari-find-model)  
(global-set-key (kbd "C-c v") 'rinari-find-view)  
(global-set-key (kbd "C-c h") 'rinari-find-helper)  
(global-set-key (kbd "C-c r") 'rinari-find-rspec)  
(global-set-key (kbd "C-c j") 'rinari-find-javascript)  
(global-set-key (kbd "C-c s") 'rinari-find-stylesheet)  
(global-set-key (kbd "C-c f") 'rinari-find-file-in-project)  


javascript 的 yasnippet 我只写了一部小部分,自己都没太用(因为从 Mootools 改为 jQuery 了,而一些模板与框架有关),以后有机会再完善。

anything 大约是个全局查找文件的工具,不用根据目录一层层找(多亏你提醒,最近都忘了用) yari 也没怎么用过,文档一般还是网上看。

多谢推荐 multi-web-mode,呆会试试,mumamu 配置上总觉着有些不方便。

#20 楼 @zw963 楼主把你的 emacs 配置放到 github,给上使用说明,让我们来直接试用一下吧。

@siyang1982 , 有 ido 配合,yari 看 ri 文档我觉得很爽啊..

anything 难道是类似于 Linux 下的 locate 的玩意儿?

C-f 和 C-b, 我映射到了 C-l 和 C-j, 这样的话,我左右上下移动光标是单手的. 左手只需要按着 Capslock 或 Meta 即可。这样改的初衷也许你会觉得很可笑, 其实初期,C-f 和 C-b 也觉得不错。不过那时候,使用 Ctrl 而不是 capslock, 感觉左手跨度有点大,右手移动范围也有点大。

最要命的是:我用本子。中间有个小红帽,该死的 B 键...

@hhuai , 好的,我尽快。不行我就先放上去吧...

主要第一是我现在还不会用 github. 我以前只用过 RCS, 一个 Linux 的本地版本管 理系统。第二:我觉得不写一篇专门的文档,传上去没有任何意义。因为我使用 Emacs 的方式应该相当另类了。就如@siyang1982说的,键位全换了。当然,绝对 比默认键位输入多了。这其中有一部分哲学,在http://www.cnblogs.com/zw963/ 当中已经讲了,当然,不见得没个人都一致。而且大把的工具,常用的,不常用 的,几乎 包涵 Emacs 能做的任何事,40 多兆... 是不是很吃惊?甚至 Emacs 下的翻 译,我都搞了两个,一个 Google 在线翻译 (整句), 另一个是 linux 的 dict daemon, 之前如果没用过或者粗粗的用过,或者不了解最基本的 lisp, 根本无用, 超不过十分钟肯定全部删掉。此外代码相当乱,无用的代码也大把。我估计绝对 没人猜到,其实我 Emacs 只用了一年而已。

#25 楼 @zw963 我在刚开始用 emacs 也尝试过 lkjh 的 vim 方式,在几年前还把 editplus 也改成这样。 后来为了体验纯粹的 emacs 按键哲学(按键按到手抽筋?),改回默认。

@siyang1982, 我的初衷就是因为不用鼠标,那个小红点太碍事儿,

而且我那几个键的键位和 Vim 也不一样哦。left, Vim 是 H, 我是 J.

现在觉得当时的选择绝对是对的。至少每个手指都很舒服。

例如:经常切换 buffer, C-x b, 然后输入关键字。ido 帮忙筛选. 如果换成 C-x n, 除了右手食指,其他手指都不用动,省劲儿啊。

现在整个键盘,除了 b, q, a, z 不多用,其他键都已经条件反射了。

另外,因为 C-f, M-f 相应的被解放出来了。使用 Capslock 作为 Ctrl, C-f 键真的是相当输入,所以,我另外绑定了一些非常重要,频繁的 快捷键了。

唯一的痛苦就是,碰到默认的 Emacs 配置,现在很绕手了。哈哈。

还有就是进入纯文本终端,不知道这里有没有办法也更换 Capslock?

#27 楼 @zw963 喜欢小红点,不过因为太好用了所以会影响快捷键的熟悉. Linux 下可以直接改键映射的 key mapping(~/.Xmodmap)

#28 楼, @siyang1982 , 嗨~ 我当然知道 xmodmap 了。

下面就是我的 xmodmap 的命令,只不过我嫌麻烦,不想搞那么多~/.????配置文件, 所以几乎我用到的所有所有环境配置,包括 rvm, 大把的别名,函数等等,都放在了 .bashrc 里面。

xmodmap -e "remove lock = 0xffe5" &>/dev/null
xmodmap -e "add control = 0xffe5" &>/dev/null
xmodmap -e "keycode 66 = 0xffe3" &>/dev/null
xmodmap -e "remove mod1 = 0xffea" &>/dev/null
xmodmap -e "add lock = 0xffea" &>/dev/null
xmodmap -e "keycode 108 = 0xffe5" &>/dev/null


上面的代码将 Capslock 替换为 Ctrl, 但是左边的 Ctrl 功能没有变. 只是我把右边的 Alt 变为 Capslock 了。

可是这些只是在 X 下的 terminal 里面有效。

我问你的是:在纯文本终端下,是否有类似功能? 我想不出来,貌似必须自己编译自己的 linux 内核才可以实现吧?

#29 楼 @zw963 这个就没研究了,不过我的键盘 Noppoo choc mini 自带一键将 Capslock 切换为 Ctrl 功能~

#30 楼 @siyang1982 只是提醒一下,如果用左手小拇指太多的话,会导致整个手很疼,有酸麻的感觉,专业术语叫做:Emacs Pinky。

因为很多时候比如移动光标的时候,都是一直按着 Ctrl 建的。

我也一开始用 caps -> control,后来还是换回来用手掌边上来按了。只有笔记本自带的键盘还是用 caps 按,那个比较省力。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号