【傻瓜教程】使用 org 管理 Emacs 配置

  1. 新建一个 org 文件,并命名为 test.org

  2. 打开文件

  3. M-x org-id-get-create 创建文件的 properties

  4. :PROPERTIES: 后面插入一个空格,然后输入 header-args:emacs-lisp :tangle

:PROPERTIES: header-args:emacs-lisp :tangle
:ID:       1E443DCC-CF1D-464D-A2C7-27497A9654B8
:END:

你也可以在后面写上文件的标题

:PROPERTIES: header-args:emacs-lisp :tangle
:ID:       1E443DCC-CF1D-464D-A2C7-27497A9654B8
:END:
#+title: test org babel tangle
  1. C-c C-, 然后按 s 就插入了一个代码块,紧接着输入 emacs-lisp :tangle yes

  2. 编辑你在上一步插入的代码块

插入一个时间戳测试一下

;; 2023-01-07T09:38:39+0800
  1. C-c C-v t 就能把以上代码块导出到与 org 文件同名的 el 文件里了。

  2. 把你已有的配置剪贴进 test.org,并重命名文件为 init.org

  3. 现在你可以在 org 里拆分你的配置到不同的代码块

  4. 每个代码块都需要显式声明 :tangle yes,未声明 的代码块不会被导出。

#+begin_src emacs-lisp :tangle yes
;; 2023-01-07T09:38:39+0800
#+end_src

Bonus

每次都按 C-c C-v t 是不是有点累?可以用 org-auto-tangle 偷个懒

配置

;; org-auto-tangle
;; {{{
(use-package org-auto-tangle
  :ensure nil
  :hook (org-mode . org-auto-tangle-mode)
  )
;; }}}

使用

只需要在文件头部添加一行 #+auto_tangle: t

:PROPERTIES: header-args:emacs-lisp :tangle
:ID:       1E443DCC-CF1D-464D-A2C7-27497A9654B8
:END:
#+title: test org babel tangle
#+auto_tangle: t

效果

org 文件

:PROPERTIES: header-args:emacs-lisp :tangle
:ID:       1E443DCC-CF1D-464D-A2C7-27497A9654B8
:END:
#+title: test org babel tangle
#+auto_tangle: t


#+begin_src emacs-lisp :tangle yes
;; 2023-01-07T09:38:39+0800
#+end_src

生成的同名 el 文件

;; 2023-01-07T09:38:39+0800

以上就是一个傻瓜写的 org 管理 Emacs 配置的教程了。 :crazy_face:

5 个赞

简单总结一下用 org 管理 Emacs 配置的好处:

  1. 可以使用 org 强大的 TAB 键折叠不同标题

  2. 可以在光标处于标题上的时候,C-c C-c 给标题加标签 :label:

  3. 可以使用 org 强大的 C-c ' 编辑单独的一个代码块,类似 Emacs 默认不开启的 narrow-to-region 功能。

  4. 可以将多个插件的配置写到一个代码块里,使用 :tangle no 一次性关闭所有配置,特别适合管理某个功能的一套插件体系。

  5. 由第四条扩展开来,也可以先把别人的配置抄进自己的 org 文件,然后逐步吸收进自己的配置。

Bonus

可以使用 parrot 插件实现 yesno 的切换

