vimにおけるphpの関数移動について
vimで関数移動といえば
[[
もしくは
]]
ですね。
関数の前方または後方に一発ジャンプしてくれる便利な奴。
ただfiletypeがphpの時はなぜか挙動が違うくて、前方または後方の関数宣言にジャンプしてしまう。
この動きに関しては特に不満はないんやけど、
困ったことに検索パターンのレジスタ(@/)を関数宣言用の正規表現で上書きしやがる。
これはひっじょ〜〜〜〜〜にウザい。
しかも
nnoremap [[ :<C-u>call search('function', 'b')<CR>
とかやっても効いてくれんっていう。
今日はこれを解決するために動き出す。
調査
まずは調査。
本来の動作と違うのでどっかでmapしてるやろうと。
:verbose map [[
ふむふむ。ftpluginか、なるほど。
なんかほぼ答えが見えてるけど、とりあえず追跡してみる。
:e $VIMRUNTIME/ftplugin/php.php
" Section jumping: [[ and ]] provided by Antony Scriven <adscriven at gmail dot com> let s:function = '\(abstract\s\+\|final\s\+\|private\s\+\|protected\s\+\|public\s\+\|static\s\+\)*function' let s:class = '\(abstract\s\+\|final\s\+\)*class' let s:interface = 'interface' let s:section = '\(.*\%#\)\@!\_^\s*\zs\('.s:function.'\|'.s:class.'\|'.s:interface.'\)' exe 'nno <buffer> <silent> [[ ?' . escape(s:section, '|') . '?<CR>:nohls<CR>' exe 'nno <buffer> <silent> ]] /' . escape(s:section, '|') . '/<CR>:nohls<CR>' exe 'ono <buffer> <silent> [[ ?' . escape(s:section, '|') . '?<CR>:nohls<CR>' exe 'ono <buffer> <silent> ]] /' . escape(s:section, '|') . '/<CR>:nohls<CR>'
てわけで普通に?と/でやってました。そら上書きされるわ。
しかも
まぁ言語ごとに関数定義の正規表現は違うんで
対応策
原因がわかったところで対応開始。
かなりやっつけですが、以下を~/.vimrcに記述。
augroup MyAutoCmd autocmd! augroup END " phpにてlast-patternを変更しない関数移動を再マップ autocmd MyAutoCmd FileType php call <SID>RemapPHPSectionJump() function! s:RemapPHPSectionJump() let l:function = '\(abstract\s\+\|final\s\+\|private\s\+\|protected\s\+\|public\s\+\|static\s\+\)*function' let class = '\(abstract\s\+\|final\s\+\)*class' let interface = 'interface' let section = '\(.*\%#\)\@!\_^\s*\zs\('.function.'\|'.class.'\|'.interface.'\)' exe "nno <buffer> <silent> [[ :call search('" . escape(section, '|') . "', 'b')<CR>" exe "nno <buffer> <silent> ]] :call search('" . escape(section, '|') . "')<CR>" exe "ono <buffer> <silent> [[ :call search('" . escape(section, '|') . "', 'b')<CR>" exe "ono <buffer> <silent> ]] :call search('" . escape(section, '|') . "')<CR>" endfunction
自分は一元管理したいので~/.vimrcに書いたけど、本来は~/.vim/ftplugin/php.vim なんかな。
とりあえずはスッキリ、ノーストレスで良い感じになりました。
同じ現象で困っている方は是非ご賞味ください。
副作用でたらゴメンナサイ。
補足
ここでpythonのftpluginをチラ見してみる。
:e $VIMRUNTIME/ftplugin/python.vim
nnoremap <silent> <buffer> ]] :call <SID>Python_jump('/^\(class\\|def\)')<cr> nnoremap <silent> <buffer> [[ :call <SID>Python_jump('?^\(class\\|def\)')<cr> nnoremap <silent> <buffer> ]m :call <SID>Python_jump('/^\s*\(class\\|def\)')<cr> nnoremap <silent> <buffer> [m :call <SID>Python_jump('?^\s*\(class\\|def\)')<cr> if exists('*<SID>Python_jump') | finish | endif fun! <SID>Python_jump(motion) range let cnt = v:count1 let save = @/ " save last search pattern mark ' while cnt > 0 silent! exe a:motion let cnt = cnt - 1 endwhile call histdel('/', -1) let @/ = save " restore last search pattern endfun
last-patternを一旦退避させてますね。えらいですね。
この優しさがphpにも欲しかった。