Emacs Auto-Completeユーザ辞書の作り方メモ

概ね自分のしたかったことが出来たので、まとめておきました。

自分用の辞書を作って出来たこと

emacs auto-complete 1
ライブラリ名表示、色分け、直前の文字の条件指定など。

emacs auto-complete 2
セレクタもこんな感じで、

emacs auto-complete 3
直前の文字が`$.'もしくは`jQuery.'の場合のみ出てくるjQueryメソッド。

emacs auto-complete 4
括弧が末尾にあった場合のみ展開後に括弧内へ移動

テスト環境

以下の通り。emacsを最低限の設定にして試しました。

  • MacOSX 10.8
  • emacs 24.3
  • auto-complete.el 1.4.0

フォルダ構成は次のようにしました。

~/.emacs.d/init.el
設定ファイル
~/.emacs.d/elisp/auto-complete/
auto-completeフォルダ
~/.emacs.d/ac-user-dict/
ユーザ辞書フォルダ

ここでは、js-mode/js2-modeにおいて、underscore.jsとjQueryの一部メソッド&セレクタ使えるようにします。

auto-complete.elの導入

すでにauto-complete.el(ver1.4.0)を使っている人は飛ばしてください。

パッケージ管理システムのmelpaからでも大丈夫ですが、ここではgitを使った方法を書いておきます。

ターミナルなどからgitコマンドを使用します。


cd ~/.emacs.d/elisp
git clone https://github.com/auto-complete/auto-complete.git
cd auto-complete
git submodule update --init

設定ファイル(~/.emacs.d/init.el)に以下を記入します。


