helm を背に ivy の門を叩く
Table of Contents
- 1. はじめに
- 2. インストール
- 3. 基本設定
- 4. デフォルト機能を便利に使う
- 5. パッケージの移行
- 6. prescient.el
- 7. 視覚化
- 8. 分析
- 9. まとめ
- 10. 謝辞
- 11. References
1. はじめに
ivy
は, helm
と双璧を成す Emacs の補完システムです.リスト表示された多くの選択肢から,自分が使いたいものを高速に絞り込んで,効率良く選び出す.このシンプル,かつ極めて重要なタスクを, ivy
や helm
が手助けしてくれます.
過去を振り返れば,特に理由もなく私は anything.el
から(強いて言えばメンテナス状況が良かった) helm.el
に移行し,そして今回, helm.el
から ivy.el
に移行することにしました. ivy
への移行の理由はいくつかありますが,シンプル軽量であり,ミニバッファで完結するインターフェイスに安定感があり,なにより all-the-icons.el
との相性が良いことです.
特に普段からモードラインを表示しない派の方は,全体的にスッキリ・シャープな Emacs に生まれ変わりますので,移行をオススメします.
よければEmacs勉強会の講演資料と設定集もご参照ください.また, ivy
以外の設定集も公開しています.この記事のソースも公開しています.
↑GUI
↑ターミナル
2. インストール
いくつかのインストール方法がありますが,パッケージ管理ツールを使うのが楽です. ivy.el
をインストールする時は,プリセット関数を集めている counsel.el
と, helm-swoop
相当の機能を提供する swiper.el
も同時に入れるのが一般的です.
counsel.el
が swiper.el
に, swiper.el
が ivy.el
に依存しているので,パッケージ管理ツールを使う場合は, counsel.el
をインストールすれば,3つのパッケージを同時にインストールできます.うまくいかない場合は,3つとも指定すれば良いです…
なお当方の環境は macOS
で,それ以外の環境では動作未確認ですが,大きな違いは無いと思います.
2.1. MELPA
counsel
をインストールします.Cask使いの場合は,一行追加で.
(depends-on "counsel")
2.2. el-get
swiper
のリポジトリを指定します.
(el-get-bundle "abo-abo/swiper")
3. 基本設定
ここでは基本的な設定と配色, ivy
の流儀と選択候補のソーティング変数を紹介します.
3.1. 設定例
個別の設定や細かなハックに移る前に,まずは,これさえあればとりあえず動くという設定を施します.
3.1.1. ivy.el
まずは ivy
を使えるようにします.ほぼ素のままで良いです.
(when (require 'ivy nil t) ;; M-o を ivy-hydra-read-action に割り当てる. (when (require 'ivy-hydra nil t) (setq ivy-read-action-function #'ivy-hydra-read-action)) ;; `ivy-switch-buffer' (C-x b) のリストに recent files と bookmark を含める. (setq ivy-use-virtual-buffers t) ;; ミニバッファでコマンド発行を認める (when (setq enable-recursive-minibuffers t) (minibuffer-depth-indicate-mode 1)) ;; 何回層入ったかプロンプトに表示. ;; ESC連打でミニバッファを閉じる (define-key ivy-minibuffer-map (kbd "<escape>") 'minibuffer-keyboard-quit) ;; プロンプトの表示が長い時に折り返す(選択候補も折り返される) (setq ivy-truncate-lines nil) ;; リスト先頭で `C-p' するとき,リストの最後に移動する (setq ivy-wrap t) ;; アクティベート (ivy-mode 1))
NOTE ivy.el (ivy-read-action-function): Fix type · abo-abo/swiper@1ad457d にて ivy-dispatching-done-hydra
が無くなり, ivy-hydra
を読み込むだけでは, M-o
がリッチな表示になりません.追加で, ivy-read-action-function
の設定が必要です.
3.1.2. counsel.el
counsel.el
は, ivy
の骨格関数である ivy-read
を様々なコマンドに拡張し,それらをプリセットとして収録しています.全文探索の counsel-ag
など,よく使うコマンドを別途インストールする必要がありません.
(when (require 'counsel nil t) ;; キーバインドは一例です.好みに変えましょう. (global-set-key (kbd "M-x") 'counsel-M-x) (global-set-key (kbd "M-y") 'counsel-yank-pop) (global-set-key (kbd "C-M-z") 'counsel-fzf) (global-set-key (kbd "C-M-r") 'counsel-recentf) (global-set-key (kbd "C-x C-b") 'counsel-ibuffer) (global-set-key (kbd "C-M-f") 'counsel-ag) ;; アクティベート (counsel-mode 1))
3.1.3. swiper
swiper
は, helm-swoop
のような文字列探索機能を提供します.カーソル位置の単語をキーに,バッファ内を探索.絞り込まれた選択候補を C-n/C-p
で変えると,それに合わせてバッファの表示も変わり,連続してプレビューできます.なお, swiper-all-thing-at-point
も実装されていて,これは開いているすべてのバッファを探索します.
(when (require 'swiper nil t) ;; キーバインドは一例です.好みに変えましょう. (global-set-key (kbd "M-s M-s") 'swiper-thing-at-point))
3.2. 検索語のハイライト
デフォルトの配色は,なかなかに個性的なので自分の好みに書き換えましょう.中途半端に書き換えると,デフォルトの配色が表に出てくるので,次にリストしたフェイスはすべて書き換える方が安全です.なお, (setq ivy-display-style t)
とすると,配色を無効にできます.
- ivy-current-match
- ミニバッファ内カーソル行の配色.
:background
を使うと,絞り込み中のカーソル行の文字色にも反映されてしまう.:distant-foreground
を使うと反映されない.ただし,指定する色の明るさに依存して期待通りにならないこともある.微調整が必要.
- ミニバッファ内カーソル行の配色.
- ivy-minibuffer-match-face-1
パターンマッチした文字列範囲の配色.ただし,
![Screen Shot 2019-08-03 at 12.57.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12232/198cc1c6-f676-b703-c121-ec83cab34217.png)ivy-re-builders-alist
で指定するフィルタの種別に依存して使われたり,使われなかったりする.デフォルトのivy--regex-plus
の場合は,使われる.
- ivy-minibuffer-match-face-{2,3,4}
検索語のハイライトに使われる.検索語が3つを超える時は,ループして使う.
![Screen Shot 2019-08-03 at 13.02.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12232/64f74be6-f61c-07c6-7750-c409e327bd9e.png)
より詳細は,マニュアルを参照してください.
(custom-set-faces '(ivy-current-match ((((class color) (background light)) :background "#FFF3F3" :distant-foreground "#000000") (((class color) (background dark)) :background "#404040" :distant-foreground "#abb2bf"))) '(ivy-minibuffer-match-face-1 ((((class color) (background light)) :foreground "#666666") (((class color) (background dark)) :foreground "#999999"))) '(ivy-minibuffer-match-face-2 ((((class color) (background light)) :foreground "#c03333" :underline t) (((class color) (background dark)) :foreground "#e04444" :underline t))) '(ivy-minibuffer-match-face-3 ((((class color) (background light)) :foreground "#8585ff" :underline t) (((class color) (background dark)) :foreground "#7777ff" :underline t))) '(ivy-minibuffer-match-face-4 ((((class color) (background light)) :foreground "#439943" :underline t) (((class color) (background dark)) :foreground "#33bb33" :underline t))))
3.3. まず始めに知っておくべき機能
ivy
への移行に際して,知っておくべきデフォルト機能・コマンドがあります.それらは helm
とは流儀が異なるので,少々戸惑うかもしれませんが,すぐ慣れます.
counsel-M-x
等の ivy
インターフェイスで,選択候補がリスト表示されていると,次のコマンドを使えるようになります.
コマンド | 効果 |
---|---|
M-o | 選択項目に対するアクションを選択できる |
C-o | ミニバッファを表示したままコマンドを発行.jk移動.gプレビュー. |
C-M-n | 候補を切り替えるとバッファも切り替わりプレビューできる(順方向) |
C-M-p | 候補を切り替えるとバッファも切り替わりプレビューできる(逆方向) |
C-M-m | 候補リストの表示を維持したまま,現在の選択候補をプレビューする |
C-M-j | 選択候補を無視して,入力中の値を使う |
C-M-m
, C-M-n
, C-M-p
は,helm-file-preview の機能をデフォルト実装した印象です. swiper
もそうですが, QuickLook
的にファイルの内容を確認できるのがとても便利です.
その他, ivy-resume
を使うと,いつでも前回のセッションに戻れます.ただし, counsel-M-x
を常用する場合や頻繁にリジュームする人は,キーバインドを設定するべきです. C-c C-r
が推奨されているようですが,私は org-reveal
との衝突をさけるために, C-c i r
をアサインしています.
プロンプトでユーザが入力する検索語は,一部の正規表現に対応しているので, ^
を付ければ先頭マッチ, $
末尾マッチというように制御できます.
3.4. ソーティングとフィルタ設定
少し細かい話になりますが, ivy
には絞り込み時の振る舞いに影響する重要な変数がいくつか定義されています.基本的に「すべてのコマンドに対する設定(全体設定)」と「個別のコマンドに対する設定」の双方を定義できます.
後述の prescient.el
を導入すると「すべてのコマンドに対する設定」を上書きするため,導入の影響で振る舞いが変化し,それが気に入らないこともありえます.その場合には,各設定を上書きしないようにするフラグ(ivy-prescient-enable-filtering
)がありますので,とりあえずフラグをOFFの状態で使い始めるのも良さそうです.
変数 | 全体設定 |
---|---|
ivy-sort-functions-alist | ivy-string< |
ivy-sort-matches-functions-alist | nil |
ivy-re-builders-alist | ivy–regex-plus |
- ivy-sort-functions-alist
- 絞り込み開始前のリストの並び方を設定します
- まだ何もしていない時の選択候補の並びが気になる時は,この変数を設定します.
prescient.el
を導入し,ivy-prescient-enable-sorting
などを正しく設定すれば,使用頻度の高い項目を上位に上げるなど,良きに計らってくれます.
- 絞り込み開始前のリストの並び方を設定します
- ivy-sort-matches-functions-alist
- 絞り込み開始後のリストの並び方を設定します
- 絞り込み開始後のリストの並び方を設定します
- ivy-re-builders-alist
- フィルタは
ivy--regex
,regexp-quote
,ivy--regex-plus
,ivy--regex-fuzzy
,ivy--regex-ignore-order
から選べます.独自実装した関数を設定することも可能です. ivy--regex-ignore-order
がhelm
の振る舞いに一番近そうです.prescient.el
は,「すべてのコマンド」に対してivy-prescient-re-builder
を設定します.
ivy-prescient-enable-filtering
がnil
ならば,設定されません.
- 絞り込み時の face に影響を与えます.デフォルトの振る舞いが気に入っている場合は,
ivy--regex-plus
を「すべてのコマンド」に対して設定しましょう.
ivy--regex-ignore-order
は,enc org と org enc で結果が同じ.ivy-minibuffer-match-face-1
不使用.ivy--regex-plus
は,enc org と org enc で結果が異なる.ivy-minibuffer-match-face-1
使用.
- フィルタは
4. デフォルト機能を便利に使う
ivy-mode
を使えるようになったら,まず counsel.el
にプリセットされているデフォルト機能から使い始めましょう.いくつかをピックアップして紹介します.必要に応じてカスタマイズすれば,さらに便利に使えるようになります.
4.1. counsel.el にプリセットされているコマンド
counsel.el (0.12.0) には,82個のコマンドが実装されています.頻繁に使うであろうコマンドと,注目のコマンドを抜粋します.完全なリストは,記事の下に示します.
コマンド | 機能 |
---|---|
counsel-minor | マイナーモードの一覧 |
counsel-unicode-char | ユニコード文字の入力補助 |
counsel-yank-pop | ペーストした文字列の選択 |
counsel-mark-ring | マーク位置の選択 |
counsel-fzf | fzf インターフェイス |
counsel-ag | ag インターフェイス |
counsel-locate | locate インターフェイス |
counsel-recentf | recentf インターフェイス |
counsel-find-library | Emacs Lisp ライブラリの選択 |
counsel-faces | フェイスの一覧 |
counsel-colors-emacs | カラーリスト |
counsel-colors-web | カラーリスト(Webカラー) |
counsel-M-x | コマンド一覧 |
counsel-set-variable | 変数の一覧と書き換え |
counsel-bookmark | ブックマーク選択 |
counsel-switch-buffer | バッファリスト(プレビュー付) |
counsel-ibuffer | iBuffer インターフェイス |
counsel-minor
はマイナーモードを表示して有効・無効化ができるので地味に便利です.ただ見やすさの点では,manage-minor-mode.elがオススメです.
4.2. org.el と共に使う
counsel.el
には,org mode ユーザ向けのコマンドとして, counsel-org-tag
, counsel-org-tag-agenda
, counsel-org-goto
, counsel-org-goto-all
, counsel-org-file
, counsel-org-entity
, counsel-org-capture
, counsel-org-agenda-headlines
が実装されています.
counsel-org-tag
は,タグの書き換え時に ivy
を使いますが,どうやってタグを削除するのかがよくわからないと思います.私も戸惑いましたが,そんな時は, C-M-j
(ivy-immediate-done) を呼び出せばよいです.
もし, org-capture
にも ivy
を使いたい場合は,次の設定を使います.ただ, org-capture
については,多くのユーザがキーバインドを記憶して呼び出していると思うので,それほど役立たない気もします.
(define-key counsel-mode-map [remap org-capture] 'counsel-org-capture)
以下は, swiper
を使う時に,カーソル位置の単語を自動選択から org mode
の見出しを除外するためのハックです.
(when (require 'swiper nil t) (defun ad:swiper-thing-at-point () "`swiper' with `ivy-thing-at-point'." (interactive) (let ((thing (if (thing-at-point-looking-at "^\\*+") nil (ivy-thing-at-point)))) (when (use-region-p) (deactivate-mark)) (swiper thing))) (advice-add 'swiper-thing-at-point :override #'ad:swiper-thing-at-point))
4.3. dired.el と共に使う
ivy-dired-history
を導入すると, dired (C-x d
) で訪問した場所を記録してソート表示してくれます.さらに,diredにコピー(C
)と移動(R
)機能を与えてくれます.ただし,コピーや移動先の表示順位を上げる機能ではないので要注意です.履歴の保存は, session.el
で明示的に管理しています.一般には savehist
を使うことが推奨されているようです.
(when (require 'ivy-dired-history nil t) (define-key dired-mode-map "," 'dired) (with-eval-after-load "session" (add-to-list 'session-globals-include 'ivy-dired-history-variable)))
なお,最近 dired
で開いたディレクトリを M-x dired-recent-open
で一覧できる dired-recent も ivy
に対応しています.こちらは規定の dired-recent-directories-file
に履歴が記録されます.
4.4. magit.el と共に使う
magit
の branch の選択などが ivy
インターフェイスになります.後述の prescient.el
を導入すれば,選択項目を上に上げたり,履歴を保存できます.
(with-eval-after-load "magit" (setq magit-completing-read-function 'ivy-completing-read))
4.5. eldoc.el と共に使う
eldoc
は eldoc-idle-delay
の値を用いて一定時間が経過したらミニバッファに情報を出します. helm
は別ウィンドウに情報を出すため衝突しませんが, ivy
はミニバッファを使うため,高頻度で衝突します. eldoc-message
をハックします.
なお (setq eldoc-print-after-edit t)
でも同様の効果がありますが,いろいろ試した結果,不十分とわかりました(例:Org を開き,counsel-recentf して,org に戻り,treeを移動した時に, org-eldoc
が反応する.)
(with-eval-after-load "eldoc" (defun ad:eldoc-message (f &optional string) (unless (active-minibuffer-window) (funcall f string))) (advice-add 'eldoc-message :around #'ad:eldoc-message))
4.6. mic-paren.el と共に使う
eldoc
と同様に,ミニバッファで衝突します.以下のコードで回避できます.
(with-eval-after-load "mic-paren" (defun ad:mic-paren-highlight (f) (if (active-minibuffer-window) (let ((paren-display-message 'never)) (funcall f)) (funcall f))) (advice-add 'mic-paren-highlight :around #'ad:mic-paren-highlight))
4.7. counsel-find-file を使わない
counsel-find-file
が find-file
を置き換えますが,私は素の find-file
を気に入っているので, counsel-find-file
を無効化します.
;; completion-in-region-function も一時的にデフォに戻さないと,TAB補完時に ;; ivy が有効化されてしまう. (defun my-disable-counsel-find-file (&rest args) "Disable `counsel-find-file' and use the original `find-file' with ARGS." (let ((completing-read-function #'completing-read-default) (completion-in-region-function #'completion--in-region)) (apply #'read-file-name-default args))) (setq read-file-name-function #'my-disable-counsel-find-file) ;; (counsel-mode 1) を設定しても counsel-find-file が呼ばれないようにする. (define-key counsel-mode-map [remap find-file] nil)
counsel-find-flie
を常用する場合には,リスト候補に不要なファイルを出さない方が見通しがよくなるので,次のように設定すると良さそうです. macOS
であれば, .DS_Store
をリスト一覧から除外できます.
(setq counsel-find-file-ignore-regexp (regexp-opt completion-ignored-extensions))
4.8. find-library のバグを回避
厳密に言えばバグではないのですが,最初に find-library
を使うと,大量の ./
を表示する問題があります.これは find-library
ではなく counsel-find-library
を直接呼べば回避できます.しかし, M-x
した時のコマンド候補には依然として find-library
が出てきますので,誤選択の原因になります.
この問題は, find-library
から interactive
を取ることで解決します.advice では無意味で,再定義が必要です.
(when (require 'find-func nil t) (defun find-library (library) "Override the original `find-library' to hide in command list." (prog1 (switch-to-buffer (find-file-noselect (find-library-name library))) (run-hooks 'find-function-after-hook))))
4.9. counsel-M-x
helm
や ivy
を使う大きな目的として,コマンドの絞り込みがあります. helm
から ivy
に移行すると, M-x
の印象がかなり違うので,必要に応じて helm
流になるように設定して使います.4点ほど設定・カスタマイズします.
まず, smex
或いは amx
を導入して,コマンドの使用履歴を保存・利用します. amx
がインストールされていると, smex
よりも優先的に使われます.なお残念ながら helm-M-x
で培った履歴をそのまま使うのは難しいようです.
(when (require 'smex nil t) (setq smex-history-length 35) (setq smex-completion-method 'ivy))
次に, M-x ^
とデフォルトで入力される ^
前方マッチ記号を非表示にします. ivy-initial-inputs-alist
を設定します.
(setq ivy-initial-inputs-alist '((org-agenda-refile . "^") (org-capture-refile . "^") ;; (counsel-M-x . "^") ;; 削除.必要に応じて他のコマンドも除外する. (counsel-describe-function . "^") (counsel-describe-variable . "^") (Man-completion-table . "^") (woman . "^")))
さらに, ivy-re-builders-alist
でフィルタを指定します.私は ivy--regex-ignore-order
を選択.デフォルトは ivy--regex-plus
です.
(setf (alist-get 'counsel-M-x ivy-re-builders-alist) #'ivy--regex-ignore-order)
最後に,絞り込み開始後のソーティング方法をカスタマイズします.
(defun ivy--sort-by-len (name candidates) "Sort CANDIDATES based on similarity of their length with NAME." (let ((name-len (length name)) (candidates-count (length candidates))) (if (< 500 candidates-count) candidates (seq-sort-by #'length (lambda (a b) (< (abs (- name-len a)) (abs (- name-len b)))) candidates)))) (setf (alist-get 'counsel-M-x ivy-sort-matches-functions-alist) #'ivy--sort-by-len)
see https://github.com/abo-abo/swiper/issues/1294
emacs25
を使っている場合は, seq-sort-by
が無いと怒られるかもしれません.その場合は,次のコードをどこかに置いてください. emacs26.3
から抽出した関数です. (unless (fboundp 'seq-sort-by))
で括っておきました.
(unless (fboundp 'seq-sort-by) (defun seq-sort-by (function pred sequence) "Sort SEQUENCE using PRED as a comparison function. Elements of SEQUENCE are transformed by FUNCTION before being sorted. FUNCTION must be a function of one argument." (seq-sort (lambda (a b) (funcall pred (funcall function a) (funcall function b))) sequence)))
4.10. counsel-ag
counsel-ag
は, grep
と同様に全文検索する ag
コマンドのインターフェイスを提供します.私はカーソル位置の単語を使って全文検索する頻度が高いので,そのようにハックします.
(defun ad:counsel-ag (f &optional initial-input initial-directory extra-ag-args ag-prompt caller) (apply f (or initial-input (ivy-thing-at-point)) (unless current-prefix-arg (or initial-directory default-directory)) extra-ag-args ag-prompt caller)) (advice-add 'counsel-ag :around #'ad:counsel-ag)
さらに,デフォルトではカレントディレクトリ以下の範囲で全文検索しますが,ディレクトリを変えて再検索したいこともあります.検索語を再入力せずディレクトリを変えるために,次の関数を実装して, M-o r
で呼び出せるようにします.
;; directory を指定して ag やり直し.クエリは再利用する (defun my-counsel-ag-in-dir (_arg) "Search again with new root directory." (let ((current-prefix-arg '(4))) (counsel-ag ivy-text nil ""))) ;; also disable extra-ag-args (ivy-add-actions 'counsel-ag '(("r" my-counsel-ag-in-dir "search in directory")))
counsel-cd
が上記の機能を意図しているようですが,想像と少々異なる振る舞いをするので,私は counsel-cd
を使っていません.
(define-key counsel-ag-map (kbd "C-x C-d") 'counsel-cd)
と設定しておけば, counsel-ag
使用中に M-o
せず直接 C-x C-d
すれば counsel-cd
を呼べます.
最後に,デフォルトだと3文字入力しないと検索が発動しませんが,2文字の文字列でも検索可能にしています.
;; 2文字でも検索が発動するようにする (add-to-list 'ivy-more-chars-alist '(counsel-ag . 2))
4.11. counsel-fzf
counsel-ag
の場合と同様に,カーソル位置の単語を使って counsel-fzf
を起動するようにハックします.
(defun ad:counsel-fzf (f &optional initial-input initial-directory fzf-prompt) (apply f (or initial-input (ivy-thing-at-point)) (or initial-directory default-directory) fzf-prompt)) (advice-add 'counsel-fzf :around #'ad:counsel-fzf)
さらに,検索語を維持したまま探索範囲を変えるための関数を登録します. counsel-fzf
を利用中に, M-o r
で発動します.
(defun my-counsel-fzf-in-dir (_arg) "Search again with new root directory." (counsel-fzf ivy-text (read-directory-name (concat (car (split-string counsel-fzf-cmd)) " in directory: ")))) (ivy-add-actions 'counsel-fzf '(("r" my-counsel-fzf-in-dir "search in directory")))
4.11.1. 検索語を入力してもヒットしないとき counsel-fzf に誘導する(半自動)
ivy
で検索語を入力しても,ヒットしないことがよくあります.入力ミス等なら再入力で済みますが,実は recentf
に記録されていないだけ,とか,探索範囲が狭すぎるだけなこともあります.そんな時は,検索語を再入力せずに探索範囲だけを広げたいと思うでしょう.
以下の設定では,検索がヒットしない時に,一定時間が過ぎたら counsel-fzf
に接続するかを [y/n]
で問うように設定しています.常に問われると煩雑なので,一つの ivy
セッションで1回だけ問うようにしています.
counsel-fzf
に誘導する機能を追加したい場合は, my-nocand-then-fzf-commands
にコマンドを追加して下さい.
また,選択候補が無いと確定してから my-nocand-then-fzf-idle-time
秒後に [y/n]
を問うようにカスタマイズできます.
このデモでは,次のフローで所望のファイルを見つけています.
- "test" "heading" で
recentf
を探索 - 見つからないので
counsel-fzf
に接続 - カレントディレクトリ以下にも存在しない
M-o r
でcounsel-fzf
を再呼び出しして,探索範囲を変更- 発見
;; 発動するコマンドを限定 (defcustom my-nocand-then-fzf-commands '(counsel-find-flie counsel-recentf counsel-projectile-find-file counsel-projectile-switch-project) "List of commands for applying extension no candidates then `counsel-fzf'." :group 'ivy :type '(list symbol)) ;; 無応答の時[y/n]を出す.待ち時間を[s]で指定 (defcustom my-nocand-then-fzf-idle-time 0.8 "Idle time for showing prompt." :group 'ivy :type 'float) (defvar my--nocand-then-fzf t) (defun my-nocand-then-fzf-reset () (setq my--nocand-then-fzf t)) (defun my-nocand-then-fzf (prompt) (when (= ivy--length 0) (if (eq (read-char prompt) ?y) ;; y-or-n-p is not applicable (ivy-exit-with-action (lambda (x) (counsel-fzf ivy-text default-directory))) (setq my--nocand-then-fzf nil)))) (defun ad:fzf:ivy--insert-prompt () (when (and my--nocand-then-fzf (memq (ivy-state-caller ivy-last) my-nocand-then-fzf-commands) (= ivy--length 0)) (let* ((std-props '(front-sticky t rear-nonsticky t field t read-only t)) (prompt (concat (my-ivy-prompt-prefix) "Switch to Counsel-fzf? [y/n] "))) (set-text-properties 0 (length prompt) `(face minibuffer-prompt ,@std-props) prompt) (run-with-idle-timer my-nocand-then-fzf-idle-time nil #'my-nocand-then-fzf prompt)))) ;; ivy--insert-prompt を adivce する. (advice-add 'ivy--insert-prompt :before #'ad:fzf:ivy--insert-prompt) ;; セッションを抜けたらフラグを戻す (add-hook 'minibuffer-setup-hook #'my-nocand-then-fzf-reset) (add-hook 'minibuffer-exit-hook #'my-nocand-then-fzf-reset)
4.12. counsel-recentf
デフォルトでは /
からファイルの表示が始まりますが, ~
から始める方が好みなので counsel-recentf
を再設定します.
(defun ad:counsel-recentf () "Find a file on `recentf-list'." (interactive) (require 'recentf) (recentf-mode) (ivy-read "Recentf: " (progn (mapcar #'substring-no-properties recentf-list) ;; no need? (mapcar #'abbreviate-file-name recentf-list)) ;; ~/ :action (lambda (f) (with-ivy-window (find-file f))) :require-match t :caller 'counsel-recentf)) (advice-add 'counsel-recentf :override #'ad:counsel-recentf)
さらに,所望のファイルがヒットしない時に, M-o z
で counsel-fzf
に移れるようにします.検索語は引き継がれるので,再入力する手間を省けます.
;; 以下の関数は,counsel-projectile-* と counsel-recentf にぶら下げる. (defun my-counsel-fzf-in-default-dir (_arg) "Search the current directory with fzf." (counsel-fzf ivy-text default-directory)) ;; add an action for counsel-recentf (M-o z) (ivy-add-actions 'counsel-recentf '(("z" my-counsel-fzf-in-default-dir "switch to fzf")))
なお, recentf
のリストには,頻繁に自動更新される一方で,実際には自分が中身を触ることがほぼないファイルも含まれます.例えば bookmarks
です.それらは,使用しないにも関わらずリストの上部に上がってきますので,除外しておくべきです. ivy
側の設定で counsel-find-file-ignore-regexp
を (regexp-opt '("~/.emacs.d/bookmarks"))
などとすれば回避できますが,それよりも, recentf
の設定で除外しておくのがよいでしょう.
(custom-set-variables '(recentf-exclude '(".recentf" "bookmarks" "org-recent-headings.dat" "^/tmp\\.*" "^/private\\.*" "^/var/folders\\.*" "/TAGS$")))
4.13. counsel-mark-ring
マーク位置をたどることができます.意図せずカーソルが飛んでしまっても,少し前の編集箇所にカーソルを戻せるようになります.ただしデフォルトのままでは,履歴がソートされてしまうので,時系列に並ぶように設定を変更します.
(with-eval-after-load "ivy" ;; counsel-mark-ring のリストをソートさせない (setf (alist-get 'counsel-mark-ring ivy-sort-functions-alist) nil)) (global-set-key (kbd "C-,") 'counsel-mark-ring) (with-eval-after-load "flyspell" (define-key flyspell-mode-map (kbd "C-,") 'counsel-mark-ring))
5. パッケージの移行
helm
で便利に使っていた外部パッケージは,同等の機能を ivy
向けに提供するパッケージが公開されています.一部は,フラグメントとして公開されているものです.幸いながら,私はほぼすべてのパッケージを無事に移行できました.
5.1. helm と ivy-counsel のコマンド対応表
個人的に helm
で依存していたコマンドの対応表です.現在メインで使用しているコマンドは概ねカバーしています.表中の「X」は,デフォルト実装されているコマンドを表します.
機能 | Helm | Ivy/Counsel | ||
---|---|---|---|---|
コマンド選択 | X | helm-M-x | X | counsel-M-x |
bookmark.el I/F | X | helm-bookmark | X | counsel-bookmark |
locate I/F | X | helm-locate | X | counsel-locate (1) |
バッファ切り替え | X | helm-buffers-list | X | counsel-ibuffer |
recentf.el I/F | X | helm-recentf | X | counsel-recentf |
キーバインド表示 | helm-descbinds | X | counsel-descbinds | |
ag I/F | helm-ag | X | counsel-ag | |
複数単語検索 | helm-swoop | X | swiper | |
bm.el I/F | helm-bm | counsel-bm (2) | ||
projectile.el I/F | helm-projectile | counsel-projectile (3) | ||
単語の辞書記録 | flyspell-correct-helm | flyspell-correct-ivy (4) | ||
heading の選択 | org-recent-headings-helm | org-recent-headings-ivy (5) | ||
global I/F | helm-gtags | counsel-gtags (6) | ||
dired 履歴 | helm-dired-history | ivy-dired-history (7) | ||
selected.el I/F | helm-selected | counsel-selected (8) | ||
flycheck.el I/F | helm-flycheck | counsel-flycheck (9) | ||
pass I/F | helm-pass | ivy-pass (10) | ||
emms.el I/F | helm-emms | nil | ||
emmet I/F | helm-emmet | nil |
(1) counsel-locate
(2) counsel-bm (fragment)
(3) counsel-projectile
(4) flyspell-correct-ivy
(5) org-recent-headings-ivy
(6) counsel-gtags
(7) ivy-dired-history
(8) counsel-selected
(9) counsel-flycheck (fragment)
(10) ivy-pass
5.2. counsel-flycheck (fragment)
https://github.com/nathankot/dotemacs/blob/master/init.el#L709 にありますので.拝借しました.関数名を変更して, caller
を追加しています.
(defvar counsel-flycheck-history nil "History for `counsel-flycheck'") (defun counsel-flycheck () (interactive) (if (not (bound-and-true-p flycheck-mode)) (message "Flycheck mode is not available or enabled") (ivy-read "Error: " (let ((source-buffer (current-buffer))) (with-current-buffer (or (get-buffer flycheck-error-list-buffer) (progn (with-current-buffer (get-buffer-create flycheck-error-list-buffer) (flycheck-error-list-mode) (current-buffer)))) (flycheck-error-list-set-source source-buffer) (flycheck-error-list-reset-filter) (revert-buffer t t t) (split-string (buffer-string) "\n" t " *"))) :action (lambda (s &rest _) (-when-let* ( (error (get-text-property 0 'tabulated-list-id s)) (pos (flycheck-error-pos error)) ) (goto-char (flycheck-error-pos error)))) :history 'counsel-flycheck-history :caller 'counsel-flycheck)))
5.3. counsel-bm (fragment)
https://www.reddit.com/r/emacs/comments/700xck/ivy_with_bmel_bookmark_manager/ に公開されているコードをアレンジしました. ivy
とは無関係ですが, <f10>
で bm.el
の bm-toggle
を呼び出し, C-<f10>
で次のブックマークに移動するように設定しています.詳細は, Configurations for GNU Emacs::4.9 [bm.el] カーソル位置をブックマークして追う を参照ください.
(when (require 'bm nil t) (defun counsel-bm-get-list (bookmark-overlays) (-map (lambda (bm) (with-current-buffer (overlay-buffer bm) (let* ((line (replace-regexp-in-string "\n$" "" (buffer-substring (overlay-start bm) (overlay-end bm)))) ;; line numbers start on 1 (line-num (+ 1 (count-lines (point-min) (overlay-start bm)))) (name (format "%s:%d - %s" (buffer-name) line-num line))) `(,name . ,bm)))) bookmark-overlays)) (defun counsel-bm () (interactive) (let* ((bm-list (counsel-bm-get-list (bm-overlays-lifo-order t))) (bm-hash-table (make-hash-table :test 'equal)) (search-list (-map (lambda (bm) (car bm)) bm-list))) (-each bm-list (lambda (bm) (puthash (car bm) (cdr bm) bm-hash-table) )) (ivy-read "Find bookmark(bm.el): " search-list :require-match t :keymap counsel-describe-map :action (lambda (chosen) (let ((bookmark (gethash chosen bm-hash-table))) (switch-to-buffer (overlay-buffer bookmark)) (bm-goto bookmark) )) :sort t))) (global-set-key (kbd "<S-f10>") 'counsel-bm))
5.4. counsel-world-clock.el
counsel-world-clock は,タイムゾーンから時刻と時差を調べるツールです.ビルトインの display-time-world
でも似たことができますが, ivy
でタイムゾーンを絞り込めるので圧倒的に便利です.
デフォルトではソートされないので,prescient.el を導入して,直近の選択を上位に移すソーティングと履歴保存を有効にしましょう.
(with-eval-after-load "ivy" ;; package 経由のインストールなら,M-x counsel-world-clock ですぐ使える. (require 'counsel-world-clock nil t))
5.5. counsel-selected.el
拙作の helm-selected を ivy
に移植しました.どちらかといえば,絞り込みしたいと言うより,領域選択から l
押下で,メニューを表示し,設定項目を思い出すために使います.
(when (require 'counsel-selected nil t) (define-key selected-keymap (kbd "l") 'counsel-selected))
5.6. counsel-osx-app.el
counse.el
には Linuxのアプリケーションを呼び出すためのインターフェイスである counsel-linux-app
が実装されています. macOS用のコマンドは counsel-osx-app に公開されています.以前はOS側のランチャーを呼び出して使っていましたが,このコマンドのおかげで,Emacs から直接アプリケーションを呼び出せるので,かなり重宝しています.
counsel-osx-app-location
を正しく設定すれば,サブディレクトリに含まれるアプリケーションもリストに入れてくれます.
NOTE "/System/Applications"
も追加します.
(global-set-key (kbd "C-M-1") 'counsel-osx-app) (with-eval-after-load "counsel-osx-app" (custom-set-variables '(counsel-osx-app-location '("/Applications" "/Applications/Utilities" "/System/Applications" "/Applications/Microsoft Remote Desktop.localized"))))
5.7. counsel-projectile.el
counsel-projectile.elは, projectile.el
に ivy
インターフェイスを提供するパッケージです. projectile-find-file
は counsel-git
に近い気もします.下記の my-counsel-fzf-in-default-dir
は, counsel-recentf
に紐付けたアクションと同じです.
;; 以下の関数は,counsel-projectile-* と counsel-recentf にぶら下げる. (defun my-counsel-fzf-in-default-dir (_arg) "Search the current directory with fzf." (counsel-fzf ivy-text default-directory)) (with-eval-after-load "projectile" (when (require 'counsel-projectile nil t) ;; M-o z で fzf を呼び出せる. ;; https://twitter.com/takaxp/status/1134481340458360832 ;; あれ,これなんで動いてるの?関数に add-to-list できるの? ;; 以下の2つの関数は,動的に生成される defcustom で規定される.すごい. (add-to-list 'counsel-projectile-switch-project-action '("z" my-counsel-fzf-in-default-dir "switch to fzf") t) (add-to-list 'counsel-projectile-find-file-action '("z" my-counsel-fzf-in-default-dir "switch to fzf") t) (setq projectile-completion-system 'ivy) (setq counsel-projectile-sort-files t) ;; 当該プロジェクト内リストをソート (setq counsel-projectile-sort-projects t) ;; プロジェクトリストをソート (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map) (counsel-projectile-mode 1)))
5.8. counsel-gtags.el
安全安心の @syohex製 https://github.com/syohex/emacs-counsel-gtags
(when (require 'counsel-gtags nil t) (setq counsel-gtags-update-interval-second 10) (dolist (hook '(c-mode-hook c++-mode-hook)) (add-hook hook 'counsel-gtags-mode)))
5.9. flyspell-correct-ivy.el
flyspell-correct.el は, flyspell
の ivy
インターフェイスです.私は使用頻度が高いので,このパッケージが使えるのは必須要件です.当初,新しい単語を追加する save
を helm のように,選択リストに含める方法を選択しましたが, ivy
を使い込んでいくうちに, M-o
で追加メニューを表示する ivy
のお作法になれる方が生産的と気づきました.
(when (require 'flyspell-correct-ivy nil t) (setq flyspell-correct-interface '#'flyspell-correct-ivy) (global-set-key (kbd "<f7>") 'flyspell-correct-word-generic))
5.10. ivy-pass.el
特に設定はしていませんが,基本的にバグっている気がします.私の環境だけかもしれません…
5.11. org-recent-headings.el
最近使用した org mode
の見出しを 高精度に 記録してくれる org-recent-headings.el の ivy
インターフェイスです.とても便利でオススメなのです. が,残念ながら,org の HEAD では壊れて使えないため,少し前の version で使ってください.動作確認ができたら,記事を後日更新します.
org-recent-headings.el
の依存関係の修正が適用されたこともあり,無事に動くようになりました.org mode (v9.2.5)とのペアで正しく動作することを確認しています.(updated: 2019-08-06)
なお,現状では履歴の cleanup 機能が無いので, org-recent-headings-save-file
は端末間で共有しない方がよいと思います.
;; for Ivy interface (global-set-key (kbd "C-c f r") 'org-recent-headings-ivy) (with-eval-after-load "org-recent-headings" ;; デフォルトでは `ivy-string<' が使われてしまい,使用履歴が反映されない. ;; つまり, recent-headings.dat に記録された順が反映されない. (setf (alist-get 'org-recent-headings-ivy ivy-sort-functions-alist) nil) ;; 履歴の保存先を調整 (setq org-recent-headings-save-file "~/.emacs.d/org-recent-headings.dat") ;; 選択した箇所に直接移動する (C-M-n/C-M-p のプレビューは効かない) (setq org-recent-headings-show-entry-function 'org-recent-headings--show-entry-direct) ;; 履歴の更新をキックするコマンドの指定 (setq org-recent-headings-advise-functions '(org-agenda-goto org-agenda-show org-agenda-show-mouse org-show-entry org-reveal org-refile org-tree-to-indirect-buffer org-bookmark-jump)) ;; アクティベート (org-recent-headings-mode))
6. prescient.el
ivy-prescient.el を導入すると,各 ivy
インターフェイスの使用履歴が記録され,最近選択した項目を上位に出してくれるようになります.ただし,すべてのコマンドが影響下に入るわけではなく, ivy-read
に正しく :caller
が設定されている場合に限られます.また, :sort nil
または :sort
設定が存在しない ivy-read
の場合は, ivy-prescient-sort-commands
に対象コマンドを追加することで, ivy-prescient.el
の影響下に置くことができます.
もう一つの機能として,イニシャル入力が可能になります.例えば counsel-M-x
で M-x fap
と入力すると, find-file-at-point
が最上位で表示されます. counsel-recentf
などでは,サブディレクトリの先頭の頭文字を入力すると,当該の情報が上位にきます.慣れれば極めて高速に絞り込みできるようになります.ただ,すべてのコマンドについてイニシャル入力を有効にすると,現状では face
を思うように制御できないので, ivy-re-builders-alist
を設定して,イニシャル入力を有効化するコマンドを限定することをオススメします.
イニシャル入力の設定周りがややこしいと感じる場合は,下記設定の2箇所の ivy-re-builders-alist
に関わる設定を使わず,代わりに (setq ivy-prescient-enable-filtering nil)
を設定すればうまく行きます.このように設定しても,使用履歴の保存には影響がありません.
なお, prescient.el
の内部アルゴリズムは ivy
以外にも company-mode
でも使えるようです.
(when (require 'prescient nil t) ;; ivy インターフェイスでコマンドを実行するたびに,キャッシュをファイル保存 (setq prescient-aggressive-file-save t) ;; ファイルの保存先 (setq prescient-save-file (expand-file-name "~/.emacs.d/prescient-save.el")) ;; アクティベート (prescient-persist-mode 1)) (when (require 'ivy-prescient nil t) ;; =ivy= の face 情報を引き継ぐ(ただし,完全ではない印象) (setq ivy-prescient-retain-classic-highlighting t) ;; コマンドを追加 (dolist (command '(counsel-world-clock ;; Merged! counsel-app)) ;; add :caller (add-to-list 'ivy-prescient-sort-commands command)) ;; フィルタの影響範囲を限定する.以下の3つは順番が重要. ;; (1) マイナーモードの有効化 (ivy-prescient-mode 1) ;; (2) =counsel-M-x= をイニシャル入力対応にする (setf (alist-get 'counsel-M-x ivy-re-builders-alist) #'ivy-prescient-re-builder) ;; (3) デフォルトのイニシャル入力を上書きする (setf (alist-get t ivy-re-builders-alist) #'ivy--regex-ignore-order))
7. 視覚化
ivy
の良いところは,アイコンを導入して視覚的な見やすさを簡単に向上できるところです.プロンプト,候補リストにアイコンを導入すると,選択対象がどのカテゴリのファイルなのかをファイル名や拡張子ではなく,アイコンで視覚的に把握できるようになります.
7.1. プロンプトを改良
プロンプトは,選択候補の数とコマンド名の組み合わせで構成されます. ivy-count-format
をカスタマイズすれば,現在のカーソル位置が,候補リストの何番目に位置するかも表示できます.
(setq ivy-count-format "(%d/%d) ")
さらに,以下のようなハックを施すと,プロンプトの前に任意の情報を書き込む事ができます.例えば,プロンプトの上部に一行空行を入れて,さらに,プロンプトの直前にアイコンを入れることも可能です.モードラインを使わない派にオススメの設定です.
ただハックの方法としては ivy--insert-prompt
を advice で override する必要があるので,落ち着いたら公式にPR出そうと考えています.
無事にマージされました. ivy-pre-prompt-function
に任意の関数を設定するだけになりました.(update: 2019-08-08)
↑適用前
↑適用後
(with-eval-after-load "ivy" (defun my-pre-prompt-function () (if window-system (format "%s\n%s " (make-string (frame-width) ?\x5F) ;; "__" (all-the-icons-faicon "sort-amount-asc")) ;; "" (format "%s\n" (make-string (1- (frame-width)) ?\x2D)))) (setq ivy-pre-prompt-function #'my-pre-prompt-function))
7.2. 現在の選択候補をわかりやすくする
ivy-format-functions-alist
にカスタマイズした関数を追加すれば,プロンプトの下部に位置するカーソル行の表示を変更できます. all-the-icons
を導入して,好みのアイコンでカーソル行のある選択候補を目立たせましょう.
↑適用前(ivy-format-function-arrow利用)
↑適用後(my-ivy-format-function-arrow利用)
(defface my-ivy-arrow-visible '((((class color) (background light)) :foreground "orange") (((class color) (background dark)) :foreground "#EE6363")) "Face used by Ivy for highlighting the arrow.") (defface my-ivy-arrow-invisible '((((class color) (background light)) :foreground "#FFFFFF") (((class color) (background dark)) :foreground "#31343F")) "Face used by Ivy for highlighting the invisible arrow.") (if window-system (when (require 'all-the-icons nil t) (defun my-ivy-format-function-arrow (cands) "Transform CANDS into a string for minibuffer." (ivy--format-function-generic (lambda (str) (concat (all-the-icons-faicon "hand-o-right" :v-adjust -0.2 :face 'my-ivy-arrow-visible) " " (ivy--add-face str 'ivy-current-match))) (lambda (str) (concat (all-the-icons-faicon "hand-o-right" :face 'my-ivy-arrow-invisible) " " str)) cands "\n")) (setq ivy-format-functions-alist '((t . my-ivy-format-function-arrow)))) (setq ivy-format-functions-alist '((t . ivy-format-function-arrow))))
7.3. all-the-icons-ivy.el
all-the-icons-ivy.elは, ivy
インターフェイスにアイコンを追加するパッケージです. all-the-icons.el
が少々導入の難しいパッケージなのですが,一度設定がうまくいけば,殺伐とした Emacs バッファに安らぎがもたらされます.
↑neotree, dired, ivy のすべてで all-the-icons を使う場合の表示例
いくつかのコマンドは,すでにアイコンを出すように設定されています.アイコンが表示されないコマンドを見つけたら, all-the-icons-ivy-buffer-commands
と all-the-icons-ivy-file-commands
にコマンドを追加すれば,アイコンが表示されるようになります.
(when (require 'all-the-icons-ivy nil t) (dolist (command '(counsel-projectile-switch-project counsel-ibuffer)) (add-to-list 'all-the-icons-ivy-buffer-commands command)) (all-the-icons-ivy-setup))
all-the-icons
を導入した結果,候補リストの行頭が揃わない場合には,次の設定が効果を発揮するかもしれません.このあたりは難しく,まだ制御しきれていません.
(with-eval-after-load "all-the-icons-ivy" (defvar my-tab-width tab-width) (defun my-tab-width-2 () (setq tab-width 2)) (defun my-tab-width-1 () (setq tab-width 1)) (defun my-tab-width-8 () (setq tab-width 8)) (defun my-tab-width-original () (setq tab-width my-tab-width)) (add-hook 'minibuffer-setup-hook #'my-tab-width-2) (add-hook 'minibuffer-exit-hook #'my-tab-width-original))
なお,試した感じでは, all-the-icons-ivy
と ivy-rich
を併用するのは厳しそうです.
Note: 2020-02-17
@ballforest さんからコメントいただきました.両者を併用できる拡張がリリースされたそうです.Thanks!
7.4. ivy-rich.el
ミニバッファに候補リストを表示する ivy
は,大きな画面で横方向に複数のウィンドウを表示する状況で,画面上に無駄なスペースが多く生じます.ivy-rich.elを導入すると,アイコンが追加され,さらに追加の情報が空きスペースに記述されるようになります.Emacsモダン化計画 -かわEmacs編- (by @Ladicle) が詳しいです.
ただし,私のように普段は80桁縛りで Emacs を使う人には相性が悪いかもしれません.
↑見切れてしまう…
(when (require 'ivy-rich nil t) (ivy-rich-mode 1))
7.5. ivy-posframe.el
ivy-posframe
を使うと,通常はミニバッファに表示されるリストを任意の位置に出すことができます.私自身,まだ使いこなせていないので今後の課題です.以下は, counsel-M-x
でコマンドリストを表示するときだけカーソル位置にフレームを出す設定です.なお,当初 ivy-posframe
はマイナーモード化されておらず不便でしたが,@conao3 氏の尽力により,現在は (ivy-posframe-mode 1)
, (ivy-posframe-mode -1)
で ON/OFFできます.Thanks!
↑未調整なため,かなり変
(with-eval-after-load "ivy-posframe" (setq ivy-posframe-display-functions-alist '((counsel-M-x . ivy-posframe-display-at-point) (t . ivy-posframe-display))) (ivy-posframe-mode 1))
8. 分析
8.1. 読み込みコスト
ivy.el
と helm.el
の読み込み時間の計測を比較しました.それぞれ依存関係のパッケージの読み込みを含みます.計測は私の貧弱環境です.3回平均の単位は[ms]です.
思った以上に ivy.el
の読み込みに時間を要しています. ivy.el
自体は約140[ms] ですが,さらに ffap.el
の読み込みで約120[ms]程度消費します.
1 | 2 | 3 | Ave. | |
---|---|---|---|---|
helm.el | 201 | 207 | 175 | 194 |
ivy.el | 430 | 412 | 403 | 415 |
counsel.el | 101 | 102 | 121 | 108 |
ivy+counsel | 531 | 514 | 524 | 523 |
8.2. パッケージサイズ
ivy
と helm
でMELPA経由でインストールする場合のパッケージサイズを比較します.バイトコンパイル済みです.単位は[MB]です.
結果, ivy
(1.36[MB]) と helm
(3.27[MB]) で ivy
が軽量のようです.ただし, ivy
は,いくつかのコマンドが init.el 側に記述されています.フラグメントなのでサイズ増加のインパクトは小さいです.
helm | size |
---|---|
flyspell-correct-helm-20181205.1932/ | 0.016 |
helm-20190726.943/ | 1.9 |
helm-ag-20170209.1545/ | 0.1 |
helm-bm-20160321.1331/ | 0.024 |
helm-core-20190726.1001/ | 0.766 |
helm-descbinds-20190501.935/ | 0.032 |
helm-dired-history-20170524.1046/ | 0.020 |
helm-flycheck-20160710.829/ | 0.024 |
helm-gtags-20170116.529/ | 0.116 |
helm-pass-20190315.1335/ | 0.020 |
helm-projectile-20190721.842/ | 0.112 |
helm-swoop-20180215.1154/ | 0.136 |
SUM | 3.27 |
ivy | size |
---|---|
flyspell-correct-ivy-20181205.1932 | 0.016 |
all-the-icons-ivy-20190508.1803/ | 0.024 |
ivy-20190726.2134/ | 0.492 |
ivy-dired-history-20170626.556/ | 0.028 |
ivy-pass-20170812.1955/ | 0.016 |
ivy-rich-20190707.107/ | 0.052 |
counsel-20190726.1745/ | 0.440 |
counsel-projectile-20190724.1903/ | 0.144 |
counsel-world-clock-20190709.2211/ | 0.036 |
swiper-20190726.1746/ | 0.116 |
SUM | 1.36 |
8.3. helm と共存の可能性
いくつかのコマンドを試しましたが,基本的に共存できる印象です.ただ同一のインターフェイスを使う方が効率が上がると思いますので,どうしても移行困難なコマンドに限定して併用するのが良さそうです.例えば, org-trello
が helm
に依存しているので,私はしばらく helm
環境を残すことになりそうです.
なお, (updated: 2019-08-06)org-recent-headings
をインストールしていると共存が厳しくなります.これはバイトコンパイルせずに使うことで回避できます.
8.4. counsel.el にプリセットされている ivy-read 一覧
実装されているコマンド一覧です. autoload
指定された関数は85個ありますが,エイリアスだったりするので,有効なのは82個です.意外なコマンドがすでに実装されているかもしれないので,一度,ざっと目を通してみてはいかがでしょう.
(除外した関数)
- counsel–org-get-tags
- counsel-outline (counsel-org-goto)
- counsel-mode (minor-mode)
Command | DOC STRING |
---|---|
counsel-el | Elisp completion at point. |
counsel-cl | Common Lisp completion at point. |
counsel-jedi | Python completion at point. |
counsel-clj | Clojure completion at point. |
counsel-company | Complete using `company-candidates'. |
counsel-irony | Inline C/C++ completion using Irony. |
counsel-describe-variable | Forward to `describe-variable'. |
counsel-describe-function | Forward to `describe-function'. |
counsel-set-variable | Set a variable SYM, with completion. |
counsel-apropos | Show all matching symbols. |
counsel-info-lookup-symbol | Forward SYMBOL to `info-lookup-symbol' |
counsel-M-x | Ivy version of `execute-extended-command'. |
counsel-command-history | Show the history of commands. |
counsel-load-library | Load a selected the Emacs Lisp library. |
counsel-find-library | Visit a selected the Emacs Lisp library. |
counsel-load-theme | Forward to `load-theme'. |
counsel-descbinds | Show a list of all defined keys and their definitions. |
counsel-describe-face | Completion for `describe-face'. |
counsel-faces | Complete faces with preview. |
counsel-git | Find file in the current Git repository. |
counsel-git-grep | Grep for a string in the current Git repository. |
counsel-git-stash | Search through all available git stashes. |
counsel-git-change-worktree | Find the file corresponding to the current buffer |
counsel-git-checkout | Call the \"git checkout\" command. |
counsel-git-log | Call the \"git log –grep\" shell command. |
counsel-find-file | Forward to `find-file'. |
counsel-dired | Forward to `dired'. |
counsel-recentf | Find a file on `recentf-list'. |
counsel-bookmark | Forward to `bookmark-jump' |
counsel-bookmarked-directory | Ivy interface for bookmarked directories. |
counsel-file-register | Search file in register. |
counsel-locate-action-extern | Pass X to `xdg-open' |
counsel-locate | Call the \"locate\" shell command. |
counsel-fzf | Open a file using the fzf shell command. |
counsel-dpkg | Call the \"dpkg\" shell command. |
counsel-rpm | Call the \"rpm\" shell command. |
counsel-file-jump | Jump to a file below the current directory. |
counsel-dired-jump | Jump to a directory (see `dired-jump') |
counsel-ag | Grep for a string in the current directory using ag. |
counsel-pt | Grep for a string in the current directory using pt. |
counsel-ack | Grep for a string in the current directory using ack. |
counsel-rg | Grep for a string in the current directory using rg. |
counsel-grep | Grep for a string in the file visited by the current buffer |
counsel-grep-backward | Grep for a string similar to `swiper-backward' |
counsel-grep-or-swiper | Call `swiper' for small buffers and `counsel-grep' |
counsel-grep-or-swiper-backward | Call `swiper-backward' and `counsel-grep-backward' |
counsel-recoll | Search for a string in the recoll database. |
counsel-org-tag | Add or remove tags in `org-mode'. |
counsel-org-tag-agenda | Set tags for the current agenda item. |
counsel-org-goto | "Jump to an outline heading with completion." |
counsel-org-goto-all | Go to a different location in any org file. |
counsel-org-file | Browse all attachments for current Org file. |
counsel-org-entity | Complete Org entities using Ivy. |
counsel-org-capture | Capture something. |
counsel-org-agenda-headlines | Choose from headers of `org-mode' files in the agenda. |
counsel-mark-ring | Browse `mark-ring' interactively. |
counsel-package | Install or delete packages. |
counsel-tmm | Text-mode emulation of looking and choosing from a menubar. |
counsel-yank-pop | Ivy replacement for `yank-pop'. |
counsel-register | Interactively choose a register. |
counsel-evil-registers | Ivy replacement for `evil-show-registers'. |
counsel-imenu | Jump to a buffer position indexed by imenu. |
counsel-list-processes | Offer completion for `process-list'. |
counsel-minibuffer-history | "Browse minibuffer history." |
counsel-esh-history | "Browse Eshell history." |
counsel-shell-history | "Browse shell history." |
counsel-hydra-heads | Call a head of the current/last hydra. |
counsel-semantic | "Jump to a semantic tag in the current buffer." |
counsel-semantic-or-imenu | |
counsel-ibuffer | Use ibuffer to switch to another buffer. |
counsel-switch-to-shell-buffer | Switch to a shell buffer, or create one. |
counsel-unicode-char | Insert COUNT copies of a Unicode character at point. |
counsel-colors-emacs | "Show a list of all supported colors for a particular frame. |
counsel-colors-web | Show a list of all W3C web colors for use in CSS. |
counsel-rhythmbox | Choose a song from the Rhythmbox library to play or enqueue. |
counsel-linux-app | "Launch a Linux desktop application, similar to Alt-<F2>. |
counsel-wmctrl | "Select a desktop window using wmctrl." |
counsel-switch-buffer | Switch to another buffer. |
counsel-switch-buffer-other-window | Switch to another buffer in another window. |
counsel-compile | Call `compile' completing with smart suggestions |
counsel-compile-env | Update `counsel-compile-env' interactively. |
counsel-minor | Enable or disable minor mode. |
9. まとめ
この記事では(長々と) helm
から ivy
に移行した時に得られた知見と設定について解説しました.幸いながら,私の helm
の利用レベルはそれほど高くなく,移行しても全く後悔はないですが, helm
への依存度がより高い人の場合は,色々と気に入らない点があるかもしれません.また, org-trello.el
等, helm
依存で ivy
が使えないパッケージもまだあるので,移行に慎重な人は,依存しているパッケージの ivy
インターフェイスが存在するかを一度確認してみることをオススメします.それ以外の人は,もう「えいや!」で移行しても後悔しないと思います.
いかがでしたか?()
最後に,今後試してみたいパッケージの一覧です.
10. 謝辞
- 数ヶ月に渡り,私の
helm2ivy
を Twitter 上で見守ってくださった心優しい Emacs ユーザの方々に感謝いたします.励ましの声が無ければ,この記事は生まれませんでした. - この記事を執筆するためのすべての機能を提供してくれた Emacs と Org mode,そして,Qiita exporter である ox-qmd に心から感謝致します.こんな便利なツールは外にありません.Vim ユーザはすぐに Emacs に乗り換えてください.或いは,vim-orgmodeを導入しましょう.
11. References
- Ivy User Manual
- さよならhelm、ようこそivy/counsel - Speaker Deck
- Introducing ivy-mode · (or emacs
- Ivy, Counsel and Swiper
- Switching to ivy from helm
- Emacsモダン化計画 -かわEmacs編- - Qiita
- swiper/Changelog.org at 596461e1ff09431eb417877a9870e53c452e1b62 · abo-abo/swiper
- It is impossible (or unclear, how exactly) to use the swiper from within itself. · Issue #309 · abo-abo/swiper
- `ivy-alt-done` wipes out buffer when called via M-x from nested minibuffer · Issue #924 · abo-abo/swiper
- Helm vs Ivy: What are the differences, what are the advantages? : emacs
- Helm or ivy? : emacs
- Dynamic sorting with ivy