配置 Emacs 的小技巧

标签: Text Editor Tips elisp Emacs | 发表时间:2011-10-09 18:05 | 作者:Kardinal return
出处:http://linuxtoy.org


前几天……大约在冬季吧,我发现了一个惊天小技巧,当然,是关于 Emacs 的……看到标题你也应该猜到

这事要从很久以前说起,我很久以前用 Vim ,很久很久以前用 Emacs ,很久很久很久以前用 Vim ……你知道的,我也不知道我到底在多久以前用 Emacs 或者 Vim…… 后来,出了个叫 Vimim 的东东,输入法再也不用担心我的切换了。然后,我就舒坦了一段时间……然而,Vim 并不太适合折腾,它的脚本语言也让我想起了恐怖的 shell script ……可能它执行效率挺高,但是,你知道的,咱们的口号是“不求效率,但求折腾!”

相对而言,Elisp 的S表达式看起来要舒服多了,但是 Emacs 的快捷键让我的手指很纠结……注意,这里的纠结表示的是动作,而不是心情。你可以参考这个例句:像麻花一样纠结。

回归正题,这个惊天小技巧就是,把 Caps Lock 和 Control 两个键换过来!我指的是软方法,就是不抠键的情况下互换;相对应的,也有硬方法……先别忙找螺丝刀……买 Emacs 脚踏板先

好了,现在正式讲关于“配置”的小技巧。

Emacs 的启动文件,大家通常用 dotmacs ,也就是 .emacs _emacs 。如果你把配置文件分成多个文件,一般会把它放到一个文件夹里,通过 dotemacs 文件读取。这样,你就多了一个文件还有一个夹,是不是挺郁闷?用 windows 的同学,哪儿凉快到哪儿去找 dotemacs

其实在 site-lisp 目录下的 site-start.el 文件作用也差不多,不过它是全局的,而且在 dotemacs 之前启动。

这是我的 site-start.el 文件