;;; auto-complete ---------------------------------
;; 各種elispを読み込む
(defvar ac-dir (expand-file-name "~/.emacs.d/elisp/auto-complete"))
(add-to-list 'load-path ac-dir)
(add-to-list 'load-path (concat ac-dir "/lib/ert"))
(add-to-list 'load-path (concat ac-dir "/lib/fuzzy"))
(add-to-list 'load-path (concat ac-dir "/lib/popup"))

(require 'auto-complete)
(require 'auto-complete-config)
(global-auto-complete-mode t)

(setq ac-use-menu-map t) ;; C-n / C-p で選択
(setq ac-auto-show-menu 0.3) ;; 候補が出るまでの時間 default 0.8

解説付き設定

~/.emacs.d/init.elに以下を記入。


;; ユーザ辞書の場所
(defvar ac-user-dict-dir (expand-file-name "~/.emacs.d/ac-user-dict/"))

;; コンプリート時の動作 - 候補の末尾に()があればその内にカーソルを置く
(defun ac-go-into-braces-action ()
  (save-restriction
    (narrow-to-region (point) (- (point) 2))
    (if (re-search-backward "()" nil t)
        (forward-char))))

;; 直前の文字を区別して辞書を使用する - 何か1文字+ドットの後の場合に補完する
(defun ac-js-dot-prefix ()
  "`x.' prefix."
  (if (re-search-backward ".\\.\\(.*\\)" nil t)
      ;; ".\\.\\(.*\\)" 何か一文字[.] ドット[\\.] 補完開始点[\\(.*\\)]
      (match-beginning 1)))

;; メニューで選択中の候補の色設定
(defface ac-my-selection-face
  '((t (:background "#000080" :foreground "#ffffff")))
  "Face for selectied candidates."
  :group 'auto-complete)

;;; 辞書1 (underscore.js)
;; 色設定
(defface ac-underscore-js-candidate-face
  '((t (:background "#730CE8" :foreground "#eeeeee")))
  "Face for underscore.js candidates."
  :group 'auto-complete)
;; 情報源に辞書ファイルを指定
(defvar ac-underscore-js-cache
  (ac-file-dictionary (concat ac-user-dict-dir "underscore-js")))
;; 辞書1の設定
(defvar ac-source-underscore-js-dict
  '((candidates . ac-underscore-js-cache) ;; 候補の情報源 これ以下はオプション
    (candidate-face . ac-underscore-js-candidate-face) ;; 候補の色設定
    (selection-face . ac-my-selection-face) ;; 選択中の色設定
    (prefix . ac-js-dot-prefix) ;; 直前の文字の条件
    (action . ac-go-into-braces-action) ;; 補完後の動作
    (symbol . "underscore.js") ;; ライブラリ名 (無理矢理。本来の意図とは違うはず)
    ;; (requires . 2) ;; 補完が開始される最低入力文字数を上書き
    ;; (limit . 30) ;; 候補を一度に表示する上限数を上書き
    ))

;;; 辞書2 (jquery)
;; 色設定
(defface ac-jquery-candidate-face
  '((t (:background "#1f679a" :foreground "#eeeeee")))
  "Face for jquery candidates."
  :group 'auto-complete)
;; 情報源に辞書ファイルを指定
(defvar ac-jquery-method1-cache
  (ac-file-dictionary (concat ac-user-dict-dir "jquery-method1")))
;; 辞書2の設定
(defvar ac-source-jquery-method-dict1
  '((candidates . ac-jquery-method1-cache)
    (candidate-face . ac-jquery-candidate-face)
    (selection-face . ac-my-selection-face)
    (prefix . ac-js-dot-prefix)
    (action . ac-go-into-braces-action)
    (symbol . "jquery method1")
    ))

;;; 辞書3 (jquery)
;; 直前の文字の条件 (`jQuery.'または`$.')
(defun ac-jquery-method2-prefix ()
  "`$' or `jQuery' prefix."
  (if (re-search-backward "\\(jQuery\\|\\$\\)\\.\\(.*\\)" nil t)
      (match-beginning 2)))
;; 情報源に辞書ファイルを指定
(defvar ac-jquery-method2-cache
  (ac-file-dictionary (concat ac-user-dict-dir "jquery-method2")))
;; 辞書3の設定
(defvar ac-source-jquery-method-dict2
  '((candidates . ac-jquery-method2-cache)
    (candidate-face . ac-jquery-candidate-face)
    (selection-face . ac-my-selection-face)
    (prefix . ac-jquery-method2-prefix)
    (action . ac-go-into-braces-action)
    (symbol . "jquery method2")
    ))

;;; 辞書4 (jqueryセレクタ)
;; 直前の文字の条件 (`x:')
(defun ac-jquery-selector-prefix ()
  "`x:' prefix."
  (if (re-search-backward ".\\:\\(.*\\)" nil t)
      (match-beginning 1)))
;; 色設定
(defface ac-jquery-selector-candidate-face
  '((t (:background "#1B919A" :foreground "#eeeeee")))
  "Face for jquery selector candidates."
  :group 'auto-complete)
;; 情報源に辞書ファイルを指定
(defvar ac-jquery-selector-cache
  (ac-file-dictionary (concat ac-user-dict-dir "jquery-selector")))
;; 辞書4の設定
(defvar ac-source-jquery-selector-dict
  '((candidates . ac-jquery-selector-cache)
    (candidate-face . ac-jquery-selector-candidate-face)
    (selection-face . ac-my-selection-face)
    (prefix . ac-jquery-selector-prefix)
    (action . ac-go-into-braces-action)
    (symbol . "jQuery selector")
    ))

;; 使用する辞書・情報源を選択
(defun ac-js-mode-setup ()
  (setq ac-sources
        '(
          ac-source-abbrev
          ac-source-words-in-same-mode-buffers
          ;; ac-source-yasnippet
          ac-source-filename
          ;; 優先順位で並べる (prefixを指定すると排他的になる; x.に$.が含まれる)
          ac-source-jquery-method-dict2  ; prefix `$.'
          ac-source-jquery-method-dict1  ; prefix `x.'
          ac-source-underscore-js-dict   ; prefix `x.'
          ac-source-jquery-selector-dict ; prefix `x:'
          )))
;; メジャーモードに反映させる
 (add-hook 'js-mode-hook 'ac-js-mode-setup)
 (add-hook 'js2-mode-hook 'ac-js-mode-setup)

;; 辞書間で重複するものが削除されるので
;; ~/.emacs.d/elisp/auto-complete/auto-complete.el L1052 (delete-dups candidates) をコメントアウト

;; ac-disable-facesの初期値は
;; (font-lock-comment-face font-lock-string-face font-lock-doc-face)
;; font-lock-string-faceがあるとクオートで囲まれた部分"..."で
;; auto-completeが反応しなくなり、セレクタを補完できないので次のように
(setq ac-disable-faces '(font-lock-comment-face font-lock-doc-face))

情報源の書き方

1行ずつ書き並べるだけです。

例: ~/.emacs.d/ac-user-dict/jquery-method1


context
length
selector
add()
addBack()
addClass()
after()
ajaxComplete()
...

終わりに

色設定に迷ったらkulerというwebサービスを使うといいと思います。

取り敢えず作った辞書と設定をgithubに置いておきます。

ShingoFukuyama/auto-complete-user-dict

詰めが甘い点やもっと良い方法などありましたらtwitterなどで教えてください。

参考

Auto Complete Mode User Manual

「Emacsのトラノマキ」連載第09回

「Emacsのトラノマキ」連載第10回