Vimを使う - 曖昧入力でファイルを開く「fzf」

【連載】

にわか管理者のためのLinux運用入門

【第237回】Vimを使う - 曖昧入力でファイルを開く「fzf」

[2020/07/07 08:00]後藤大地 ブックマーク ブックマーク

本連載ではまだ取り上げていないが、Linuxのアドバンスドユーザーが好むツールの一つに「fzf」がある。fzfはファイルやディレクトリなどの曖昧選択を可能にするツールで、パスの一部を入力するだけでパスの選択を可能にしてくれる。絞り込みできるのはパスだけでなく、履歴やさまざまなデータが対象となっており、とにかく最大限に手を抜き、かつ、クールに仕事をするのに欠かせないツールだ。

fzfそのものについてはいずれ取り上げるとして、今回はこのツールをVimから使う方法を紹介しよう。本連載では、これまでファイルを開く方法として「Denite」と「NERDTree」を取り上げた。どちらも比較的ビジュアル化されたツールで、Visual Studio CodeのようなUI/UXでファイル選択が可能だった。タイピングやVimに慣れていないユーザーには扱いやすいプラグインではないかと思う。

一方、キー入力だけでもっと高速にファイル選択ができるやり方を好むユーザーも多い。結局、慣れてくると便利なUIは逆に操作が遅くなる原因にもなる。動作がわかっているなら、fzfのようなツールを使ったほうが高速な作業が可能だ。もしこれまでfzfを使ったことがなければ、ぜひ今回のプラグインで体験していただきたい。

fzfのインストールと設定

まず前回までに作成してきた設定ファイル~/.vimrcを確認しよう。次のようになっているはずだ。

"dein Scripts=============================
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=~/.cache/dein/./repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('~/.cache/dein/.')
  call dein#begin('~/.cache/dein/.')

  " Let dein manage dein
  " Required:
  call dein#add('~/.cache/dein/./repos/github.com/Shougo/dein.vim')

  " Add or remove your plugins here
  call dein#add('junegunn/seoul256.vim')
  call dein#add('vim-airline/vim-airline')
  call dein#add('vim-airline/vim-airline-themes')
  call dein#add('preservim/nerdtree')
  call dein#add('tpope/vim-commentary')
  call dein#add('tpope/vim-fugitive')
  call dein#add('fholgado/minibufexpl.vim')
  call dein#add('dense-analysis/ale')

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
if dein#check_install()
  call dein#install()
endif

" seoul256
let g:seoul256_background = 233
colo seoul256

" vim-airline
let g:airline_powerline_fonts = 1
let g:airline_theme = 'molokai'

" NERDTree
"  <C-o> open NERDTree
nnoremap <silent> <C-o> :NERDTreeToggle<CR>

" minibufexpl
nnoremap <silent> bn :<C-u>:bnext<CR>
nnoremap <silent> b1 :<C-u>:b1<CR>
nnoremap <silent> b2 :<C-u>:b2<CR>
nnoremap <silent> b3 :<C-u>:b3<CR>
nnoremap <silent> b4 :<C-u>:b4<CR>
nnoremap <silent> b5 :<C-u>:b5<CR>
nnoremap <silent> b6 :<C-u>:b6<CR>
nnoremap <silent> b7 :<C-u>:b7<CR>
nnoremap <silent> b8 :<C-u>:b8<CR>
nnoremap <silent> b9 :<C-u>:b9<CR>

"End dein Scripts=========================

set number
syntax on
set whichwrap=b,s,[,],<,>,~,h,l
set cursorline
set incsearch
set hlsearch
set ignorecase

まずfzfのプラグインを読み込ませるために、「call dein#add(‘dense-analysis/ale’)」という記述の部分を次のように変更する。

  call dein#add('dense-analysis/ale')
  call dein#add('junegunn/fzf', {'build': './install --all'})
  call dein#add('junegunn/fzf.vim')

