可以直接用lm-commentary
(from builtin lisp-mnt
)获取Commentary
,不用自己手动搜索了。
刚刚想到 local variables 简单用 ```
包裹起来就可以在 emacs-lisp-mode
下编辑(冒号不影响缩进):
;; ```
;; Local Variables:
;; ...
;; End:
;; ```
或专门写个 comment-edit-el-local-variables
函数来处理 local variables 块 (加上之前的 commend-edit-el-commentary
和 el-commentary-to-readme-md
一并重新整理如下):
(defun comment-edit/region-between-regexps (begin-regexp end-regexp)
(save-excursion
(goto-char (point-min))
(when (re-search-forward begin-regexp)
(let ((begin (point)))
(when (re-search-forward end-regexp nil t)
(goto-char (match-beginning 0))
(cons begin (point)))))))
(defun comment-edit/edit-region (region edit-buffer-mode &optional leave-blank-p)
(let* ((comment-edit-default-mode edit-buffer-mode)
(comment-edit-leave-blank-line-in-comment leave-blank-p))
(comment-edit (list :beginning (car region)
:end (cdr region)))))
(defun comment-edit-el-commentary ()
(interactive)
(comment-edit/edit-region
(comment-edit/region-between-regexps "^;;; Commentary:\n+" "\n;;; .*$")
'markdown-mode
t))
(defun comment-edit-el-local-variables ()
(interactive)
(comment-edit/edit-region
(comment-edit/region-between-regexps "^;; Local Variables:\n+" "\n;; End:$")
'emacs-lisp-mode))
(defun el-commentary-to-readme-md ()
(interactive)
(let ((filename (expand-file-name "README.md")))
(when (yes-or-no-p (format "%s %S? "
(if (file-exists-p filename)
"Overwrite"
"Create")
filename))
(let* ((reg (or (comment-edit/region-between-regexps "^;;; Commentary:\n+" "\n;;; .*$")
(error "Commentary not found in current file!")))
(str (buffer-substring-no-properties (car reg) (cdr reg))))
(with-temp-buffer
(insert str)
(comment-edit--remove-comment-delimiter
(comment-edit--comment-delimiter-regexp 'emacs-lisp-mode))
(write-file filename))))))
试用了一下,非常棒!
写 rust
时正好可以使用这个插件较美观的写 doc comment 了。
不过有一个问题,在 indirect-edit buffer 里的空白行也会在源文件里尾部添加一个空格,如图
我发了一个 pr 来可选去除尾部的空格了
EDIT: pr
写了个简单函数,从Elisp文件中直接提取Commentary
生成README。
(require 'subr-x)
(require 'org)
(require 'pcase)
(require 'lisp-mnt)
(defun limon-doc--sanitize-commentary (commentary)
"Clean up the COMMENTARY returned from `lm-commentary' for export."
(let ((bodies (cdr (split-string (string-trim commentary) "\n")))
(result nil))
(dolist (s bodies)
(pcase s
((or ";;" ";; ") nil)
((rx bol ";; " (let rest (1+ any))) (push rest result))
(some (push some result))))
(string-join (nreverse result) "\n")))
(defun limon-doc-export-commentary (dest)
"Export Org-formatted Commentary section in this buffer to DEST."
(interactive "F")
(pcase (lm-commentary)
(`nil (user-error "No valid commentary section in this buffer!"))
(some
(let ((body (limon-doc--sanitize-commentary some))
(summary (lm-summary)))
(with-temp-buffer
(insert body)
(org-export-to-file 'org dest nil nil nil nil `(:title ,summary)))))))
前面的自定义函数 comment-edit-el-local-variables
可以删除了,comment-edit:77bc3d1 现在已经可以识别 Local Variables 块,并且以 emacs-lisp-mode
作为编辑模式:
可以加一个 feature 吗?
例如这样
class Foo {
/// 这是一个加一操作
/// 当前 buffer 的 fill-column 为 80, 如果在 comment-edit 编辑时,自动计算
/// 好 comment-edit 里的 fill-column 为 80 - (4空格 + 3个/ + 1个空格) = 72
/// 这样只需要在 comment-edit 的 buffer 里调用一下 fill-paragraph 就可以排版好而无需写完
/// documentation comment 之后再排版一下。
int add1(int x) {
return x + 1;
}
};
我稍后看看怎么实现。
lentic后来我也放弃了,有一些特殊情况需要注意,每次都用的小心翼翼。。。
我是习惯直接在el文件中裸写 org 格式的 commentary 然后生成 readme.md
功能已经好了,待我明天提交。
用法是这样:
(require 'comment-edit)
;; 继续源 buffer 没有用完的 fill-column 宽度
(setq comment-edit-continue-fill-column t)
;; 在 hook 中决定如何使用 fill-column 或者做更多的事
(add-hook 'comment-edit-buffer-creation-hook #'auto-fill-mode)
剩余 fill-column 有可能计算错误,这取决于快首空白行的情况。如需修正,也可以自行在 hook 中完成。
增加了手动选择编模式的支持。
例如想要把字符串 "console.log(\"foo\")
当作 js 代码编辑,然而当前上下文没有足够的信息让 comment-edit
去猜测该使用何种模式。
这时就需要手动模式了,按 C-u C-c ’ 即可在进入编辑之前选择模式。
改名之心日盛。
昨晚一不小心又通宵了,顺便想了几个名称:
-
transient-edit
表示短暂离开当前模式,临时进入到另一种编辑状态 -
separedit
取 separate 前半部,表示隔离、分开编辑的意思 -
ripedit
表示把内容剥离出来编辑
目前比较满意的是 separedit
,应该不会有歧义。
期待上 melpa
commented
Org-mode 的快捷键是 C-c '
进入代码块的编辑模式,在编辑模式中按 C-c '
完成编辑。
看能不能兼容一下,或者可以方便这样子定制。
目前这个包就是这么设计的,因为要考虑到在 edit buffer 中再打开 edit buffer 再打开 edit buffer…,所以【进入】和【退出】分别采用不同的按键。
如果你不需要嵌套进入,你可以试着改一下。
现在这个模式跟 magit
的操作方式是一样的,我觉得挺好的。
都是 C-c C-c
提交, C-c C-k
取消
没办法,个人使用时的心理模型跟 org-mode 的 source code 编辑一样,平时操作起来按 快捷键是靠肌肉记忆,hack 了一下基本上跟 org-mode 一样了:
(defun my/ad-comment-edit (orig-fun &optional block)
(if (string-prefix-p "*edit-indirect " (buffer-name))
(progn
(if (buffer-modified-p)
(edit-indirect-commit)
(edit-indirect-abort)))
(funcall orig-fun block)))
(advice-add 'comment-edit :around 'my/ad-comment-edit)
另外,我感觉如果出现嵌套编译注释的情况,就该反思是不是注释写得太复杂了,快捷键一 般来讲应该是为常用直观的场景进行设置,如果不常用估计也记不住。
已更名为 separedit.el
注释/文档中嵌代码块很常见,所以必须保证功能上可以应对这种情况,具体用什么键在其次。
另外,进入/提交/中断这几个键都是可定制的,不需要 advice: