[分享] 发现一个在其他模式使用 org mode source block 的用法(可能不算新颖)

彼时,我正在写 CMakeLists.txt,由于要添加比较多的源文件名到 txt 中,又不想切出 emacs 到命令行中去 ls ./*.cpp >> CMakeLists.txt,故而寻找并尝试了几种(半)自动化解决方案。

在CMakeLists.txt中这么写(使用了 cogapp 这个 python 模块):

set(SRC_FILES "")

# [[[cog
#    import cog, glob
#    for src in glob.glob('*.cpp'):
#       if "skeleton" in src: continue
#       cog.outl("SET(SRC_FILES ${SRC_FILES} %s)" % src)
# ]]]
# [[[end]]]

add_library(mylib STATIC  ${SRC_FILES})

然后执行:

python -m cogapp -r CMakeLists.txt

就会在 txt 中生成类似下面的代码:

# [[[cog
... Omit...
# ]]]
SET(SRC_FILES ${SRC_FILES} "./yyyyyy.cpp")
# [[[end]]]

但是感觉在 emacs 下面这么玩有点别扭(仍然要开一个 terminal),遂继续尝试:

  • 第二种,使用emacs-lisp,这个就比较简单,可以直接选中代码块执行 M-x eval-print-last-sexp
(shell-command-to-string "ls ./*.cpp")

但仍然觉得很别扭,因为毕竟是在 cmake-mode 做 emacs-lisp-mode 的事情,感觉有点奇怪,于是就又上网搜了搜,找到了下面这种神奇的用法:

  1. 选中你需要的行,然后 M-x narrow-to-region 进入这个选中区域。
  2. 将模式切换为org-mode。
  3. 然后使用 org-babel,使用你最熟悉的语言写出代码列出上述源文件,比如还是用 shell:
#+begin_src shell
ls ./src/logger
#+end_src
  1. 使用 C-c C-c 运行代码块。
  2. 退出 narrow 状态。

这种方法虽然看起来步骤更多,但是只要有顺手的快捷键,就相当于只有中间的直接使用org-mode的3步,在享受快捷的同时,还能借助 org 强大的 babel 能力,找到这个方案的时候,顿感眼前一亮。

当然,以上只是在我视野范围内的一些方案,如果大佬们有更好的方案,也不妨在评论区一起讨论一番啊。

2 个赞

可以直接写elisp函数来生成文件列表 directory-files

确实,如果使用场景单一且频繁的话,elisp 函数会更高效一些,但是对于比较随机的情况,比如这里不迭代文件了,改成获取某些文件的某些内容了,那么宽容性更高的方案兼容性可能更通用一些,当然对elisp高手而言,elisp就是最好的方案就是了 >v<

src block不用注释了么

跟第二种方案其实是一个思路,eval-print-last-sexp 之类的命令类似于已经对你选中的部分应用了 emacs-lisp-mode(这么说也不对,应该是通过某个命令对选中部分做统一/通用处理,而无视其所在的具体 mode),而第三种方案中,通过 narrow-to-region 进入了只对选中部分有效的一个可修改的临时buffer(姑且不论这种说法是否准确),而在这个 buffer 将模式设置为 org-mode 之后,跟正常的 org-mode buffer 应该是没有区别的,因为此时在语境上已经不在 CMakeLists.txt 的语境(或者不直接在其)下了,所以自然 source block 也就不用注释了。

我猜 4 楼的意思是,block 不注释,就这么一直放在 CMakeLists.txt 中?

如果只是临时放一下,用完即删,那也太麻烦了。

对,我的场景里,就是用完即删,因为一般的命令都很简单且比较随机,所以也还好,突然发现跟在 eshell 下直接用命令输出(仅示例场景)再 copy 差不多…

C-u M-! ls ./src/logger 直接输出结果到光标位置。

3 个赞

赞,完美的方案!