今回も、カーソル移動の設定方法を紹介する。テキストファイルの編集速度を向上させる上で、自由自在にカーソル移動できるスキルは欠かせない。その習得は、将来に渡って発生する編集作業の時間を短縮することにつながるので、多少時間をかけてでもじっくりとやっておきたいところだ。

今回は、一文ごとにカーソルを移動させる方法に注目したい。Vimでは「(」と「)」にこの機能が割り当てられており、「)」で次の一文へ、「(」で前の一文へカーソルが移動する。しかし、この機能は次の理由で使いにくい。

● 日本語の一文に対応していない。


visのときと同じだ。「(」と「)」で日本語の文でも移動ができればよいのだが、デフォルトではできないのである。ということで、ここではvisを日本語に対応させたときと同じ要領で、「(」と「)」を日本語に対応させることにする。別のショートカットキーにしてもよいのだが、覚えるショートカットは少ないに越したことはないのだ。「(」と「)」に上書きしてしまおう。

「(」と「)」の日本語対応版

visのときと同様、オリジナルの機能を完全に模倣するのは面倒なのでやめておく。何となく似た動作をすれば良しとしよう。

まずは、完成形をお見せしよう。ここでは、次のような後方検索で「)」を上書きした。

nnoremap ) /\(。\\|、\\|[.:][ \t\n]\\|^\n\)<CR>l

オリジナルの動作に加えて日本語の句点「。」と読点「、」に対応させている。ほかの句読点を使っている場合には、ここにその句読点の設定を追加すればよい。句点だけにしたければ読点の設定を削除しよう。動作させると次のようになる。

「)」で次の句読点へ移動

「)」で次の句読点へ移動

「)」で次の句読点へ移動

「)」で次の句読点へ移動

「)」を押すごとに次の句読点へ移動することがわかる。前回は「Tab」キーと「Shift」+「Tab」キーである程度まとめてカーソルを移動できるようにしたが、こちらのやり方であれば、句読点という区切りでカーソルが移動するようになり、前回よりも意図的な移動が可能になる。

