使用 Company 补全 org block

发布于 2024-11-05 11:46:33 字数 3956 浏览 5 评论 0

早在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

来世叙缘

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

lee_heart

文章 0 评论 0

往事如风

文章 0 评论 0

春风十里

文章 0 评论 0

纸短情长

文章 0 评论 0

qq_pdEUFz

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文