マイナビニュースマイナビ

Vimを使う - ジャンプをカスタマイズする例(その2)

【連載】

にわか管理者のためのLinux運用入門

【第269回】Vimを使う - ジャンプをカスタマイズする例(その2)

[2021/02/23 08:00]後藤大地 ブックマーク ブックマーク

前回は、「)」を押したときに、自分の求める場所へカーソルをジャンプさせる設定方法について説明した。最終的に、以下のような設定にしたことで開始タブの次の場所へカーソルがジャンプするようになり、不必要な場所へはジャンプしないようになった。

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>

※ 本記事は掲載時点の情報であり、最新のものとは異なる場合がございます。予めご了承ください。

一覧はこちら

連載目次

関連リンク

この記事に興味を持ったら"いいね!"を Click
Facebook で TECH+ の人気記事をお届けします
注目の特集/連載
[解説動画] Googleアナリティクス分析&活用講座 - Webサイト改善の正しい考え方
ニューノーマル時代のオウンドメディア戦略
ミッションステートメント
教えてカナコさん! これならわかるAI入門
AWSではじめる機械学習 ~サービスを知り、実装を学ぶ~
対話システムをつくろう! Python超入門
Kubernetes入門
SAFeでつくる「DXに強い組織」~企業の課題を解決する13のアプローチ~
PowerShell Core入門
AWSで作るマイクロサービス
マイナビニュース スペシャルセミナー 講演レポート/当日講演資料 まとめ
セキュリティアワード特設ページ

一覧はこちら

今注目のIT用語の意味を事典でチェック!

一覧はこちら

会員登録(無料)

ページの先頭に戻る