Skip to content
Tags

helm で正規表現などを無効化する

2014/10/13

動機

helm は絞り込みが高機能で正規表現による絞り込みはもちろん、 バッファをメジャーモードで絞り込んだりするなど情報源によっては 情報源が用意している記法を用いることで様々な絞り込みができるらしいのですが、 自分はほとんどこの機能を使ったことがありません。 便利かもしれないのですが、絞り込む文字列を増やすことで個人的には十分でした。

そこで、 helm で入力した文字列を見た目通りに扱えるようにしよう、 というのが今回の動機です。

方針

helm では情報源の match 属性にある関数が情報源に合わせた絞り込みを 行っていますが、今回はこれを無効化して helm-match-plugin に絞り込みを任せます。

helm-match-plugin

helm-match-plugin のデフォルトの状態1で絞り込みを担っている helm-mp-3-match で正規表現が無効化されるようにします。2

helm-mp-3-match ではパターン生成に helm-mp-3-get-patterns を使用しているので、この関数の戻り値を加工することで正規表現を無効化します。 helm-mp-3-get-patterns の戻り値は述語関数と正規表現の連想リストのような 構造をしているので正規表現の部分に regexp-quote を適応すればよいでしょう。3

(require 'helm-match-plugin)

(defvar my-enable-helm-without-regexp t)

(defadvice helm-mp-3-get-patterns
    (after my-helm-without-regexp activate)
  (when my-enable-helm-without-regexp
    (setq ad-return-value
          (mapcar (lambda (it)
                    (cons (car it) (regexp-quote (cdr it))))
                  ad-return-value))))

あとは情報源の絞り込みに helm-match-plugin が使われるように情報源の match 属性を削除します。また、 dont-plug 属性に helm-compile-source--match-plugin が含まれていても helm-match-plugin が使用されなくなってしまうので、これも取り除きましょう。

使い回しできるように関数として用意します。また変数を加工するときには cl-callf が便利です。

(require 'cl-lib)

(defun my-make-helm-source-without-regexp (source)
  (cl-loop for (key . value) in source
           unless (eq key 'match)
           if (eq key 'dont-plug)
           collect (cons key (remove 'helm-compile-source--match-plugin value))
           else
           collect (cons key value)))

;; 例として `helm-source-buffers-list'
(require 'helm-buffers)

(cl-callf my-make-helm-source-without-regexp helm-source-buffers-list)

helm-migemo

migemo を使用する情報源の場合、上のコードだけでは不十分なので 追加の対策をします。というのも migemo-get-pattern では 入力は文字列として処理されるので、エスケープ用の “\\” も文字として 扱われてしまうからです。当然といえば当然の動作ですね。

  • migemo-get-pattern の動作例
    (migemo-get-pattern "c\\+\\+")
    ;; => "\\(c\\s-*\\\\\\s-*+\\s-*\\\\\\s-*+\\|c\\s-*¥\\s-*+\\s-*¥\\s-*+\\)"
    

したがって、 helm-mp-3migemo-match 内では helm-mp-3-get-patterns の戻り値を加工せず migemo-get-pattern の戻り値の必要な箇所を regexp-quote で加工します。

(require 'cl-lib)
(require 'helm-migemo)

(defvar my-enable-helm-migemo-without-regexp nil)

(defadvice helm-mp-3migemo-match
    (around my-helm-without-regexp activate)
  (if my-enable-helm-without-regexp
      (let ((my-enable-helm-without-regexp nil)
            (my-enable-helm-migemo-without-regexp t))
        ad-do-it)
    ad-do-it))

(defadvice migemo-get-pattern
    (after my-helm-without-regexp activate)
  (when my-enable-helm-migemo-without-regexp
    (let ((str   ad-return-value)
          (start 0))
      (save-match-data
        (while (string-match "\\\\s-\\*\\([^[\\]\\)" str start)
          (let ((newtext (regexp-quote (match-string 1 str))))
            (setq str   (replace-match newtext t t str 1)
                  start (+ (cl-second (match-data))
                           (1- (length newtext)))))))
      (setq ad-return-value str))))

おわりに

とりあえず自分の環境では目的の動作を得ることが出来ました。 “c++” のような文字列や拡張子を入力するのがいくらか楽になりました。 既存の情報源を加工するのではなく、それを元に新しく情報源を定義したほうが 行儀がいいかもしれませんね。 絞り込みが若干もたつくようになった気もしますが、そのあたりは必要に応じて 直していこうかと思います。 そういえば、以前 “\” を使って絞りこみをしようとしたらうまく動作しなかったのは migemo が関係していたのかも…

Footnotes:

1

helm-mp-matching-methodmulti3 の状態。

2

helm-mp-3-match だけでなく helm-mp-exact-match も絞り込みを 担っていますが今回は手を付けません。

3

正確にはこれだけだと “!” によるマイナス検索が有効なままに なってしまいますが、これも今回は手を付けません。

広告

From → Emacs

コメントする

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。