Больше не нужно портить пробелы в VIM - PullRequest
2 голосов
/ 09 января 2012

К моему .vimrc добавлен хук BufWritePre, который обрезает конечные пробелы перед сохранением буфера.Это очень удобно для меня при редактировании собственного кода или кода других пользователей, у которых также есть политика всегда удалять конечные пробелы.Тем не менее, это иногда заставляет меня испортить пробел в окружении других, что не очень хорошо выглядит в управлении версиями.

У меня есть две идеи, как это можно решить в целом, с обоими из которых у меня есть определенные проблемы:

Опция 1

После открытия файла (возможно, с помощью хука BufReadPost) определите, есть ли в файле конечные пробелы.Если да, установите локальный флаг буфера, чтобы сообщить об этом.Если флаг установлен, отключите обрезку перед сохранением.

Проблема, с которой я сталкиваюсь при таком подходе, заключается в том, что я, похоже, не могу понять , как я могу определить, есть ли конечные пробелы в буфере.Я знаю о =~, но как мне получить содержимое буфера в виде строки?Или, что еще лучше, я могу выполнить поиск, используя /\s+$<cr>, но как я могу проверить, был ли поиск успешным (если есть попадания)?

Вариант 2 (более интеллектуальный)

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

Я новичок в Vimscript, поэтому буду признателен за любые советы или подсказки :)

ОБНОВЛЕНИЕ: Сейчас я выбрал вариант 1:

" configure list facility
highlight SpecialKey term=standout ctermbg=yellow guibg=yellow
set listchars=tab:>-,trail:~

" determine whether the current file has trailing whitespace
function! SetWhitespaceMode()
  let b:has_trailing_whitespace=!!search('\v\s+$', 'cwn')
  if b:has_trailing_whitespace
    " if yes, we want to enable list for this file
    set list
  else
    set nolist
  endif
endfunction

" trim trailing whitespace in the current file
function! RTrim()
  %s/\v\s+$//e
  noh
endfunction

" trim trailing whitespace in the given range
function! RTrimRange() range
  exec a:firstline.",".a:lastline."substitute /\\v\\s+$//e"
endfunction

" after opening and saving files, check the whitespace mode
autocmd BufReadPost  * call SetWhitespaceMode()
autocmd BufWritePost * call SetWhitespaceMode()
" on save, remove trailing whitespace if there was already trailing whitespace
" in the file before
autocmd BufWritePre  * if !b:has_trailing_whitespace | call RTrim() | endif

" strip whitespace manually
nmap <silent> <leader>W :call RTrim()<cr>
vmap <silent> <leader>W :call RTrimRange()<cr>

Ответы [ 3 ]

4 голосов
/ 09 января 2012

Опция 1 может использовать функцию search(), например:

let b:has_trailing_spaces=!!search('\v\s+$', 'cwn')

search() Функция возвращает номер совпавшей строки (они начинаются с 1) или 0, если ничего не найдено, !! превращает его в 1 или 0, отбрасывая информацию о том, в какой строке search() найден завершающий пробел.Без n flag search() перемещает курсор, что, я думаю, нежелательно.Без w он может искать только в той части буфера, которая находится после курсора (действительно зависит от опции 'wrapscan').

Предлагаемая реализация варианта 2 - это хак, использующий InsertLeave и '[, '] маркеры:

augroup CleanInsertedTrailingSpaces
    autocmd!
    autocmd InsertLeave * let wv=winsaveview() | keepjumps lockmarks '[,']s/\s\+$//e | call winrestview(wv)
augroup END

Предполагается, что вы добавляете только пробельные символы после ввода.Он сломается, если вы наведете курсор на линии в режиме вставки.Вы также можете попробовать добавить

    autocmd CursorHold * if getpos("'.")[1]!=0 | let wv=winsaveview() | keepjumps lockmarks '.s/\s\+$//e | call winrestview(wv) | endif

, это должно удалить завершающие пробелы в строке последнего изменения (здесь не может использоваться только одна строка, '[ и '], поскольку они указывают на первую ипоследние строки часто бывают полезными).Обе автокоманды должны добавить информацию в дерево отмены.

Для опции 2 есть вторая опция: git annotate может аннотировать текущее состояние файла, таким образом, вы можете использовать grep для фильтрации строк, которые имеюти завершающие пробелы, и незавершенные изменения, и используйте ловушку для удаления ненужных пробелов из них перед фиксациейПечально, но hg annotate не может этого сделать, поэтому вам придется написать что-то более сложное, возможно, на python.Я ничего не могу сказать о других системах VC.

Полагаю, было бы лучше, если бы вы использовали set list listchars+=trail:-, чтобы увидеть такие пробелы и, таким образом, иметь возможность удалить их вручную, если они случайно появляются (лично я могу 'Я не забываю, что постоянно добавляю завершающие пробелы случайно, хотя в комментариях и документации они используются мной намеренно, чтобы указать, что абзац продолжается).Что вы делаете, чтобы появилась эта проблема?

3 голосов
/ 09 января 2012

Я не позволяю vim автоматически обрезать что-либо. Как вы говорите, это может быть кошмаром, если иметь дело с кодексом других людей, и может привести к ненужным конфликтам. Подход, который я использую, чтобы сохранить мой собственный код в чистоте, состоит в том, чтобы сделать пробел видимым. С помощью vim этого можно добиться, добавив в файл ~/.vimrc следующее:

highlight SpecialKey ctermfg=DarkGray
set listchars=tab:>-,trail:~
set list

В результате вы увидите следующие пробелы:

vim show whitespace

Это позволяет мне сохранять файлы в чистоте, пока я пишу их. Большинство других (GUI) редакторов также могут отображать пробелы.

2 голосов
/ 10 января 2012
" Show trailing whitepace and spaces before a tab:
:highlight ExtraWhitespace ctermbg=red guibg=red
:match ExtraWhitespace /\s\+$\| \+\ze\t/
:autocmd ColorScheme * highlight ExtraWhitespace ctermbg=red guibg=red

Таким образом, любой плохой пробел будет светиться красным.Это довольно трудно пропустить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...