Это невозможно с регулярными выражениями vim (поскольку язык, допускающий такие вложенные конструкции, не является регулярным), но возможно с «регулярными» выражениями, предоставляемыми perl (а также с другими языками, которых я не знаю достаточно, чтобы быть уверенным) и perl можно использовать изнутри vim.Мне не нравятся привязки vim-perl (потому что они очень ограничены), но если вы знаете все случаи, которые должны работать, то вы можете использовать функцию рекурсии регулярных выражений perl (требуется более новый perl, у меня есть 5.12 *):
perl VIM::Msg($+{"outer"}) if $curbuf->Get(3) =~ /someKeyword\((?'outer'(?'inner'"(?:\\.|[^"])*"|'(?:[^']|'')*'|[^()]*|\((?P>inner)*\))*)\)/
Обратите внимание, что если вы можете избежать таких регулярных выражений, вы должны это сделать (поскольку вы слишком сильно зависите от re-compiler), поэтому я предлагаю использовать движения vim напрямую:
let s:reply=""
function! SetReplyToKeywordArgs(...)
let [sline, scol]=getpos("'[")[1:2]
let [eline, ecol]=getpos("']")[1:2]
let lchar=len(matchstr(getline(eline), '\%'.ecol.'c.'))
if lchar>1
let ecol+=lchar-1
endif
let text=[]
let ellcol=col([eline, '$'])
let slinestr=getline(sline)
if sline==eline
if ecol>=ellcol
call extend(text, [slinestr[(scol-1):], ""])
else
call add(text, slinestr[(scol-1):(ecol-1)])
endif
else
call add(text, slinestr[(scol-1):])
let elinestr=getline(eline)
if (eline-sline)>1
call extend(text, getline(sline+1, eline-1))
endif
if ecol<ellcol
call add(text, elinestr[:(ecol-1)])
else
call extend(text, [elinestr, ""])
endif
endif
let s:reply=join(text, "\n")
endfunction
function! GetKeywordArgs()
let winview=winsaveview()
keepjumps call search('someKeyword', 'e')
setlocal operatorfunc=SetReplyToKeywordArgs
keepjumps normal! f(g@i(
call winrestview(winview)
return s:reply
endfunction
Выможет использовать что-то вроде
let savedureg=@"
let saved0reg=@0
keepjumps normal! f(yi(
let s:reply=@"
let @"=savedureg
let @0=saved0reg
вместо operatorfunc для сохранения и восстановления регистров, но приведенный выше код оставляет все регистры и пометки нетронутыми, что я не могу гарантировать с сохраненными * данными.Это также гарантирует, что если вы удалите join()
вокруг text
, вы сохраните информацию о расположении NULL (если вы, конечно, заботитесь о них).Это невозможно с вариантом регистров.