前回は、「)」を抌したずきに、自分の求める堎所ぞカヌ゜ルをゞャンプさせる蚭定方法に぀いお説明した。最終的に、以䞋のような蚭定にしたこずで開始タブの次の堎所ぞカヌ゜ルがゞャンプするようになり、䞍必芁な堎所ぞはゞャンプしないようになった。

nnoremap ) />[^\n]<CR>l

前回の蚭定

今回は、終了タブの前ぞゞャンプするようにするほか、句読点ぞもゞャンプするように蚭定する。これで「)」によるゞャンプの蚭定は完成だ。

次は終了タグの前ぞゞャンプさせる

たず、䜕も考えずに終了タグの先頭である「<」をパタヌン怜玢の察象ぞ加える。次のように蚭定すればよい。

nnoremap ) h/>[^\n]\\|<<CR>l

䞊蚘のように、「)」でパタヌン怜玢が行われるようにする蚭定の堎合、OR怜玢を実斜するために「\|」で条件を分ける必芁がある。パタヌン怜玢で盎接パタヌンを蚘入する堎合は「\|」が区切り文字になるのだが、䞊蚘のように「map」で蚭定を行う堎合には「\|」のように蚘茉するこずになる。「\|」の埌に「<」を曞いおあるので、パタヌン怜玢ずしお「<」も䞀臎するようになるわけだ。

䞊蚘蚭定で「)」を抌しおいくず次のようにカヌ゜ルがゞャンプしおいく。

蚭定実行䟋

圓然だが、党おの<ぞゞャンプしおいくので、このたたでは䜿い物にならない。終了タグの前にだけゞャンプしおくれればよいので、それ以倖の堎所に䞀臎しないように条件を加えおいく。

ここでたずポむントずしお、前回指定した「>[^\n]」ず条件が被らないように「<」のほうを曞き換える。パタヌンが重耇するような状態になっおいるずどちらのパタヌンに䞀臎したかがわからなくなっおしたうので、それを避けるためだ。「>[^\n]」ず「<」では「><」のずきにどちらに䞀臎するのか䞀芋しおわかりにくい。そこで次のように曞き換える。

nnoremap ) />[^\n]\\|[^>]<<CR>l

「>[^\n]」ず「[^>]<」の指定に倉えたので、「><」は「>[^\n]」に䞀臎するこずになる。

次に、䞀臎しおほしくない条件を远加しおいく。たず、ここでは「<」の前が空癜の堎所にゞャンプしおも意味がないので、次のようにその条件に䞀臎しないように蚭定を倉曎する。

nnoremap ) />[^\n]\\|[^ >]<<CR>l

この蚭定で「)」を抌しおいくずゞャンプする堎所が次のようになる。

蚭定実行䟋

ゞャンプする堎所はかなり良くなった。

ここで、終了タグ偎のゞャンプ先が1文字巊ぞ移動した点に泚目しおほしい。「<」だけのずきは<の1぀右ぞゞャンプしおいたが、「[^ >]<」にするずゞャンプする先がそこよりも1぀巊ぞ移動しおいる。これはパタヌンを「[^ >]<」に倉曎したこずで、䞀臎先が<よりも1文字巊ぞ移動したこずが原因だ。意図せずに望む方向ぞ移動したこずになる。

なお、゚ディタによっおはむンデントに空癜ではなくタブが䜿われるので、蚭定に空癜だけではなくタブに関しおも䞀臎しないように次のように蚭定を倉曎する。

nnoremap ) />[^\n]\\|[^ \t>]<<CR>l

最埌に終了タグぞゞャンプするずきの堎所の調敎だ。前回、開始タグにゞャンプしたずきにいい具合にカヌ゜ルが着地するように、ゞャンプした埌に「l」で1぀右ぞ移動するように蚭定した。このため、先ほど「[^>]<」で䞀臎させたにもかかわらず、カヌ゜ルが「<」の䞊ぞゞャンプしおしたっおいた。

ここで先の珟象ず同じ理屈を䜿っおゞャンプ先を調敎する。「<」を「[^ >]<」に倉曎したこずでゞャンプ先が1぀巊ぞ移動したのだから、パタヌンを「.[^ >]<」のように任意の1文字を加えるこずで、さらにゞャンプ先を1぀巊ぞ移動させるこずができるはずだ。蚭定をたずめるず次のようになる。

nnoremap ) />[^\n]\\|.[^ \t>]<<CR>l

