guide-key の表示を自分好みにカスタマイズする

プレフィックスキーに続くキーバインドを自動的にポップアップする [guide-key] (https://github.com/kbkbkbkb1/guide-key/blob/master/README.ja.org) という elisp があります。

例えば [projectile-rails] (https://github.com/asok/projectile-rails) のプレフィックスキー `C-c r` ではこんな表示をしてくれます。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/1637/5f8ba308-6ef4-8fb1-d5e6-a60c46a0a526.png)

しかし、 elisp 特有の長い関数名のせいで見た目が非常によろしくありません。

全関数名の先頭に `projectile-rails` と付いているのがうっとうしいですよね。そもそも projectile-rails を使うために `C-c r` を入力したというのに。

そこで guide-key の内容を自由に置換できる elisp 書いてみました。

```emacs-lisp
(defun guide-key-replace (x)
  (or (loop for i in guide-key-replace-list
            when (equal (car i) (nth 2 x))
            return `(,(nth 0 x) ,(nth 1 x) ,(nth 1 i)) )
      x))

(defun guide-key/format-guide-buffer (key-seq &optional regexp)
  "Format guide buffer. This function returns the number of following keys."
  (let ((fkey-list nil)        ; list of (following-key space command)
        (fkey-str-list nil)    ; fontified string of `fkey-list'
        (fkey-list-len 0)      ; length of above lists
        (key-dsc (key-description key-seq)))
    (untabify (point-min) (point-max))  ; replace tab to space
    (goto-char (point-min))
    ;; extract following keys from buffer bindings
    (while (re-search-forward
            (format "^%s \\([^ \t]+\\)\\([ \t]+\\)\\(\\(?:[^ \t\n]+ ?\\) +\\)$" (regexp-quote key-dsc)) nil t)
      (add-to-list 'fkey-list
                   (list (match-string 1) (match-string 2) (match-string 3)) t))
    ;; filtering
    (setq fkey-list (mapcar 'guide-key-replace fkey-list))
    (erase-buffer)
    (when (> (setq fkey-list-len (length fkey-list)) 0)
      ;; fontify following keys as string
      (setq fkey-str-list
            (loop for (key space command) in fkey-list
                  collect (guide-key/fontified-string key space command regexp)))
      ;; insert a few following keys per line
      (guide-key/insert-following-key fkey-str-list
                                      (popwin:position-horizontal-p guide-key/popup-window-position))
      (goto-char (point-min)))
    fkey-list-len))
```

guide-key/format-guide-buffer は元の定義に `(setq fkey-list (mapcar 'guide-key-replace fkey-list))` を追加しただけです。

これで `guide-key-replace-list` に置換の定義を書けば表示を変更できます。

`guide-key-replace-list` は以下のように定義します。

```emacs-lisp
(defvar guide-key-replace-list
  '(("function1" "func1")
    ("function2" "func2")
    ...))
```

これで function1 という表示を func1 に、 function2 という表示を func2 に、というように置換が行えます。

例えば projectile-rails の例に以下のような定義を行ってみます。

```emacs-lisp
(defvar guide-key-replace-list
  '(("projectile-rails-find-model" "f) model")
    ("projectile-rails-find-controller" "f) controller")
    ("projectile-rails-find-view" "f) view")
    ("projectile-rails-find-javascript" "f) javascript")
    ("projectile-rails-find-stylesheet" "f) stylesheet")
    ("projectile-rails-find-helper" "f) helper")
    ("projectile-rails-find-spec" "f) spec")
    ("projectile-rails-find-migration" "f) migration")
    ("projectile-rails-find-lib" "f) lib")
    ("projectile-rails-find-initializer" "f) initializer")
    ("projectile-rails-find-environment" "f) environment")
    ("projectile-rails-find-log" "f) log")
    ("projectile-rails-find-locale" "f) locale")
    ("projectile-rails-find-mailer" "f) mailer")
    ("projectile-rails-find-layout" "f) layout")
    ("projectile-rails-goto-file-at-point" "goto-file-at-point")
    ("projectile-rails-goto-gemfile" "goto-gemfile")
    ("projectile-rails-goto-routes" "goto-routes")
    ("projectile-rails-goto-schema" "goto-schema")
    ("projectile-rails-goto-spec-helper" "goto-spec-helper")
    ("projectile-rails-find-current-spec" "f) current-spec")
    ("projectile-rails-find-current-controller" "f) current-controller")
    ("projectile-rails-find-current-view" "f) current-view")
    ("projectile-rails-find-current-javascript" "f) current-javascript")
    ("projectile-rails-find-current-stylesheet" "f) current-stylesheet")
    ("projectile-rails-find-current-spec" "f) current-spec")
    ("projectile-rails-find-current-migration" "f) current-migration")
    ("projectile-rails-extract-region" "extract-region")
    ("projectile-rails-console" "console")
    ("projectile-rails-server" "server")
    ("projectile-rails-rake" "rake")
    ("projectile-rails-generate" "generate")
    ("projectile-rails-mode-run-map" "mode-run-map")
    ("projectile-rails-find-current-helper" "f) current-helper")
    ("projectile-rails-find-current-model" "f) current-model")
    ("projectile-rails-find-feature" "f) feature")
    ("projectile-rails-mode-goto-map" "mode-goto-map")))
```

すると以下のように表示が変更されます。

![after.png](https://qiita-image-store.s3.amazonaws.com/0/1637/dfc76839-8386-4a59-cee4-2fba1c0296ed.png)

随分見やすくなったのではないでしょうか。

別に `projectile-rails-` を空文字に置換するとかでもよかったのですが、「定義は面倒でも、定義さえすれば好きな表示にできる」ために、あえて完全一致した関数名のみ置換としました。

英語じゃパッと見わからないという人はこんな定義を書いてみるといいかもしれません。。

```emacs-lisp
(defvar guide-key-replace-list
  '(("projectile-rails-find-model" "モデル検索")))
```

![after2.png](https://qiita-image-store.s3.amazonaws.com/0/1637/f72bb7ca-2851-7a03-9904-abdd177d397f.png)