Showing posts with label emacs. Show all posts
Showing posts with label emacs. Show all posts

Wednesday, October 8, 2008

[转载]在Emacs下用C/C++编程

版权说明和参考文献

按照惯例,我写的文章在最开始处放版权说明和参考文献。

参考文献:

  • hhuu @ newsmth 的《Emacs的日常生活》
  • emacs 的文档
  • emacs 相关插件的文档

版权说明:

转载请注明转自曹乐的个人主页 www.caole.net


序

用emacs写程序也有5个年头了,深切地体会到Emacs的强大。程序员有三种,一种是用vi的,一种是用emacs的,还有一种是其他。或许有些夸张,但也颇能体现出emacs在程序员中的地位。

emacs最大的问题在于入门门槛较高。它看起来和多数人想象中的IDE相差甚远,很多人看到emacs的第一眼就觉得它是个记事本(还是个非常难用的记事本),稍微好些的往往觉得emacs也就是个ultraEditor而已,真是暴殄天物了。

我是个懒人,不喜欢记太多的快捷键,相信很多人和我一样。所以从我后面的叙述可以看出来,除了常用的命令都是快捷键外,其他命令多数都是用M-x执行或者用鼠标点菜单。这仅仅是个人风格问题,先说明一下。

我的基本编程环境是:

  • Debian GNU/Linux sid 操作系统
  • Gnome 2.10.0 桌面环境
  • GUN Emacs 23.0.0.1 for debian
  • 使用 Gnu tool chains(gcc,make,gdb等等)

后面的叙述都基于上述环境。另外,本文主要针对C/C++程序开发,对其他语言有些也适用,从难度上说,本文主要针对入门者。

本文肯定会有很多错误,请指正,谢谢。


基本流程

写C++程序基本上是这么几个步骤:

  1. 编辑代码
  2. 编写Makefile
  3. 编译代码,修改编译错误
  4. 调试代码,修改逻辑错误

当然,往往还需要阅读别人的代码。

根据上述步骤,本文主要针对以下几个方面:

  • 配置Emacs,建立便利的代码编辑环境和Makefile编写环境。
  • 在Emacs中编译代码,并修改编译错误。
  • 在Emacs中配合GDB调试程序。
  • 利用cscope和ecb在emacs中阅读代码。

基本环境设置

编辑环境配置

要写C++程序,当然要用到cc-mode插件。CC-Mode原本是支持C语言的,但现在也能支持很多语言,比如C++,Java, Objective-C,CORBA,AWK,Pike等等。CC-Mode是gnu-emacs的标准插件。如果您要求不高,那么默认的配置或许就能满 足。CC-Mode的各种行为都可以自由地定制,您可以参考这里的文档:CC-Mode参考文档

这里是我的.emacs文件中关于CC-Mode配置的部分,仅供参考:

