本記事は Vim Advent Calendar 2019 - Qiita の 17 日目の記事です。
この記事では vifm についてご紹介します。
vifm とは
vifm とは ncurses ベースで vi[m] ライクな、ターミナル内で操作できるファイラ(ファイルマネージャ)の一つです。おそらく vi[m] (like) file manager の略で vifm なのだと思います。
ncurses は TUI (Text User Interface) を構築する際によく用いられるライブラリで、以前こちらで紹介した Tig など、多くのソフトウェアで使われています。
自分とファイラ
少しだけ自分の話をすると、昔から 2 画面ファイラと呼ばれるものを長年愛用していました。2 画面ファイラとは左右にファイル一覧が表示されるファイルマネージャで、コピーや移動などの操作を左のペインから右のペインに (あるいは右のペインから左のペインに) 向けて実行でき、高速なファイル操作が行えるのが特徴です。
以前 Windows 機をメインにしていた際は 2画面ファイラーKF や だいなファイラー などを愛用していました。
作業環境を Mac に変更してからは、Java で開発されている muCommander を使用していました。その後メンテナンスが滞ったタイミングで、 GPL の muCommander のコードを fork して開発を継続している trolsoft の trolCommander を使用していました。
trolCommander は概ね満足いくファイラでしたが 、GUI ソフトウェアなので自分の様に git 操作に Tig を使っていたり、普段からターミナルで作業することが多い人間は少し手間に感じていました。そのため、ターミナル内で実行できる 2 画面ファイラで、かつ操作性や拡張性がよいものを長年探していました。
そして数年前に vifm を使い始めてから、 trolCommander と同等以上に自分のニーズを満たしてくれることを確認できたので移行しました。今では手放せない存在になっています。
以下では、 vifm の初期設定での操作方法と、便利な設定について説明していきます。
ちなみに vim でのファイラは色々と有名なプラグインがあります(※)が、vifm 本体は vim を起動せずにスタンドアロンで起動します。それとは別に、プラグインで vim から呼び出す方法もあります (後述) 。起動は非常に速く、一瞬で立ち上がります。
※ 参考:mattn さんのファイラ記事
vifm のインストール方法
公式ページ (Vifm - Downloads) にバイナリがあります。また各種OSやディストリビューション向けにパッケージも用意されています。
Mac ユーザであれば
$ brew install vifm
で簡単にインストールできます。
基本的な操作方法
ここで紹介する内容はすべて公式マニュアルに書かれているので、詳細については本家ドキュメントをご確認ください。便利な Cheetsheet もあります。
終了方法
定番のコマンドですが、 vim と同じ操作で終了できます。
キー | 説明 |
---|---|
:q | vifm を終了する |
ZZ | vifm を終了する |
ZQ | エラーコードで vifm を終了する (後述) |
(※ ただし毎回これを打つのは手間なので、自分は q
に vifm 終了コマンドを割り当てています (後述))
カーソル移動
キー | 説明 |
---|---|
j | カーソルを下に移動 |
k | カーソルを上に移動 |
h | ひとつ上のディレクトリに移動 |
l | カーソル配下がディレクトリならそのディレクトリに移動する。ファイルならファイルをエディタで開く (デフォルトは vim ) |
gg | カーソルを最上段に移動 |
G | カーソルを最下段に移動 |
[SPACE] | 反対側のペインに移動 |
[TAB] | 反対側のペインに移動 |
Ctrl-i | 反対側のペインに移動 |
その他のキーバインドは マニュアルの Basic Movement を参照してください。
ファイル操作
キー | 説明 |
---|---|
e | 現在のペインでファイルを表示する |
yy | ファイルを vifm のクリップボードにコピー (yank) する |
Y | ファイルを vifm のクリップボードにコピー (yank) する |
C | ファイルをクローンする (同じディレクトリに ファイル名(1).拡張子 という名前で複製する) |
p | yank したファイルをコピーする。または dd で削除したファイルをコピーする |
P | yank したファイルを移動する (元の場所からは消える) |
dd | ファイルを vifm の trash ディレクトリに入れる (p で貼り付けられる) |
DD | ファイルを完全に削除する |
cw | ファイルをリネームする |
cW | ファイルをリネームする (拡張子を除く) |
al | yank したファイルの symbolic link を絶対パスで作成する |
rl | yank したファイルの symbolic link を相対パスで作成する |
t | カーソル配下のファイル/ディレクトリを選択状態にする |
trash ディレクトリについてはマニュアルの Trash directory をご参照ください。筆者のデフォルトでは ~/.local/share/Trash
でした。
カスタマイズ
上記のコマンドを覚えておけば最低限のファイル操作はできると思いますが、やはり手に馴染むようにカスタマイズしてこそのファイラなので、カスタマイズの方法をご紹介します。
設定ファイルのロード順についてはマニュアルの Startup に書かれています。最優先は ~/.vifm/vifmrc
ファイルですが、インストール直後にはこのファイルは存在しないので ~/.config/vifm/vifmrc
ファイルが読み込まれていると思います。このファイルは以下のいずれかがインストールされています。
まずはこのディレクトリをコピーしてカスタマイズを始めてみます。
$ cp -a ~/.config/vifm ~/.vifm
表示変更
デフォルトの画面だと情報量が少なすぎるので、だいたい以下のようにしています。それぞれの詳細については マニュアルの :set options をご確認ください。
set timefmt=" %Y/%m/%d %H:%M:%S"
set statusline=" %t [%T]%= %A %10u:%-7g %15s %20d [%a free]"
set viewcolumns=-45%{name}..,-{ext},10{size},12{perms},21{mtime}
set sizefmt=units:iec,precision:3
また、執筆当時最新の ver 0.10.1 を入れてみたところ、カラースキームが微妙になっていたので修正しています。カラースキームはデフォルトでは colorscheme Default
が指定されているため ~/.vifm/colors/Default.vifm
が読まれます(前述の ~/.config/vifm
ディレクトリをコピーしている場合)。
カラースキームは color_scheme.c で動的に作られているようですが、自分の場合 OtherWin
の設定値が目立ちすぎていたのでコメントアウトしています。
" highlight OtherWin cterm=bold,underline,reverse,standout ctermfg=default ctermbg=default
本記事の最初にも貼りましたが、上記を設定した際の筆者の iTerm2 (色調整した Solarized Dark テーマ) での vifm のスクリーンショットはこのような感じです。(右下のカレントパーティションの空き容量 [%a free]
の値はうまくとれていないようですが)
ちなみに vifm-colors というサブプロジェクトにも各種カラースキームが置かれています。
これらのカラースキームごとのサンプルは公式サイトに一覧があります。
エディタ/ビューア変更
l
でファイルをチラ見するときに毎回 vim が開くと閉じるのが手間なので less
に変えています。
set vicmd='less -N'
(-N
は --LINE-NUMBERS
のことで行数表示のオプションです)
また、 h
キーで less
を抜けられるように、 lesskey.conf
を以下のように書いて
h quit
$ lesskey -o ~/.lesskey lesskey.conf
を実行することで less
も h
キーで抜けられるようになります。
コマンド定義
マニュアルの Commands に書かれているコマンドを(ノーマルモードの)キーにバインドする場合は、 vim の .vimrc
と同様に
nnoremap C :copy
の様に書きます(デフォルトの C
キーを上書きしています)。 :copy
は組み込みコマンドで、反対側のペインにコピーを行います。
前述した、 q
で vifm を抜けるようにするには
nnoremap q :quit<cr>
と書きます。(<cr>
はコマンド行で確認せずに Enter します)
外部コマンド呼び出し
組み込みコマンド以外をシェル経由で実行するには、 !
をつけます (%
引数については後述します)
nnoremap Z :!zip -r %D/%c:r.zip %f
また、コマンドを定義しておいて、内部コマンドの様に読み出すこともできます。
command! zip -r %D/%c:r.zip %f
nnoremap Z :zip
そのほか、前述のとおり l
キーによる vicmd
を変更してしまっているので、改めて vim に割り当て直す場合は次のように書きます。
command! vim vim %f
nnoremap E :vim<cr>
コマンド引数
例えば unzip コマンドを U
に割り当てたい場合、
nnoremap U :!unzip %f -d %D
と書くことでコマンド引数を展開することができます。ここで %f
はカーソル配下のファイルパス、 %D
は反対側ペインのディレクトリを指します。このあたりの変数の詳細は マニュアルの Command macros や、設定ファイル ~/.vifm/vifmrc に書かれています。
仮想ディレクトリ
一般にファイラは、 zip などのアーカイブも展開せずに中を開くことができるのが一般的です。vifm で zip ファイルを仮想ディレクトリとして開くには FUSE を利用します。
Mac OS の場合は、Home - FUSE for macOS からダウンロード&インストールするか、 Homebrew Cask が利用可能な場合は以下のコマンドでインストールできます。
$ brew cask install osxfuse
さらに zip ファイルを開くために fuse-zip を入れます。 公式サイト からダウンロード&インストールするか、Mac では Homebrew でインストールできるので、以下のコマンドでインストールしてください。
$ brew install fuse-zip
そして *.zip
やその他の対応ファイルタイプに対して fuse-zip を割り当てます。
filetype *.zip,*.jar,*.war,*.ear FUSE_MOUNT|fuse-zip %SOURCE_FILE %DESTINATION_DIR
と書いてみて気づきましたが、執筆当時最新の vifm v0.10.1 の初期設定ファイル には fuse-zip がある場合は自動で上記設定が有効になるようになってたので、現状では特に設定は不要となっているようです。
その他の FUSE Mount
その他、 sshfs
や curlftpfs
などの FUSE mount の記述が 初期設定 にあります。
sshfs については、
$ brew install sshfs
のようにインストールしたのち、
username@hoge.example.com:/home/username
と .ssh
と拡張子を持つファイルに sshfs
に渡す接続情報を書いておけば、 l
キーでそのファイルを開こうとすると透過的に ssh 先のサーバを手元の vifm で開くことができます。ローカルのコンテナの接続情報を書いていても便利だと思います。
vifm 起動ショートカット
ターミナルでは vifm か tig かエディタを開いて生活しているので、コマンド一つで vifm が開けると便利です。
zsh の場合は ~/.zshrc
に以下の設定を入れておけば Alt-j
で vifm をカレントディレクトリですぐに開けます。
bindkey -s '\ej' '^a vifm . \n'
(history に残さないように、頭に空白を入れています。これを有効にするには setopt hist_ignore_space
を .zshrc
に記載しておいてください)
起動シェルのカレントディレクトリ変更
vifm を抜けた際に、最後のディレクトリを呼び出したシェルのカレントディレクトリとして欲しいケースが多いと思います。
公式マニュアルにその設定 が紹介されています。
以下は ~/.zshrc
の例です。(公式マニュアルには .bashrc
の設定が載っています)
function vicd() {
local dst="$(command vifm $1 $2 --choose-dir -)"
if [ -z "$dst" ]; then
echo 'Directory picking cancelled/failed'
return 1
fi
cd "$dst"
}
これで vicd
コマンドで実行された vifm が正常終了 (:q
or ZZ
) の場合は、 vifm の最後のディレクトリがカレントディレクトリに設定されます。
こちらを普段使うため、上記 Alt-j
コマンドは vicd に書き換えています。
bindkey -s '\ej' '^a vicd . \n'
また、 ZQ
で抜けた場合は起動時のディレクトリのままになります。
ちなみに自分の場合、q
と Q
をそれぞれに割り当て直しています。
nnoremap q :quit<cr>
nnoremap Q :cquit<cr>
その他便利なコマンドのキー割り当て
以下は筆者が設定しているキー割り当ての一部です。これまでに説明していないもののうち、特に設定しておいたほうが便利だと思うものを挙げてみます。(キーバインドはお好みのものに変更してください)
" ディレクトリを作成する
nnoremap K :mkdir<space>
" カレントファイルを関連付けられたデフォルトのアプリケーションで開く。フォルダの場合は Finder で開く (Mac)
nnoremap X :!open %f<cr>
" 反対側のペインをカレントペインと同期する
nnoremap , :sync!<cr>
" スペースキーを「カレントファイルを選択して、カーソルを1つ下に移動」にする
nnoremap <space> t<down>
(上記以外については筆者の vifmrc を参照してください)
その他
AFP (Mac のファイル共有プロトコル) でマウントしたサーバに対して :move
コマンドによるファイルの移動をすると更新日時が保持されないバグ(仕様?)があったので(現バージョンで解消されているかは未確認ですが)リモートサーバを操作する場合は事前に動作検証をしておくとよいと思います。
Vim 連携
ここまではスタンドアロンの vifm について説明してきましたが、 vim から vifm を呼び出すプラグインも存在しています。
Vundle の場合、 call vundle#begin()
~ call vundle#end()
間に以下の指定をして :PluginInstall
でインストールされます。
Plugin 'vifm/vifm.vim'
プラグインのドキュメントによると以下のコマンドが定義されています。(マニュアルの Plugin にも同様の説明があります)
Commands:
*vifm-:EditVifm*
:EditVifm select a file or files to open in the current buffer.
*vifm-:Vifm*
:Vifm alias for :EditVifm.
*vifm-:SplitVifm*
:SplitVifm split buffer and select a file or files to open.
*vifm-:VsplitVifm*
:VsplitVifm vertically split buffer and select a file or files to open.
*vifm-:DiffVifm*
:DiffVifm select a file or files to compare to the current file with
:vert diffsplit.
*vifm-:TabVifm*
:TabVifm select a file or files to open in tabs.
上記設定例で vicmd
変数を less
にして l
キーを less
で開くようにしていましたが、 vim plugin から呼び出すと、 less
ではなく vim で開かれるようになります。
まとめ
本記事では、 Vim ベースのファイルマネージャ vifm をご紹介しました。皆様のターミナル生活の一助になれば幸いです。
最後までお読みいただきありがとうございました。