我正在使用vim编辑乳胶文档。通常,我会想要将变量的名称更改为其他名称。但是,当我搜索变量名称时,必须经过不相关的匹配项有点烦人。我只想在tex语法文件中定义的“数学区域”中搜索。有没有一种简单的方法可以将搜索限制到特定的语法区域?
我正在使用vim编辑乳胶文档。通常,我会想要将变量的名称更改为其他名称。但是,当我搜索变量名称时,必须经过不相关的匹配项有点烦人。我只想在tex语法文件中定义的“数学区域”中搜索。有没有一种简单的方法可以将搜索限制到特定的语法区域?
Answers:
这是您可以尝试的功能。我只测试了一点,但似乎工作正常。
function! JJSyntaxSearch(pattern, syntaxitem)
while search(a:pattern, 'W') > 0
for id in synstack(line("."),col("."))
if synIDattr(id,"name") =~? a:syntaxitem
return line(".")
endif
endfor
endwhile
return 0
endfunc
command! -nargs=* JJSyntaxSearch call JJSyntaxSearch(<f-args>)
该函数在循环中调用Vim的搜索函数,直到找到与特定语法项也“合格”匹配的“普通”匹配,或者直到到达缓冲区末尾为止。
它有两个参数。第一个是搜索模式,它不变地传递给Vim的search()
函数。请参阅:help search()
以了解该功能的工作原理。第二个参数是要在其上过滤这些匹配项的语法项的名称。这也可以是模式,并作为不区分大小写的正则表达式进行比较。
要在数学区域中找到模式“ alpha”,您可以执行
:JJSyntaxSearch alpha texMathZone.
所述.
在端部为任何单个字符的图案原子,见:help /.
。这是因为有许多数学区域语法项目叫texMathZoneA
,texMathZoneB
等。
该search()
功能将光标移至下一个“普通”匹配项。然后,我们的函数使用来获取该新光标位置的所有语法项ID synstack()
。遍历它们,它依次检索每个项目的名称,并根据syntaxitem
参数对其进行测试。请参阅:help synstack()
和:help synIDattr()
。如果存在“限定”匹配,则返回行号。如果到达缓冲区末尾而没有找到任何“限定”匹配,则返回0
。该函数的重点是使光标移至下一个“限定”匹配,因此您可以在那里进行一些操作,但是返回“行号或0”以指示再次调用该函数是否有意义,对于此操作很有用。实例,如果您想从另一个函数或宏重复调用该函数。
我选择将W
标志用于,search()
因为它可以防止“缠绕”缓冲区的末端。否则,该函数可能会卡住,因为它会不断查找相同的“普通”匹配项,但找不到“合格”的匹配项。
如果您的“数学区域”通过某种语法模式(例如字符串“ math”)来限定,那么您至少可以使用模式序列来查找具有匹配模式的行,例如:
:/math//your pattern/
(注意:这两种模式可能在不同的行上!)
这可能不会将您的比赛限制在区域内-因为您需要标识区域的末端-但是它只会在初始模式/ math /之后显示那些比赛。您可以使用ex-mode历史记录(:
up-arrow
enter
)重复搜索下一次出现的情况。
/math//your pattern/
用更少的打字优势和使用的n
和N
命令,但我无法证实对于我当前的vim版本。
如果您正在搜索的字符串foo
内$...$
或$$...$$
,这应该工作:
\$.*\zsfoo
这将匹配项锚定到一个$
字符,但仅选择字符串foo
。
这并不是一个简单的解决方案,但是可以使用:global
+ :substitute
查找“数学区域”并在其中搜索:
:global /\v\\begin\{%(align|alignat|displaymath)\}/ +1,/\\end/-1 s/foo/&/gc
假设这:substitute
是一个搜索命令,您可以使用转到下一个出现的位置,n
然后使用退出q
。如果您错误地确定替换,则不会有任何问题。
您将必须在%(
... 内将列表设置为)
您所使用的数学环境的名称(完整列表有点繁琐:)align|alignat|displaymath|eqnarray|equation|flalign|gather|math|multline|subequations|xalignat|xxalignat
。请注意,我在这里使用了一种非常魔术(\v
)模式。
说明:
:global
执行Ex命令(:s
每行),其中所述图案匹配(:help :global
)
/\v
启动一个非常魔图案(:h /
,:h pattern
,:h magic
)
\\begin\{
匹配一个\begin{
%(align|alignat|displaymath)
匹配任何这些字(:h /\%(
,:h /bar
)
\}/
匹配文字}
和结束图形。
+1,/\\end/-1
由下一行(从查找到的数开始:global
)到搜索模式找到的之前的一行的范围/\\end
。在这个范围内
s/foo/&/gc
foo
确认(:h :substitute
)后,用文字本身搜索并替换每次出现的文字
\mathit
围绕变量名使用,则查找它们会容易得多。
如果你的字符串“早晨”内部文件检索
/morning
,然后enter按n前进方向
I would like to search only in "math zones"
您的方法会搜索整个文件,而不会划定研究范围。
别无选择,只能为此编写一个专用功能。我编写了一个函数,该函数搜索所需的字符串,并且仅在以下情况之一时停止:
您只需使用要搜索的字符串来调用它。
function! Finmath(nextstr)
while 1
if search(a:nextstr)==0
break
endif
if searchpairpos('\(', '','\)','n')!=[0,0]
break
endif
if searchpairpos('\[', '','\]','n')!=[0,0]
break
endif
let a = getcurpos()
if count(strpart(getline('.'),0,a[2]),'$')%2==1
break
endif
endwhile
endfunction
我打算为GrammerousCheck写一个类似的函数,该函数仅在数学之外的语法错误时停止。