Vimが提供しているカーソルの移動機能を使えば、当然CSVファイルでもカーソルを移動させることができる。「chrisbra/csv.vim」は、これに加えてセルの間を移動するためのショートカットを提供している。主なショートカットは次の通りだ。
移動キー | 内容 |
---|---|
「Ctrl」+「→」 | 右の列へ移動 |
L | 右の列へ移動 |
W | 右の列へ移動 |
「Ctrl」+「←」 | 左の列へ移動 |
E | 左の列へ移動 |
H | 左の列へ移動 |
↑ | 列を上へ移動 |
K | 列を上へ移動 |
↓ | 列を下へ移動 |
J | 列を下へ移動 |
右のセルへの移動と、左のセルへの移動、この2つのショートカットは結構使うことになる。何種類か用意されているので、覚えやすいものを使ってもらえればと思う。
例えば、カーソルが次のように1列目にあったとする。
この状態で「L」または「W」または「Ctrl」+「→」を押すと、次のようにカーソルが次のセルへ移動する。
このセルの移動はVimの規則に従って数字と組み合わせて連続実行させることができる。再びカーソルを行の先頭に戻してから(「0」でカーソルが行の先頭へ戻る)、次のように「4L」または「4W」、もしくは「4」+「Ctrl」+「→」のように入力する。こうすると、4回右のセルへ移動し、5列目へカーソルが移動する。
最低限として、「L」や「W」で右側のセルへ移動する方法だけ覚えておけばよい。Vimでは「0」でカーソルが行頭に移動するので、「0」を押してから「4」+「L」といった操作で特定の列まで移動させることで左側のセルへ移動する操作の代替とすることができるからだ。
現在の列番号、列ヘッダ、行ヘッダを表示
検索や列の移動を繰り返していると、「あれ、いま何列目にいるんだっけ」ということがよくある。スプレッドシートアプリケーションならば上部にセル番号が表示されているので何列目かわかりやすいが、chrisbra/csv.vimだとよくわからなくなってしまう。そんなときは、CSVWhatColumnコマンドだ。このコマンドでカーソルのある列が何列目かを表示させることができる。
CSVWhatColumnコマンドは「CSVWhatColumn!」のように「!(エクスクラメーションマーク)」を付けると1行目の同じ列の値を表示してくれる。つまり、その列のヘッダを表示させることができるわけだ。
列数が多い場合には1列目が表示されない状態が続くことも多く、プライマリIDのような値が確認できなくなる。スプレッドシートアプリケーションなら、列を固定して常時表示させるようにするところだろう。chrisbra/csv.vimでは、CSVVHeaderコマンドで同じことができる。
CSVファイルのなかでカーソルを移動させているときは、「CSVWhatColumn」「CSVWhatColumn!」「CSVVHeader」で自分の場所を把握することができる。この操作はぜひ覚えてしまいたい。
ユーザー関数を定義してカスタマイズしよう
このようにセルを左右に移動する方法は提供されているのだが、指定した列に移動する方法は提供されていない。例えば6列目に移動する場合、chrisbra/csv.vimでは次のように操作することになる。
- ESC
- 0
- 「5」+「L」
できれば「6列目へ移動」といったコマンドを入力したい。「:Retu 6」みたいな入力で移動してくれるとわかりやすい。頭の中で列数から1を引いて「ESC」+「0」+「5」+「L」のように高速入力するのは、ささやかな手間だが度重なると面倒だ。
また、先述の通り、居場所を確認するには「CSVWhatColumn」「CSVWhatColumn!」「CSVVHeader」を使えばよいのだが、これらのコマンドは名前が長いし、覚えにくい。とは言えCSVファイルの編集を頻繁にするのであれば必須の機能なので、もっと使いやすくしたいところだ。
そこで、このプラグインを便利に利用するための機能を自分でつくってみよう。ここでは次のようなコマンドを作ることにする。
コマンド | 内容 |
---|---|
Retu | カーソルのある列の列番号を表示 |
Retu 列番号 | 指定した列へカーソルを移動 |
Retumei | カーソルのある列のヘッダ内容を表示 |
Retumei 列番号 | 指定した列のヘッダ内容を表示 |
今回は実装例を掲載しておく。次のようなコードを設定ファイルに追加しておけば、上記のコマンドが使用できるようになる。基本的に、先ほど説明した操作をユーザー定義関数のなかで実行しているだけだ。
" 列番号が指定された場合、その列へ移動
" 列番号が指定されなかった場合、連剤の列の列番号を表示
function MyCSVMoveToColumn(...)
if a:0 == 0
CSVNrColumns
else
let cmd = "normal 0"
execute(cmd)
let offset = a:1 - 1
let cmd = "normal " . offset . "L"
execute(cmd)
end
endfunction
command -nargs=? Retu call MyCSVMoveToColumn(<f-args>)
" 現在の列または指定した列のヘッダを表示
function MyCSVShowHeaderNameOfColumn(...)
if a:0 == 0
CSVWhatColumn!
else
let cursor_pos = getpos(".")
call MyCSVMoveToColumn(a:1)
CSVWhatColumn!
call setpos('.',cursor_pos)
end
endfunction
command -nargs=? Retumei call MyCSVShowHeaderNameOfColumn(<f-args>)
上記の設定については、カスタマイズについて説明するときに詳しく取り上げるので、ここでは使用例を見ていきたい。まず次のスクリーンショットは「:Retu 4」を実行した結果だ。カーソルが4列目へ移動していることがわかる。
また、次のスクリーンショットは「:Retu 6」を実行した結果だ。6の数字に隠れてしまっていてとてもわかりにくいのだが、カーソルは6列目へ移動している。
次のスクリーンショットは「:Retumei」を実行したところだ。カーソルのある列の1行目の値、いわゆるヘッダの内容が出力されていることがわかる。
このように、よく使う機能に関しては自分が使いやすいように組み合わせるなどカスタマイズして一発で処理が完了するようにしておくとよい。こういったカスタマイズをするとしないのとでは、操作にかかる時間が大きく変わってくる。どういう処理を行いたいのか整理し、それをユーザー定義関数として定義してコマンドやショートカット入力で実行できるようにすることで、作業効率が大幅にアップする。ここまでできるようになれば、Vimによる作業効率は最高に向上するだろう。
最初は簡単なユーザー定義関数を書くのも苦労するかもしれないが、慣れてくるとサクサクと作れるようになってくる。そうなるとさらに自分だけの機能を実装するようになり、Vimが手放せなくなってくる。ある程度整理したらGitHub.comにアップロードするなどすれば、Deinなどのプラグイン管理機能でも管理できるようになり、新しい環境への導入も簡単になる。こうしてどんどん”沼”にはまっていき、Vimから抜け出せなくなっていくわけだ。とは言え、その努力に報いるだけの編集効率は得られるようになるので、悪くない時間の投資ではないかと思う。
使っている設定ファイルとセットアップ方法
プラグインを使うためにプラグインマネージャ「Dein」をセットアップする方法と、本連載で使っている設定ファイル(~/.vimrc)は以下の通りだ。
◆プラグインを使うために「Dein」をセットアップする方法
mkdir -p ~/.cache/dein
cd ~/.cache/dein/
curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
sh ./installer.sh .
rm ./installer.sh
◆本連載で使っている~/.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')
call dein#add('junegunn/fzf', {'build': './install --all'})
call dein#add('junegunn/fzf.vim')
call dein#add('sheerun/vim-polyglot')
" 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
付録「chrisbra/csv.vim」の操作/設定方法まとめ
コマンド | 内容 |
---|---|
CSVWhatColumn | カーソルが何列目にあるか |
CSVWhatColumn! | 同列1行目の内容を表示 |
CSVNrColumns | 最大列数を表示(先頭から10行で判断) |
CSVSearchInColumn /パターン/ | 現在の列をパターンで検索 |
CSVSearchInColumn 列番号 /パターン/ | 指定した列をパターンで検索 |
CSVHiColumn | 現在の列を強調表示 |
CSVHiColumn 列番号 | 指定した列を強調表示 |
CSVHiColumn! | 列の強調表示を解除 |
CSVArrangeColumn | テーブル形式での表示へ切り替え(実験的機能) |
CSVTabularize | テーブル形式でのプレビュー表示 |
CSVDeleteColumn | 現在の列を削除 |
CSVDeleteColumn 列番号 | 指定した列を削除 |
CSVHeader | 1行目を別ウィンドウで表示 |
CSVHeader 行数 | 先頭から指定行数分を別ウィンドウで表示 |
CSVHeader! | 開いた行ヘッダウィンドウを閉じる |
CSVVHeader | 1列目を別ウィンドウで表示 |
CSVVHeader 列番号 | 行頭から指定列数分を別ウィンドウで表示 |
CSVVHeader | 開いた列ヘッダウィンドウを閉じる |
CSVSort | 現在の列でファイルをソート |
CSVSort 列番号 | 現在の列でファイルをソート |
CSVSort! | 現在の列でファイルを逆順にソート |
CSVSort! 列番号 | 現在の列でファイルを逆順にソート |
CSVColumn | 現在の列をコピー |
列番号CSVColumn | 指定した列をコピー |
CSVMoveColumnor | 現在の列を最後の列の右側へ移動 |
CSVMoveColumn 列番号 列番号 | 最初に指定した列を、2つ目に指定した列の右側へ移動 |
CSVSumCol | 現在の列の合計を出力 |
CSVSumCol 列番号 | 指定した列の合計を出力 |
CSVSumRow | 行の合計を出力 |
CSVNewRecord | 新しい行を作成 |
CSVNewDelimiter デリミタ | 区切り文字を変更 |
CSVConvertData | データをほかの形式に変換 |
CSVDuplicates 列番号 | 指定した列で重複している行を出力 |
CSVAnalyze | 現在の列を分析する(値とその数、割合など) |
CSVAnalyze 列番号 | 指定した列を分析する(値とその数、割合など) |
CSVVertFold | 1列目から現在の列を折りたたむ |
CSVVertFold 列番号 | 1列目から指定した列までを折りたたむ |
CSVVertFold! | 列の折りたたみを解除する |
CSVTranspose | 列と行を入れ替える(転置) |
CSVAddColumn | 現在の列の右側に新しい列を追加 |
CSVAddColumn 列番号 | 指定した列の右側に新しい列を追加 |
CSVDupColumn | 現在の列を右側に複製 |
CSVDupColumn 列番号 | 指定した列を右側に複製 |
CSVSubstitute 列番号/パターン/文字列/ | 指定した列で置換 |
CSVColumnWidth | 列ごとの最大文字数を出力 |
CSVCountCol | 現在の列内の値の数を出力 |
CSVCountCol 列番号 | 指定した列内の値の数を出力 |
CSVMaxCol | 現在の列内の最大値を出力 |
CSVMaxCol 列番号 | 指定した列内の最大値を出力 |
CSVMaxMin | 現在の列内の最小値を出力 |
CSVMaxMin 列番号 | 指定した列内の最小値を出力 |
CSVAvgCol | 現在の列内のデータの平均値を出力 |
CSVAvgCol 列番号 | 指定した列内のデータの平均値を出力 |
PopVarCol | 現在の列の母集団分散を出力 |
PopVarCol 列番号 | 指定した列の母集団分散を出力 |
SmplVarCol | 現在の列の標本分散を出力 |
SmplVarCol 列番号 | 指定した列の標本分散を出力 |
PopStdCol | 現在の列の母標準偏差を出力 |
PopStdCol 列番号 | 指定した列の母標準偏差を出力 |
SmplStdCol | 現在の列の標本標準偏差を出力 |
SmplStdCol 列番号 | 指定した列の標本標準偏差を出力 |
移動キー | 内容 |
---|---|
「Ctrl」+「→」 | 右の列へ移動 |
L | 右の列へ移動 |
W | 右の列へ移動 |
「Ctrl」+「←」 | 左の列へ移動 |
E | 左の列へ移動 |
H | 左の列へ移動 |
↑ | 列を上へ移動 |
K | 列を上へ移動 |
↓ | 列を下へ移動 |
J | 列を下へ移動 |
フィルタキー | 内容 |
---|---|
↩️ | 現在の列と一致しないすべての行を動的に折りたたむ |
Space | 現在の列と一致するすべての行を動的に折りたたむ |
BS | 動的フィルタから最後のアイテムを削除 |
設定項目 | 内容 |
---|---|
g:csv_delim | デフォルトのデリミタ |
g:csv_no_conceal | 1に設定するとデリミタ部分を|で視覚的に表示(デフォルトは設定されていない) |
g:csv_highlight_column | ‘y’に設定するとカーソルがある列を自動でハイライト |
b:csv_headerline | ヘッダの行数を指定。0を指定するとヘッダとしてのハイライトが行われなくなる |