(use-package parrot
  :defer 2
  :bind (
         ("H-w r" . parrot-rotate-prev-word-at-point)
         ("H-w t" . parrot-rotate-next-word-at-point)
         )
  :config
  (parrot-mode)
  (parrot-set-parrot-type 'emacs)
  (setq parrot-rotate-dict
        '(
          (:rot ("alpha" "beta") :caps t :lower nil)
          ;; => rotations are "Alpha" "Beta"

          (:rot ("snek" "snake" "stawp"))
          ;; => rotations are "snek" "snake" "stawp"

          (:rot ("yes" "no") :caps t :upcase t)
          ;; => rotations are "yes" "no", "Yes" "No", "YES" "NO"

          (:rot ("&" "|"))
          ;; => rotations are "&" "|"

	  (:rot ("nil" "t"))
	  
          ;; default dictionary starts here ('v')
          (:rot ("begin" "end") :caps t :upcase t)
          (:rot ("enable" "disable") :caps t :upcase t)
          (:rot ("enter" "exit") :caps t :upcase t)
          (:rot ("forward" "backward") :caps t :upcase t)
          (:rot ("front" "rear" "back") :caps t :upcase t)
          (:rot ("get" "set") :caps t :upcase t)
          (:rot ("high" "low") :caps t :upcase t)
          (:rot ("in" "out") :caps t :upcase t)
          (:rot ("left" "right") :caps t :upcase t)
          (:rot ("min" "max") :caps t :upcase t)
          (:rot ("on" "off") :caps t :upcase t)
          (:rot ("prev" "next"))
          (:rot ("start" "stop") :caps t :upcase t)
          (:rot ("true" "false") :caps t :upcase t)
          (:rot ("&&" "||"))
          (:rot ("==" "!="))
          (:rot ("." "->"))
          (:rot ("if" "cond" "else" "elif"))
          (:rot ("ifdef" "ifndef"))
          (:rot ("int8_t" "int16_t" "int32_t" "int64_t"))
          (:rot ("uint8_t" "uint16_t" "uint32_t" "uint64_t"))
          (:rot ("1" "2" "3" "4" "5" "6" "7" "8" "9" "10"))
          (:rot ("1st" "2nd" "3rd" "4th" "5th" "6th" "7th" "8th" "9th" "10th"))
          )
        )
  )

简单说明一下为什么绑定 H-w rH-w t,w 指单词 word,r和t是 rotate 和 revert 中的两个字母。

还以为是比较经典的(org-babel-load-file (expand-file-name "path/to/your/config.org"))

2 个赞

有个 org-babel-tangle-publish 的函数可以指定输入文件与输出位置,忽略property里的位置。这样可以把org文件与el文件分开放,避免删除时很麻烦。

emacs.d/Makefile at master · nasyxx/emacs.d · GitHub

对我这样的小脑袋瓜子来说太复杂了 :laughing:

看不懂啊 :rofl:

目前我就两个 org 文件,分别管理 early-init 和 init。以后应该也不会再拆分了。

以前用了六十多个文件分别设置,改起来太累了,找内容麻烦,注释麻烦,二分 debug 也麻烦。

搞两个org 干嘛,一个就可以了啊,可以tangle到不同的文件当中。

:rofl: 因为我还没搞懂 tangle,只好用笨办法了。

人是懒惰的,以后根本不会想写org。 :crazy_face:

我直接用得 Org-transclusion 不过有些时候会罢工

我之前的配置,在文件头部:

#+PROPERTY: header-args:emacs-lisp :results silent :tangle "~/.emacs.d/init.el"
#+AUTO_TANGLE: t

默认tangle 到init.el这个文件当中。

需要tangle 到early-init.el中,在src block用下面的这个:

#+begin_src emacs-lisp :tangle "~/.emacs.d/early-init.el"
#+end_src

其他的用:

#+begin_src emacs-lisp
#+end_src

临时注销某个配置可以在org-heading 前加上comment,这样就不会tangle 对应heading 下的src block.如果只是需要取消某个src block 可以用:

#+begin_src emacs-lisp :tangle no
#+end_src
2 个赞

是不是用两个一级标题分别设置 early-init 和 init 啊?让子标题继承 properties。

看来我得花时间好好研究一下 header-args 的参数了。

可以这样设置。early-init的内容不怎么变,我就放在了一个block中。

不过我现在不使用这种模式管理emacs配置了,还是真接用el文件,方便使用git管理。

其实完全可以用 org 来记录配置文件的配置过程,至于配置的代码内容完全可以用 GitHub - nobiot/org-transclusion: Emacs package to enable transclusion with Org Mode 来引用到 org 当中,这样修改配置的时候,也不需要修改 org。

tangle nil 有用吗?印象中好像应该 tangle no 才行(

依赖外部插件是个大问题,debug 的时候不方便。

你是对的,是我记错了。去看了下之前的配置文件写的是no不是nil。

就像有人说的用org-babel-load-file就可以了,你这样用org生成.el文件,还要用org-roam管理,平时倒没问题,就是环境崩了,就麻烦了。我个人感觉emacs的配置环境还是尽量减少依赖。

用你说的这个方法配置其他软件的配置倒是可以。

我很好奇你从哪里看出来我这个方法依赖 org-roam 的?

我的十步里没有任何一个命令、快捷键是第三方插件的。

是我搞错了,我一直以为org-id-get-create是org-roam的命令,创建property用#+property: 就行了,我一直以为创建id要用org-roam管理才需要