为什么这个功能在第63行“跳过”?

时间:2012-03-15 21:09:16

标签: function vim

我正在尝试修改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文件中的光标位置。我会说,每百行中有一行会触发光标出现在错误位置的错误。

1 个答案:

答案 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。这确保了该功能不会修改窗口的外观,并且使用起来更加愉快。

希望这有帮助!