我正在尝试修改this terrific VIM script但是原始版本和修改版本都有一个令人抓狂的错误,有时候光标显示在错误的位置。我可以做的最简单的例子是下面的71行文本文件。请注意,复制文件时,空格很重要。
<?php
/**
* Some silly method
*
* @param string Some silly string
*/
function someFunction()
{
global $class, $cv, $go, $pae;
global $messages, $counters, $ltn;
global $sh, $sub, $temp;
$charsets = array(
'us',
'si',
'pr',
'op',
'co',
'pa',
'av',
'pr',
'al',
'pc',
'pe',
'pi',
'pp',
'su',
'qu',
'de',
'ze',
'xo',
'mo',
'wo',
'de',
'mo',
'de',
'mo',
'dr',
'mo',
'de',
'mo',
'ev',
'pa',
'so',
'ms',
'bu',
'at',
'cu',
'pr',
'de',
'mo',
'nv',
'nl',
'nf',
'ne',
'nq',
'nt'
);
}
这是带有函数的相关.vimrc文件:
set cul
hi CursorLine term=none cterm=none ctermbg=20
set nu
set statusline+=%{WhatFunctionAreWeIn()}
set laststatus=2
fun WhatFunctionAreWeIn()
let strList = ["while", "foreach", "ifelse", "if else", "for", "if", "else", "try", "catch", "case"]
let foundcontrol = 1
let position = ""
normal mz
while (foundcontrol)
let foundcontrol = 0
" The idea here is to go back to non-whitespace character before
" the last hanging open { and to check if it is a close paran.
" If so, then go to the matching open paren and search for the
" preceding it.
" If not, then go ahead and check the keyword right there.
normal [{
?\S
let tempchar = getline(".")[col(".") - 1]
if (match(tempchar, ")") >=0 )
normal %
?\S
endif
let tempstring = getline(".")
for item in strList
if( match(tempstring,item) >= 0 )
let position = item . " - " . position
let foundcontrol = 1
break
endif
endfor
if(foundcontrol == 0)
normal `z
return tempstring.position
endif
endwhile
normal `z
return tempstring.position
endfun
从文件的开头开始,反复按j
,直到第63行。请注意,突出显示的光标线保持在正确的行(63),但光标显示在第55行。直接跳到第63行不会触发错误,只会反复按j
直到你到达那一行。
为什么会发生这种情况,我该如何解决?请注意,当光标出现在错误的位置时,按“z”确实会将光标捕捉到正确的位置。这是关于Kubuntu 11.10的VIM 7.3.154。
修改
我注意到在其他安装(Debian,CentOS)中测试错误是不确定的,它偶尔发生但不是在每个系统上的相同位置!您可以通过按j
来测试此代码,并注意您可能遇到的任何PHP文件中的光标位置。我会说,每百行中有一行会触发光标出现在错误位置的错误。
答案 0 :(得分:3)
我对这个函数的逻辑感到有些困惑,但我怀疑导致问题的是?\S
。它向后搜索非空白字符,并在文件到达顶部时环绕到文件的底部。
尝试用
替换?\S
的两次出现
call search('\S','bW')
(此处b
标志向后搜索,W
阻止文件环绕。)
编辑(第二次尝试)
该功能还会导致大量跳转视图。其根源是不断设置标记mz
并来回跳跃。 vimscripts中更好的方法是使用以下命令保存当前视图(而不是normal mz
):
let pos=getpos(".") " This saves the cursor position
let view=winsaveview() " This saves the window view
然后您可以使用这些来恢复视图:
call cursor(pos) " This restores the cursor position to that of "pos"
call winrestview(view) " This restores the window view to that of "view"
因此,我会在call cursor(pos)
命令之前使用`z
代替call winrestview(view)
和return
。这确保了该功能不会修改窗口的外观,并且使用起来更加愉快。
希望这有帮助!