2014-12-09 1 views
2

Я пытаюсь создать простой, быстрый метод складывания для больших файлов разметки. Я использую метод fold-expr в vim. Например, если я хотел бы начать складки на H1 и H2 записей уценки, мой vimscript код:vim замедляется при использовании fold-expr

function! MarkdownLevel() 
    if getline(v:lnum) =~ '^# ' 
     " begin a fold of level one here 
     return ">1" 
    elseif getline(v:lnum) =~ '^## ' 
     " begin a fold of level two 
     return ">2" 
    else 
     return "=" 
    endif 
endfunction 

Это отлично работает, и я получаю вложенные складки. Однако, когда у меня есть большой файл уценки, vim значительно замедляется. Это неудивительно и, по сути, указано в справке с помощью expr в vim. Это потому, что знак = говорит vim сканировать назад в файле до тех пор, пока не будет найдена первая строка с явно указанным foldlevel; это может быть тысячи линий.

Я попытался заменить последнюю строку с

else 
     " set foldlevel to foldlevel of previous line 
     return foldlevel(v:lnum-1) 
    endif 

Но это не работает, как ожидалось. Кто-нибудь знает, как это исправить? Понятно, что я не понимаю, как работает функция foldlevel, или как реализуется алгоритм сгибания в vim.

ответ

1

Вы думаете об использовании плагина Drew Nelstrom's vim-markdown-folding?

Вы также можете посмотреть, что эпизод Vimcast: Profiling Vimscript performance. Этот эпизод фактически говорит об уклонении от складывания.

Cautionary мысли

Я не могу быть наверняка, потому что я не профилированный код (и вы должны действительно свой код), но как раз выражение вызывается на каждой линии каждый раз, когда вещи становятся перерисованы это может быть очень облагается налогом на Vim. Некоторые догадки:

  • Использование относительных выражений кратные как = означает, что нам нужно вычислить предыдущую строку, так как вы можете себе представить, это может стать проблематичным. Попытайтесь использовать точные глубины, не вычисляя другие линии, если сможете.
  • Вы используете getline() дважды в функции без необходимости
  • Некоторые файлы только собирается вызвать проблемы принять этот факт и отключить складывающиеся с помощью zi
+0

Спасибо, я попробую профилировать его. – user128063

+0

Я профилировал его, и проблема заключается в 'return '=" '. Его часто называют, и он занимает довольно много времени для запуска. Кажется, у меня не получается альтернативный запуск с 'return foldlevel (v: lnum-1)'. Интересно, есть ли способ обойти это. – user128063

+0

Думаю, я исправил это. Буду признателен за любые отзывы, комментарии. – user128063

0

То есть можно ожидать, так как Vim должен вычислить ваше выражение много для каждой линии. Это также упоминается в справке ниже :h fold-expr

Note: Since the expression has to be evaluated for every line, 
this fold method can be very slow! 

Try to avoid the "=", "a" and "s" return values, since Vim often 
has to search backwards for a line for which the fold level is 
defined. This can be slow. 
+0

Спасибо. Я знаю об этом; это указано в моем посте. Я пытаюсь найти альтернативу знаку '='. – user128063

1

Я понял, как исправить замедление и узнал нечто о том, как fold-expr работает в Vim. Я тестировал проблемы с производительностью в файле 3000 md.

Я полагался на следующие функции автоматического складывания, которые должны иметь fold-expr: он начинает сгиб, если складной уровень текущей линии меньше, чем складной уровень следующего. Он заканчивается сгибом, если уровень сложения текущей линии больше, чем складной уровень следующего. Оказывается, что это не работает, как я предполагал.

То, что работало в том, чтобы явно указать Vim, что складка начинает здесь используя return ">1", где 1 заменяется соответствующим номером.

После обучения, как профиль ВЬЕТ скрипты из @PeterRinker, я понял, что return "=" заявления оценивается много, много раз, когда я линия (к примеру) 3000.

Это было мое исправление редактирования: если Слой уровня текущей линии не попадает ни в один из типов заголовков и уже был определен уровень сложения предыдущей строки, текущая строка должна просто наследовать уровень сложения предыдущей строки. Это очевидное решение, но оно не работает, если я использовал return "1" вместо return ">1" выше. На первом проходе необходимо указать return "=", чтобы выяснить уровень складок.

Так что мои стартовые времена немного большие (около 1 секунды) для 3000-строчного файла, но теперь редактирование очень плавное. Ниже приведен готовый, упрощенный код. Другие более сложные проекты по уценке не имеют этого полезного упрощения.

function! MarkdownLevel() 
    let theline = getline(v:lnum) 
    let nextline = getline(v:lnum+1) 
    if theline =~ '^# ' 
     " begin a fold of level one here 
      return ">1" 
    elseif theline =~ '^## ' 
     " begin a fold of level two here 
      return ">2" 
    elseif theline =~ '^### ' 
     " begin a fold of level three here 
      return ">3" 
    elseif nextline =~ '^===*' 
     " elseif the next line starts with at least two == 
     return ">1" 
    elseif nextline =~ '^---*' 
     " elseif the line ends with at least two -- 
     return ">2" 
    elseif foldlevel(v:lnum-1) != "-1" 
     return foldlevel(v:lnum-1) 
    else 
     return "=" 
    endif 
end 
Смежные вопросы