org-modeでの補完候補はorg-pcomplete.elで設定しているようで、特に#+で始まるオプションについてはpcomplete/org-mode/file-option
関数で候補を生成しています。そのソースコードは次の通りです。
;; org-pcomplete.elより引用 (defun pcomplete/org-mode/file-option () "Complete against all valid file options." (require 'org-element) (pcomplete-here (org-pcomplete-case-double (append (mapcar (lambda (keyword) (concat keyword " ")) org-options-keywords) (mapcar (lambda (keyword) (concat keyword ": ")) org-element-affiliated-keywords) (let (block-names) (dolist (name '("CENTER" "COMMENT" "EXAMPLE" "EXPORT" "QUOTE" "SRC" "VERSE") block-names) (push (format "END_%s" name) block-names) (push (concat "BEGIN_" name ;; Since language is compulsory in ;; export blocks source blocks, add ;; a space. (and (member name '("EXPORT" "SRC")) " ")) block-names) (push (format "ATTR_%s: " name) block-names))) (mapcar (lambda (keyword) (concat keyword ": ")) (org-get-export-keywords)))) (substring pcomplete-stub 2)))
この関数で次のような文字列を補完候補として生成しています。
org-options-keywords
=>#+ARCHIVE:
,#+AUTHOR:
, ....org-element-affiliated-keywords
=>#+CAPTION
,#+DATA
, ....("CENTER" "COMMENT" "EXAMPLE" "EXPORT" "QUOTE" "SRC" "VERSE")
=>#+BEGIN_*
,#+END_*
,#+ATTR_*
- (
org-get-export-keywords
) =>#+HTML_HEAD
,#+HTML_HEAD_EXTRA
,#+LATEX_HEADER
, ...
なぜこれを調べたかというと、 #+ATTR_HTML
が補完候補に現れないことに気が付いたからです。
理由は上のコードを見れば分かるとおり、ATTR_で始まるものはCENTER、COMMENT、EXAMPLE、EXPORT、QUOTE、SRC、VERSEしか登録していないからです。
え、ちょっと待って? #+ATTR_CENTER:
#+ATTR_COMMENT:
#+ATTR_EXAMPLE:
#+ATTR_EXPORT:
#+ATTR_QUOTE:
#+ATTR_SRC:
#+ATTR_VERSE:
なんてありましたっけ? 聞いたこともありませんし使ったこともありません。ちょっと検索しても分かりませんでした。どういうこと??
ATTR_HTMLはエクスポートキーワードの中にあるのかなとも思ったのですが、そういうわけでも無さそうです。
ATTR_HTMLを追加しようにもこの関数の途中に処理を挟むのは難しいので、諦めて全部上書きしてしまうことにしました。ついでに独自のspecial blocks(org-special-blocks.el ― turn blocks into LaTeX envs and HTML divs)も補完候補に加えます(#+begin_figures-col2
を <div class="figures-col2>
にしてくれます)。ATTR_CENTER等は削除してしまいましょう。よく分かりませんし、使いませんし。
(with-eval-after-load "org-pcomplete" ;; org-pcomplete.elの`pcomplete/org-mode/file-option'よりコピーして改変 (defun pcomplete/org-mode/file-option () "Complete against all valid file options." (require 'org-element) (pcomplete-here (org-pcomplete-case-double (append (mapcar (lambda (keyword) (concat keyword " ")) org-options-keywords) (mapcar (lambda (keyword) (concat keyword ": ")) org-element-affiliated-keywords) ;; ★[変更]: 追加 (mapcar (lambda (keyword) (concat keyword ": ")) '("ATTR_HTML" "ATTR_ORG")) (let (block-names) (dolist (name '("CENTER" "COMMENT" "EXAMPLE" "EXPORT" "QUOTE" "SRC" "VERSE" ;; ★[変更]: 追加。CSSで画像を並べるのに使っています "FIGURES-FLOW" "FIGURES-COL2" "FIGURES-COL3") block-names) (push (format "END_%s" name) block-names) (push (concat "BEGIN_" name ;; Since language is compulsory in ;; export blocks source blocks, add ;; a space. (and (member name '("EXPORT" "SRC")) " ")) block-names) ;; ★[変更]: 削除。ATTR_CENTERって何……? ;;(push (format "ATTR_%s: " name) block-names) )) (mapcar (lambda (keyword) (concat keyword ": ")) (org-get-export-keywords)))) (substring pcomplete-stub 2))))
この所Corfuの自動補完をいじっていましたが、もちろんこれらの設定も自動補完に影響します。 #+beg
くらいまで打てば自動で補完候補が出現します。corfu-auto-prefix
が3なので#+の後に3文字入力したら表示されるのでしょう。
本当は #+
と入力しただけで補完候補が現れてくれればいいのですが。
一応次のようにすれば実現出来ます(corfu--auto-complete-deferred
にいったい幾つadviceを仕掛けるつもりだ)。
(defun my-corfu--auto-complete-deferred:around:for-org (oldfun &rest args) (let (;; org-modeで#+が出たら即自動補完する (corfu-auto-prefix (if (and (derived-mode-p 'org-mode) ;;org-modeで…… ;; <bol><spaces>#+<identifier> (save-excursion (and (skip-chars-backward "-A-Za-z0-9_+") (eq (char-before) ?+) (eq (char-before (1- (point))) ?#) (goto-char (- (point) 2)) (skip-chars-backward " \t") (bolp)))) 0 corfu-auto-prefix))) (apply oldfun args))) (advice-add 'corfu--auto-complete-deferred :around #'my-corfu--auto-complete-deferred:around:for-org)
[[
を入力したらリンクタイプも補完してほしいんですよね。先日書いたやつの [[elisp-function:
を入力するのが大変なので(よくfucntionやらfunctoinやら打ち間違えます。やっぱり [[elfun:
にでもしておけば良かったかな)。 まぁ、そのうち。
(追記:リンクタイプも補完するようにしました)
ああよく見たら、同じくorg-pcomplete.elにpcomplete/org-mode/link
というのがあるんですね。
;; org-pcomplete.elより引用 (defun pcomplete/org-mode/link () "Complete against defined #+LINK patterns." (pcomplete-here (pcomplete-uniquify-list (copy-sequence (mapcar (lambda (e) (concat (car e) ":")) (append org-link-abbrev-alist-local org-link-abbrev-alist))))))
リンクタイプを差し置いてlink abbrevだけあるのかよ!
まぁ、これもそのまま修正しちゃいましょう。(2024-02-23追記:org-link-completion.elでリンクタイプを補完できるようにしたので、それを使えば次の変更は不要です)
(with-eval-after-load "org-pcomplete" ;; org-pcomplete.elの`pcomplete/org-mode/link'よりコピーして改変 (defun pcomplete/org-mode/link () "Complete against defined #+LINK patterns." (pcomplete-here (pcomplete-uniquify-list (copy-sequence (mapcar (lambda (e) (concat (car e) ":")) (append org-link-abbrev-alist-local org-link-abbrev-alist ;; ★[変更]: 追加 org-link-parameters)))))))
上で書いたコードもちょっと修正して [[
で自動補完が開始されるようにしましょう。あ、ソースコードブロック中の [[
にも反応しちゃうかな。まあいいや。
(defun my-corfu--auto-complete-deferred:around:for-org (oldfun &rest args) (let (;; org-modeで#+や[[が出たら即自動補完する (corfu-auto-prefix (if (and (derived-mode-p 'org-mode) ;;org-modeで…… (or ;; <bol><spaces>#+<identifier> (save-excursion (and (skip-chars-backward "-A-Za-z0-9_") (eq (char-before) ?+) (eq (char-before (1- (point))) ?#) (goto-char (- (point) 2)) (skip-chars-backward " \t") (bolp))) ;; [[<link-type> (save-excursion (and (skip-chars-backward "-A-Za-z0-9_+") ;;file+sysがある (eq (char-before) ?\[) (eq (char-before (1- (point))) ?\[))) ;; (2024-02-18追記:見出しの補完を追加) ;; [[*<heading> (save-excursion (and (skip-chars-backward "^*\t\n[") (eq (char-before) ?*) (eq (char-before (1- (point))) ?\[) (eq (char-before (- (point) 2)) ?\[))))) 0 corfu-auto-prefix))) (apply oldfun args))) (advice-add 'corfu--auto-complete-deferred :around #'my-corfu--auto-complete-deferred:around:for-org)