在开发过程中,我们往往要用到很多工具,如编辑器、编译器、调试器等等,随着软件越来越复杂,集成开发环境(IDE)出现了,它通过统一的界面把很多工具隐藏起来,并且还提供了索引功能,如跳到函数(或变量)声明(或定义)处等等。IDE在Windows平台发展得非常火,以至于有些Windows程序员只知道IDE,如微软的Visual Studio或Borland的Delphi等等,却不甚明了具体使用了那些工具。然而,IDE在*NIX
平台上却鲜有问津,我想,部分原因可以归结于Emacs的开放性和可扩展性。
Emacs支持多种编程语言,常见的如:C、C++、Java、Perl、Python、Ruby等,每种语言都有一个相应的Mode,这个Mode提供基本的语法高亮、缩进、快捷键管理等功能,还有快速定位光标,注释代码块等等。Emacs的缩进功能十分方便,不得不提。对于绝大多数Windows上的编辑器来说,当光标位于当前行第一个非空格字符前的时候,按一次TAB键,该行就向右缩进一级,实际上就是插入一个TAB键或一定数量的空格。而在Emacs里,TAB键实际就是一个缩进键,因此,无论光标处于当前行的任何位置,只需按一次TAB键就可以完成缩进,不论实际上需要缩进几级。Emacs这么设计是有道理的,试想,我们写程序的时候,是需要改变缩进的时候多,还是需要插入TAB键的机会多?恐怕后者出现的机会少之又少吧。所以,Emacs把输入TAB键的方式改为C-q TAB。
更炫的是,Emacs提供快捷键(C-M-)缩进当前选中的region。比如说,我们发现一段代码实际上应该只在某个条件下才需要执行,那么就用一条if语句将这段代码包围起来,然后需要做的就是改变其缩进。如果只有三行,那么按照Windows方式一行行地做缩进也还凑合,如果是十行、三十行呢?Emacs的操作序列是这样的:
- 在输入完if语句的右大括号之后,按C-space建立一个mark;
- 按C-M-p将光标移动到对应的左大括号处,相应地,这一对大括号所包围的区域就成了当前的region;
- 按C-M-缩进选中的region。
虽然Emacs不提供项目管理功能,但我们仍然可以在Emacs里编译,命令是:M-x compile。缺省的,Emacs调用make完成编译功能,编译输出信息显示在一个单独的buffer里,它可以高亮显示编译错误,点击该错误或在该行按回车键,Emacs会自动显示语法错所在的文件并将光标定位到相应的行,这与IDE所做的一模一样。当然也可以配制成其它方式来做编译,因为本质上就是调用一个外部命令然后将输出导入到一个buffer里。另外,Emacs也可以调用gdb
或perl -d
等外部命令调试程序,由于Emacs可以用一个单独的buffer显示源文件,所以要比直接在命令行上运行调试命令方便得多。
软件开发必然少不了版本控制。Emacs与版本控制工具(如CVS
)结合得相当完美,我们可以很方便地察看log(C-x v l)、与repository上的代码做比较(C-x v =)、查看以前的版本(C-x v ~)等等。Emacs提供了两个包:VC和PCL-CVS,VC通常是针对单个文件的,当我们打开一个文件的时候,它会检查是否有与这个文件相关的版本控制信息,比如该文件所在目录是否有个CVS目录,有的话则将其与该文件关联起来。这样,我们就可以完成上面提到的一些操作了。而PCL-CVS则是针对整个模块的。更绝的是,Emacs为每个命令的输出都作了高亮处理,毕竟,看没有高亮的diff结果可不是很容易的。
Emacs还提供了etags和ebrowse做索引,这样就可以在代码间跳来跳去了,etags支持多种语言,而ebrowse则为面向对象语言提供了特殊的支持。
看到这里也许觉得Emacs就是一个IDE嘛。实际上,相对于IDE来说,Emacs具有更强的程序设计语言中立性和集成工具中立性,而这些,正是Emacs的开放性和可扩展性带来的。所以我更愿意说,Emacs不是IDE,胜似IDE。
请教一个emacs 问题:如何在状态栏显示当前函数名?
没用过。
Add this line in ~/.emacs
(which-func-mode t)
你好,请问EMACS中如何定义一个快捷键来运行编译的程序?如F5来直接运行编译的程序,而不用切换到SHELL下
编译是M-x compile,无需shell。
啊呀,是我说我不清楚,就是运行程序,如我已经编译好了一个程序a,想运行它得先切换到shell下然后./a,每次这样做挺麻烦的,就是想一个快捷键直接运行a,呵呵
呵呵,运行是M-!,可惜没有路径补全,用起来不是很舒服。
呵呵原来是这个命令,我不懂LISP编程,就借鉴智能编译函数(http://pluskid.lifegoo.com/wiki/EmacsSmartCompile.html),照葫芦画瓢了一个函数,还能凑合用,呵呵谢谢提示啦
函数如下:
(global-set-key (kbd “f5”) ‘smart-run)
(defun smart-run()
(interactive)
;; 查找 Makefile
(let ((candidate-make-file-name ‘(“woahtisawhdiksdjfefsadfknsdf”))
(command nil))
(if (not (null
(find t candidate-make-file-name :key
‘(lambda (f) (file-readable-p f)))))
(setq command “make -k “)
;; 没有找到 Makefile ,查看当前 mode 是否是已知的可编译的模式
(if (null (buffer-file-name (current-buffer)))
(message “Buffer not attached to a file, won’t compile!”)
(if (eq major-mode ‘c-mode)
(setq command
(concat “”
(file-name-sans-extension
(file-name-nondirectory buffer-file-name))
“”
))
(if (eq major-mode ‘c++-mode)
(setq command
(concat “”
(file-name-sans-extension
(file-name-nondirectory buffer-file-name))
“”
))
(message “Unknow mode, won’t run!”)))))
(if (not (null command))
(let ((command (read-from-minibuffer “Shell command: ” command)))
(shell-command command)))))