ここでちょっと説明が必要だ。fzfのプラグイン自体は「junegunn/fzf.vim」で、「junegunn/fzf」はfzfのコマンドそのもののリポジトリを指定している。fzf.vimは実際にfzfコマンドを実行して動作するためだ。上記の設定ではfzfをクローンしてビルドを行い、fzfコマンドを生成している。パッケージ管理システムを使ってfzfをインストールしてもよいのだが、設定の関係で上記のようにしておいたほうが簡単にセットアップが完了する。

次にfzfを使用するためのショートカットを追加する。設定ファイルで次の部分を見つけてほしい。

" minibufexpl
nnoremap <silent> bn :<C-u>:bnext<CR>
nnoremap <silent> b1 :<C-u>:b1<CR>
nnoremap <silent> b2 :<C-u>:b2<CR>
nnoremap <silent> b3 :<C-u>:b3<CR>
nnoremap <silent> b4 :<C-u>:b4<CR>
nnoremap <silent> b5 :<C-u>:b5<CR>
nnoremap <silent> b6 :<C-u>:b6<CR>
nnoremap <silent> b7 :<C-u>:b7<CR>
nnoremap <silent> b8 :<C-u>:b8<CR>
nnoremap <silent> b9 :<C-u>:b9<CR>

これを次のように変更する。

" minibufexpl
nnoremap <silent> bn :<C-u>:bnext<CR>
nnoremap <silent> b1 :<C-u>:b1<CR>
nnoremap <silent> b2 :<C-u>:b2<CR>
nnoremap <silent> b3 :<C-u>:b3<CR>
nnoremap <silent> b4 :<C-u>:b4<CR>
nnoremap <silent> b5 :<C-u>:b5<CR>
nnoremap <silent> b6 :<C-u>:b6<CR>
nnoremap <silent> b7 :<C-u>:b7<CR>
nnoremap <silent> b8 :<C-u>:b8<CR>
nnoremap <silent> b9 :<C-u>:b9<CR>

" fzf
nnoremap <silent> fzf :Files<CR>
nnoremap <silent> ls :Buffers<CR>

これで次のような操作が可能になる。

ショートカットキー 内容
fzf ファイルやディレクトリ一覧から選択
ls バッファ一覧から選択

fzf.vimでは主な機能として以下を提供している。上記の設定は、これらのうち「:Files」と「:Buffers」を呼び出すものだ。

コマンド 内容
:Files [PATH] ファイルやディレクトリ一覧から選択
:GFiles [OPTS] git ls-filesコマンド実行結果から選択
:GFiles? git statusコマンド実行結果から選択
:Buffers バッファ一覧から選択
:Colors カラースキーマ一覧から選択
:Ag [PATTERN] ar実行結果から選択
:Rg [PATTERN] rg実行結果から選択
:Windows ウィンドウ一覧から選択
:Locate PATTERN locateコマンド実行結果から選択
:History これまでに編集したファイルやバッファ一覧から選択
:History: コマンド履歴から選択
:History/ 検索履歴から選択

fzfを使うとファイルやディレクトリの選択のみならず、バッファやコマンド履歴などさまざまなものから選択を行うことができる。以前、「minibufexpl」を使ってバッファ一覧をタブのように表示する機能や、デフォルトの機能を使ってバッファ間を行き来する方法を説明したが、fzfの:Buffersを使えばバッファの一覧表示もそこからの選択もどちらもできる。慣れてきたらfzfのほうが素早く操作できるかもしれないので、ぜひ試してみていただきたい。

fzfプラグインの使用サンプル

実際にサンプルの使用例を見てみよう。ファイル編集中にノーマルモードで「fzf」と入力すると、下半分にfzf用のウィンドウが開いて、下部にキーワード入力用のプロンプトが表示されるようになる。右側に表示されているのは現在選択されているファイルの中身だ。

「:Files」を実行したところ

プロンプトに適当に文字を入力していくと、その文字をベースに曖昧検索が行われていき、表示される対象が絞り込まれていく。

キーワードに応じて絞り込みが進んでいく

