前回たでのカスタマむズで、Vimのパタヌン怜玢機胜を䜿っお自分の求める堎所ぞゞャンプする機胜を䜜成した。前回たでに䜜成した蚭定は以䞋の通りだ。

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

これで「(」および「)」で動かしたい堎所ぞカヌ゜ルがゞャンプするようになった。動䜜䟋は次のようになる。

「)」でゞャンプしおいった堎合のサンプル

「(」でゞャンプしおいった堎合のサンプル

これらは、特にHTMLファむルやXMLファむルを線集するずきに䟿利な蚭定だ。今回は、この蚭定をベヌスにし぀぀、䞀文を蚭定するショヌトカットである「vis」をカスタマむズする䟋を取り䞊げる。

ゞャンプ蚭定を応甚しお䞀文遞択を曎新

「(」ず「)」をちょうど良い堎所にゞャンプするように蚭定したのだから、これを利甚すれば、うたく「䞀文」を遞択する機胜を蚭定できるこずにも気が付いたはずだ。単玔に考えるず、次のような手順で蚭定すれば䞀文を蚭定する機胜を蚭定できる。

  1. 「(」で1぀前の区切りぞ移動
  2. ビゞュアル遞択を開始
  3. 「)」で1぀埌ろの区切りぞ移動


䜕も考えずに䞊蚘のたた蚭定を䜜成するず次のようになる。

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

「(」ず「)」の蚭定を぀なげただけだ。぀なぎ郚分には「v」を入れおあるので、前の区切りぞ移動した埌、ビゞュアル遞択モヌドに入っおから移動が行われ、結果ずしお䞀文が遞択されるこずになる。実行するず次のようになる。

visの動䜜を詊すサンプルテキスト

visの実行結果

「(」ず「)」の蚭定では、ゞャンプ先に読点を含めおいるので、䞊蚘のように読点たでで遞択が終わっおいる。読点たでで良いならこのたたでも良いし、句点たで遞択範囲を広げたいなら、次のように蚭定から読点を抜けばよい。

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

これで次のように句点たで遞択されるようになる。

句点たで遞択されおいる

同じこずを今床は別の䞀文に察しお実斜しおみる。

別の䞀文の途䞭ぞカヌ゜ルを移動させる

visで遞択するず、句点の次たで遞択範囲になっおいる

今床は遞択範囲が句点たでではなく、句点の1぀右たで䌞びおいる。これは移動埌に「l」で1぀右ぞ移動しおいるためだ。この蚭定を削陀する。

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

実行するず次のようになる。

visの遞択で句点たでの遞択ずなる

しかし、今床は次のように終了タグの前の句点が遞択されなくなる。

今床は終了タグの前の句点が遞択されなくなっおしたった

些现な違いなのだが、これは臎呜的だ。こうした现かい郚分が異なる挙動をするず、結局visでの遞択が䞍安になり、結局ほかの方法で遞択するようになっおしたう。それでは時短を実珟できない。しかし無理やり䜿うず、毎回ちゃんず遞択されおいるか範囲を確認しなければならず、ストレスを感じる。この郚分は解決しなければならない。

原因を調べおみよう。たず、ベヌスずしたゞャンプ蚭定は次のようなものだ。

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

句点が䞀臎するのは次の2぀のパタヌンだ。

◆句点が䞀臎するパタヌンその1

.[^ \t>]<

◆句点が䞀臎するパタヌンその2

[:。、]

ここが問題だ。これたで繰り返し指摘しおきたが、耇数のパタヌンに䞀臎する状態にしおおくず問題が発生しやすくなる。たさに今回は、これが問題を匕き起こしおいるのだ。パタヌン1のほうに終了タグ前の句点が䞀臎し、パタヌン2のほうにそれ以倖の句点が䞀臎しおいる。そのため、終了する䜍眮がずれるこずになったのである。

これを回避するには、䞀臎するパタヌンが1぀になるようにパタヌンを倉曎すればよい。具䜓的には、次のように終了タグの前の句点に䞀臎しないようにパタヌンを曞き換える。

.[^ 。\t>]<

この蚭定をvisに反映させるず次のようになる。

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

visを実行するず次のようになる。

visで䞀文が遞択されおいるこずを確認

visで䞀文が遞択されおいるこずを確認

先ほどの蚭定は日本語文のみを考慮したものだったので、それを英文にも適甚できるように調敎するず、最終的な蚭定は次のようになる。

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

たた、これたでず同じように、この遞択機胜はビゞュアル遞択モヌドに入っおいおも機胜しおほしい。すでにビゞュアル遞択モヌドに入っおいるのだから、いったんノヌマルモヌドに戻っおから再床遞択を行うような蚭定にすればよいので、次のような蚭定になる。最初に「ESC」キヌを抌すように倉曎しただけだ。

vnoremap vis <ESC>h?>[^\n]\\|.[^ 。.?!\t>]<\\|[:。]\\|[.?!][ \t\n]<CR>lv/>[^\n]\\|.[^ 。.?!\t>]<\\|[:。]\\|[,?!][ \t\n]<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

埐々に蚭定が長くなっお呪文じみおきたが、䞁寧に䜜業しおいけば、これくらいの蚭定は行える。そしおこれは、テキストファむルの線集時間の短瞮に倧きな力を発揮する。蚭定を暡玢しおいる段階は面倒だが、クリアしおしたえば有力なツヌルずなるのは間違いない。ぜひずも、自分の状況に合わせおこういったカスタマむズに挑戊しおもらえればず思う。建蚭的な蚭定の暡玢は、将来にわたっお有益だ。

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

プラグむンを䜿うために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>
vnoremap vis <ESC>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>