VisualStudioCodeの勢いがすごい昨今、周りでもVim派とVisualStudioCode派とそれぞれの言語用のIDE派の人たちが大部分を占めている。 Emacsユーザーに出会う機会も少ないし、まして熱心にEmacsを使っている人はもっと少ないように感じる。 もはやEmacsはマイナーなエディターになってしまったのか。 悲しい限りではあるが、私にとってはまだまだ他のエディターと比べて使いやすくカスタマイズしやすい最高のエディターだ。 ただ最高のエディターとは書いたが不満はたくさんある。 これらの不満を自分のペースで解決していきやすいところがEmacsの良いところだ。

今回はEmacsの補完機能をカスタマイズする。今回はcompany-modeを取り上げる。 company-modeのWiki1に従って簡単な補完を実装する。

fooと入力すると

  • foobar

  • foobaz

  • foobarbaz

を提案して来るようになる。

(setq company-idle-delay 0)
(setq company-minimum-prefix-length 1)
(setq company-selection-wrap-around t)

(require 'cl-lib)
(require 'company)

(defun company-simple-backend (command &optional arg &rest ignored)
  (interactive (list 'interactive))
  (print command)
  (print arg)
  (print ignored)
  (cl-case command
    (interactive (company-begin-backend 'company-simple-backend))
    (prefix (when (looking-back "foo\\\\>")
	      (match-string 0)))
    (candidates (when (equal arg "foo")
		  (list "foobar" "foobaz" "foobarbaz")))
    (meta (format "This value is named %s" arg))))

(add-to-list 'company-backends 'company-simple-backend)

もう少し複雑な処理をしたい場合の例を示す。

(require 'cl-lib)

(defvar company-advanced-keywords
  '(("foo" "overload 1") ("foo" "overload 2") ("bar" "method 1")))

(defun company-advanced–make-candidate (candidate)
  (let ((text (car candidate))
	(meta (cadr candidate)))
    (propertize text 'meta meta)))

(defun company-advanced–candidates (prefix)
  (let (res)
    (dolist (item company-advanced-keywords)
      (when (string-prefix-p prefix (car item))
	(push (company-advanced–make-candidate item) res)))
    res))

(defun company-advanced–meta (candidate)
  (format "This will use %s of %s"
	  (get-text-property 0 'meta candidate)
	  (substring-no-properties candidate)))

(defun company-advanced–anotation (candidate)
  (format " (%s)" (get-text-property 0 'meta candidate)))

(defun company-advanced (command &optional arg &rest ignored)
  (interactive (list 'interactive))
  (cl-case command
    (interactive (company-begin-backend 'company-advanced))
    (prefix (company-grab-symbol-cons "\\\\.\\\\|->" 2))
    (candidates (company-advanced–candidates arg))
    (annotation (company-advanced–anotation arg))
    (meta (company-advanced–meta arg))))

(add-to-list 'company-backends 'company-advanced)

脚注