前回、次のVimプラグインとして「junegunn/vim-easy-align」をインストールした。デリミタ区切りのテキストデータをスプレッドシートアプリケーションのように表状に整理するVimプラグインだ。こうしたプラグインはほかにもいくつか存在している。そうしたプラグインのなかでもvim-easy-alignは利用者が多い。設定が豊富で、表データのみならずJSONやプログラミング言語といった構造化されたテキストデータも整理できるところが人気のある理由かもしれない。

今回はvim-easy-alignを使ってデリミタ区切りのテキストデータを表形式に変換する際の基本的な操作方法を取り上げる。テキストデータを表形式に整理する方法はいろいろと応用が効くので、知っておいて損はないだろう。表形式データの整理ができるということは、2値のテキストデータの整理も当然行うことができる。何かと便利な操作方法だ。

vim-easy-alignの使い方 基礎

操作するテキストデータは何でもよい。デリミタ区切りのテキストデータで代表的なものはカンマ区切りのCSVデータだ。その類似データとしては、空白区切りのSSVデータやタブ区切りのTSVデータなどがある。例えば、Linuxの設定ファイルの例だと、アカウントデータを保持している/etc/passwdがコロン区切りのデータになっている。これも表データの一つということになる。今回は/etc/passwdをvim-easy-alignで操作してみる。

/etc/passwd

まず、最も基本的な操作として「vipga:」を取り上げる。「vip」でデータをビジュアル選択、「ga」でvim-easy-alignの呼び出し、「:」でデリミタを指定、だ。この指定方法でその行の最初の「:」を区切り文字としてデータを整理する。実行すると次のようになる。

「vipga:」の実行結果サンプル

もっと短い入力がよいなら「gaip:」でもよい。頭のなかで操作のイメージができているなら、こちらのほうが操作が速くて済む。ただし、この方法だと明示的にビジュアル選択が表示されるわけではないので、選択されている範囲がわかりにくい。このため、本稿では「vip」のほうで操作を統一しておく。「vip」で目的の範囲が選択されない場合には、これまでに説明した方法でビジュアル選択を行い、その後で「ga」を入力してvim-easy-alignの機能を実行してみてほしい。

先ほどは、2値のデータ整理になっていた。次は「vipga*:」だ。「vip」で対象をビジュアル選択、「ga」でvim-easy-alignの機能に入り、「*:」で全ての「:」を対象とし表的なデータとして処理を行う。先ほどとの違いは「:」か「*:」かだ。vim-easy-alignでは基本的に「場所」「デリミタ」という指定を行う。「:」だけ指定したときは「1:」という指定をしたのと同じ意味として処理されており、省略形での指定という扱いになる。「*」はワイルドカードで全てのデリミタを対象としている。このため、「vipga*:」で対象を表として処理するということになる。実行すると次のようになる。

「vipga*:」の実行結果サンプル

vim-easy-alignは対象指定に「*」だけではなく「**」というワイルドカードを2個続けた表記を用意している。これは実行結果を見てみたほうがわかりやすいだろう。次のスクリーンショットが「vipga**:」の実行結果だ。

「vipga**:」の実行結果サンプル

「*」で整理した場合、それぞれのセルは左寄せになっている。「**」で整理した場合、寄せの方向が行頭から順に左寄せ、右寄せ、左寄せ、右寄せ、左寄せ、右寄せ……と交互になっている。どこに需要があるのかよくわからないが、こうした指定が可能だ。

「vipga5:」のようにすると、5つ目の列に対して処理を行うことができる。まず、テキストデータを「vipga*」で次のように表として整理した状態にしておく。

「vipga*:」で表データとして整理

次に、「vipga5↩️:」と実行する。これで5列目が右寄せになる。「Enter」キーを押すと、寄せの方向がデフォルトの左寄せから右寄せに変わる。実行すると次のようになる。

「vipga5↩️:」の実行結果サンプル

「vipga*:」した後の状態から「vipga5↩️↩️:」のように実行すると、今度は5列目が中央寄せになる。「Enter」キーを押すことで、(左寄せ)→右寄せ→中央寄せ→左寄せ→右寄せ→中央寄せ……と寄せる方向が変わっていく。そのため、「Enter」キー2回で中央寄せになっている。

