使用 Company 补全 org block
早在 2015 年,我将 <
键绑定到 hydra 中以便快速插入 org blocks. 这个想法来源于 Oleg 的那篇讲述 Hydra 中的 org-mode block 模板的文章 ,我毫不费力就将这项快捷键变成了肌肉记忆。
快进到 2019 年 2 月,当 org-try-structure-completion
被从 org mode 中移除后,我用 org-insert-structure-template 替代了 hydra,没什么大不了的,因为我依然可以使用 <
作为快捷键,而几乎感觉不到什么变化。
由于我使用 easy templates 的主要场景就是插入 代码 blocks ,除了插入代码块本身,我还希望能够快速选择源码语言。通过一小段 company mode 的补全后端可以很好地满足我的主要场景。
company 后端如下所示 (警告: 需要 Org v9.2 ):
(require 'map)
(require 'org)
(require 'seq)
(defvar company-org-block-bol-p t "If t, detect completion when at
begining of line, otherwise detect completion anywhere.")
(defvar company-org--regexp "<\\([^ ]*\\)")
(defun company-org-block (command &optional arg &rest ignored)
"Complete org babel languages into source blocks."
(interactive (list 'interactive))
(cl-case command
(interactive (company-begin-backend 'company-org-block))
(prefix (when (derived-mode-p 'org-mode)
(company-org-block--grab-symbol-cons)))
(candidates (company-org-block--candidates arg))
(post-completion
(company-org-block--expand arg))))
(defun company-org-block--candidates (prefix)
"Return a list of org babel languages matching PREFIX."
(seq-filter (lambda (language)
(string-prefix-p prefix language))
;; Flatten `org-babel-load-languages' and
;; `org-structure-template-alist', join, and sort.
(seq-sort
#'string-lessp
(append
(mapcar #'prin1-to-string
(map-keys org-babel-load-languages))
(map-values org-structure-template-alist)))))
(defun company-org-block--template-p (template)
(seq-contains (map-values org-structure-template-alist)
template))
(defun company-org-block--expand (insertion)
"Replace INSERTION with actual source block."
(delete-region (point) (- (point) (1+ ;; Include "<" in length.
(length insertion))))
(if (company-org-block--template-p insertion)
(company-org-block--wrap-point insertion
;; May be multiple words.
;; Take the first one.
(nth 0 (split-string insertion)))
(company-org-block--wrap-point (format "src %s" insertion)
"src")))
(defun company-org-block--wrap-point (begin end)
"Wrap point with block using BEGIN and END. For example:
,#+begin_BEGIN
|
,#+end_END"
(insert (format "#+begin_%s\n" begin))
(insert (make-string org-edit-src-content-indentation ?\s))
;; Saving excursion restores point to location inside code block.
(save-excursion
(insert (format "\n#+end_%s" end))))
(defun company-org-block--grab-symbol-cons ()
"Return cons with symbol and t whenever prefix of < is found.
For example: \"<e\" -> (\"e\" . t)"
(when (looking-back (if company-org-block-bol-p
(concat "^" company-org--regexp)
company-org--regexp)
(line-beginning-position))
(cons (match-string-no-properties 1) t)))
要使用它,则添加该补全后端,然后在 org-mode
中启用 company-mode
:
(add-to-list 'company-backends 'company-org-block)
(company-mode +1)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论