新人入坑,neovimmer 想趁着学 SICP 的机会入坑 emacs。在费劲千辛万苦把 doomemacs 安装在我的 Windows 之后,我终于可以开始做练习题了。注释 + 源代码写着还是有点不舒服,尤其 SICP 的练习题也不全是敲代码 – 于是我转向了 org-mode。
#+begin_src racket :lang sicp
(define (sum-of-maxes x y z)
(cond [(> x y) (+ (max y z) x)]
[(> y z) (+ (max x z) y)]
[(> z x) (+ (max x y) z)]))
#+end_src
这很棒了,C-c C-c 可以直接运行。C-c ' 也可以直接打开编辑。可是默认打开的时候没有设置 racket-ex-mode,被 LS 惯坏了的我怎么能容忍这种事情发生!
新的问题又出现了。熟悉 racket 的人都知道,这不是 racket 的语法,而打开的 buffer 里面又没有 #lang sicp,这不就报错了嘛。
什么!想让我每次都在里面添加 #lang sicp?那怎么行!我宁可把上面中括号改成小括号都不会干这事的。
最后我拷打 GLM 5.0,写出了自动在 org-src-mode 时添加/删除 #lang 的设置。思路是打开新 buffer 时候用 hook 解析 #+begin_src racket 的参数并添加,用 define-advice org-edit-src-exit hook 关闭 buffer 的时候删除。
(defun my/org-src-header-args ()
(let* ((el (org-src-do-at-code-block (org-element-context)))
(params-string (org-element-property :parameters el)))
(org-babel-parse-header-arguments params-string)))
(defvar-local my/org-src--racket-auto-lang nil
"The name of the #lang automatically inserted, or nil if none.")
(defun my/racket-src-mode-auto-lang-shebang (lang)
"Add #lang line in org-src-mode + racket-mode by org-element-context,
when LANG argument matches the `:lang' param in org-element.
Match any language if LANG is empty string.
Set `my/org-src--racket-auto-lang' locally."
(when (derived-mode-p 'racket-mode)
(let ((header-lang (alist-get :lang (my/org-src-header-args))))
(when (and (stringp header-lang) (or (string= lang header-lang) (string= lang "")))
(save-excursion
(goto-char (point-min))
(unless (re-search-forward "^#lang" nil t)
(insert (format "#lang %s\n" header-lang))
(setq-local my/org-src--racket-auto-lang header-lang)))
(racket-xp-mode +1)))))
(define-advice org-edit-src-exit (:before () my-cleanup-auto-lang)
"Delete #lang line in org-src-mode + racket-mode, which is set by
`my/org-src-header-args'. Do nothing if `my/org-src--racket-auto-lang' is not
set."
(when (and (stringp my/org-src--racket-auto-lang)
(derived-mode-p 'racket-mode))
(save-excursion
(goto-char (point-min))
(when (looking-at-p (format "#lang %s\n" my/org-src--racket-auto-lang))
(delete-line)))))
(after! org
;; (add-hook 'org-src-mode-hook (lambda () (my/racket-src-mode-auto-lang-shebang "sicp")))
(add-hook 'org-src-mode-hook (lambda () (my/racket-src-mode-auto-lang-shebang "")))
)
我舒服多了。
请问各位有没有更好的解决办法?