;;;; CC-mode配置 http://cc-mode.sourceforge.net/
(require 'cc-mode)
(c-set-offset 'inline-open 0)
(c-set-offset 'friend '-)
(c-set-offset 'substatement-open 0)
;;;;我的C/C++语言编辑策略

(defun my-c-mode-common-hook()
(setq tab-width 4 indent-tabs-mode nil)
;;; hungry-delete and auto-newline
(c-toggle-auto-hungry-state 1)
;;按键定义
(define-key c-mode-base-map [(control \`)] 'hs-toggle-hiding)
(define-key c-mode-base-map [(return)] 'newline-and-indent)
(define-key c-mode-base-map [(f7)] 'compile)
(define-key c-mode-base-map [(meta \`)] 'c-indent-command)
;; (define-key c-mode-base-map [(tab)] 'hippie-expand)
(define-key c-mode-base-map [(tab)] 'my-indent-or-complete)
(define-key c-mode-base-map [(meta ?/)] 'semantic-ia-complete-symbol-menu)
;;;;我的C/C++语言编辑策略

(defun my-c-mode-common-hook()
(setq tab-width 4 indent-tabs-mode nil)
;;; hungry-delete and auto-newline
(c-toggle-auto-hungry-state 1)
;;按键定义
(define-key c-mode-base-map [(control \`)] 'hs-toggle-hiding)
(define-key c-mode-base-map [(return)] 'newline-and-indent)
(define-key c-mode-base-map [(f7)] 'compile)
(define-key c-mode-base-map [(meta \`)] 'c-indent-command)
;; (define-key c-mode-base-map [(tab)] 'hippie-expand)
(define-key c-mode-base-map [(tab)] 'my-indent-or-complete)
(define-key c-mode-base-map [(meta ?/)] 'semantic-ia-complete-symbol-menu)

注意一下,上面最后两行是代码自动补齐的快捷键。后面我会提到代码自动补齐。

;;预处理设置
(setq c-macro-shrink-window-flag t)
(setq c-macro-preprocessor "cpp")
(setq c-macro-cppflags " ")
(setq c-macro-prompt-flag t)
(setq hs-minor-mode t)
(setq abbrev-mode t)
)
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

;;;;我的C++语言编辑策略
(defun my-c++-mode-hook()
(setq tab-width 4 indent-tabs-mode nil)
(c-set-style "stroustrup")
;; (define-key c++-mode-map [f3] 'replace-regexp)
)

自动补齐

自动补齐通常用的都是hippie-expand,我也用了很长时间。不过有时候会觉得这个自动补齐“傻”了一点,常会补齐出一些毫不相干的东西,因为hippie-expand是根据你敲过的词和kill-ring等进行判断的,并不对程序语法进行分析。

所以你还需要安装一个代码分析工具,然后把它加进hippie-expand的扩展策略里去。我们可以用semantic。实际上,hippie-expand+semantic是我所发现的最好的选择了,如果您有更好的,请您也告诉我一声:)

Semantic是CEDET中的一个工具,CEDET是Collection of Emacs Development Environment Tools的缩写,它包含了好几个工具,都挺不错的。可惜我只会用其中两个。

您可以在.emacs中对Semantic进行配置,下面是我的.emacs相关的配置,仅供参考:

导入cedet:

(load-file "~/lib/emacs-lisp/cedet-1.0pre3/common/cedet.el")

配置Semantic的检索范围:

(setq semanticdb-project-roots
(list
(expand-file-name "/")))

自定义自动补齐命令,这部分是抄hhuu的,如果在单词中间就补齐,否则就是tab。

(defun my-indent-or-complete ()
(interactive)
(if (looking-at "\>")
(hippie-expand nil)
(indent-for-tab-command))
)

(global-set-key [(control tab)] 'my-indent-or-complete)

hippie的自动补齐策略,优先调用了senator的分析结果:

(autoload 'senator-try-expand-semantic "senator")

(setq hippie-expand-try-functions-list
'(
senator-try-expand-semantic
try-expand-dabbrev
try-expand-dabbrev-visible
try-expand-dabbrev-all-buffers
try-expand-dabbrev-from-kill
try-expand-list
try-expand-list-all-buffers
try-expand-line
try-expand-line-all-buffers
try-complete-file-name-partially
try-complete-file-name
try-expand-whole-kill
)
)

注意一下我前面CC-Mode配置中有这么两行:

(define-key c-mode-base-map [(tab)] 'my-indent-or-complete)
(define-key c-mode-base-map [(meta ?/)] 'semantic-ia-complete-symbol-menu)

这样,我们在CC-Mode中就可以调用自定义的hippie补全了,快捷键是Tab。

另外,我还把快捷键“Alt + / ”绑定到了semantic-ia-complete-symbol-menu命令上,这是semantic的命令,它会根据分析结果弹出补齐的菜单,效果如图显示:

CEDET中还有一个不错的工具是speedbar,你可以用它在多个文件中快速切换。在我的.emacs配置文件里,我把speedbar关联到了F5上:

(global-set-key [(f5)] 'speedbar)

这样用F5就可以调出speedbar,效果如下:

不过说实话,我自己很少用到speedbar,我通常都是用dired配合bookmark使用:)

编译和调试程序

按上面的配置,写完程序和Makefile文件后,在Emacs源代码窗口中按F7就可以进行编译。因为在my-c-mode-common-hook()函数里,有这么一行:

(define-key c-mode-base-map [(f7)] 'compile)

默认情况下,emacs的compile命令是调用make -k,我把它改成了make。你也可以把它改成其他的,比如gcc之类的。改下面的“make”就行了。

'(compile-command "make")

Emacs会划分一个窗格显示编译的消息,在编译结束后,emacs会自动将编译器的输出和程序关联起来,告诉你第几行的程序有问题。直接在出错的行号上按Enter,就可以跳转到相应文件的相应行。其实我通常都是用鼠标中键去点出错行号:)

搞定了编译错误后,接着要和逻辑错误斗争了。其实对简单的程序来说,把中间结果打印到终端是最简单好用的调试办法:)不过稍微复杂点的程序就会晕菜了,这时我们就需要拿gdb跟踪程序流程了。

你用下面的命令就可以启动gdb了。

M-x gdb

通常我喜欢进入gdb-many-windows模式,这样就会把一个Frame划分为5个窗格,同时显示:gdb命令窗口,当前局部变量,程序文本,调用栈和断点。

gdb的命令就不在这里说了,它的文档几乎到处都是。emacs把gdb的命令和快捷键做了绑定,对于常用的命令,还是输入快捷键比较方便。比如,C-c C-n是Next line,C-c C-s是step in,其实用的最多的快捷键也就是这两个。

下面是我的gdb效果图:

阅读代码

在emacs下读代码通常有三种工具,最简单的是etags,最复杂的是ecb(emacs code browser),位于中间的是cscope。

etags和ctags一样,只不过前者是用于emacs的,后者是用于vi的。我个人觉得etags功能稍稍显得不够用一点,当然,也可能是我用的不好:) 欢迎大牛指导。

使用tags之前要先对源代码分析建立tags文件,在代码所在目录中运行:etags -R 即可。

我常用的就这几个命令和快捷键:

M-x visit-tags-table FILE 选择tags文件
M-. [TAG] 访问标签
M-* 返回
C-u M-. 寻找标签的下一个定义

ecb据说功能强大,但是太复杂了,我懒得折腾它。谁搞定了教教我吧:) 下面是一张ecb的效果图。

cscope是我感觉比较合适的一个工具。它其实是一个独立的软件,完全可以脱离vi和emacs使用。但是结合emacs的强大功能, cscope就显得更加方便了。GNU Emacs默认自带cscope的支持。在使用之前,cscope也需要对代码进行索引。在emacs中可以这样做:

C-c s a 设定初始化的目录,一般是你代码的根目录
C-s s I 对目录中的相关文件建立列表并进行索引

建完索引之后,你就可以用cscope在代码里游荡了。常用的一些命令如下:

C-c s s 序找符号
C-c s g 寻找全局的定义
C-c s c 看看指定函数被哪些函数所调用
C-c s C 看看指定函数调用了哪些函数
C-c s e 寻找正则表达式
C-c s f 寻找文件
C-c s i 看看指定的文件被哪些文件include

上面这些快捷键其实我自己也常常记不全,没关系,抬头看看上面的菜单栏,有一栏就是Cscope,这些命令里头都有:)

贴一个cscope的效果图吧:

Tuesday, July 15, 2008

jerry-key-bindings.el

;;; jerry-key-bindings.el --- 全局键盘绑定设置

;;; Code:

;;统一设置键帮定,并尽量放在配置文件的最后,以免被绑定的键不小心被后面
;;的配置文件覆盖
;;常用习惯,F1打开帮助,常用帮助有info和woman(就是在emacs中看man)
(global-set-key [f1] 'info)
;;显示man在一个buffer里面,常用
(global-set-key [(control f1)] 'woman)
;;恢复,常用键
(global-set-key [f2] 'undo)
;;打开sawfish的配置文件
(global-set-key [(control f3)] 'my-open-dot-sawfishrc)
;;打开.emacs的快捷方式
(global-set-key [(control f2)] 'my-open-dot-emacs)
;;打开fvwm的.fvwm2rc和config的快速方式,我现在使用fvwm,常用
;(global-set-key [(control f3)] 'my-open-fvwmconfig)
;;反恢复,不是很常用,但是绑定了还是方便些
(global-set-key [f3] 'redo)
;;F4,kill键,习惯设置,关闭当前buffer
(global-set-key [f4] 'kill-this-buffer)
;(global-set-key [f5] 'speedbar)
;;文件管理器,常用
(global-set-key [f6] 'dired-jump)
;;打开一个终端,根据你的爱好可以绑定为:eshell,shell,terminal-emulator
(global-set-key [f5] 'eshell)
;(global-set-key [f5] 'ansi-term)
;;同clear相识,具体功能在jerry-functions.el讲过
(global-set-key [f7] 'my-line-to-top-of-window)
;;本人正在学scheme,常用
;(global-set-key [f8] 'run-scheme)
;;;F9:列举我的书签
(global-set-key [f8] 'list-bookmarks)
;;;F9:添加当前页到书签中
;;(global-set-key [f9] 'bookmark-set)
;;看新闻组,常用的很,不过更多时间现在sir里
(global-set-key [f9] 'gnus)
;;习惯设置,打开/关闭菜单
(global-set-key [f10] 'menu-bar-mode)
;;编译等,暂时还不常用
(global-set-key [f11] 'compile)
;(global-set-key [f12] 'todo-show)
(global-set-key [f12] 'gdb)

;;习惯设置,Home键设定光标到文件开头
(global-set-key [(home)] 'beginning-of-buffer)
;;习惯设置,End键设定光标到文件结尾
(global-set-key [(end)] 'end-of-buffer)

;; Meta
(global-set-key "\M- " 'set-mark-command)
(global-set-key "\M-\C-h" 'backward-kill-word)
(global-set-key "\M-\C-r" 'query-replace)
(global-set-key "\M-r" 'replace-string)
;(global-set-key "\M-g" 'goto-line)
(global-set-key "\M-h" 'help-command)
;;Alt+s : 让speedbar获得焦点
(global-set-key (kbd "M-s") 'speedbar-get-focus)

;;meta在常用PC键上就是Alt键
;;这三个绑定主要是光标移动的
(global-set-key [(meta down)] 'goto-line)
(global-set-key [(meta left)] 'backward-sexp)
(global-set-key [(meta right)] 'forward-sexp)
;;NB:这下面的几个快捷键还没有熟练使用
;;注释region
;;比较常用,来回改的麻烦,还是这个方便
(global-set-key [(meta m)] 'comment-region)
(global-set-key [(meta u)] 'uncomment-region)
;; 常用补全命令
(global-set-key (kbd "M-/") 'hippie-expand)

;; ;;小键盘的bindings
;; (global-set-key [up] "\C-p")
;; (global-set-key [down] "\C-n")
;; (global-set-key [left] "\C-b")
;; (global-set-key [right] "\C-f")
;; ;(global-set-key [home] "\C-a")
;; ;(global-set-key [end] "\C-e")
;; (global-set-key [prior] "\M-v"); prior就是上翻页pg up
;; (global-set-key [next] "\C-v"); AKA pg dn
;; (global-set-key [C-up] "\M-\C-b")
;; (global-set-key [C-down] "\M-\C-f")
;; (global-set-key [C-left] "\M-b")
;; (global-set-key [C-right] "\M-f")
;; (global-set-key [C-home] "\M-<")
;; (global-set-key [C-end] "\M->")
;; ;(global-set-key [C-prior] "\M-<"); AKA pg up
;; ;(global-set-key [C-next] "\M->") ; AKA pg dn

;;快速切换buffer,prior就是上翻页pg up,next就是pg dn键盘
(global-set-key [C-prior] 'swbuff-switch-to-previous-buffer)
(global-set-key [C-next] 'swbuff-switch-to-next-buffer)
;;Win更换tabbar不错吧,前两个是在不同的分组切换,后面的是在同组
;;切换
(global-set-key [s-up] 'tabbar-backward-group)
(global-set-key [s-down] 'tabbar-backward-group)
;(global-set-key (kbd "M-]") 'tabbar-forward-group)
(global-set-key [s-left] 'tabbar-backward-tab)
(global-set-key [s-right] 'tabbar-forward-tab)
;;括号配对
(global-set-key "%" 'my-match-paren)
;;类似vi的f命令,使用方法为C-c a "x",x为任意字符,找第几个字符
(define-key global-map (kbd "C-c a") 'my-go-to-char)
;;hide region
(global-set-key (kbd "C-c r") 'hide-region-hide)
(global-set-key (kbd "C-c R") 'hide-region-unhide)
;;hide lines
(global-set-key (kbd "C-c l") 'hide-lines)
(global-set-key (kbd "C-c L") 'show-all-invisible)
;; 因为C-c m不是已有的前缀,所以要先定义一下
(define-prefix-command 'ctl-cm-map)
(global-set-key (kbd "C-c m") 'ctl-cm-map)
;; msf-abbrev的几个快捷键
(global-set-key (kbd "C-c ml") 'msf-abbrev-goto-root)
(global-set-key (kbd "C-c ma") 'msf-abbrev-define-new-abbrev-this-mode)
;;todo的几个快捷键
(global-set-key "\C-ct" 'todo-show) ;; switch to TODO buffer
(global-set-key "\C-ci" 'todo-insert-item) ;; insert new item
;;使用的ibuffer
(global-set-key (kbd "C-x C-b") 'ibuffer)
;; (global-set-key (kbd "C-x C-b") 'ibuffer-other-window)
;;remember的快捷键
(define-key global-map (kbd "C-c C-r") 'remember)
;(define-key global-map [f9] 'remember-region)
;;C-x C-r ,TAP列出最近打开的文件列表
(global-set-key "\C-x\C-r" 'recentf-open-files-compl)
;;让当前buffer生效的快捷方式
(add-hook 'emacs-lisp-mode-hook
  (lambda ()
  (local-set-key "\C-c\C-c" 'eval-buffer)
  ))
;;为什么我就不能使用这个键呢,原来和fcitx输入法冲突了
(global-set-key [C-k] 'kill-line)


;;打开org的记事本,纪念,网络链接等
(define-key global-map "\C-cs" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
;(define-key global-map "\C-cr" 'org-remember)
;;用Emacs时常用多个窗口,窗口之间的移动很常见
;; 默认的打开文件太差劲,使用通用的操作方式吧
;(global-set-key [(control o)] 'ido-find-file)
(global-set-key [(meta o)] 'other-window)
;;这就是我的切换buffer的设置,同windows操作相识
;;没法,windows用了两年多,有些习惯还真不好改
;;不过emacs的配置就是好配,随你配
(global-set-key [(control tab)] 'tabbar-forward)
;;这个设置是改变outline的快捷键前缀
;;outline主要用于编程等,目前用的不多
(setq outline-minor-mode-prefix (kbd "C-o"))
(mapc (lambda (bind)
  (define-key outline-minor-mode-map
  (car bind)
  (cdr bind)))
  `((,(kbd "C-o q") . hide-sublevels)
  (,(kbd "C-o a") . show-all)
  (,(kbd "C-o t") . hide-body)
  (,(kbd "C-o c") . hide-entry)
  (,(kbd "C-o e") . show-entry)
  (,(kbd "C-o l") . hide-leaves)
  (,(kbd "C-o k") . show-branches)
  (,(kbd "C-o d") . hide-subtree)))

;;自定义自动补齐命令,这部分是抄hhuu的,如果在单词中间就补齐,否则
;; 就是tab。
;(global-set-key [(control tab)] 'my-indent-or-complete)
;; 直观地把矩形显示出来
;; 作为和绑定到 C-x C-x 的 exchange-point-and-mark 对应起来
(global-set-key (kbd "C-x r C-x") 'rm-exchange-point-and-mark)
;;快速跳转到当前buffer所对应的目录
;(define-key global-map (kbd "C-x C-j") 'dired-jump)
(define-key global-map (kbd "C-x 4 C-j") 'dired-jump-other-window)


;;默认的Ctrl-z是什么来着,关闭emacs吧,好像还是强行关闭,不好,用
;;C-x c就好了
;;我就将Ctrl-z作为我的键的绑定
(define-prefix-command 'ctl-z-map)
(global-set-key (kbd "C-z") 'ctl-z-map)
;;启动picture (artist)模式
(global-set-key (kbd "C-z a") 'artist-mode)
;;编译当前emacs-lisp源码为elc
(global-set-key (kbd "C-z b") 'emacs-lisp-byte-compile)
;;打开我得日历
(global-set-key (kbd "C-z c") 'calendar)
;;字典功能,就是查单词
(global-set-key (kbd "C-z d d") 'dictionary-lookup-definition)
;;与上面类似
(global-set-key (kbd "C-z d s") 'dictionary-search)
;;查询当前单词的匹配的单词,用于补全单词
(global-set-key (kbd "C-z d m") 'dictionary-match-words)
;;字典提示模式,同字典的自动取词功能相似
;;查stardict字典
(global-set-key (kbd "C-z d t") 'sdcv-search)
;(global-set-key (kbd "C-z d t") 'kid-sdcv-to-buffer)
;(global-set-key (kbd "C-z d m") 'kid-star-dict)
;(global-set-key (kbd "C-z d t") 'dictionary-tooltip-mode)
;;编辑环境变量,很好用的功能
(global-set-key (kbd "C-z e e") 'edit-env)
;;启动我的IRC客户端,到sir去
(global-set-key (kbd "C-z e s") 'erc-irc)
;;到fans聊天去
(global-set-key (kbd "C-z e f") 'erc-fans)
;;启动拼写检查模式,只检查打开后输入的单词
(global-set-key (kbd "C-z f m") 'flyspell-mode)
;;对整个buffer进行拼写检查
(global-set-key (kbd "C-z f b") 'flyspell-buffer)
;;打开gnus
(global-set-key (kbd "C-z g") 'gnus)
;;数数本文件有多少文字
(global-set-key (kbd "C-z h c") 'my-count-words-region)
;;同Clear键
(global-set-key (kbd "C-z h l") 'my-line-to-top-of-window)
;;使用hyperspec查询common lisp的symbol定义
(global-set-key (kbd "C-z h s") 'hyperspec-lookup)
;;把高亮显示当前buffer输出为html格式的文件
(global-set-key (kbd "C-z h z") 'htmlize-buffer)
;;拼写检查
(global-set-key (kbd "C-z i") 'ispell-minor-mode)
;;debug
(global-set-key (kbd "C-z j") 'jdb)
;;查看前面删除的内容记录
(global-set-key (kbd "C-z k") 'browse-kill-ring)
;;关闭没有用的buffer
(global-set-key (kbd "C-c k") 'my-clean-buffers)
;;打印当前buffer
;(global-set-key (kbd "C-z l") 'lpr-buffer)
(global-set-key (kbd "C-z l") 'my-longest-line)
;;启动我得maxima,漂亮模式
;(global-set-key (kbd "C-z m m") 'imaxima)
;;看看我的键绑定
(global-set-key (kbd "C-z m k") 'my-keytable)
;;emms相关的快捷键
;; global key-map
(global-set-key (kbd "H-b") 'emms-playlist-mode-go)

(global-set-key (kbd "C-c e t") 'emms-play-directory-tree)
(global-set-key (kbd "C-c e x") 'emms-start)
(global-set-key (kbd "C-c e v") 'emms-stop)
(global-set-key (kbd "C-c e n") 'emms-next)
(global-set-key (kbd "C-c e p") 'emms-previous)
(global-set-key (kbd "C-c e o") 'emms-show)
(global-set-key (kbd "C-c e h") 'emms-shuffle)
(global-set-key (kbd "C-c e e") 'emms-play-file)
(global-set-key (kbd "C-c e f") 'emms-play-playlist)
(global-set-key (kbd "C-c e SPC") 'emms-pause)
(global-set-key (kbd "C-c e a") 'emms-add-directory-tree)

(global-set-key (kbd "C-c e r") 'emms-toggle-repeat-track)
(global-set-key (kbd "C-c e R") 'emms-toggle-repeat-playlist)

(global-set-key (kbd "C-c e s u") 'emms-score-up-playing)
(global-set-key (kbd "C-c e s d") 'emms-score-down-playing)
(global-set-key (kbd "C-c e s o") 'emms-score-show-playing)
;; playlist-mode-map
(define-key emms-playlist-mode-map (kbd "SPC") 'emms-pause)
(define-key emms-playlist-mode-map (kbd "+") 'emms-volume-raise)
(define-key emms-playlist-mode-map (kbd "-") 'emms-volume-lower)
(define-key emms-playlist-mode-map (kbd "")
  (lambda () (interactive) (emms-seek-forward)));;+10)))
(define-key emms-playlist-mode-map (kbd "")
  (lambda () (interactive) (emms-seek-backward)));;-10)))
;; (define-key emms-playlist-mode-map (kbd "")
;; (lambda () (interactive) (emms-seek +60)))
;; ;(define-key emms-playlist-mode-map (kbd (""))
;; ; (lambda () (interactive) (emms-seek -60)))
(define-key emms-playlist-mode-map (kbd "S u") 'emms-score-up-file-on-line)
(define-key emms-playlist-mode-map (kbd "S d") 'emms-score-down-file-on-line)
(define-key emms-playlist-mode-map (kbd "S o") 'emms-score-show-file-on-line)
(define-key emms-playlist-mode-map (kbd "S l") 'emms-score-less-tolerant)
(define-key emms-playlist-mode-map (kbd "S m") 'emms-score-more-tolerant)
(define-key emms-playlist-mode-map (kbd "S t") 'emms-score-set-tolerance)
(define-key emms-playlist-mode-map (kbd "S s") 'emms-score-show-playing)

;;发送邮件
(global-set-key (kbd "C-z m s") 'mew-send)
;;接收邮件
(global-set-key (kbd "C-z m r") 'mew)

;;绑定两个narrow功能
(global-set-key (kbd "C-z n n") 'narrow-to-region)
(global-set-key (kbd "C-z n w") 'widen)
;;occur使用正则查找,列出一个buffer
(global-set-key (kbd "C-z o") 'occur)

;;几个小游戏
(global-set-key (kbd "C-z p g") 'gomoku)
(global-set-key (kbd "C-z p t") 'tetris)
;;训练绑定键盘的
(global-set-key (kbd "C-z p k") 'keywiz)
;;由于在html-helper-mode模式中F4键失效,用这个绑定来关闭buffer
(global-set-key (kbd "C-z q") 'kill-this-buffer)
;;带正则表达式的搜索
(global-set-key (kbd "C-z r") 'query-replace-regexp)
;;我得scheme也是可以在emacs中运行的
;(global-set-key (kbd "C-z s") 'run-scheme)
;;打开行号显示,和vi一样的
(global-set-key (kbd "C-z s s") 'setnu-mode)
;;把speedbar集成到emacs的frame里
;(global-set-key (kbd "C-z s b") 'reset-window-config)
;;我的终端
(global-set-key (kbd "C-z t") 'term)
;;我的文件管理器
(global-set-key (kbd "C-z u d") 'dired-jump)
;; ;;FIXME 还是使用dired-single吧
;; (global-set-key (kbd "C-z u d")
;; 'joc-dired-magic-buffer)
;; (global-set-key (kbd "C-z 4 d")
;; (lambda (directory)
;; (interactive "D")
;; (let ((win-list (window-list)))
;; (when (null (cdr win-list)) ; only one window
;; (split-window-vertically))
;; (other-window 1)
;; (joc-dired-magic-buffer directory))))
(global-set-key (kbd "C-z u f") 'folding-mode)
(global-set-key (kbd "C-z u o") 'outline-minor-mode)
;;查询service,见jerry-other-elisp.el
(global-set-key (kbd "C-z u s") 'services-lookup)
;;可以在emacs编辑文件使用vim习惯,常用的是vi-mode和viper-mode
(global-set-key (kbd "C-z v") 'vi-mode)
;;wiki中的绑定设置,还用的不多
(global-set-key (kbd "C-z w c") 'emacs-wiki-change-project)
(global-set-key (kbd "C-z w f") 'emacs-wiki-find-file)
(global-set-key (kbd "C-z w h") 'emacs-wiki-preview-html)
(global-set-key (kbd "C-z w i") 'emacs-wiki-index)
(global-set-key (kbd "C-z w p") 'emacs-wiki-publish)
(global-set-key (kbd "C-z w s") 'emacs-wiki-search)
;;我的浏览器
(global-set-key (kbd "C-z w w") 'w3m)
;;同C-z b有点不同,在编译后并加载
(global-set-key (kbd "C-z x") 'emacs-lisp-byte-compile-and-load)
;;同yank有点不一样,但具体怎样忘了,感觉这个比yank好点
(global-set-key (kbd "C-z y") 'clipboard-yank)
;;修改后的设定mark的绑定,由于经常忘了放住control键,就给这个功能两个绑
;;定了
(global-set-key (kbd "C-z z") 'set-mark-command)
(global-set-key (kbd "C-z C-z") 'set-mark-command)


;;there are severl other key-map below in other files
;;ctrl-f-folding-mode-prefix
;;ido key-map
;;severl self define functions related key-bindings.

(provide 'jerry-key-bindings)

;;; jerry-key-bindings.el ends here

jerry-other-elisp.el

;;; jerry-other-elisp.el ---

;; ASCII码表
(autoload 'ascii "ascii-table" "ASCII TABLE" t)
;; 保存状态
(require 'session)
(add-hook 'after-init-hook
  'session-initialize)
;;use both desktop and session
;(setq desktop-globals-to-save '(desktop-missing-file-warning))

;; redo
(require 'redo)

;; Add "Open Recent" menu to the Files menu.
;; Must be set before require, else not passed on initial call to
;; package it seems. Not sure why.
(setq recentf-save-file (expand-file-name "recentf" "~/.emacs.d/")
  recentf-max-saved-items 100
  recentf-max-menu-items 20
  ;recentf-exclude '("/VM/" "/Gnus/" "/bbdb" "\\`/[a-zA-Z0-9@]+:")
  )
;; 一个使用recentf可以打开最近打开文件列表的功能
(defun recentf-open-files-compl ()
  (interactive)
  (let* ((all-files recentf-list)
  (tocpl (mapcar (function
  (lambda (x) (cons (file-name-nondirectory x) x))) all-files))
  (prompt (append '("最近打开的文件: ") tocpl))
  ;;(prompt (append '("File name: ") tocpl))
  (fname (completing-read (car prompt) (cdr prompt) nil nil)))
  (find-file (cdr (assoc-string fname tocpl)))))

(require 'recentf)
(recentf-mode 1)

;;firefox风格的tabbar
(require 'tabbar)
(tabbar-mode)

;;快速切换buffer
(require 'swbuff)
(setq swbuff-exclude-buffer-regexps
  '("^ " "\\*.*\\*"))
(setq swbuff-status-window-layout 'scroll)
(setq swbuff-clear-delay 1)
(setq swbuff-separator "|")
(setq swbuff-window-min-text-height 1)

;;制作图表的
;(require 'table)
(autoload 'table-insert "table" "WYGIWYS table editor")
(add-hook 'text-mode-hook 'table-recognize)

;; 观看kill-ring
(require 'browse-kill-ring)
(browse-kill-ring-default-keybindings)

(autoload 'sawfish-mode "sawfish" "sawfish-mode" t)

(autoload 'maxima "maxima" "Maxima interaction" t)
(autoload 'maxima-mode "maxima" "Maxima mode" t)
(autoload 'emaxima-mode "emaxima" "Emaxima" t)
(add-hook 'emaxmia-mode-hook 'emaxima-mark-file-as-emaxima)

(autoload 'imaxima "imaxima" "Image support for Maxima." t)

;;2种编辑html的好模式
(autoload 'html-helper-mode "html-helper-mode" "Yay HTML" t)
(autoload 'css-mode "css-mode" "Mode for editing CSS files" t)

;;查看端口
(autoload 'services-lookup "services" "Perform a service lookup" t)
(autoload 'services-clear-cache "services" "Clear the service cache" t)

;;查看C的type
(require 'ctypes)
(ctypes-auto-parse-mode 1)
;;使用xcscope
(require 'xcscope)

;;emacs的grep
;(require 'igrep)
(autoload 'igrep "igrep"
  "*Run `grep` PROGRAM to match EXPRESSION in FILES..." t)
(autoload 'igrep-find "igrep"
  "*Run `grep` via `find`..." t)
(autoload 'igrep-visited-files "igrep"
  "*Run `grep` ... on all visited files." t)
(autoload 'dired-do-igrep "igrep"
  "*Run `grep` on the marked (or next prefix ARG) files." t)
(autoload 'dired-do-igrep-find "igrep"
  "*Run `grep` via `find` on the marked (or next prefix ARG) directories." t)
(autoload 'Buffer-menu-igrep "igrep"
  "*Run `grep` on the files visited in buffers marked with '>'." t)
(autoload 'igrep-insinuate "igrep"
  "Define `grep' aliases for the corresponding `igrep' commands." t)
(autoload 'igrep-find-query-replace "igrep-find-query-replace" "" t)
(put 'igrep-files-default 'c++-mode
  (lambda () "*.h *.cpp *.c"))
(put 'igrep-files-default 'c-mode
  (lambda () "*.[ch]"))

;;fvwm的高亮显示
;(require 'fvwm-mode)
(autoload 'fvwm-mode "fvwm-mode" "Mode for editing for fvwm files" t)

;;cscope的前端
;(require 'xcscope)


;; hide region
(require 'hide-region)

;; hide lines
(require 'hide-lines)

;; sdcv mode使用sdcv查字典
(require 'sdcv-mode)

;; windzoom平滑分割窗口
;(require 'windzoom)

;; emms 配置
;;; setup emms
;;(add-to-list 'load-path
;; (expand-file-name "~/emacs/packages/emms"))

(require 'emms-source-file)
(require 'emms-source-playlist)
(require 'emms-player-simple)
(require 'emms-player-mplayer)
(require 'emms-playlist-mode)
(require 'emms-info)
(require 'emms-cache)
(require 'emms-mode-line)
(require 'emms-playing-time)
(require 'emms-score)
(require 'emms-volume)

(setq emms-playlist-default-major-mode 'emms-playlist-mode)
(add-to-list 'emms-track-initialize-functions 'emms-info-initialize-track)
(add-to-list 'emms-info-functions 'kid-emms-info-simple)
(setq emms-track-description-function 'kid-emms-info-track-description)
(when (fboundp 'emms-cache)
  (emms-cache 1))

(setq emms-player-list
  '(emms-player-mpg321
  emms-player-ogg123
  emms-player-mplayer))

(setq emms-info-asynchronously nil)
(setq emms-playlist-buffer-name "*Music*")
; use faster finding facility if you have GNU find
(setq emms-source-file-directory-tree-function 'emms-source-file-directory-tree-find)
; My musics
(setq emms-source-file-default-directory "/media/hda6/舞曲")
(add-hook 'emms-player-started-hook 'emms-show)
; mode line format
(setq emms-mode-line-format "[ %s "
  emms-playing-time-display-format "%s ]")
(setq global-mode-string
  '("" emms-mode-line-string " " emms-playing-time-string))
;
(defun kid-emms-info-simple (track)
  "Get info from the filename.
mp3 标签的乱码问题总是很严重,幸好我系统里面的音乐文件
都放得比较有规律,所以我决定直接从文件名获取标签信息。"
  (when (eq 'file (emms-track-type track))
  (let ((regexp "/\\([^/]+\\)/\\([^/]+\\)\\.[^.]+$")
  (name (emms-track-name track)))
  (if (string-match regexp name)
  (progn
  (emms-track-set track 'info-artist (match-string 1 name))
  (emms-track-set track 'info-title (match-string 2 name)))
  (emms-track-set track
  'info-title
  (file-name-nondirectory name))))))

(defun kid-emms-info-track-description (track)
  "Return a description of the current track."
  (let ((artist (emms-track-get track 'info-artist))
  (title (emms-track-get track 'info-title)))
  (format "%-10s +| %s"
  (or artist
  "")
  title)))

;; show the line number
(require 'setnu)
(autoload 'setnu-plus "setnu-plus" t)

;; 把高亮显示的文本输出为html
;(require 'htmlize)
(setq htmlize-html-charset "gb2312")
(autoload 'htmlize-buffer "htmlize" "" t)

;; 高亮过于长的行
(require 'highlight-beyond-fill-column)

;;CJK Table
(if window-system
  (autoload 'keisen-mode "keisen-mouse" "MULE table" t)
  (autoload 'keisen-mode "keisen-mule" "MULE table" t))

;;图像化的矩形操作
(require 'rect-mark)

;; Auto rename the重名buffer
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)

;; svn的客户端
(require 'psvn)

;;;;;"Remember" is a mode for remembering data.
(autoload 'remember "remember" nil t)
(autoload 'remember-region "remember" nil t)

;; 多主模式的使用
(autoload 'mmm-mode "mmm-mode" "Multiple Major Modes" t)
(autoload 'mmm-parse-buffer "mmm-mode" "Automatic MMM-ification" t)
;(set-face-background 'mmm-default-submode-face nil)

;;使用ibuffer,把菜单里的也换掉
(require 'ibuffer)
(setq ibuffer-delete-window-on-quit t)
(defadvice ibuffer-quit (after kill-ibuffer activate)
  "Kill the ibuffer buffer on exit."
  (kill-buffer "*Ibuffer*"))
;; NB unusual way to modify menu entry. Found by C-h v menu-bar- [TAB].
(setq menu-bar-buffers-menu-command-entries
  ;;'(list-all-buffers menu-item "List All Buffers" ibuffer
  ;; (nil)
  ;; :help "Pop up a window listing all Emacs buffer"))
  '((command-separator "--")
 ;;(next-buffer menu-item "Next Buffer" next-buffer
 (next-buffer menu-item "下一个Buffer" next-buffer
  ([24 C-right]
  . " (C-x )")
  :help "在一个循环里切换到 \"next\" buffer")
  ;;:help "Switch to the \"next\" buffer in a cyclic order")
 ;;(previous-buffer menu-item "Previous Buffer" previous-buffer
 (previous-buffer menu-item "前一个Buffer" previous-buffer
  ([24 C-left]
  . " (C-x )")
  :help "在一个循环里切换到 \"previous\" buffer")
  ;;:help "Switch to the \"previous\" buffer in a cyclic order")
 ;;(select-named-buffer menu-item "Select Named Buffer..." switch-to-buffer
 (select-named-buffer menu-item "从Buffer的名字里选择..." switch-to-buffer
  ([24 98]
  . " (C-x b)")
  :help "提示buffer的名字,并把选中的buffer显示在当前的窗口")
  ;;:help "Prompt for a buffer name, and select that buffer in the current window")
 ;;(list-all-buffers menu-item "List All Buffers" ibuffer ;;就是这样
 (list-all-buffers menu-item "列出所有的buffers" ibuffer ;;就是这样
  ([24 98]
  . " (C-x C-b)")
  ;;(nil)
  :help "弹出一个窗口列出所有打开的buffer")))
  ;;:help "Pop up a window listing all Emacs buffers")))
;; Ibuffer的彩色效果
(setq ibuffer-formats '((mark modified read-only " " (name 16 16) " "
  (size 6 -1 :right) " " (mode 16 16 :center)
  " " (process 8 -1) " " filename)
  (mark " " (name 16 -1) " " filename))
  ibuffer-elide-long-columns t
  ibuffer-eliding-string "&")

;; edit-env 编辑环境变量
(require 'edit-env)

;; keywiz游戏- 训练你的键绑定-crazy game
(require 'keywiz)

;; todo mode
(autoload 'todo-mode "todo-mode"
  "Major mode for editing TODO lists." t)
(autoload 'todo-show "todo-mode"
  "Show TODO items." t)
(autoload 'todo-insert-item "todo-mode"
  "Add TODO item." t)
(setq todo-file-do "~/.emacs.d/todo-do")
(setq todo-file-done "~/.emacs.d/todo-done")
(setq todo-file-top "~/.emacs.d/todo-top")

;; slime
(add-to-list 'load-path "~/lib/emacs-lisp/slime-2.0/") ; your SLIME directory
;;(setq inferior-lisp-program "/opt/sbcl/bin/sbcl") ; your Lisp system
(require 'slime)
(slime-setup)
;;如果安装了 Emacs-w3m 的话,直接在 Emacs-w3m 里面打开 HyperSpec 就更方便了:
(require 'hyperspec)
(setq common-lisp-hyperspec-root "file:/usr/share/doc/hyperspec/")
;; (setq browse-url-browser-function
;; '(("/usr/share/doc/hyperspec/" . w3m-browse-url)
;; ("." . browse-url-default-browser)))

(provide 'jerry-other-elisp)

;;; jerry-other-elisp.el ends here

jerry-mew.el

;;; jerry-mew.el --- mew的配置
;;;;;;;;;;;;;;;;;;;;;
;;启动和初始化mew的设置
;;将emacs收发邮件的默认设置为gnus改为mew
;;;;;;;;;;;;;;;;;;;;;
(autoload 'mew "mew" nil t)
(autoload 'mew-send "mew" nil t)
;;设定图表所在文件夹,这个和w3m类似,如果不正确,mew无法启动
;(setq mew-icon-directory "/usr/share/mew")
(if (boundp 'read-mail-command)
  (setq read-mail-command 'mew))
(autoload 'mew-user-agent-compose "mew" nil t)
(if (boundp 'mail-user-agent)
  (setq mail-user-agent 'mew-user-agent))
(if (fboundp 'define-mail-user-agent)
  (define-mail-user-agent
  'mew-user-agent
  'mew-user-agent-compose
  'mew-draft-send-message
  'mew-draft-kill
  'mew-send-hook))


;;;;;;;;;;;;;;;;;;;;;;
;;信件引用设置
;;;;;;;;;;;;;;;;;;;;;;
(setq mew-cite-fields '("From:" "Subject:" "Date:" "Message-ID:"))
(setq mew-cite-format "From: %s\nSubject: %s\nDate: %s\nMessage-ID: %s\n\n")
(setq mew-cite-prefix-function 'mew-cite-prefix-username)


;;;;;;;;;;;;;;;;;;;;;
;;用w3m来读html格式邮件
;;w3m的使用将在以后讲到
;;;;;;;;;;;;;;;;;;;;;
(setq mew-mime-multipart-alternative-list '("Text/Html" "Text/Plain" "*."))
(condition-case nil
  (require 'mew-w3m)
  (file-error nil))


;;;;;;;;;;;;;;;;;
;;一些其他设置,未归类
;;;;;;;;;;;;;;;;;
(setq mew-pop-size 0)
(setq toolbar-mail-reader 'Mew)
(set-default 'mew-decode-quoted 't)
;;设定公共钥匙所用程序,下面采用的是GnuPG
(setq mew-prog-pgp "gpg")


;;;;;;;;;;;;
;;设定用户信息
;;;;;;;;;;;;
(setq mew-name "Jarod Lau")
(setq mew-user "jerry")


;;;;;;;;;;;;
;;设定smtp服务器
;;个人原因,这里不列出我的正确Email
;;;;;;;;;;;;
(setq mew-smtp-user "jarodlau@163.com")
(setq mew-mail-domain "163.com")
(setq mew-smtp-server "smtp.163.com")
;;smtp服务器认证设定
(setq mew-smtp-auth-list (quote ("CRAM-MD5" "LOGIN" "PLAIN")))
;;smtp服务器不用认证采用下面设定
;(setq mew-smtp-auth-list nil)


;;;;;;;;;;;
;;设定pop3服务器
;;个人原因,这里不列出我的正确Email
;;;;;;;;;;;
(setq mew-pop-server "pop.163.com")
(setq mew-pop-user "jarodlau@163.com")
(setq mew-pop-auth 'pass) ;;认证方式
(setq mew-pop-delete nil) ;;将邮件留在服务器上

;;;;;;;;;;;;
;;设定将密码保存一段时间,默认20分钟
;;;;;;;;;;;;
(setq mew-use-cached-passwd t)
;;gnus可以将密码放在配置文件里,收邮件的时候就不用输入密码了
;;我找了一下,发现下面这个变量应该有类似功能,但没有搞掂,高人帮忙!
(setq mew-passwd-alist '(ilyjerry))

;;;;;;;;;;;;;;;;;;;;;
;;语言设置
;;这个不知道有用没,好像在下一版emacs对unicode支持好了就可以了
;;当然这个试用emacs-cvs
;;;;;;;;;;;;;;;;;;;;;
(when (boundp 'utf-translate-cjk)
  (setq utf-translate-cjk t)
  (custom-set-variables
  '(utf-translate-cjk t)))
(if (fboundp 'utf-translate-cjk-mode)
  (utf-translate-cjk-mode 1))

(provide 'jerry-mew)

;;; jerry-mew.el ends here

jerry-mode.el

;;; jerry-mode.el --- 编程模式mode的配置

(add-hook 'text-mode-hook 'turn-on-auto-fill)

;;{{{ Menu ;;;;

(if (boundp 'vc-menu-map)
  (add-to-list 'minor-mode-map-alist
  `(vc-mode keymap
  (menu-bar keymap
  (VC menu-item "VC" ,vc-menu-map)))))

(define-key-after menu-bar-tools-menu [server-start]
  '("(重新)启动server" . server-start) t)
  ;;'("(Re)start Server" . server-start) t)


(defun my-menu-bar-find-file (file doc help)
  "Make a menu-item to visit a file read-only.
FILE is the file to visit, relative to `data-directory'.
DOC is the text to use the menu entry.
HELP is the text to use for the tooltip."
  `(menu-item ,doc
  (lambda () (interactive)
  (find-file-read-only
  (expand-file-name ,file data-directory)))
  :help ,help))

(let ((last 'emacs-problems) ; start point in menu
  file doc this)
  (mapcar (lambda (elem)
  (setq file (car elem)
  doc (cdr elem)
  ;; NB how make symbol on the fly. Not `make-symbol'.
  this (intern (concat "emacs-" (downcase file))))
  (define-key-after menu-bar-help-menu `[,this]
  (my-menu-bar-find-file file doc doc)
  last)
  (setq last this))
  '(("TODO" . "Emacs的TODO")
  ("DEBUG" . "Emacs调试信息")
  ("JOKES" . "Emacs笑话")
  ("future-bug" . "Emacs未来的bug"))))
  ;; '(("TODO" . "Emacs TODO List")
  ;; ("DEBUG" . "Emacs Debugging Information")
  ;; ("JOKES" . "Emacs Jokes")
  ;; ("future-bug" . "Emacs Future Bug"))))


;; cf menu-bar-make-mm-toggle.
(defmacro my-menu-bar-make-local-mm-toggle (fname doc help &optional props)
  "Make a menu-item for a local minor mode toggle.
FNAME is the minor mode's name (variable and function).
DOC is the text to use the menu entry.
HELP is the text to use for the tooltip.
PROPS are additional properties."
  `'(menu-item ,doc ,fname
  ,@(if props props)
  :help ,help
  :button (:toggle . (and (boundp ',fname)
  ,fname))))

(or (fboundp 'menu-bar-make-mm-toggle) ; for 21.3
  (defmacro menu-bar-make-mm-toggle (fname doc help &optional props) ""
  `'(menu-item ,doc ,fname
  ,@(if props props)
  :help ,help
  :button (:toggle . (and (default-boundp ',fname)
  (default-value ',fname))))))


(when (boundp 'menu-bar-options-menu)

  ;; Note that an error in a definition of this kind caused Emacs to exit
  ;; after "loading tooltip" portion of startup.
  (define-key-after menu-bar-options-menu [show-trailing-whitespace]
  (my-menu-bar-make-local-mm-toggle
  show-trailing-whitespace
  "高亮句子结尾的空格"
  "高亮句子结尾的空格(显示结尾的空白)")
  ;;"Trailing Whitespace Highlighting"
  ;;"Highlight whitespace at line ends (Show Trailing Whitespace)")
  'highlight-paren-mode)

  (define-key-after menu-bar-options-menu [toggle-auto-image]
  (menu-bar-make-mm-toggle auto-image-file-mode
  "自动显示图片文件"
  "以查看图片的方式显示图片")
  ;; "Automatic Display of Image Files"
  ;; "Visit image files as images")
  'toggle-auto-compression)

  (define-key-after menu-bar-options-menu [debug-on-signal]
  (menu-bar-make-toggle
  toggle-debug-on-signal debug-on-signal
  "以信号的方式进入Debugger" "在 %s 信号上调试"
  "不管条件处理模式,进入Lisp的调试模式")
  ;; "Enter Debugger on Signal" "Debug on Signal %s"
  ;; "Enter Lisp debugger regardless of condition handlers")
  'debug-on-error)

  (if (boundp 'menu-bar-showhide-menu)
  (define-key menu-bar-showhide-menu [ruler]
  (my-menu-bar-make-local-mm-toggle ruler-mode
  "Ruler" "ruler显示/不显示"))
  ;;"Ruler" "Turn ruler on/off"))

  (define-key-after menu-bar-options-menu [tool-bar-separator]
  '("--") 'debug-on-quit)

  (define-key-after menu-bar-options-menu [tool-bar]
  (menu-bar-make-mm-toggle tool-bar-mode "收起工具条"
  "切换工具条的显示")
  ;;"Toggle Tool Bar"
  ;;"Toggle display of the tool-bar")
  'tool-bar-separator)

  (define-key-after menu-bar-options-menu [display-time]
  (menu-bar-make-mm-toggle
  display-time-mode "切换显示 时间/邮件"
  "切换显示 时间/邮件 的指示器"))))
  ;;"Toggle Display Time/Mail"
  ;;"Toggle display of the time and mail indicator"))))

;;}}} Menu ;;;;

;;{{{ Font-lock ;;;;
;;;
;;启动语法高亮模式
(global-font-lock-mode t)
;;使用gdb的图形模式
(setq gdb-many-windows t)
(global-font-lock-mode 1)
;;一些具体的设置,从别的地方拷过来的,目前编程较少,所以也没具体改了,感觉目前配置还是非常不错的
;;如果你是一个程序员,这块你可以仔细改改
(setq font-lock-maximum-decoration t
  ;; Removed text-mode from this exclusion list for 21.
  ;; Otherwise yanking preserves font-lock attributes of kill buffer,
  ;; which is annoying. Still need hook to actually enable
  ;; font-lock mode for text-mode - see below.
  ;; Then put back in as it messes up latex mode as well.
  font-lock-global-modes '(not shell-mode text-mode)
  font-lock-verbose t
  font-lock-maximum-size '((t . 1048576) (vm-mode . 5250000)))

;; Extra highlighting.
(mapcar '(lambda (element)
  (let ((mode (car element))
  (comment (cdr element)))
  (font-lock-add-keywords
  mode
  '((,comment ("\\<\\(GM\\|NB\\|TODO\\|FIXME\\)\\>" nil nil
  (0 'font-lock-warning-face t)))
  (,comment ("[* ]\\*\\([a-zA-Z].*\\)\\*" nil nil
  (1 'font-lock-warning-face t)))
  (,comment ("`\\([^`']+\\)'" nil nil
  (1 'font-lock-constant-face t)))))))
 '((awk-mode . "#")
  (sh-mode . "#")
  (fortran-mode . "^C")
  (f90-mode . "!")
  (makefile-mode . "#")))

;; Support mode.
;; jit-lock doesn't seem to work for MIME messages in VM.
(setq font-lock-support-mode
  (if (boundp 'jit-lock-mode)
  '((vm-mode . fast-lock-mode) (t . jit-lock-mode))
  'fast-lock-mode))

;; Jit-lock.
(setq jit-lock-stealth-verbose nil
  jit-lock-stealth-time 2
  ;; If system load rises above this value, pause stealth fontification.
  jit-lock-stealth-load 90
  ;; Seconds to pause between chunks of stealth fontification.
  jit-lock-stealth-nice 0.5
  ;; If nil, deferred fontification only on lines directly modified.
  ;; If t, on those line plus any following.
  ;; Any other value, only if syntactic fontification for that buffer.
  jit-lock-defer-contextually 'syntax-driven)

;; Fast-lock. Caches font-lock information to speed up loads.
(setq fast-lock-minimum-size 50000 ; but not for small files
  fast-lock-verbose 50000 ; so keep quiet
  ;; Or kill-buffer, kill-emacs. If did not save, do not care.
  fast-lock-save-events '(save-buffer)
  fast-lock-save-others nil ; no font-caching for others' files
  ;; Prefer all information to be in one place rather than ./
  fast-lock-cache-directories `(,(expand-file-name "flc" "~/.emacs.d/")))

(mapcar '(lambda (element)
  (let ((dir (if (listp element) (cdr element) element)))
  (or (file-directory-p dir) (make-directory element))))
 fast-lock-cache-directories)
;;;
;;}}} Font-lock ;;;;

;;{{{ 缩写词abbrev mode
;; ensure abbrev mode is always on
(setq-default abbrev-mode t)
;; do not bug me about saving my abbreviations
(setq save-abbrevs nil)
;; load up msf-abbrevs for these modes
(require 'msf-abbrev)
(setq msf-abbrev-verbose t) ;; optional
(setq msf-abbrev-root "~/.emacs.d/mode-abbrevs")
;; (global-set-key (kbd "C-c ml") 'msf-abbrev-goto-root)
;; (global-set-key (kbd "C-c ma") 'msf-abbrev-define-new-abbrev-this-mode)
(msf-abbrev-load)
;;}}}

;;{{{ c-mode 的配置,专门为kernel的编程风格做一个模块

;; face
(font-lock-add-keywords
 'c-mode
 `(("/\\*" ("\\<\\(GM\\|NB\\|FIXME\\|TODO\\)\\>"
  nil nil (0 'font-lock-warning-face t)))
  ;; More complex than usual to avoid comments commented by coment-region.
  ("/\\*" ("\\*\\([^ ][^*]*[^ ]*\\)\\*[^//]"
  nil nil (1 'font-lock-warning-face t)))
  ("/\\*" ("`\\([^`']+\\)'" nil nil (1 'font-lock-constant-face t)))
  (,(regexp-opt '("&&" "||" "<=" ">=" "==" "!=" ; overkill?
  "++" "--" "+=" "-=" "*=" "/=") t) .
  font-lock-constant-face)))
;; This will define the M-x my-linux-c-mode command. When hacking on a
;; module, if you put the string -*- linux-c -*- somewhere on the first
;; two lines, this mode will be automatically invoked. Also, you may want
;; to add
;; (add-hook 'c-mode-hook
;; '(lambda () (hs-minor-mode 1)
;; (or (file-expand-wildcards "[Mm]akefile")
;; (set (make-local-variable 'compile-command)
;; (format "gcc %s" buffer-file-name)))))

;; (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . my-linux-c-mode)
;; auto-mode-alist))
;; (setq auto-mode-alist (cons '("/home/jerry/linux.*/.*\\.[ch]$" . my-linux-c-mode)
;; auto-mode-alist))

;; 我的linux的kernel的编辑策略

(defun my-linux-c-mode ()
  "C mode with adjusted defaults for use with the Linux kernel."
  (interactive)
  (c-mode)
  (c-set-style "k&r")
  (setq tab-width 8)
  (setq indent-tabs-mode t)
  (setq c-basic-offset 8))

;; FIXME 我的C/C++语言编辑策略

(defun my-c-mode-common-hook()
  (c-set-style "k&r")
  (setq tab-width 4 indent-tabs-mode t)
;;;(setq tab-width 4 indent-tabs-mode nil)
;;; hungry-delete and auto-newline
  (c-toggle-auto-hungry-state 1)
  (hs-minor-mode 1)
  (setq abbrev-mode 1)
  ;;按键定义
  (define-key c-mode-base-map [(control \`)] 'hs-toggle-hiding)
  (define-key c-mode-base-map [(return)] 'newline-and-indent)
  (define-key c-mode-base-map [(f7)] 'compile)
  (define-key c-mode-base-map [(f8)] 'ff-get-other-file)
  (define-key c-mode-base-map [(meta \`)] 'c-indent-command)
  ;; (define-key c-mode-base-map [(tab)] 'hippie-expand)
  (define-key c-mode-base-map [(tab)] 'my-indent-or-complete)
  (define-key c-mode-base-map [(meta ?/)] 'semantic-ia-complete-symbol-menu)
  ;;预处理设置
  (setq c-macro-shrink-window-flag t)
  (setq c-macro-preprocessor "cpp")
  (setq c-macro-cppflags " ")
  (setq c-macro-prompt-flag t)
  ;; (require 'xcscope)
  ;; ;;显示C的typedef
  ;; (require 'ctypes)
  ;; (ctypes-auto-parse-mode 1)
  )
(add-hook 'c-mode-common-hook 'my-c-mode-common-hook)

(add-hook 'c-mode-hook 'imenu-add-menubar-index)

;; (defun my-ctypes-load-hook ()
;; (ctypes-read-file "~/.ctypes_std_c" nil t t))
;; (add-hook 'ctypes-load-hook 'my-ctypes-load-hook)

;;打开c mode的时候打开cscope,和type define

;;;;我的C++语言编辑策略
(defun my-c++-mode-hook()
  (setq tab-width 4 indent-tabs-mode nil)
  ;; (require 'xcscope)
  ;; ;;显示C的typedef
  ;; (require 'ctypes)
  ;; (ctypes-auto-parse-mode 1)
  (c-set-style "stroustrup")
  ;; (define-key c++-mode-map [f3] 'replace-regexp)
  )

(add-hook 'c++-mode-hook 'my-c++-mode-hook)

;;;;C/C++语言启动时自动加载semantic对/usr/include的索引数据库
(setq semanticdb-search-system-databases t)
(add-hook 'c-mode-common-hook
  (lambda ()
  (setq semanticdb-project-system-databases
  (list (semanticdb-create-database
  semanticdb-new-database-class
  "/usr/include")))))
;;}}} c mode

;;{{{ 我的Java语言编辑策略
(defun my-java-mode-hook()
  (setq tab-width 4 indent-tabs-mode nil)
  )

(add-hook 'java-mode-hook 'my-java-mode-hook)
;;}}}

;;{{{ Python Mode设置
;; (add-to-list 'load-path "/home/jerry/lib/emacs-lisp/python-mode-1.0")
;; (require 'python-mode)
;; ;;(require 'pycomplete)
;; (require 'doctest-mode)
;;}}}

;;{{{ 注释配置
;; (load-file "/home/jerry/lib/emacs-lisp/gnome-doc.el")
;;}}}


;;{{{ makefile-mode ;;;;
(add-hook 'makefile-mode-hook 'imenu-add-menubar-index)
;;}}} makefile-mode ;;;;

;;{{{ Lisp-mode ;;;;

;; 增加一些常用的高亮颜色
(font-lock-add-keywords
 'emacs-lisp-mode
 '((";" ("\\<\\(GM\\|NB\\|TODO\\|FIXME\\)\\>" nil nil
  (0 'font-lock-warning-face t)))
  (";" ("[* ]\\*[ \t]*\\(\\w.*\\)\\*" nil nil
  (1 'font-lock-warning-face t)))))


;; (mapcar (function (lambda (elem)
;; (add-hook 'emacs-lisp-mode-hook elem)))
;; '(imenu-add-menubar-index turn-on-eldoc-mode))
;; ;; checkdoc-minor-mode))

;; lisp 开发用的
(defun my-emacs-lisp-mode-hook-fn ()
  "Function added to `emacs-lisp-mode-hook'."
  (local-set-key "\C-cd" 'my-jump-to-defun)
  ;;(hs-minor-mode 1)
  ;; A little shorter than "Emacs-Lisp".
  ;; Avoid lisp-interaction and other derived modes.
  (if (eq major-mode 'emacs-lisp-mode)
  (setq mode-name "Elisp"))
  (when (boundp 'comment-auto-fill-only-comments)
  (setq comment-auto-fill-only-comments t)
  (kill-local-variable 'normal-auto-fill-function)))

(add-hook 'emacs-lisp-mode-hook 'my-emacs-lisp-mode-hook-fn)

(defun my-lisp-interaction-mode-hook-fn ()
  "Function added to `lisp-interaction-mode-hook'."
  (setq mode-name "Lisp Int"))
(add-hook 'lisp-interaction-mode-hook 'my-lisp-interaction-mode-hook-fn)

(setq eval-expression-print-level 10
  eval-expression-print-length 100)

;;}}} Lisp-mode ;;;;

;;{{{ WoMan ;;;;
(setq
 woman-cache-filename (expand-file-name "woman.cache" "~/.emacs.d/")
 woman-bold-headings nil
 woman-imenu-title "WoMan-imenu"
 woman-imenu t
 woman-use-own-frame nil ;不使用单独的frame
 woman-use-topic-at-point nil
 woman-fill-frame nil
 woman-show-log nil)

;;配置一下woman的颜色设置
(defun my-woman-pre-format-fn ()
  "."
  (face-spec-set 'woman-bold-face '((t (:foreground "white" :weight normal))))
  (face-spec-set 'woman-italic-face '((t (:foreground "yellow"))))
  (face-spec-set 'woman-addition-face '((t (:foreground "orange"))))
  (face-spec-set 'woman-unknown-face '((t (:foreground "cyan"))))
  ;; TODO can a function know its name?
  (remove-hook 'woman-pre-format-hook 'my-woman-pre-format-fn))

(add-hook 'woman-pre-format-hook 'my-woman-pre-format-fn)

;; So that each instance will pop up a new frame.
;; Maybe `special-display-regexps' would be better?
(add-hook 'woman-post-format-hook (lambda () (setq woman-frame nil)))
;;}}} WoMan ;;;;

;;{{{ eshell ;;;;

(defface my-eshell-code-face
  '((t (:foreground "Green")))
  "Eshell face for code (.c, .f90 etc) files.")

(defface my-eshell-img-face
  '((t (:foreground "magenta" :weight bold)))
  "Eshell face for image (.jpg etc) files.")

(defface my-eshell-movie-face
  '((t (:foreground "white" :weight bold)))
  "Eshell face for movie (.mpg etc) files.")

(defface my-eshell-music-face
  '((t (:foreground "magenta")))
  "Eshell face for music (.mp3 etc) files.")

(defface my-eshell-ps-face
  '((t (:foreground "cyan")))
  "Eshell face for PostScript (.ps, .pdf etc) files.")

(setq my-eshell-code-list '("f90" "f" "c" "bash" "sh" "csh" "awk" "el")
  my-eshell-img-list
  '("jpg" "jpeg" "png" "gif" "bmp" "ppm" "tga" "xbm" "xpm" "tif" "fli")
  my-eshell-movie-list '("mpg" "avi" "gl" "dl")
  my-eshell-music-list '("mp3" "ogg")
  my-eshell-ps-list '("ps" "eps" "cps" "pdf")
  eshell-ls-highlight-alist nil)

(let (list face)
  (mapcar (lambda (elem)
  (setq list (car elem)
  face (cdr elem))
  (add-to-list 'eshell-ls-highlight-alist
  (cons `(lambda (file attr)
  (string-match
  (concat "\\." (regexp-opt ,list t) "$")
  file))
  face)))
  '((my-eshell-code-list . my-eshell-code-face)
  (my-eshell-img-list . my-eshell-img-face)
  (my-eshell-movie-list . my-eshell-movie-face)
  (my-eshell-music-list . my-eshell-music-face)
  (my-eshell-ps-list . my-eshell-ps-face))))

(defun my-tidy-pwd (string)
  "Replace leading ~ by $HOME in output of pwd.
Argument STRING pwd."
  (replace-regexp-in-string "^~" (getenv "HOME") string))

(defun my-eshell-prompt-function ()
  "Return the prompt for eshell."
  (format "[%s@%s %s]%s "
  (eshell-user-name)
  (replace-regexp-in-string "\\..*" "" (system-name))
  (eshell/basename (eshell/pwd))
  (if (zerop (user-uid)) "#" "$")))

(defun my-eshell-line-discard ()
  "Eshell implementation of C-u."
  (interactive)
  (eshell-bol)
  (kill-line))


(defun my-eshell-clear-buffer ()
  "Eshell clear buffer."
  (interactive)
  (let ((eshell-buffer-maximum-lines 0))
  (eshell-truncate-buffer)))

(defalias 'eshell/clear 'my-eshell-clear-buffer)


(setq eshell-directory-name (expand-file-name "eshell" "~/.emacs.d/")
  eshell-pwd-convert-function 'my-tidy-pwd
  eshell-prompt-function 'my-eshell-prompt-function
  eshell-prompt-regexp "^\\[.*\\][#$] "
  eshell-ask-to-save-history 'always
  eshell-banner-message `(format-time-string
  "Eshell startup: %T, %A %d %B %Y\n\n"))


(defun my-eshell-first-time-mode-hook-fn ()
  "Function added to `eshell-first-time-mode-hook'."
  (face-spec-set 'eshell-ls-backup-face '((t(:foreground "Goldenrod"))))
  (face-spec-set 'eshell-ls-archive-face '((t(:foreground "red" :weight bold))))
  (face-spec-set 'eshell-ls-missing-face '((t(:foreground "orchid"))))
  (define-key eshell-mode-map "\C-ca" 'eshell-bol)
  (define-key eshell-mode-map "\C-c\C-u" 'my-eshell-line-discard)
  (mapcar (lambda (elem)
  (add-to-list 'eshell-visual-commands elem))
  '("pico" "nano")))

(add-hook 'eshell-first-time-mode-hook 'my-eshell-first-time-mode-hook-fn)

;;}}} eshell ;;;;


;;{{{ Shell-mode ;;;;
;;; Prefer terminal-mode really. Eshell even better.
(setq explicit-shell-file-name "bash"
;;; shell-file-name "/bin/bash"
  ;; Auto-generated variable name.
  explicit-bash-args '("--login")
  comint-scroll-to-bottom-on-input t
  comint-scroll-show-maximum-output t
  comint-scroll-to-bottom-on-output 'all
  comint-input-ignoredups t ; 1 copy only of identical input
  comint-completion-autolist t
  comint-completion-addsuffix t
  comint-buffer-maximum-size 200 ; lines
  comint-highlight-input nil ; highlight previous input
  comint-highlight-prompt nil)

(autoload 'ansi-color-for-comint-mode-on "ansi-color" nil t)

(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)


(defun my-shell-mode-hook-fn ()
  "Function added to `shell-mode-hook'."
  ;; M-p by default.
  (define-key shell-mode-map [up] 'comint-previous-input)
  ;; M-n by default.
  (define-key shell-mode-map [down] 'comint-next-input)
  (define-key shell-mode-map [backspace] 'my-shell-backspace))

(add-hook 'shell-mode-hook 'my-shell-mode-hook-fn)


;; Passing with lambda expression not liked.
(add-hook 'comint-output-filter-functions 'comint-watch-for-password-prompt)
(add-hook 'comint-output-filter-functions 'comint-strip-ctrl-m)
(add-hook 'comint-output-filter-functions 'comint-truncate-buffer)

;;}}} Shell-mode ;;;;

;;{{{ 对相应的文件设定相应的模式,以便正确的语法显亮
;;文件名用正则表达式表示,注意不要后面覆盖了前面的而引起的误会
;;修改这个之前先C-h v auto-mode-alist查查已有的设置
;;一个简单的办法设置 auto-mode-alist, 免得写很多 add-to-list
(mapcar
 (function (lambda (setting)
  (setq auto-mode-alist
  (cons setting auto-mode-alist))))
 '(
  ("\\.\\(xml\\|rdf\\)\\'" . sgml-mode)
  ("\\.\\([ps]?html?\\|cfm\\|asp\\)\\'" . html-helper-mode)
  ("\\.html$" . html-helper-mode)
  ("\\.css\\'" . css-mode)
  ("\\.\\(emacs\\|session\\|gnus\\)\\'" . emacs-lisp-mode)
  ("\\.wiki\\'" . emacs-wiki-mode)
  ("\\.\\(jl\\|sawfishrc\\)\\'" . sawfish-mode)
  ("\\.scm\\'" . scheme-mode)
  ("\\.py\\'" . python-mode)
  ("\\.\\(ba\\)?sh\\'" . sh-mode)
  ("\\.l\\'" . c-mode)
  ("\\.max\\'" . maxima-mode)
  ;;("\\config" . fvwm-mode)
  ("\\.fvwm2rc$" . fvwm-mode)
  ("\\.fvwmrc$" . fvwm-mode)
  ("\\.strokes$" . fvwm-mode)
  ("\\.conkyrc$" . fvwm-mode)
  ))

;;}}}auto-list-mode

(provide 'jerry-mode)

;;; jerry-mode.el ends here

jerry-function.el

;;; jerry-function.el --- my function

;;{{{ 如果你正在编辑一个东西(在位置A),突然想到别的某处(位置B)要修改或查看

;;或别的,总之你要过去看看,你可以用C-.来在当前位置做个标记,然后去你想去的
;;地方B,看了一会你觉的我可以回A去了,用C-,就回到刚才做标记的地方A,再用C-,又会回到B
;;这个由王垠创作
(global-set-key [(control ?.)] 'ska-point-to-register)
(global-set-key [(control ?\,)] 'ska-jump-to-register)
(defun ska-point-to-register()
  "Store cursorposition _fast_ in a register.
  Use ska-jump-to-register to jump back to the stored
  position."
  (interactive)
  (setq zmacs-region-stays t)
  (point-to-register 8))

(defun ska-jump-to-register()
  "Switches between current cursorposition and position
  that was stored with ska-point-to-register."
  (interactive)
  (setq zmacs-region-stays t)
  (let ((tmp (point-marker)))
  (jump-to-register 8)
  (set-register 8 tmp)))

;;}}}

;;{{{ 使用%就可以上下翻动,匹配的括号
;;如果没有括号就输入%
;;这个由王垠创作
(defun my-match-paren (arg)
  "Go to the matching paren if on a paren; otherwise insert %.
Argument ARG paren."
  (interactive "p")
  (cond ((looking-at "\\s\(") (forward-list 1) (backward-char 1))
 ((looking-at "\\s\)") (forward-char 1) (backward-list 1))
 (t (self-insert-command (or arg 1)))))
;;}}}

;;{{{ go-to-char
(defun my-go-to-char (n char)
  "Move forward to Nth occurence of CHAR.
Typing `my-go-to-char-key' again will move forwad to the next Nth
occurence of CHAR."
  (interactive "p\ncGo to char: ")
  (search-forward (string char) nil nil n)
  (while (char-equal (read-char)
  char)
  (search-forward (string char) nil nil n))
  (setq unread-command-events (list last-input-event)))
;;}}}
;; emacs-lisp-mode

;; 1. 再emacs中编译整个目录下的.el文件输入 [Alt]-x 。 当提示输入命令时,输入
;; byte-force-recompile [Enter] 。
;; 2. 如何再emacs下编译整个目录下的*.el文件两个办法,一是在dired里面用m标记,
;; 然后用B编译还有就是用emacs的批处理:

;; emacs -batch -f batch-byte-compile *.el

;; 这个忘了是从哪个地方弄来的,在保存~/.emacs文件自动编译为.elc文件
;;目前只是对~/.emacs有效,其余的*.el文件还没有去弄,以后有空我会改的
;;小知识:由于配置文件越来越大,你的*.el配置文件最好都编译为*.elc文件,这样
;;在启动emacs速度会有很大的提升
;; (defun autocompile nil
;; "Compile itself if ~/.emacs."
;; (interactive)
;; (if (string= (buffer-file-name) (concat default-directory ".emacs"))
;; (byte-compile-file (buffer-file-name))))
;; (add-hook 'after-save-hook 'autocompile)

;;{{{ 自动编译一个目录下的el文件
(defconst dotemacs-basic-conf-dir "~/lib/emacs-lisp/")
;(defconst dotemacs-ext-elisp-dir "~/.emacs.d/config/ext-elisp/")
;(defconst dotemacs-program-dir "~/.emacs.d/config/program/")

(defun autocompile nil
  "Automagically compile change to .emacs and other dotfiles."
  (interactive)
  (cond ((string= (buffer-file-name) (concat default-directory ".emacs"))
  (byte-compile-file (buffer-file-name)))

  ((string= (abbreviate-file-name (buffer-file-name))
  (concat dotemacs-basic-conf-dir
  (replace-regexp-in-string "\\.el" "" (buffer-name)) ".el"))
  (byte-compile-file (buffer-file-name)))

 ;; ((string= (abbreviate-file-name (buffer-file-name))
 ;; (concat dotemacs-ext-elisp-dir
 ;; (replace-regexp-in-string "\\.el" "" (buffer-name)) ".el"))
 ;; (byte-compile-file (buffer-file-name)))

 ;; ((string= (abbreviate-file-name (buffer-file-name))
 ;; (concat dotemacs-program-dir
 ;; (replace-regexp-in-string "\\.el" "" (buffer-name)) ".el"))
 ;; (byte-compile-file (buffer-file-name)))
  )

  )
(add-hook 'after-save-hook 'autocompile)
;; emacs-lisp-mode
;; 1. 再emacs中编译整个目录下的.el文件输入 [Alt]-x 。 当提示输入命令时,输入
;; byte-force-recompile [Enter] 。
;; 2. 如何再emacs下编译整个目录下的*.el文件两个办法,一是在dired里面用m标记,然后用B编译还有就是用emacs的批处理:
;; emacs -batch -f batch-byte-compile *.el
;;}}}
;;{{{ 自定义自动补齐命令,如果在单词中间就补齐,否则就是tab。
(defun my-indent-or-complete ()
  "在单词中间就补齐,否则就tab."
  (interactive)
  (if (looking-at "\\>")
  (hippie-expand nil)
  (indent-for-tab-command))
  )
;;}}}

;;这个是从emacs-lisp-introduction的那个文档拷过来
;;{{{ 功能同word的计算文字数相似,不过这个功能有待完善,对中文不大好使
(defun my-recursive-count-words (region-end)
  "Number of words between point and REGION-END."
  (if (and (< (point) region-end)
  (re-search-forward "\\w+\\W*" region-end t))
  (1+ (my-recursive-count-words region-end))
  0))
(defun my-count-words-region (beginning end)
  "Print number of words in the region.
Words are defined as at least one word-constituent
character followed by at least one character that is
not a word-constituent. The buffer's syntax table
determines which characters these are.
Argument BEGINNING region's beginning.
Argument END region's end."
  (interactive "r")
  (message "Counting words in region ... ")
  (save-excursion
  (goto-char beginning)
  (let ((count (my-recursive-count-words end)))
  (cond ((zerop count)
  (message
  "The region does NOT have any words."))
  ((= 1 count)
  (message "The region has 1 word."))
  (t
  (message
  "The region has %d words." count))))))
(defun my-count-words-buffer ()
  "Count the number of words in current buffer;
print a message in the minibuffer with the result."
  (interactive)
  (save-excursion
  (let ((count 0))
  (goto-char (point-min))
  (while (< (point) (point-max))
 (forward-word 1)
 (setq count (1+ count)))
  (message "buffer contains %d words." count))))
;;}}}

;;这也忘了是从哪弄来的了 ; replace C-u 0 C-l
;;{{{ 功能是将当前行设为本页第一行,同终端下的clear命令有点相似
(defun my-line-to-top-of-window ()
  "Move the line point is on to top of window."
  (interactive)
  (recenter 0))
;;}}}
;;{{{ 在文档里插入时间,用户名还有系统的信息
(defun my-stamp (&optional arg)
  "Insert current date, user, and system information.
With optional argument ARG, use \"*Created: -- *\" format."
  (interactive "*P")
  ;; Get this from time-stamp-format somehow?
  (let ((string (format " %s %s on %s "
  (format-time-string " %04y-%02m-%02d %02H:%02M:%02S")
  user-login-name
  system-name)))
  (if arg (setq string (format "*Creation: %s*" string)))
  (if (interactive-p)
  (insert string)
  string)))
;;}}}
;;{{{ 时间戳设置,插入文档内的
(defun my-timestamp ()
  "Insert the \"Time-stamp: <>\" string at point."
  (interactive)
  (if (interactive-p)
  (insert " Time-stamp: <>")
  " Time-stamp: <>"))
;;}}}

;;{{{ 打开.sawfishrc的快捷方式,ctrl-f1
(defun my-open-dot-sawfishrc ()
  "Open the dot-sawfishrc file."
  (interactive)
  (find-file "~/.sawfishrc")
  )
;;}}}

;; NB :添加的几个函数
;;{{{ 打开.emacs的快捷方式,ctrl-f2
(defun my-open-dot-emacs ()
  "Open the dot-emacs file."
  (interactive)
  (find-file "~/.emacs")
  )
;;}}}

;;{{{ 打开.sawfishrc配置文件,ctrl-f3
(defun my-open-fvwmconfig ()
  "Open the fvwm's config file."
  (interactive)
  (find-file "~/.fvwm/config")
;(find-file "~/.fvwm/fvwm.strokes")
  )
;;}}}

;;{{{ 找到这个buffer里最长的一行,并且到达哪里,很不错的功能
(defun my-longest-line (&optional goto)
  "Find visual length (ie in columns) of longest line in buffer.
If optional argument GOTO is non-nil, go to that line."
  (interactive "p") ; NB not p
  (let ((maxlen 0)
  (line 1)
  len maxline)
  (save-excursion
  (goto-char (point-min))
  (goto-char (line-end-position))
  ;; Not necessarily same as line-end - line-beginning (eg tabs)
  ;; and this function is for visual purposes.
  (setq len (current-column))
  (if (eobp) ; 1 line in buffer
  (setq maxlen len
  maxline line)
  (while (zerop (forward-line))
  (goto-char (line-end-position))
  (setq line (1+ line)
  len (current-column))
  (if (> len maxlen)
  (setq maxlen len
  maxline line)))))
  (if (not (interactive-p))
  maxlen
  (message "最长的一行是第%s行 (%s)" maxline maxlen)
  ;(message "Longest line is line %s (%s)" maxline maxlen)
  (if goto (goto-line maxline)))))
;;}}}

;;{{{ 给 Options 增加一个"去掉文件末尾空白"的菜单
(when (boundp 'show-trailing-whitespace)
  ;; Mode name must be same as mode variable.
  (define-minor-mode show-trailing-whitespace
  "Toggle display of trailing whitespace.
With optional numeric argument ARG, activate trailing whitespace display if
ARG is positive, otherwise deactivate it."
  :init-value nil
  :lighter " WS")

  (defun my-show-trailing-whitespace ()
  "Activate `show-trailing-whitespace' mode."
  (show-trailing-whitespace 1))

  (mapcar (lambda (hook) (add-hook hook 'my-show-trailing-whitespace))
  '(sh-mode-hook emacs-lisp-mode-hook f90-mode-hook
  fortran-mode-hook awk-mode-hook
  change-log-mode-hook c-mode-hook)))
;;}}}
;;{{{ TODO 去掉文件尾部的空白,在写文件的时候自动加载
;; Better functions than this exist in Emacs.
(defun my-delete-trailing-whitespace ()
  "Delete all trailing whitespace in buffer.
Return values are suitable for use with `write-file-functions'."
  (condition-case nil
  (progn
  ;; Don't want to do this to mail messages, etc.
  ;; Would an exclude list be better?
  ;; Error was occurring in VM-mode for some reason.
  (when (memq major-mode '(text-mode sh-mode emacs-lisp-mode
  f90-mode awk-mode c-mode))
  (message "Cleaning up whitespace...")
  (delete-trailing-whitespace)
  (message "Cleaning up whitespace...done")
  nil))
  (error (message "Cleaning up whitespace...ERROR")
  t)))
;;Too invasive?
(add-hook (if (boundp 'write-file-functions) 'write-file-functions
  'write-file-hooks) 'my-delete-trailing-whitespace)
;;}}}

;;{{{ 删除一些临时的buffers,少占我的内存
(defvar my-clean-buffers-names
  '("\\*Completions" "\\*Compile-Log" "\\*.*[Oo]utput\\*$"
  "\\*Apropos" "\\*compilation" "\\*Customize" "\\*Calc""\\keywiz-scores"
  "\\*BBDB\\*" "\\*trace of SMTP" "\\*vc" "\\*cvs" "\\*keywiz"
  "\\*WoMan-Log" "\\*tramp" "\\*desktop\\*" ;;"\\*Async Shell Command"
  )
  "List of regexps matching names of buffers to kill.")

(defvar my-clean-buffers-modes
  '(help-mode );Info-mode)
  "List of modes whose buffers will be killed.")

(defun my-clean-buffers ()
  "Kill buffers as per `my-clean-buffer-list' and `my-clean-buffer-modes'."
  (interactive)
  (let (string buffname)
  (mapcar (lambda (buffer)
  (and (setq buffname (buffer-name buffer))
  (or (catch 'found
  (mapcar '(lambda (name)
  (if (string-match name buffname)
  (throw 'found t)))
  my-clean-buffers-names)
  nil)
  (save-excursion
  (set-buffer buffname)
  (catch 'found
  (mapcar '(lambda (mode)
  (if (eq major-mode mode)
  (throw 'found t)))
  my-clean-buffers-modes)
  nil)))
  (kill-buffer buffname)
  (setq string (concat string
  (and string ", ") buffname))))
  (buffer-list))
  (if string (message "清理buffer: %s" string)
  ;(if string (message "Deleted: %s" string)
  (message "没有多余的buffer"))))
  ;(message "No buffers deleted"))))
;;}}}

;;{{{ 打印出我的键盘图,很酷吧.
(defun my-keytable (arg)
  "Print the key bindings in a tabular form.
Argument ARG Key."
  (interactive "sEnter a modifier string:")
  (with-output-to-temp-buffer "*Key table*"
  (let* ((i 0)
  (keys (list "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n"
  "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"
  "" "" "" "" ""
  "" "" "" "" "" "" ""
  "" "" "" "" "" "" ""
  "1" "2" "3" "4" "5" "6" "7" "8" "9" "0"
  "`" "~" "!" "@" "#" "$" "%" "^" "&" "*" "(" ")" "-" "_"
  "=" "+" "\\" "|" "{" "[" "]" "}" ";" "'" ":" "\""
  "<" ">" "," "." "/" "?"))
  (n (length keys))
  (modifiers (list "" "C-" "M-" "S-" "M-C-" "S-C-")))
  (or (string= arg "") (setq modifiers (list arg)))
  (setq k (length modifiers))
  (princ (format " %-10.10s |" "Key"))
  (let ((j 0))
  (while (< j k)
  (princ (format " %-50.50s |" (nth j modifiers)))
  (setq j (1+ j))))
  (princ "\n")
  (princ (format "_%-10.10s_|" "__________"))
  (let ((j 0))
  (while (< j k)
  (princ (format "_%-50.50s_|"
  "__________________________________________________"))
  (setq j (1+ j))))
  (princ "\n")
  (while (< i n)
  (princ (format " %-10.10s |" (nth i keys)))
  (let ((j 0))
  (while (< j k)
  (let* ((binding
  (key-binding (read-kbd-macro (concat (nth j modifiers)
  (nth i keys)))))
  (binding-string "_"))
  (when binding
  (if (eq binding 'self-insert-command)
  (setq binding-string (concat "'" (nth i keys) "'"))
  (setq binding-string (format "%s" binding))))
  (setq binding-string
  (substring binding-string 0 (min (length
  binding-string) 48)))
  (princ (format " %-50.50s |" binding-string))
  (setq j (1+ j)))))
  (princ "\n")
  (setq i (1+ i)))
  (princ (format "_%-10.10s_|" "__________"))
  (let ((j 0))
  (while (< j k)
  (princ (format "_%-50.50s_|"
  "__________________________________________________"))
  (setq j (1+ j))))))
  (delete-window)
  (hscroll-mode)
  (setq truncate-lines t)) ; for emacs 21
;;}}}

;;{{{
;; ;; 调用 stardict 的命令行接口来查辞典
;; ;; 如果选中了 region 就查询 region 的内容,
;; ;; 否则就查询当前光标所在的词
;; (defun kid-star-dict ()
;; "Serch dict in stardict."
;; (interactive)
;; (let ((begin (point-min))
;; (end (point-max)))
;; (if mark-active
;; (setq begin (region-beginning)
;; end (region-end))
;; (save-excursion
;; (backward-word)
;; (mark-word)
;; (setq begin (region-beginning)
;; end (region-end))))
;; ;; 有时候 stardict 会很慢,所以在回显区显示一点东西
;; ;; 以免觉得 Emacs 在干什么其他奇怪的事情。
;; (message "searching for %s ..." (buffer-substring begin end))
;; (tooltip-show
;; (shell-command-to-string
;; (concat "sdcv -n "
;; (buffer-substring begin end))))))

;; ;; 如果选中了 region 就查询 region 的内容,否则查询当前光标所在的单词
;; ;; 查询结果在一个叫做 *sdcv* 的 buffer 里面显示出来,在这个 buffer 里面
;; ;; 按 q 可以把这个 buffer 放到 buffer 列表末尾,按 d 可以查询单词
;; (defun kid-sdcv-to-buffer ()
;; "Search dict in region or world."
;; (interactive)
;; (let ((word (if mark-active
;; (buffer-substring-no-properties (region-beginning) (region-end))
;; (current-word nil t))))
;; (setq word (read-string (format "Search the dictionary for (default %s): " word)
;; nil nil word))
;; (set-buffer (get-buffer-create "*sdcv*"))
;; (buffer-disable-undo)
;; (erase-buffer)
;; (let ((process (start-process-shell-command "sdcv" "*sdcv*" "sdcv" "-n" word)))
;; (set-process-sentinel
;; process
;; (lambda (process signal)
;; (when (memq (process-status process) '(exit signal))
;; (unless (string= (buffer-name) "*sdcv*")
;; (setq kid-sdcv-window-configuration (current-window-configuration))
;; (switch-to-buffer-other-window "*sdcv*")
;; (local-set-key (kbd "d") 'kid-sdcv-to-buffer)
;; (local-set-key (kbd "q") (lambda ()
;; (interactive)
;; (bury-buffer)
;; (unless (null (cdr (window-list))) ; only one window
;; (delete-window)))))
;; (goto-char (point-min))))))))
;;}}}

;;{{{ lisp 里快速找到函数
(defvar my-defun-re
  (regexp-opt '("defun" "defsubst" "defmacro" "defadvice") 'paren)
  "Regular expression used to identify a defun.")

(defun my-jump-to-defun (func)
  "Jump to the definition of function FUNC in the current buffer, if found.
Return the position of the defun, or nil if not found."
  (interactive
  ;; From `describe-function'. *NB ?*
  (let ((fn (function-called-at-point)))
  (list (completing-read (if fn
  (format "Find defun for (default %s): " fn)
  "Find defun for: ")
  obarray 'fboundp t nil nil (symbol-name fn)))))
  (let (place)
  (save-excursion
  (goto-char (point-min))
  (if (re-search-forward
  (concat "^[ \t]*(" my-defun-re "[ \t]+"
  (regexp-quote func) "[ \t]+") (point-max) t)
  (setq place (point))))
  (if (not place)
  (if (interactive-p) (message "No defun found for `%s'" func))
  (when (interactive-p)
  (push-mark)
  (goto-char place)
  (message "Found defun for `%s'" func))
  place)))
;;}}}

;;{{{ 改变 tabbar-buffer-groups-function
;; 原来的 tabbar 强行对你的 buffer 进行分组,但是如果你想在你编辑的buffer间切换而不论它们是什么组,那么似乎没有
;; 一个好办法。但是 tabbar 本来提供了一个机制,让你可以自己确定 tab 属于哪组,只要修改
;; tabbar-buffer-groups-function 就行了。

;; 这样,我可以把每个 buffer 同时加入它所在的 major mode 的组和一个叫做 "default" 的组,这样我在 default 组里就
;; 可以方便的浏览到所有的 buffer 了。而切换到其它组就可以分组浏览。你还可以自行把某些 buffer 分到一组,比如我可
;; 以把 scheme-mode 的 buffer 和 inferer-scheme-mode 的 buffer 分到同一个组。
(setq tabbar-buffer-groups-function 'tabbar-buffer-ignore-groups)

(defun tabbar-buffer-ignore-groups (buffer)
  "Return the list of group names BUFFER belongs to.
Return only one group for each buffer."
  (with-current-buffer (get-buffer buffer)
  (cond
  ((or (get-buffer-process (current-buffer))
  (memq major-mode
  '(comint-mode compilation-mode)))
  '("Process")
  )
  ((member (buffer-name)
  '("*scratch*" "*Messages*"))
  '("Common")
  )
  ((eq major-mode 'dired-mode)
  '("Dired")
  )
  ((memq major-mode
  '(help-mode apropos-mode Info-mode Man-mode))
  '("Help")
  )
  ((memq major-mode
  '(rmail-mode
  rmail-edit-mode vm-summary-mode vm-mode mail-mode
  mh-letter-mode mh-show-mode mh-folder-mode
  gnus-summary-mode message-mode gnus-group-mode
  gnus-article-mode score-mode gnus-browse-killed-mode))
  '("Mail")
  )
  (t
  (list
  "default" ;; no-grouping
  (if (and (stringp mode-name) (string-match "[^ ]" mode-name))
  mode-name
  (symbol-name major-mode)))
  )
  )))
;;}}}

;;{{{ TODO 让speedbar获得类似ECB的显示效果,把speedbar集成到emacs主窗口里
;; (require 'tramp)
;; (defconst my-junk-buffer-name "Junk")
;; (setq junk-buffer (get-buffer-create my-junk-buffer-name)
;; )
;; (require 'speedbar)
;; (defconst my-speedbar-buffer-name "SPEEDBAR")
;; (setq speedbar-buffer (get-buffer-create my-speedbar-buffer-name)
;; speedbar-frame (selected-frame)
;; dframe-attached-frame (selected-frame)
;; speedbar-select-frame-method 'attached
;; speedbar-verbosity-level 0
;; speedbar-last-selected-file nil)
;; (setq right-window (split-window-horizontally 24))
;; (setq left-window (frame-first-window))
;; ;;(walk-windows (lambda (w) (setq left-window w)) "nominibuffer" t)
;; (set-buffer speedbar-buffer)
;; (speedbar-mode)
;; (speedbar-reconfigure-keymaps)
;; (speedbar-update-contents)
;; (speedbar-set-timer 1)
;; (set-window-buffer left-window "SPEEDBAR")
;; (set-window-dedicated-p left-window t)
;; (toggle-read-only) ; HACK, REQUIRED for Tramp to work ????
;; (select-window right-window)
;; (defun select-right-window () (select-window right-window))
;; ;;(defun reset-window-config () (interactive)
;; ;; (walk-windows (lambda (w) (when (not (or (eq w left-window) (eq w right-window))) (delete-window w))) "nominibuffer" t)
;; ;; )
;; (defun reset-window-config () (interactive)
;; (delete-other-windows)
;; (setq right-window (split-window-horizontally 24))
;; (setq left-window (frame-first-window))
;; (set-window-buffer left-window speedbar-buffer)
;; (set-window-dedicated-p left-window t)
;; (select-window right-window)
;; (set-window-dedicated-p right-window nil)
;; (when (eq speedbar-buffer (window-buffer right-window)) (set-window-buffer right-window (next-buffer)))
;; (set-window-dedicated-p right-window nil)
;; )
;; ;;(global-set-key "\C-x1" 'reset-window-config)
;;}}}

(provide 'jerry-function)

;;; jerry-function.el ends here