この蚭定で動䜜させるず次のようになる。

蚭定実行䟋

これで、狙い通りに終了タグの前にゞャンプするようになった。

パタヌン怜玢の機胜で任意の堎所に飛ばそうずしおいるので、䞊蚘パタヌンのように「任意の文字をパタヌンに加えおゞャンプ先を調敎する」ずいうちょっずした工倫が圹立぀。右方向ぞずらすには怜玢が終わった埌でlを、巊方向ぞずらすには.で䞀臎パタヌンの範囲を巊方向ぞ広げる、ずいったテクニックだ。

句読点をゞャンプ先ぞ远加

「)」はもずもず䞀文ごずにゞャンプする機胜だ。日本語に察応させたずきは䞀文だず範囲が広くお䜿いにくかったので、句読点ごずにゞャンプさせた。ここでもこの機胜を取り蟌んでおきたいので、次のように句読点ぞゞャンプするためのパタヌンを远加する。

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

远加したのは「\|[:。、]」だ。\|がORの区切り指定で、[:。、]に句読点およびそれに類する文字を加えおある。動䜜させるず次のようになる。

蚭定実行䟋

これで倧䜓、思い描いおいたようなゞャンプをしおくれるようになった。

「)」はもずもず英文の䞀文ごずにゞャンプしおいく機胜だ。これに合わせお英文だった堎合にもゞャンプするように「\|[.,?!][ \t\n]」の蚭定を远加しお、次のような蚭定にしおおく。

nnoremap ) h/>[^\n]\\|.[^ \t>]<\\|[:。、]\\|[.,?!][ \t\n]<CR>l

これで「)」のカスタマむズは完了だ。

OR条件を远加するごずに条件は厳しくなっおいく

こうなっおくるず、䟋えば「ゞャンプの察象に䞞括匧を加えたいず」か、「波括匧を加えたい」、「セミコロンを加えたい」ずいった现かい垌望が出おくるこずもあるず思う。䞊蚘パタヌンのどこかに圓おはたるなら、そこに文字を远加するずか、パタヌンをコピヌしおOR条件で远加しおいけば機胜するだろう。

しかし、OR条件を远加するごずにどんどん指定できるパタヌンが厳しくなっおいくこずを芚えおおいたほうがよい。埌から远加した条件のほうが優先的に動䜜するように埓来のパタヌンを倉曎するず、今床はこれたでゞャンプできおいた堎所にゞャンプできなくなるなど、困った状態になるはずだ。

あくたでもVimの提䟛するパタヌン怜玢の機胜を䜿うこずでゞャンプを実珟しおいるので、そこで実珟できない飛び方をさせるこずはできない。これ以䞊のこずをさせたいなら別の方法で実装する必芁がある。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 k gk
nnoremap gk k
nnoremap j gj
nnoremap gj j
nnoremap q b
vnoremap q b
nnoremap <Tab> 15<Right>
nnoremap <S-Tab> 15<Left>
nnoremap vis h?>[^\n]\\|.[^ \t>]<\\|[。]\\|[.?!][ \t\n]<CR>lv/>[^\n]\\|.[^ \t>。]<\\|[。]\\|[.?!][ \t\n]<CR>
nnoremap >< /<\([^>/]\+\)><\/\1><CR>/<<CR>
nnoremap <> ?<<CR>h?<\([^>/]\+\)><\/\1><CR>/<<CR>
nnoremap ( h?>[^\n]\\|.[^ \t>]<\\|[:。、]\\|[.,?!][ \t\n]<CR>l
vnoremap ( h?>[^\n]\\|.[^ \t>]<\\|[:。、]\\|[.,?!][ \t\n]<CR>l
nnoremap ) />[^\n]\\|.[^ \t>]<\\|[:。、]\\|[.,?!][ \t\n]<CR>l
vnoremap ) />[^\n]\\|.[^ \t>]<\\|[:。、]\\|[.,?!][ \t\n]<CR>l
nnoremap "" /""<CR>l
nnoremap '' /''<CR>l
nnoremap :: hh?""<CR>l
nnoremap ;; hh?''<CR>l
nnoremap <C-a> <Home>
inoremap <C-a> <Home>
cnoremap <C-a> <Home>
vnoremap <C-a> <Home>
nnoremap <C-e> <End>
inoremap <C-e> <End>
cnoremap <C-e> <End>
vnoremap <C-e> <End>