Nano Hash - криптовалюты, майнинг, программирование

vim замедляется при использовании fold-expr

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

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 значительно замедляется. Это неудивительно и фактически указано в справке fold-expr в vim. Это связано с тем, что знак = говорит vim сканировать файл в обратном направлении, пока не будет найдена первая строка с явно определенным уровнем сгиба; это может быть тысячи строк.

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

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

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

09.12.2014

Ответы:


1

Думали ли вы об использовании подключаемого модуля vim-markdown-folding Дрю Нельстрема?

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

Предостерегающие мысли

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

  • Использование выражений относительного сворачивания, таких как =, означает, что нам нужно вычислить предыдущую строку, так что, как вы понимаете, это может стать проблематичным. Попробуйте использовать точную глубину без вычисления других линий, если можете.
  • Вы используете getline() дважды в своей функции без необходимости
  • Некоторые файлы просто вызовут проблемы, примите этот факт и отключите сворачивание через zi
09.12.2014
  • Я профилировал его, и проблема в return "=" . Он вызывается очень часто и требует довольно много времени для запуска. Кажется, я не могу найти альтернативу, работающую с return foldlevel(v:lnum-1). Интересно, есть ли способ обойти это. 10.12.2014
  • Я думаю, что исправил это. Буду рад любым отзывам, комментариям. 10.12.2014

  • 2

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

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

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

    Узнав, как профилировать сценарии vim от @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
    
    10.12.2014

    3

    Этого и следовало ожидать, поскольку 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.
    
    09.12.2014
  • Спасибо. Я знаю об этом; это указано в моем посте. Я пытаюсь найти альтернативу знаку =. 10.12.2014
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..