初學 Emacs Lisp 小技巧

我完全不會寫程式,但在去年的寒假開始學習使用 Emacs。虛擲大量時間在找別人的設定檔,卻一直沒有去學 Emacs Lisp。

Emacs 用一用,為了實現一些自己要的功能,好像還是一定得去學 Emacs Lisp。學了 Lisp 以後真的方便很多很多,也才開始開始實際掌握到 Emacs 的威力。

這篇不是教學,只是一些瑣碎筆記。當初不知道這種問題該怎麼問人或問誰(IRC 其實是個非常棒的發問管道,即時又有效,在 freenode 上的#emacs,還有中文的#emacs.tw),所以一開始寫時覺得很痛苦。

在這裡記下一些能讓入門 Emacs Lisp 更輕鬆方便的小技巧,需要的人許可以參考。

Eval

  • 在任何 mode 下,C-x C-e 可以將游標之前的 S-expression(就是 Lisp 運算式,常簡寫成 sexp)eval (求值) 並輸出結果到 minibuffer 中。

    • 前面加一個 C-u 的話會把結果插入目前游標位置。(所以高興的話可以在 Emacs 裡任何地方寫 Lisp 式子來當計算機。)
    • 如果你在 emacs-lisp-mode 下,C-M-x (eval-defun) 則能夠 eval 目前的 defun
    • 因為覺得內建的 eval 快速鍵要拿來作其他用途有點不方便(例如拿來當作臨時的計算機),所以我自己是另外弄了設定讓他更方便:
      1. Eval 目前的 sexp,輸出其 eval 結果後,直接自動刪除該 sexp。
      2. 加上一個 C-u prefix 就是先按 C-u 再按 key-binding。
        C-u 在 Emacs 裡稱作 universal-argument,很多 function 在前面加 C-u 都會有不同功能。
        的話,不刪除 sexp,而且會先插入一個箭頭 => 再插入 eval 結果。例如(+ 1 5) => 6
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        ;; Makes eval elisp sexp more convenient
        (defun eval-elisp-sexp ()
        "Eval Elisp code at the point, and remove current s-exp
        With one `C-u' prefix, insert output following an arrow"
        (interactive)
        (cond ((equal current-prefix-arg nil) ;if no prefix
        (let ((OUTPUT (eval (preceding-sexp))))
        (kill-sexp -1)
        (insert (format "%S" OUTPUT))))
        ((equal current-prefix-arg '(4)) ;one C-u prefix
        (save-excursion
        (let ((OUTPUT (eval (preceding-sexp))))
        (insert (format "%s%S" " => " OUTPUT)))))))
        (global-set-key (kbd "C-c C-x C-e") 'eval-elisp-sexp)
        ;; avoid key-binding conflict with org
        (define-key org-mode-map (kbd "C-c C-x C-e") 'org-clock-modify-effort-estimate)
  • 在 lisp-interaction-mode 中 (例如 *Scratch* ) ,可以在一個運算式的最後一個括弧後面按下 C-j 直接 eval 並直接將 eval 結果插入當前游標後面。

    Read More