(setq

init-start (time-to-seconds)

init-dir (expand-file-name (if (eq system-type 'windows-nt) (concat exec-directory "../init.emacs/") "~/init.emacs/"))

init-files (mapc 'load (directory-files init-dir t "^[0-9].*el$"))

init-stop (time-to-seconds) )

(add-hook 'emacs-startup-hook '(lambda () (message "load %d init file , spend %g seconds ; startup spend %g seconds" (length init-files) (- init-stop init-start) (- (time-to-seconds) init-start))))

这个文件里面,用 (time-to-seconds) 获得三次时间,然后计算出加载启动文件所用时间和整个启动过程所用时间。

"(mapc 'load (directory-files init-dir t "^[0-9].*el$"))" load 所有 init-dir 目录下数字开头且 el 结尾的文件, 我设置的 init-dir 在 linux 下为 "~/init.emacs/" ……特别感人的一点是,如果没有 init-dir ,它也不会报错。

你可以修改文件名前面的数字,按照指定的顺序读取。禁用已经在序列中的文件的话,可以再给它加个 bak 后缀,在 dired 模式下按 b 就可以了……如果按 b 没有反应的话,在 04_dired.el 文件中添加:

(autoload 'dired-update-file-line "dired-aux" "" t nil)
(add-hook 'dired-mode-hook (lambda ()
  (local-set-key "b"
              '(lambda () "rename file to .bak"
                 (interactive)
                 (let* (buffer-read-only
                        (suffix "bak")
                        (from-file (dired-get-filename))
                        (new-file 
                         (if (string-equal suffix (file-name-extension from-file))
                             (file-name-sans-extension from-file)
                           (concat from-file "." suffix))))
                   (rename-file from-file new-file)
                   (dired-update-file-line new-file)
                   )))
 ))

我的 init-dir 目录里第一个文件是 00_func.el ,定义一些函数,每个函数下面的注释为示例

;; * add-to-list-x
(defun add-to-list-x (LIST-VAR LIST)
  (mapc (lambda(ELEMENT) (add-to-list LIST-VAR ELEMENT)) LIST))

;(add-to-list-x 'load-path (list ;;如果列表中的元素不需要求值,可以用 '( ; (expand-file-name "misc/" init-dir) ; (expand-file-name "color-theme/" init-dir) ;))

;; * require-extensions (defun require-extensions (action lst) (mapcar (lambda(ext) (funcall action ext)) lst))

;(require-extensions 'require ; '( ; cedet ; eieio ; semantic ; srecode ; ede ; speedbar ; ecb ;))

;; * define-key-s (defun define-key-s (keymap key-defs) "(define-key-s map '(key def key def ...))" (let ((map (cond ((eq keymap 0) (current-global-map)) ((eq keymap 1) (current-local-map)) (t keymap)))) (while (cadr key-defs) (let* ((key (pop key-defs)) (def (pop key-defs))) (define-key map (eval `(kbd ,key)) def) ))))

;(define-key-s 0 '( ;; 0 global-set-key ; 1 local-set-key ; mode map ;;;第一个参数为 1 的时候,可能有问题。懒得管了,不推荐用这个参数,可以指定具体的 mode map ; "C-x C-j" ido-execute-extended-command
; "C-o" set-mark-command
; "C-w" backward-kill-word-or-kill-region
; "C-c C-v" view-mode
; "C-." redo
; "C-;" toggle-comment-region
;))

(defun def-key-s (keymap &rest key-defs) "(def-key-s map key 'def key 'def ...)" (define-key-s keymap key-defs) )

;;;把 define-key-s 包装了一下,参数不需要是列表。但是命令前面需要加单引号,一般定义的内容较少的时候用 ;(def-key-s view-mode-map ; "p" 'View-scroll-page-backward ; "n" 'View-scroll-page-forward ; "k" 'View-scroll-line-backward ; "j" 'View-scroll-line-forward ; "f" 'View-search-last-regexp-forward ; "b" 'View-search-last-regexp-backward ; )

;; * backward-kill-word-or-kill-region ;; 选择区域的时候删除区域,否则回删单词 (defun backward-kill-word-or-kill-region () (interactive) (if mark-active (call-interactively 'kill-region) (call-interactively 'backward-kill-word)))

;; * toggle-comment-region (defun toggle-comment-region (beg end &optional n) "... " (interactive "r\nP") (if n (comment-region beg end (prefix-numeric-value n)) (save-excursion (goto-char beg) (beginning-of-line) ;; skip blank lines (skip-chars-forward " \t\n") (if (looking-at (concat "[ \t]*\(" (regexp-quote comment-start) "+\)")) (uncomment-region beg end) (comment-region beg end)))))

我的 01init.el 文件

;; * load-path
(add-to-list-x 'load-path (list
                           init-dir
                           (expand-file-name "misc/" init-dir)
                           (expand-file-name "_color-theme/" init-dir)
))

;; * working dir (setq sand-box (expand-file-name "_sandbox/" init-dir)) (cd sand-box)

;; * 打开特定文件时使用 View 模式 (add-hook 'find-file-hook '(lambda () (when (and (file-exists-p (buffer-file-name)) ; 已存在文件 (member (file-name-extension (buffer-name)) '("el" "bak" "txt"))) ; 匹配扩展名 (view-mode) )))

;; * 文件编码 (setq buffer-file-coding-system 'utf-8-unix)

;; * 开启服务器模式 ;(server-start)

02_setting.el 文件里是一些乱七八糟的设置,我完全相信你可以弄的比我还要乱……自由发挥吧

值得注意的是 setq setq-default 都可以设定多组值,很多同学可能不知道

(setq-default                   ; 使用空格缩进 
        indent-tabs-mode nil    ; t 使用 TAB 作格式化字符  nil 使用空格作格式化字符
        tab-always-indent nil
        tab-width 4)

可以指定某字符的类型,比如 _ [ ] 指定为单词的一部分;具体情况 C-h s

(modify-syntax-entry ?_ "w")
(modify-syntax-entry ?[ "w")
(modify-syntax-entry ?] "w")

03_outline.el

;; * 设定主题
(set-display-table-slot
 standard-display-table
 'selective-display
 (let ((face-offset (* (face-id 'shadow) (lsh 1 22))))
   (vconcat (mapcar (lambda (c) (+ face-offset c)) " [...] "))))

如果你想自定义 outline 的层级关系,比如 *** 是 * 的上一级,可以定义 outline-heading-alist ,不过里面的东西必须是 outline-regexp 中定义过了的

(add-hook 'diff-mode-hook
      (function (lambda ()
              (setq outline-regexp "diff\|@@\|\{10,\}")
              (setq outline-heading-alist
                '(("diff" . 1) ("@@" . 2) ("\{10,\}" . 2))
                )
              (outline-minor-mode)
;             (hide-body)
              (view-mode)
              )))

22_color.el 缓冲区两侧的指示条里面显示的连行符号,就是那些弯曲的小箭头,一般都比较晃眼,可以设置成和缓冲区背景一样的颜色 (set-face-attribute 'fringe nil :foreground (background-color-at-point))

54_gui.el 我的标题栏设置,因为我老是分不清我用的到底是 emacs 23 还是 24 ,所以把版本也显示在标题栏了

       (defun fname-title-string ()
         "Return the file name of current buffer, using ~ if under home directory"
         (let
             ((fname (or
                      (buffer-file-name (current-buffer))
                      (buffer-name))))
           (when (string-match (getenv "HOME") fname)
             (setq fname (replace-match "~" t t fname))        )
           fname))

    (setq frame-title-format             
                    '(:eval (concat (user-login-name) "@" (system-name) "[Emacs" 
                     (nth 2 (split-string (version))) "]  " (fname-title-string))))

60_tabbar.el tabbar group 这个扩展挺变态的,你知道的,我也不知道该不该用它。下面是我的分组规则,18禁

(defun substring-buffer-name (m n &optional x)
  "使用 substring 截取文件名时,在 buffer-name 后面加几个字符,
   防止文件名过短引发错误"
  (substring (concat
              (if x
                  (buffer-file-name)
                (buffer-name))
              (make-string n ?*))
             m n))

(defun tabbar-buffer-groups () "Return the list of group names the current buffer belongs to. Return a list of one element based on major mode." (list (cond ; ((or (get-buffer-process (current-buffer)) ; ;; Check if the major mode derives from comint-mode' or ; ;;compilation-mode'. ; (tabbar-buffer-mode-derived-p ; major-mode '(comint-mode compilation-mode))) ; "Process")

((member (buffer-name)
         '("*scratch*" "*Messages*"))
 "Common")

((memq major-mode
       '(help-mode apropos-mode Info-mode Man-mode))
 "Help")

((eq major-mode 'dired-mode)
 "Dired")

((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")

((string-equal "*vc-" (substring-buffer-name 0 4))
 "VC-mode Buffer")

((string-equal "*sdcv*" (substring-buffer-name 0 6))
 "User Buffer")

((string-equal "*" (substring-buffer-name 0 1))
 "Emacs Buffer")

;;;; ((or (string-equal "emacs" (substring-buffer-name 1 6)) (string-equal init-dir (substring-buffer-name 0 (length init-dir) t))) "Configuration") ;;;; (t "User Buffer") )))

(setq tabbar-buffer-groups-function 'tabbar-buffer-groups)

OK,差不多了,有什么我忘了说的……就当我没说好了

分类: Text Editor, Tips | 永久链接 | 收藏到 del.icio.us | Email 给好友 | 25 评论 | 捐助本站

相关 [emacs 技巧] 推荐:

配置 Emacs 的小技巧

- return - LinuxTOY
前几天……大约在冬季吧,我发现了一个惊天小技巧,当然,是关于 Emacs 的……看到标题你也应该猜到. 这事要从很久以前说起,我很久以前用 Vim ,很久很久以前用 Emacs ,很久很久很久以前用 Vim ……你知道的,我也不知道我到底在多久以前用 Emacs 或者 Vim…… 后来,出了个叫 Vimim 的东东,输入法再也不用担心我的切换了.

灵异 Emacs 之画皮

- 月乾 - LinuxTOY
好吧,这回真的是一个小技巧,我以本站站长的名誉担保……如果你觉得我撒谎了,你可以把站长找出来随意处置……(神秘的声音:偶们是无辜的,找 Kardinal 就行). 话说比较讲究的同学,都喜欢给 emacs 设置个漂亮的字体,一般都是矢量字体,大黑二黑三黑啥的,就不点名了,你懂的……. 可是这样也有麻烦的时候,比如说我最近比较爱玩的 eshell ,或者版本控制的 diff 界面之类的……总之,有些情况下,用点阵字体又比较舒服点.

emacs 新手必看: undo-tree

- leafduo - LinuxTOY
火星人都知道,emacs 只有 undo ,没有 redo ……或者说它有 redo,但是相当的诡异,套用一句经典台词就是: 猥琐,非常的猥琐. 简单的说,emacs 的 redo 就是 undo undo ,也就是传说中的负负得正. 可能有些 emacs 新手,还不知道怎么去操作,因为一般情况下,无论你 undo 多少次,都不会发生 redo 的现象.

Emacs被发现未遵守GPL许可

- elis - Solidot
Emacs 23.2和23.3被发现没有遵守GPL许可证的要求公开所有源代码. 自2009年12月9日Emacs 23.1.90发布起,Emacs发行包包含了众多用Bison创建的未提供源代码的解析器. Emacs作者、自由软件基金会主席Richard Stallman称此事不仅仅是法律问题,而且是道德问题.

Emacs & cflow 生成函数调用树

- yboren - Emacs中文网
介绍 Emacs 中使用cflow制作函数的调用树. 以上内容取自 cflow 的网站: http://www.gnu.org/software/cflow/manual/html_node/Intro.html#Intro. cflow 的代码包中提供了cflow-mode.el (cflow-1.3/elisp/cflow.el), 该文件提供了 emacs 的 cflow-mode,.

我是如何从vim转向Emacs的

- flychen50 - Emacs中文网
以前,我多次试图从 vim 转变到 emacs 都失败了. 原因很多,主要原因是 vim 的确一个很强大的 editor 不愧为 emacs 的主要竞争对手,vim 很多强大的功能,很难在 emacs 中找到相应的功能,那个时候还没有水木Emacs版,如果有的话,情况会好一些, 还有一个原因就是我周围几乎没有人用 emacs ,现在也是.

大话 Emacs Shell Mode 第 3 部分

- ndv - IBM developerWorks 中国 : Linux : Articles,Tutorials
这是《大话 Emacs Shell Mode 》的最后一篇. 这一篇中介绍了 GNU Emacs 下窗口操作的一些高级技巧和扩展函数的编写方法. 通过这些扩展,可以对 Emacs 环境下的窗口与缓冲区进行灵活自如的配置,甚至旋转,由此打造一个更加灵活,舒适的 Shell 工作环境.

Emacs 普通人的编辑利器

- tisyang - 学无止境@一点一滴
现代生活中,文档越来越重要,电脑已经成为编辑文本最主要的工具,程序员的工作其实就是编辑文档,选择高效的文本工具,自然要考虑程序员用的工具. 而 Emacs 就是一个是适合普通人使用的高效文档编写工具. 谈及 Emacs,很多人第一个感觉就是很复杂,随之而来就有一个疑问“很难用的吧. 但是,我虽然不是程序员,现在使用 Emcas + Org-mode(Emcas 上的插件) 的组合,感觉行云流水,毫无碍难.

为何 Emacs 和 Vim 被称为两大神器

- mgo - LinuxTOY
Emacs 是神的编辑器,而 Vim 是编辑器之神. 二者为何会有如此美誉,且听本文向你一一道来. Author: Jiqing Wu email:[email protected] homepage:http:://hi.baidu.com/jiqing0925 create:2011-01-09 update:2011-01-09 面向的读者:经常用电脑处理文本和编程的同学.

gocode——VIM 和 Emacs 的 golang 代码自动补全

- XiaoHui - Some reminiscences, some memories
虽然 golang 自身提供了 VIM 的语法高亮之类的脚本,但 autocompletion 并没有官方解决方案. 无意之中发现 gocode 这个支持 VIM 和 Emacs 的 autocompletion daemon. 这里有个Flash 动画演示,展示了 gocode 的强大. 我得说,用过之后,感觉速度确实够快.