Почему эта функция «пропускается» в строке 63? - PullRequest
0 голосов
/ 16 марта 2012

Я пытаюсь изменить этот потрясающий сценарий VIM , однако как в оригинальной, так и в моей измененной версии есть сводящая с ума ошибка, из-за которой иногда курсор отображается не в том месте.Простейший пример, который я могу сделать, это текстовый файл из 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` фактически приводит курсор в правильное положение.Это на VIM 7.3.154 на Kubuntu 11.10.

РЕДАКТИРОВАТЬ: При тестировании в других установках (Debian, CentOS) я замечаю, что ошибка не определена, иногда она возникает, но не водно и то же место в каждой системе!Вы можете проверить этот код, нажав j и обращая внимание на расположение курсора в любых PHP-файлах, на которые вы могли наткнуться.Я бы сказал, что примерно одна строка из каждых ста строк вызывает ошибку, при которой курсор оказывается не в том месте.

1 Ответ

3 голосов
/ 16 марта 2012

Меня слегка смущает логика этой функции, но я подозреваю, что именно ?\S вызывает проблемы. Он ищет в обратном направлении непробельный символ и переносится в конец файла, как только он достигает вершины.

Попробуйте заменить оба вхождения ?\S на

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

(Здесь флаг b выполняет поиск в обратном направлении, а W предотвращает обтекание файла.)

РЕДАКТИРОВАТЬ (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) вместо `z и call winrestview(view) непосредственно перед командами return. Это гарантирует, что функция не изменяет внешний вид окна и обеспечивает более приятное использование.

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...