Как настроить Vim для работы с одним предложением в строке?

17

В настоящее время я пишу много простого текста (и LaTeX с минимальным форматированием в абзацах), и было бы неплохо, если бы я мог настроить vim, чтобы сохранить каждое предложение (для простоты, текст заканчивается на «.», «!» или '?' - это завершающая пунктуация, за которой следует пробел, чтобы не разбивать десятичные числа) на отдельной строке, чтобы различия в VCS были более полезными.

Как минимум, я хотел бы gqотформатировать текст из:

He lay flat on the brown, pine-needled floor of the forest, his chin on his
folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he
could see the dark of the oiled road winding through the pass. There was a
stream alongside the road and far down the pass he saw a mill beside the
stream and the falling water of the dam, white in the summer sunlight. 

Для того, чтобы:

He lay flat on the brown, pine-needled floor of the forest, his chin on his folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he could see the dark of the oiled road winding through the pass.
There was a stream alongside the road and far down the pass he saw a mill beside the stream and the falling water of the dam, white in the summer sunlight.

Но было бы неплохо, если бы vim также выполнял это форматирование по мере ввода текста (как это происходит с переформатированием текстовой полосы). Это возможно?

Мое текущее решение состоит в том, чтобы присоединиться к абзацу J, а затем запустить, :'<,'>s/\. /.\r/gчто довольно неплохо, поскольку в нем мало восклицательных и вопросительных знаков, но было бы намного лучше, если бы я мог сделать gq немного умнее.

Alex
источник

Ответы:

23

'formatexpr'вариант

Вы можете добиться этого, используя 'formatexpr'опцию. Из справки:

Выражение, которое вычисляется для форматирования диапазона строк для оператора gq или автоматического форматирования (см. «Formatoptions»). Когда эта опция пуста, используется formatprg.

'formatexpr'Правильная настройка будет работать как при использовании, так gqи при вставке текста.

Простой пример

Вот простая функция VimScript и соответствующее 'formatexpr'значение, которое должно делать эту работу. Я не тестировал его во всех крайних случаях, но он хорошо работал для моих простых тестов.

function! MyFormatExpr(start, end)
    silent execute a:start.','.a:end.'s/[.!?]\zs /\r/g'
endfunction

set formatexpr=MyFormatExpr(v:lnum,v:lnum+v:count-1)

объяснение

Выражение является вызовом функции MyFormatExpr(), передавая начальную и конечную строки, к которым будет применено форматирование. Эти строки вычисляются с использованием автоматически заполненных переменных v:lnum(первая строка для форматирования) и v:count(количество строк для форматирования).

MyFormatExpr()Функция создает :substituteкоманду с переданному в диапазоне, и заменяет пробел после знака препинания конца-предложений ( ., !или ?) с новой строкой ( \r).

Предостережения

  • MyFormatExpr()Функция не сохраняет ведущий отступ. Чтобы это исправить, понадобится более сложная логика.
  • Могут быть другие крайние случаи, когда это разваливается. Проведите тест-драйв и настройте по мере необходимости!
tommcdo
источник
О, да, это путь, игнорируй мой ответ.
Суким
Это круто! Я хотел бы, чтобы функция запускала макрос, такой как «перейти к следующему предложению )и вставить новую строку; повторять до тех пор, пока не достигнете конца диапазона». Тогда он предположительно будет применять любые правила отступов. Но мой Вимфу слишком слаб для этого. :)
Натан Лонг
Это распадается, например e.g. blah, и Blah et al. 2018это немного раздражает. Вы можете сопоставить подобные шаблоны с чем-то вроде 's/\(e\.g\|\<al\)\@<![.!?]\zs /\r/g'. Просто добавьте больше шаблонов в первую группу, чтобы избежать других вещей, на которые вы не хотите делиться. В противном случае, это супер полезно, спасибо. Я не сталкивался gqраньше, и gqipэто супер полезно для форматирования текста, который искажены текстовые редакторы соавтора.
naught101
Есть ли способ добавить это поведение к поведению по умолчанию? Я хотел бы иметь возможность обтекания при заданной ширине текста, а также разбиение в конце предложений ..
naught101
1

Ну, вы можете настроить некоторые карты и автокоманды:

function! AddSentenceMaps()
  imap .<Space> .<CR>
  imap !<Space> !<CR>
  imap ?<Space> ?<CR>
  exec "nmap gq vipJ:s/\\([.!?]\\)\\s\\+/\\1\\r/g<CR>"
endfunction

autocmd Filetype customtxt call AddSentenceMaps()

Затем просто установите тип файла в customtxt или вызовите AddSentenceMapsфункцию вручную.

Sukima
источник
0

Я хочу добавить свои мысли по этому вопросу. Обычно люди хотят такой особенности из - за перепрыгивая через завернутые линии , когда те , перемещаясь по коду с jи kкоманды , которые по умолчанию поведение Vim. Для навигации по заштрихованным линиям я использую gj- двигаться вниз и gk- двигаться вверх. Также есть возможность переназначения стандарта jи kкоманды на g-префиксные аналоги, но ИМХО это было бы излишним.

Александр Мышов
источник
или есть ключ , чтобы сделать это remaping от jи kдо , gjи gkкогда вы хотите ;-)
Антони
0

Он не отвечает на ваш конкретный вопрос о переформатировании, но «set wrap» вместе с «set linebreak» могут сделать редактирование длинных строк намного более приятным. Объедините это с gj и gk для навигации по заштрихованным строкам. Я отображаю стрелки вверх и вниз на gj и gk соответственно, так что у меня есть выбор между перемещением вверх и вниз реальных линий или визуальных линий. Как и для Home / End до g0 / g $.

Нарисовалась
источник