歡迎您光臨本站 註冊首頁

配置 Emacs 的小技巧

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  

前幾天……大約在冬季吧,我發現了一個驚天小技巧,當然,是關於 Emacs 的……看到標題你也應該知道的

這事要從很久以前說起,我很久以前用 Vim ,很久很久以前用 Emacs ,很久很久很久以前用 Vim ……你知道的,我也不知道我到底在多久以前用 Emacs 或者 Vim…… 後來,出了個叫 Vimim 的東東,輸入法再也不用擔心我的切換了。然後,我就舒坦了一段時間……然而,Vim 並不太適合折騰,它的腳本語言也讓我想起了恐怖的 shell script ……可能它執行效率挺高,但是,你知道的,咱們的口號是“不求效率,但求折騰!”

相對而言,Elisp 的S表達式看起來要舒服多了,但是 Emacs 的快捷鍵讓我的手指很糾結……注意,這裡的糾結表示的是動作,而不是心情。你可以參考這個例句:像麻花一樣糾結。

 

回歸正題,這個驚天小技巧就是,把 Caps Lock 和 Control 兩個鍵換過來!我指的是軟方法,就是不摳鍵的情況下互換;相對應的,也有硬方法……先別忙找螺絲刀……買 Emacs 腳踏板先

好了,現在正式講關於“配置”的小技巧。

Emacs 的啟動文件,大家通常用 dotemacs ,也就是 .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/"))

null (dolist (init-lp (directory-files init-dir t "^_")) (when (file-directory-p init-lp) (add-to-list 'load-path init-lp)))

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) 獲得三次時間,然後計算出載入啟動文件所用時間和整個啟動過程所用時間。

dolist 那部分把 init-dir 裡面以 “_” 開頭的文件夾添加到 load-path 。

"(mapc 'load (directory-files init-dir t "^[0-9].*el$"))" load 所有 init-dir 目錄下數字開頭且 el 結尾的文件, 我設置的 init-dir 在 linux 下為 "~/init.emacs/" ……特別感人的一點是,如果沒有 init-dir ,它也不會報錯。

你可以修改文件名前面的數字,按照指定的順序讀取,比如我的 init-dir 裡面的文件為 load-pathdirs/ dirs/ 00xxx.el 01xxx.el 02_xxx.el 。。。。秀一下我的init-dir 目錄

  00_func.el  01_init.el  02_settings.el  03_outline.el  04_dired.el  05_ido.el    06_viewmode.el  07_session.el  08_modeline.el.bak  09_hl-line.el.bak  10_run-file.el    11_addons.el  12_auto-complete.el  13_yasnippet.el.bak  14_auto-complete-yasnippet.el.bak    18_VsnCtrl.el  21_linum+.el.bak  22_color.el  33_keybindings.el  54_gui.el  55_font.el    60_tabbar.el  66_sdcv.el  68_novel.el  77_dev.el.bak  80_gnus.el.bak  81_rss.el.bak  99_test.el    site-start.el  _color-theme/  _misc/  _sandbox/  auto-complete/  git-emacs/  rss/  yasnippet/ ......    

禁用其中的文件的話,推薦給它加個 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 &rest REST)    (mapc (lambda(ELEMENT) (add-to-list LIST-VAR ELEMENT)) REST))

 

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

(defun add-to-list-l (LIST-VAR LIST) (apply 'add-to-list-x LIST-VAR LIST)) ;; 第二個參數是列表,方便自己對參數進行處理 ;(add-to-list-l 'load-path ;或者;(apply 'add-to-list-x 'load-path ; (mapc fn list) ;)

(defun add-to-list-p (LIST-VAR &optional BASE &rest REST) (mapc (lambda(ELEMENT) (add-to-list LIST-VAR (expand-file-name ELEMENT BASE))) REST)) ;; 這個和上面的那個差不多,是路徑專用的,用於一些特殊情況。比如 ;; init-dir 裡面有一個 cedet 目錄,裡面又有 "common" "eieio" "semantic" ;; "srecode" "ede" 等子目錄,要把這些目錄添加到 load-path,可以這樣 ;; (add-to-list-p 'load-path (expand-file-name "cedet/" init-dir) ;; "" ;; 添加 init-dir/cedet/ 目錄本身 ;; "common" "eieio" "semantic" "srecode" "ede") ;; 如果用 add-to-list-x 的話,就得這樣 ;; (add-to-list-x 'load-path ;; "init-dir/cedet/" ;; "init-dir/cedet/common" ;; "init-dir/cedet/eieio" ;; "init-dir/cedet/semantic" ;; "init-dir/cedet/srecode" ;; "init-dir/cedet/ede" ;; )

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

;(require-x '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 包裝了一下,參數不需要是列表。 ;;但是 elisp 會先對表達式中的參數部分求值……你知道的 ;;命令前面需要加單引號,一般定義的內容較少的時候用 ;(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 文件

;; * 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) ))) ;; 其實各種 hook,也是列表,可以用 C-h v find-file-hook 查看裡面的內容。

;; * max (setq max-lisp-eval-depth 1000 ;lisp最大執行深度 500 max-specpdl-size 10000 ;最大容量 1000 kill-ring-max 1024 ;kill ring 60 undo-outer-limit 5000000 ;撤銷限制 12000000 mark-ring-max 1024 ;mark ring 16 )

;; * Common (setq message-log-max t ;完整的 message-log inhibit-startup-message t ;關閉起動時閃屏 initial-scratch-message ;初始內容 (purecopy "\ ;; In sandbox "))

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

 

 

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

 

 

還有一個關於滑鼠的設置

;; 滑鼠指針規避游標 ;; exile 模式,游標靠近滑鼠指針 mouse-avoidance-threshold 範圍,指針 ;; 跳到 (mouse-avoidance-banish-destination) 的返回值,默認右上角。 ;; exile模式下,游標離開那個範圍后,指針返回原處;banish 模式基本差 ;; 不多,但是指針不返回 (mouse-avoidance-mode 'exile) (setq mouse-avoidance-threshold 10) ;游標靠近該範圍,指針規避

 

;; (defun mouse-avoidance-banish-destination() ;; (let* ((pos (window-edges))) ;; pos 里四個數字為緩衝區的 左上右下 ;; (cons (- (nth 2 pos) 2) ;; 橫坐標 ;; (nth 1 pos)))) ;; 縱坐標

 

 

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,差不多了,有什麼我忘了說的……就當我沒說好了



[火星人 ] 配置 Emacs 的小技巧已經有663次圍觀

http://coctec.com/docs/linux/show-post-65383.html