パスワードを忘れた? アカウント作成
11823924 journal
日記

ujimushiの日記: T-code's night 第五夜 「君と付き合うまでのすれ違い」 手探りのauto-tc-complete

日記 by ujimushi

auto-complete-modeは,補完候補が見つかった時点でポップアップメニューが 表示され,カーソルキーで選択するという非常に分かりやすい操作性です。

特に設定ファイルの編集等でEmacs lispのファイルを編集している時には,非常に便利だと実感します。

ただ,auto-complete-modeにも不満があります。基本的にEmacsの単語の区切り単位でしか補完しません。 そのため,日本語の文章のようにスペースを入れない文章を書く時は補完が効かず, 行の先頭の時だけものすごい長いフレーズの候補が表示されるという動作になってしまいます。 日本語の文章のテキストファイルを作る時は不便ですね。

それなら,tc-completeとauto-complete-modeのいいとこ取りが出来ればベスト。

で,何かいい情報が無いかと探していると,auto-completeの拡張方法について 制作者が紹介している記事がありました。 それではその内容, 「Emacsのトラノマキ」連載第10回「auto-completeを拡張しよう」 を確認していきます。

記事の内容をざっと流し読みして,次のように理解しました。

  • 「candidate」属性に候補リストを放り込む
  • Emacsの単語区切り以外で区切るので「prefix」に一致している部分を放り込む

さて,前夜のところで「tcode-complete-candidate-list」の内容が

  ((333 . "ダメ")  "ダメよ~" "ダメダメ")

のようになっていることを確認しました。ならば,

  • “ダメ” → prefix
  • (“ダメよ~” “ダメダメ”) → candidate

ってすればイケるかも。と思ったのが長い苦難の日々の始まりでした…。

ということで,まずprefix属性とcandidate属性を作ってみましょう。carとかcdrを使えば 「tcode-complete-candidate-list」から簡単に取り出せるようです。 そして返り値は最後の式の評価値のようです。 スクラッチバッファで色々試してみながら 次のように実装しました。

  (defun tcode-ac-prefix ()
  "auto-completeに一致する正規表現を渡す"
  (cdr (car tcode-complete-candidate-list)))

(defun tcode-ac-candidate ()
  "auto-completeに候補リストを渡す"
  (cdr tcode-complete-candidate-list))

そして,「tcode-complete-display」には表示機能とか時間待ちとか余分な機能がついているので, 新たに関数を作ってそれを使うことにします。 何とか格闘しながら最終的にはこうなりました。

(defun tcode-ac-complete-set ()
  "Auto-complete用に完全候補リストを設定する。
バッファローカルの変数である
`tcode-complete-candidate-list' に格納される。
`tcode-complete-display' を参考にした"
  (let* ((candidates (tcode-complete-search-candidate
              (tcode-complete-scan-backward)))
     (prefix (cdr (car candidates))))
    (if (< (length prefix) tcode-complete-min-context-length)
    (setq tcode-complete-candidate-list nil)
      (setq tcode-complete-candidate-list candidates))
       ))

  1. ローカル変数「candidates」に一旦「tcode-complete-candidate-list」にコピーする内容を代入
  2. さっきのところでいう「ダメ」に相当する文字列をローカル変数「prefix」に代入
  3. 「prefix」の文字数が「tcode-complete-min-context-length」未満なら 「tcode-complete-candidate-list」にnilを代入。 それ以外の時は,「candidates」を代入

という流れ。

また,さっき作った関数を呼び出すところも新たに作ります。 時間待ちを除いただけですね。

(defun tcode-ac-complete-set-function ()
  "`post-command' にフックしてバックグラウンドで候補リストを作成する。
`tcode-complete-display-function' を参考にした。"
  (if (and (tcode-on-p)
       (memq last-command tcode-input-command-list))
  (tcode-ac-complete-set)))

そして,auto-complete-modeに渡す拡張機能のセットを定義します。

(defvar ac-source-tcode-complete
  '(
    (prefix . tcode-ac-prefix)
    (candidates . tcode-ac-candidate)
    (symbol . "T"))
  "tc-completeの機能を使ったAuto-Completeの補完機能")

確認のためにシンボルを付けます。当然「T」です。言わずもがなですね。(auto-completeの命名規約からは外れています) そして最後にフックする関数を変更します。

;(add-hook 'post-command-hook 'tcode-complete-display-function)

; 従来のtc-complete表示の代わりにauto-complete用の候補作成ルーチンをhookする
(add-hook 'post-command-hook 'tcode-ac-complete-set-function)

.tcの内容も確認します。tcode-ready-hookで「tc-complete」をロードします。

(setq tcode-complete-max-candidate-count 10)    ; 最大10件の候補を出す
(setq tcode-complete-min-context-length 2)      ; 最小2文字
(setq tcode-complete-max-context-length 8)      ; 最長8文字前まで見る
(setq tcode-complete-mazegaki-prefix-length 3) ; 交ぜ書き変換辞書の中を確認する文字数

(add-hook 'tcode-ready-hook
      (function
       (lambda ()
         (require 'tc-complete)
    )))

そしてEmacsを立ち上が直して…あれ,あれ,うまくいかない…

何回も色々変えてやってみますが,うまくいきません。で,もう一度記事の読み直し。

prefix属性に関数を指定した場合は、その関数の返り値を補完対象の開始位置とします。

え~。完全に見落としてた。そこでさっきの「tcode-ac-prefix」関数を修正します。

  (defun tcode-ac-prefix ()
  "auto-completeに開始位置を渡す"
    (car (car tcode-complete-candidate-list)))

実質cdrをcarに変えただけですね。それでは試してみましょう。(何度Emacsを立ち上げ直したことか)

そんなん言うてもダメ
          │ダメよ~ T│
          │ダメダメ  T│
          └────────┘

おお~。でけた~。やった~。

今夜はここまで。動作を確認した内容は次回に説明します。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

※ただしPHPを除く -- あるAdmin

読み込み中...