2012-03-15 42 views
0

我试图修改this terrific VIM script但是原始版本和我的修改版本都有一个令人生气的错误,其中有时光标显示在错误的地方。我可以做的最简单的例子是下面的71行文本文件。请注意,复制文件时,空格是重要的。为什么此功能在第63行“跳过”?

<?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注意,强调cursorline岿然不动正确的行(63),但光标显示在第55行。直接跳到第63行不会触发该错误,只需重复按j,直到您到达该行为止。

为什么会发生这种情况,我该如何解决?请注意,当光标出现在错误的位置时,按下“z”实际上会将光标捕捉到正确的位置。这在Kubuntu 11.10的VIM 7.3.154上。

编辑: 我在其他安装(Debian的,CentOS的),该错误是不是确定的测试发现,它有时但不是发生在同一个地方的每个系统上!您可以通过按j并注意您可能绑定的任何PHP文件中的光标位置来测试此代码。我会说,每百行中有一行触发了光标出现在错误位置的错误。

+0

尝试在相关行放置注释,而不是使用行号来引用它们。行号不显示在StackOverflow代码中。 – 2012-03-15 21:38:44

+0

评论使bug消失。这就是为什么我在'.vimrc'文件中提到'set nu'的原因。 – dotancohen 2012-03-15 21:57:30

回答

3

我对这个函数的逻辑有些困惑,但我怀疑是造成问题的?\S。它向后搜索非空白字符,并在文件到达顶端时将其包装到文件底部。

尝试用

call search('\S','bW') 

更换的?\S出现两次(在这里,b标志搜索倒着和W防止文件周围包裹。)

EDIT(第2次尝试)

该功能还会导致视图周围出现大量跳跃。这个根源不断设置标记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)而不是`zcall winrestview(view)就在return命令之前。这确保了该功能不会修改窗口的外观,并且使用起来更舒适。

希望这会有所帮助!

+0

谢谢王子炖牛肉。然而,将'?\ S'改为'call search('\ S','bW')'并没有帮助。我不相信将文件封装到文件末尾是个问题,因为问题所在的地区肯定存在非空白字符。但是,谢谢你试图帮助! – dotancohen 2012-03-15 22:32:28

+0

我编辑了代码以添加一个明确的评论。 – dotancohen 2012-03-15 22:35:54

+0

我不确定我是否正确地再现了这个问题,但是我已经在解决方案中再次出现了问题。 – 2012-03-15 22:35:54