「vipga5↩️↩️:」の実行結果サンプル

もう一つ、デリミタの位置を調整する方法も取り上げておく。まず、基本となるvipga*:に戻ってこよう。

「vipga*:」の実行結果サンプル

この場合、デリミタがセルのテキストのほうにくっついている点に注目してほしい。「vipga*:」を実行する前の素のテキストデータに戻した状態で、今度は「vipga*→:」と実行する。「→」はテンキーの右矢印だ。実行すると次のようになる。

「vipga*→:」の実行結果サンプル

今度はデリミタがセルとは独立して、それ単体として整ったことがわかる。この場合は「:」だが、これが「|」だったりするとかなり表感が出てくる。このように「→」はデリミタを独立させる指定であり、逆に「←」にするとセルのテキストにくっつくようになる。

これまでに説明してきたように、処理は列ごとに指定することもできる。例えば、素のテキストデータの状態から「vipga*→:vipga1:」のように入力すれば、1列目はデリミタがセルに接続し、2つ目以降のデリミタが独立するようになる。

「vipga*→:vipga1:」

テキストデータを表として整理するとなると、デリミタの位置を揃えて表のように見せたいというのはよくあることだ。今回取り上げたのは基本的な操作だが、これだけでも多くのことができる。

「vipga*→:vipga1:」のような操作になってくるといよいよ呪文感が出てくるが、上記で説明したように慣れてしまえばシンプルな操作であり、わかりやすいものだ。Vimはこのように操作の目的に応じてプラグインを設定して命令を整えておくことで、自分だけの高効率編集環境を用意しておくことができる。整理に投資しただけの見返りが得られるエディタであり、後少しだけ、もうちょっとだけとつい入れ込んでしまう。これが”沼”たる所以だ。

付録: vim-easy-alignの主な設定と操作方法

操作 内容
ノーマルモードで:EasyAlignまたはビジュアルモードでga vim-easy-alignのインタラクティブモードを起動する。
デフォルトのデリミタ文字 備考
空白 = : , | . # & =は==や!=や+=といったように等号を含む演算子がデリミタと認識される。
Ctrl-X 正規表現 Ctrl-Xを入力するとそのあとはデリミタとして正規表現を使用できる。
キー 内容
デリミタ 最初に一致したデリミタで左揃え。
2デリミタ 2番目に一致したデリミタで左揃え。
3デリミタ 3番目に一致したデリミタで左揃え。
-デリミタ 最後に一致したデリミタで左揃え。
-2デリミタ 最後から1つ前に一致したデリミタで左揃え。
-3デリミタ 最後から2つ前に一致したデリミタで左揃え。
*デリミタ 一致したすべてのデリミタで左揃え。
**デリミタ 一致したすべてのデリミタで揃え(左揃えと右揃えを交互に適用)。
キー 位置 内容
↩️ 最初 押すごとに右揃え、中央揃え、左揃え、右揃え、中央揃え、左揃え… と揃えを変更。
ショートカットキー オプション 
Ctrl-F filter 文字列([gv]/.*/?)
Ctrl-I indentation shallow、deep、none、keep
Ctrl-L left_margin 数字または文字列
Ctrl-R right_margin 数字または文字列
Ctrl-D delimiter_align left、center、right
Ctrl-U ignore_unmatched 0、1
Ctrl-G ignore_groups [], [‘String’], [‘Comment’], [‘String’, ‘Comment’]
Ctrl-A align 文字列(/[lrc]+\*{0,2}/)
stick_to_left { ‘stick_to_left’: 1, ‘left_margin’: 0 }
stick_to_left { ‘stick_to_left’: 0, ‘left_margin’: 1 }
*_margin { ‘left_margin’: 0, ‘right_margin’: 0 }

付録: 使っている設定ファイルとセットアップ方法

プラグインを使うために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')
  call dein#add('junegunn/vim-easy-align')

  " 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>

" vim-easy-align
xmap ga <Plug>(EasyAlign)
nmap ga <Plug>(EasyAlign)

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

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