最後まで文字を入力して絞り込むこともできるし、途中でカーソルキーの「↑」「↓」を使って表示されているリストからファイルを選択することもできる。

「↑」「↓」でリストから直接選択することもできる

次のスクリーンショットは「ls」でバッファ一覧を表示させたところだ。曖昧検索でさらに絞り込むこともできるし、一覧から選択してバッファを開くこともできる。

「:Buffers」を実行したところ

fzfを使いこなすことができるとファイル選択のストレスをかなり減らすことができる。ただし、fzfはかなり好みがはっきり分かれる機能だということも言っておきたい。肌に合わない人は、この手の曖昧な操作はまるで受け付けないのではないかと思う。

しかし、無駄な入力を省いて目的のファイルに到達する方法として、fzfはこの上ないことは間違いない。使ったことがないのであればぜひ一度体験してみていただきたい。

今回の成果物

今回のプラグイン設定を追加した設定ファイルは以下の通りだ。

"dein Scripts=============================
if &compatible
  set nocompatible               " Be iMproved
endif

" Required:
set runtimepath+=~/.cache/dein/./repos/github.com/Shougo/dein.vim

" Required:
if dein#load_state('~/.cache/dein/.')
  call dein#begin('~/.cache/dein/.')

  " Let dein manage dein
  " Required:
  call dein#add('~/.cache/dein/./repos/github.com/Shougo/dein.vim')

  " Add or remove your plugins here
  call dein#add('junegunn/seoul256.vim')
  call dein#add('vim-airline/vim-airline')
  call dein#add('vim-airline/vim-airline-themes')
  call dein#add('preservim/nerdtree')
  call dein#add('tpope/vim-commentary')
  call dein#add('tpope/vim-fugitive')
  call dein#add('fholgado/minibufexpl.vim')
  call dein#add('dense-analysis/ale')
  call dein#add('junegunn/fzf', {'build': './install --all'})
  call dein#add('junegunn/fzf.vim')

  " Required:
  call dein#end()
  call dein#save_state()
endif

" Required:
filetype plugin indent on
syntax enable

" If you want to install not installed plugins on startup.
if dein#check_install()
  call dein#install()
endif

" seoul256
let g:seoul256_background = 233
colo seoul256

" vim-airline
let g:airline_powerline_fonts = 1
let g:airline_theme = 'molokai'

" NERDTree
"  <C-o> open NERDTree
nnoremap <silent> <C-o> :NERDTreeToggle<CR>

" minibufexpl
nnoremap <silent> bn :<C-u>:bnext<CR>
nnoremap <silent> b1 :<C-u>:b1<CR>
nnoremap <silent> b2 :<C-u>:b2<CR>
nnoremap <silent> b3 :<C-u>:b3<CR>
nnoremap <silent> b4 :<C-u>:b4<CR>
nnoremap <silent> b5 :<C-u>:b5<CR>
nnoremap <silent> b6 :<C-u>:b6<CR>
nnoremap <silent> b7 :<C-u>:b7<CR>
nnoremap <silent> b8 :<C-u>:b8<CR>
nnoremap <silent> b9 :<C-u>:b9<CR>

" fzf
nnoremap <silent> fzf :Files<CR>
nnoremap <silent> ls :Buffers<CR>

"End dein Scripts=========================

set number
syntax on
set whichwrap=b,s,[,],<,>,~,h,l
set cursorline
set incsearch
set hlsearch
set ignorecase

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で IT Search+ の人気記事をお届けします
注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
[解説動画] 個人の業務効率化術 - 短時間集中はこうして作る
ミッションステートメント
教えてカナコさん! これならわかるAI入門
AWSではじめる機械学習 ~サービスを知り、実装を学ぶ~
対話システムをつくろう! Python超入門
Kubernetes入門
SAFeでつくる「DXに強い組織」~企業の課題を解決する13のアプローチ~
PowerShell Core入門
AWSで作るマイクロサービス
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

会員登録(無料)

ページの先頭に戻る