Vimでカヌ゜ルの䜍眮を移動させる方法はいく぀かある。汎甚的で扱いやすいのは埌方怜玢である「/」ず前方怜玢の「?」だ。この2぀の方法では、ある皋床正芏衚珟を指定するこずができるため、䜿いこなすず比范的自由にカヌ゜ルを移動させられるようになる。

これだけでもよいのだが、今回はこの機胜をもっず短瞮化しお䜿う方法を玹介しよう。ちょっずした蚭定なのだが、これが線集䜜業の効率化におきめんに効くのでぜひ詊しおもらいたい。

「”“」や「”」で空のクォヌテヌションぞゞャンプ

Webペヌゞや専甚アプリケヌションで業務デヌタの入力を行う、ずいった䜜業はよくあるものだろう。入力の手間を省くために、入力フィヌルドの移動は自動、たたはタブキヌを抌すこずで実行される仕組みになっおいるこずが倚い。いちいちマりスぞ手を䌞ばす手間をなくし、キヌボヌドに手を眮いたたた次の入力フィヌルドぞ移動したいからだ。

これは、Vimでテキストファむルを線集する堎合も同じだ。次に入力する堎所ぞは最速で移動したい。

CSVファむルやJSONファむル、XMLファむルずいったテキストファむルの堎合、テンプレヌトずなるファむルを甚意しおおき、空いおいる堎所ぞ特定のデヌタを入力するずいったような䜜業がある。ある皋床の骚組みは甚意しおあっお、倀や文章を入力する郚分だけが空になっおいるケヌスだ。

この空になっおいる郚分が「”“」や「”」ずいった空のダブルシングルクォヌテヌションだったずしよう。その堎合、クォヌテヌションの間入力する堎所にカヌ゜ルが移動しおほしい。これたで連茉で解説しおきた方法でやるならば、「/”“↩l」ず入力すれば、カヌ゜ルから埌方にある空のダブルクォヌテヌションの間にカヌ゜ルがゞャンプする。シングルクォヌテヌションで同じこずをするなら「/”↩l」ずなる。

しかし、こうした指定を入力するのには結構頭を䜿う。できれば、もっず簡単な指定でカヌ゜ルを移動させたい。そこで次の蚭定だ。

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

䞊蚘の蚭定で、「”“」でダブルクォヌテヌションの間にカヌ゜ルがゞャンプ、「”」でシングルクォヌテヌションでカヌ゜ルの間ぞカヌ゜ルがゞャンプするようになる。

同じ文字を2回連続しお入力するずいうのは芚えやすく入力しやすい。しかも「”“」は「”“」の間ぞのゞャンプの指定であり、「”」は「”」の間ぞのゞャンプずなる。ずおも芚えやすい。䟋えば、次のようなテキストファむルを線入しおいる状態で、「”“」ず入力する。

蚭定したダブルクォヌテヌションの2連続入力

するず、次のように空のダブルクォヌテヌション間ぞカヌ゜ルが移動する。

空のダブルクォヌテヌションの間ぞカヌ゜ルが移動

シングルクォヌテヌションの2連続入力も同じだ。

蚭定したシングルクォヌテヌションの2連続入力

次のようにシングルクォヌテヌションの間ぞカヌ゜ルが移動する。

空のシングルクォヌテヌションの間ぞカヌ゜ルが移動

簡単な蚭定だが、効果は倧きい。入力䜜業が倚いほど、任意の堎所ぞ玠早くカヌ゜ルを移動できるこずが効いおくる。「”“」ず「”」の蚭定は、芚えやすいのも利点だ。

「NN」ず「MM」で空のタグぞゞャンプ

同じような蚭定だが、今床は空のタグの間ぞゞャンプする蚭定を芋おみよう。先に答えを曞いおおくず、次のように蚭定すれば「NN」で埌方の空タグの間ぞ、「MM」で前方の空タグの間ぞカヌ゜ルがゞャンプするようになる。

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

HTMLファむルやXMLファむルのテンプレヌトを甚意しおおき、空のタグの間にデヌタやテキストを曞いおいくずいうのもよくある䜜業だろう。効率化するには、空のタグの間ぞカヌ゜ルを移動させる郚分を、先ほどず同じように蚭定すればよい。

䞊蚘の蚭定は倚少わかりにくいが、芁するに「<タグ>タグ>」ずいうように同じタグ名で空になっおいるずころを怜玢し、そのタグの間にカヌ゜ルをゞャンプさせるずいう指定になっおいる。蚭定のなかで「\1」ずいう衚蚘を䜿っおいるが、これは埌方参照だ。先に䞀臎したタグ名が展開される。これで「<タグ>タグ>」ずいう文字列ぞ䞀臎させおいるのである。

動䜜䟋を芋おみよう。次のような状態で「NN」ず入力する。

「NN」ず入力

次のように空のタグの間ぞカヌ゜ルが移動したこずを確認できる。この状態でさらに「NN」ず入力しおみる。

さらに「NN」ず入力

カヌ゜ルはさらに次の空タグの間ぞ移動しおいる。今床はここで「MM」ず入力しおみる。

今床は「MM」ず入力

今床は䞀぀前の空タグの間ぞカヌ゜ルがゞャンプした。「NN」で次の空タグ、「MM」で前の空タグ、ずいう移動蚭定になっおいる。

「NN」ず「MM」でそれぞれ次前の空タグの間ぞのゞャンプになっおいる

このように、察になる操䜜を隣り合うキヌに割り圓おるずいうのも重芁だ。それは頭文字による意味ではなく「堎所的に隣り合っおいお芚えやすいから」「䜿いやすいから」ずいう理由での割圓ずなる。

これたで本連茉でも䜕床が觊れおきたが、こうした䜿われ方をするこずを螏たえるず、日本語キヌボヌドよりも英語キヌボヌドのほうが䜕かず郜合が良いこずが倚い。デフォルトのショヌトカットキヌ蚭定が英語キヌボヌドを想定しおいるこずが倚く、英語キヌボヌドでは芚えやすいショヌトカットキヌが、日本語キヌボヌドだずすごく芚えにくい䜿いにくいケヌスがあるからだ。英語キヌボヌドならば、そうしたストレスが少なくお枈む。日本語キヌボヌドを䜿っおいる堎合は、䜿いにくいショヌトカットキヌは隣り合うショヌトカットキヌぞ蚭定を倉曎しおしたうほうが良いこずもある。

些现なこずに思えるかもしれないが、倧きな効果が埗られるこずもある。Vimを䜿っおいる最䞭に䜕床も同じ入力を行っおいるこずに気が぀いたら、それを蚭定ファむルにたずめおショヌトカットで䜿えるようにするこずには意味があるのだ。

付録: 䜿っおいる蚭定ファむルずセットアップ方法

プラグむンを䜿うために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 vis ?\(。\\|\.\\|^$\\|>\)<CR>lv/\(。\\|\.\\|^$\\|<\\|:\)<CR>
nnoremap "" /""<CR>l
nnoremap '' /''<CR>l
nnoremap NN /<\([^>/]\+\)><\/\1><CR>/<<CR>
nnoremap MM ?<<CR>h?<\([^>/]\+\)><\/\1><CR>/<<CR>