Vimでファイルを開く方法(基本編)

この記事はVim Advent Calendar 2016の4日目の記事です。

Vimでファイルを開くのに

プラグインを使っている人はたくさんいると思います。
これらのプラグインは大変便利なインターフェースを提供してくれているのですが、 依存しすぎてしまうと標準機能でファイルを開く方法を忘れてしまうかもしれません。

...さすがにそんなVimmerはいないと思いますが、ファイルを開く

をおさらいしてみましょう。

コマンドで開く

以下のコマンド*1の引数としてファイル名を指定します。

コマンド 説明
:e[dit] 現在のバッファでファイルを開く
:sp[lit] 水平分割してファイルを開く
:vs[plit] 垂直分割してファイルを開く
:tabe[dit] 新しいタブページを作成してファイルを開く

このとき、

  • <Tab>(または<CTRL-I>)でファイル名の補完
    • 動作はwildmode(:help wildmode)で変更可能
  • <CTRL-D>で入力にマッチするファイル名の一覧表示

をすることができます。

また、対象のファイル名を探すのに

  • ***などのワイルドカード(:help wildcard)
  • :p:hなどのファイル名修飾子(:help filename-modifiers)

を用いることもできます。

" <CTRL-D>で一覧を表示し、
:e */index<CTRL-D>
public/index.html  src/index.css      src/index.js

" <Tab>を押すと最初の候補が選択される
:e */index<Tab>
:e public/index.html

" もう1度<Tab>を押すと次の候補が選択される
:e public/index.html<Tab>
:e src/index.css
  • /usr/lib/golang/src/配下のreader.goを探す
:e /usr/lib/golang/src/**/reader.go<CTRL-D>
/usr/lib/golang/src/archive/tar/reader.go
/usr/lib/golang/src/archive/zip/reader.go
/usr/lib/golang/src/bytes/reader.go
/usr/lib/golang/src/compress/lzw/reader.go
/usr/lib/golang/src/compress/zlib/reader.go
/usr/lib/golang/src/debug/elf/reader.go
/usr/lib/golang/src/encoding/csv/reader.go
/usr/lib/golang/src/go/doc/reader.go
/usr/lib/golang/src/image/gif/reader.go
/usr/lib/golang/src/image/jpeg/reader.go
/usr/lib/golang/src/image/png/reader.go
/usr/lib/golang/src/mime/quotedprintable/reader.go
/usr/lib/golang/src/net/textproto/reader.go
/usr/lib/golang/src/strings/reader.go
/usr/lib/golang/src/testing/iotest/reader.go
" カレントディレクトリが/rootの状態で
:pwd
/root

" swagger-codegen/samples/server/petstore/go-api-server/main.goを開いている時
:echo expand('%:p')
/root/swagger-codegen/samples/server/petstore/go-api-server/main.go

" 最初の:hで"/main.go"、次の:hで"/go-api-server"が除去される
:e %:h:h/**/pom.xml<CTRL-D>
swagger-codegen/samples/server/petstore/java-inflector/pom.xml
swagger-codegen/samples/server/petstore/java-msf4j/pom.xml
swagger-codegen/samples/server/petstore/jaxrs/jersey1/pom.xml
swagger-codegen/samples/server/petstore/jaxrs/jersey2/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-cxf/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-cxf-cdi/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-resteasy/default/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-resteasy/joda/pom.xml
swagger-codegen/samples/server/petstore/jaxrs-spec/pom.xml
swagger-codegen/samples/server/petstore/scalatra/pom.xml
swagger-codegen/samples/server/petstore/spring-mvc/pom.xml
swagger-codegen/samples/server/petstore/spring-mvc-j8-async/pom.xml
swagger-codegen/samples/server/petstore/springboot/pom.xml
swagger-codegen/samples/server/petstore/undertow/pom.xml

キーマッピングで開く

ファイル名がある場所にカーソルを移動し、以下のキー*2を入力します。

キー 説明
gf 現在のバッファでファイルを開く
CTRL-W f 水平分割してファイルを開く
CTRL-W CTRL-F
CTRL-W gf 新しいタブページを作成してファイルを開く

現在開いているバッファにファイル名があれば良いですが、無い場合は:r!lsfindなどの外部コマンドを用いてファイル一覧を作成してしまいましょう。

" 新しいバッファにカレントディレクトリのファイル一覧を作成
:new | r! ls

なお、:newでバッファを作成した場合、デフォルトではgfでファイルを開く際にエラー(E37)になってしまいます。
その場合、

  • set hidden ... ウィンドウ内に表示されなくなる際にバッファを隠す

    • 全てのバッファが対象
    • Vim終了時に未保存バッファが残っているとエラーになる
  • set bufhidden=hide ... ウィンドウ内に表示されなくなる際にバッファを隠す

    • カレントバッファのみが対象
    • Vim終了時に当該バッファが未保存だとエラーになる
  • set buftype=nofile ... バッファを書き込まれる予定のないバッファにする

    • カレントバッファのみが対象
    • Vim終了時に当該バッファが未保存でもエラーにならない

などの設定でバッファを保存せずに切り替えられるようにしてあげる必要があります。

また、ファイル一覧に大量のファイルが表示されてしまった場合

  • /{pattern}で検索したり、
  • :g/{pattern}/dでフィルタしてあげると

目的のファイルが探しやすくなります。

:new | r! find . -type f
" Windowsの場合
:new | r! dir . /b /s /a-d
  • 現在開いているファイルがあるディレクトリ配下のファイル一覧を作成
" findの引数は実行前に<Tab>で展開しておく
:new | r! find %:p:h<Tab> -type f
" Windowsの場合
:new | r! dir %:p:h<Tab> /b /s /a-d
  • ファイル一覧を作成するユーザコマンドの定義

上記のコマンドを毎回入力するのが面倒な場合、.vimrcに以下のようなコマンドを追加しておくと便利です。

" 新しいscratchバッファ(:help special-buffers 参照)を作成する
command! -bar NewScratch new | setlocal buftype=nofile bufhidden=hide noswapfile

" :NewScratchで作成したバッファにfindコマンドの出力内容を挿入する
" FIX: <args>は""で囲まないとスペースの入ったパスが正しく処理できない(derisさん、ありがとうございます)
command! -nargs=1 -complete=dir Files NewScratch | r! find "<args>" -type f
" Windowsの場合
" FIX: <args>は""で囲まないとスペースの入ったパスが正しく処理できない(derisさん、ありがとうございます)
" command! -nargs=1 -complete=dir Files NewScratch | r! dir "<args>" /b /a-d /s

" %:p:hを引数として:Filesを実行する(<args>には%:p:hが展開された状態で渡される)
command! FilesBuffer Files %:p:h

" .を引数として:Filesを実行する
command! FilesCurrent Files .

まとめ

Vimの標準の機能でファイルを開く方法を紹介しました。

単にファイルを開くだけなら十分ですが、インタラクティブ性や非同期性が必要な場面になると物足りないところがあるかもしれません。
そういった時には組み込み関数と合わせて使ってみたり、プラグインを活用すると良いと思います。

*1:詳細は :help edit-a-file, :help opening-window, :help tab-page-commands 参照

*2:詳細は :help window-tag 参照