Чувствительность к контексту в комментариях - PullRequest
1 голос
/ 05 марта 2012

При ручной настройке сгибов было бы удобно, если бы можно было установить commentstring с учетом контекста. Рассмотрим случай, когда в языке используются маркеры комментариев в стиле BCPL (то есть комментарии начинаются с // и заканчиваются новой строкой), первая строка визуального блока содержит комментарий, а последняя строка - нет. В настоящее время, если commentstring установлено на //%s, избыточные символы // будут добавлены к первой строке, когда zf используется для создания сгиба.

Можно ли установить commentstring так, чтобы символы // добавлялись, только если они еще не появляются в строке?

1 Ответ

1 голос
/ 06 марта 2012

В соответствии с :help fold-create-marker, автоматическая вставка маркера складывания не работает должным образом, когда:

  • Строка уже содержит маркер с номером уровня. Vim тогда не знать, что делать.
  • Складки рядом используют номер уровня в своем маркере, который мешает.
  • Строка внутри комментария, commentstring не пустая и не вложенная комментарии не работают. Например с C: добавление /* {{{ */ внутри комментарий урезает существующий комментарий.

Таким образом, невозможно изменить поведение zf по умолчанию, изменив commentstring настройка.

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

nnoremap <silent> <leader>zf :set opfunc=CreateMarkerFold<cr>g@
vnoremap <silent> <leader>zf :<c-u>call CreateMarkerFold(visualmode(), 1)<cr>
function! CreateMarkerFold(vt, ...)
    let range = map(['[<', ']>'], 'line("''".v:val[a:0])')
    let mark = split(&foldmarker, ',')
    let pat = escape(&commentstring, '\')
    let pat = '\V' . substitute(pat, '\\\@<!%s', '\\zs\\ze\\.\\{-}', '')
    for i in [1, 0]
        let line = getline(range[i])
        if line =~ pat
            let line = substitute(line, pat, escape(mark[i], '\'), '')
        else
            let line .= printf(&commentstring, mark[i])
        endif
        call setline(range[i], line)
    endfor
endfunction

Оба отображения следуют одной и той же процедуре. Перед добавлением запуска и заканчивая складывание маркеров, он отдельно проверяет, является ли первый и последний линии блока для сгиба соответствуют шаблону commentstring. Для каждого из два, которые совпадают, он вставляет соответствующий маркер внутри первого найденного комментарий, в самом начале своего текста. В противном случае маркер оформлен по шаблону commentstring и добавлен в конце линия.

Если в последнем случае предпочтительнее разделить маркер на отдельной строке, можно изменить цикл for, как показано ниже.

    for i in [1, 0]
        let line = getline(range[i])
        if line =~ pat
            let line = substitute(line, pat, escape(mark[i], '\'), '')
            call setline(range[i], line)
        else
            call append(range[i] - !i, printf(&commentstring, mark[i]))
        endif
    endfor

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

...