次は逆方向の「(」だ。設定は次のようになる。基本的に先ほどの後方検索を前方検索に変えているだけだ。

nnoremap ( ?\(。\\|、\\|[.:][ \t\n]\)<CR>h?\(。\\|、\\|[.:][ \t\n]\)<CR>l

動作させると次のようになる。

「(」で前の文の頭へ移動

「(」で前の文の頭へ移動

「(」で前の文の頭へ移動

これで、文単位で移動する「(」と「)」を日本語に対応させたことになる。Vimはもともと英語を想定して開発されているため、分かち書きを行わない日本語文とはこの辺りの操作面で相性が悪い。しかし、全く同じようにとはいかないのだが、上述のような設定で日本語に対応させれば、Vimの基本機能と同じショートカットキーで似た操作が可能になる。ぜひとも積極的に使っていきたいところだ。

キーボードに合わせたチューニング

本連載では、これまでに「”“」と「”」でそれぞれ「”“」と「”」の間へカーソルが移動するように次のような設定を行った。これは後方検索の機能を使って設定したので、基本的に後方に対する移動となる。

nnoremap "" /""<CR>l
nnoremap '' /''<CR>l

操作の仕方として、後方検索方向へ移動するとなると、逆に前方検索方向へも移動してほしくなる。行き過ぎた場合などに戻る操作が欲しいのだ。その場合、逆方向に進むキーは位置的に近いものであるとわかりやすい。つまり、「”“」と「”」のキーの隣のキーを逆方向への移動とする、といった感じだ。これなら迅速に前後を移動できるようになる。

この設定はキーボードレイアウトに合わせて行う必要がある。例えば、英語キーボードの場合なら「”」と「’」は同じキーに割り当てられており、その左隣りのキーには「:」と「;」が割り当てられている。つまり、「”“」の対として「::」を、「”」の対として「;;」を設定しておけば、左側のキーを押すことで前方方向へ移動させることができる。設定は次のようになる。

nnoremap :: ?""<CR>l
nnoremap ;; ?''<CR>l

このように隣り合うキーに逆方向への移動を割り当てておくと、何も考えずに手を動かしやすくなって便利だ。

覚えやすいキーへチューニング

本連載では、これまでにXMLやHTMLファイルの編集向けに空の要素へ移動するショートカットキーとして「NN」と「MM」を設定した。「NN」は「何となくNext」的な意味で、「MM」はNキーの隣にあり、かつ、ホームポジションから操作しやすいという理由で採用した。要するに、割り当てたキーに特に意味はなかった。

nnoremap NN /<\([^>/]\+\)><\/\1><CR>/<<CR>
nnoremap MM ?<<CR>h?<\([^>/]\+\)><\/\1><CR>/<<CR>

カーソル移動に限らず、多くの設定を追加するようになってくると、設定が衝突するケースも発生する。そして、設定そのものを忘れやすくもなる。そんな場合は、割り当てたショートカットキーをもっと覚えやすいものに変更すればよい。

「”“」と「”」はその好例だ。「”“」で「”“」の間へジャンプし、「”」で「”」の間へジャンプする。飛びたい場所とその操作キーが一致しているので覚えやすく、思い出しやすい。であれば、空要素への移動にもこれと同じロジックを適用すればよい。

「空要素への移動」は、つまり「><の真ん中へカーソルを移動させる」ということだ。なので、ショートカットキーを><にしてしまえばよい。これなら長らくXMLやHTMLを編集していなかったとしても、ショートカットキーをすぐに思い出すことができるだろう。

そしてこれが後方方向への移動となるので、前方方向への移動はキーを押す順序を逆に設定する。><の逆なので<>だ。押すキーは同じで、押す順序を逆にすれば移動する方向が逆になる。これも覚えやすいだろう。設定は次のようになる。

nnoremap >< /<\([^>/]\+\)><\/\1><CR>/<<CR>
nnoremap <> ?<<CR>h?<\([^>/]\+\)><\/\1><CR>/<<CR>

自分が自分のために行う設定は絶対的なものではない。不便になったり使わなくなったりしたら整理する。こうした作業を細かく繰り返してくことで、本当に有用な設定だけが残っていく。生き残った設定は、将来の自分にとって大きな資産となってくれるはずだ。 

そしてやっぱり英語キーボード

こうしてショートカットキーを駆使するようになってくると、英語キーボードのほうが扱いやすいことに気づくだろう。英語キーボードは。括弧や「+」「-」が隣り合ったキー配置になっているので、ショートカットキーを直感的に扱えるからだ。

日本語キーボードでは「+」「-」は隣り合っていないし、「”」と「’」は別々の場所にあり、「{」と「}」や「[」と「]」も隣り合っていない。扱いやすいようにショートカットキーを設定すると、ショートカットキーと刻印が一致しないので違和感が出ることは否めない。

自身の業務においてキーボード操作の巧拙が重要だと思うのであれば、英語キーボードの採用も選択肢の一つに入れるとよいのではないだろうか。

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

プラグインを使うために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
nnoremap k gk
nnoremap gk k
nnoremap j gj
nnoremap gj j
nnoremap <Tab> 15<Right>
nnoremap <S-Tab> 15<Left>
nnoremap vis ?\(。\\|\.\\|^$\\|>\)<CR>lv/\(。\\|\.\\|^$\\|<\\|:\)<CR>
nnoremap >< /<\([^>/]\+\)><\/\1><CR>/<<CR>
nnoremap <> ?<<CR>h?<\([^>/]\+\)><\/\1><CR>/<<CR>
nnoremap ( ?\(。\\|、\\|[.:][ \t\n]\)<CR>h?\(。\\|、\\|[.:][ \t\n]\)<CR>l
nnoremap ) /\(。\\|、\\|[.:][ \t\n]\\|^\n\)<CR>l
nnoremap "" /""<CR>l
nnoremap '' /''<CR>l
nnoremap :: ?""<CR>l
nnoremap ;; ?''<CR>l