Згорнути vim складку до одного рядка, подібно до Atom або Sublime Text


13

Я прихильник того, що Atom і Sublime Text обробляють складку рядків, де видно перший рядок кожної складки (у комплекті з підсвічуванням синтаксису), а маркер додається до кінця рядка, який позначає складку.

Дивіться знімок екрана, де порівнюється відступ Vim (згори) та Atom (знизу):Складання коду Vim проти Atom

Vim виділяє два рядки для кожної складки. Перший рядок виступає в якості заголовка, а другий рядок описує деяку інформацію про складку (кількість рядків і текст всередині сторінки).

Atom використовує лише один рядок і використовує невеликий маркер у кінці рядка для позначення згину разом із кольором, доданим до номерів рядків зліва. Складний стиль Atom використовує менше екрана нерухомості, але все ще передає всю інформацію, яка мені справді потрібна.

Я частковий до стилю складання Atom. На мою думку, це виглядає більш чітким і послідовним, особливо, якщо в рядку перераховується кілька методів або атрибутів (як на наведеному вище скріншоті).

Чи є спосіб приблизно наблизити стиль складання Atom у Vim?


1
Я думаю, це тому, що твої складки насправді не починаються з лінії, що містить дужки, що відкриваються. Vim використовує лише текст складок у рядку, з якого починається складка. Подивіться, наприклад, як розміщення брекетів
muru

Але це Python, жодних брекетів не включається ( from __future__ import braces) ... Як ви налаштували складку? І чи можете ви вставити цей фрагмент коду (чи інший, який демонструє проблему)? Vim складається в одну лінію, але, як згадував Муру, ваші складки починають лінію пізно.
Мартін Турной

@Carpetsmoker брекети служать лише для ілюстрації того місця, де починається складка. Такий же ефект можна побачити, скажімо, на Haskell.
муру

@MikeHearn Моя попередня відповідь була абсолютно неправильною. Я оновив його, щоб включити рішення проблеми.
Багатий

Відповіді:


12

Дві лінії проти однієї лінії

У Vim всі рядки в складці будуть згорнуті в один рядок, а 'foldtext'потім параметр визначає конспект цих рядків (зазвичай тире, кількість складених рядків та вміст з першого (або всіх) рядків).

У вашому прикладі у Vim {...}складено лише сам блок параметрів; рядок вище (який використовує параметри) не є частиною складки. Навпаки, в іншому редакторі цей рядок, що використовує параметри, належить до складки, а її складний текст (для використання терміналогії Vim) є вмістом цього рядка плюс доданий маркер.

Адаптація

У Vim складки можна генерувати різними способами (див. :help fold-methods), І це залежить 'filetype'від буфера. Від цього залежить складність включення зазначеного рядка в складку; перевірити :setlocal foldmethod?. При складанні відступів ви нічого не можете вплинути; вам доведеться перейти на інший метод. Для складання синтаксису це означатиме адаптацію визначень синтаксису, і це може бути дуже хитро. У вас буде більше удачі, якщо вираз буде використаний, але це все одно означатиме розуміння та зміну логіки. (Навряд чи автор плагіну файлів надав конфігурацію, щоб впливати на це.)

Підсвічування синтаксису складеної лінії

Це, на жаль, взагалі неможливо. Vim завжди використовує Foldedгрупу виділення для всієї складеної лінії. Ви можете налаштувати це за допомогою :highlightкоманд у вашому ~/.vimrc, але індивідуальна диференціація синтаксису буде втрачена.


5

Vim вже відображає складки як єдиний рядок. Однак у складі Віма indentвсі рядки, що мають однаковий відступ, включені в складку. Отже, на екрані екрана рядки, які ви називаєте "заголовками" (наприклад, той, що починається collection_base_url), не знаходяться в складках.

Ви можете домогтися чогось подібного до складання Atom, скориставшись Vim foldexpr foldmethod:

" Finds the indent of a line. The indent of a blank line is the indent of the
" first non-blank line above it.
function! FindIndent(line_number, indent_width)
    " Regular expression for a "blank" line
    let regexp_blank = "^\s*$"

    let non_blank_line = a:line_number
    while non_blank_line > 0 && getline(non_blank_line) =~ regexp_blank
        let non_blank_line = non_blank_line - 1
    endwhile
    return indent(non_blank_line) / a:indent_width
endfunction

" 'foldexpr' for Atom-style indent folding
function! AtomStyleFolding(line_number)
    let indent_width = &shiftwidth

    " Find current indent
    let indent = FindIndent(a:line_number, indent_width)

    " Now find the indent of the next line
    let indent_below = FindIndent(a:line_number + 1, indent_width)

    " Calculate indent level
    if indent_below > indent
        return indent_below
    elseif indent_below < indent
        return "<" . indent
    else
        return indent
    endif
endfunction

set foldexpr=AtomStyleFolding(v:lnum)
set foldmethod=expr

Це визначає вираз складки (див. :help fold-expr) Наступним чином:

  • Для рядків, що безпосередньо передують відступним лініям, він повертає відступ блоку, що випливає.
  • Для відступних рядків повертає відступ. (Ділиться на ширину зсуву, тому кожен рівень відступу збільшує повернене значення на 1)
  • Для рядків у кінці блоку відступних рядків він повертає рядок "<N", де N встановлюється до відступу. Це говорить Віму, що складка рівня N закінчується на цьому рядку.

Оновлення

@alxndr запитує в коментарях, чи можна розширити це, щоб включити обриси Рубі endв складки. Ви можете почати, замінивши " Calculate indent levelрозділ наступним:

if indent_below > indent
    return indent_below
elseif getline(a:line_number) =~ '^\s*end\s*$'
    return "<" . (indent + 1)
else
    return indent
endif

Насправді це не найнадійніше рішення (наприклад, воно вийде з ладу, якщо endоператор буде на тому ж рядку, після крапки з двокрапкою). Ви можете налаштувати регулярний вираз та оточуючий код для вирішення цього питання, але оскільки ви зараз перебуваєте в царині розбору фактичного синтаксису файлу, я підозрюю, що все може скластися набагато складніше, перш ніж ви матимете хороше рішення.


Чудовий підхід. Чи можна цю відповідь узагальнити і для того, щоб сказати Рубі, з її наміченим endзавершити блок?
alxndr

1
@alxndr Я відредагував свою відповідь під час деякої дискусії.
Багатий

@Rich: Я також знаходжу Sublime текст-складку, яка показує позначку лише ...в кінці рядка як символ складеного текстового блоку, дуже корисною і робить менше відволікань, ніж доведеться виділити весь перший рядок текстового блоку, як in vim. Я спробував ваше згортання вгорі з типовою поведінкою складки vim, просто не працює. Як скласти, що дають позначку в кінці першого рядка текстового блоку з python? Чи варто відкривати нове запитання? Я просто перевіряю ще раз вашу складку, вона справді дуже добре працює з відступом. супер Спасибі
Туйен Фам

Це дивно! Я шукав щось, що робить org-mode, як складання, і це дуже допомагає!
priomsrb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.