Заставьте Vi / Vim использовать ведущие вкладки только на retab! - PullRequest
13 голосов
/ 28 февраля 2011

Есть ли способ заставить vim использовать вкладки для выполнения начального отступа, но при запуске retab! команда НЕ заменяет внутренний пробел между символами табуляции?

Ответы [ 2 ]

16 голосов
/ 28 февраля 2011

По моему опыту, лучший способ сделать это с помощью пользовательской функции:

" Retab spaced file, but only indentation
command! RetabIndents call RetabIndents()

" Retab spaced file, but only indentation
func! RetabIndents()
    let saved_view = winsaveview()
    execute '%s@^\( \{'.&ts.'}\)\+@\=repeat("\t", len(submatch(0))/'.&ts.')@'
    call winrestview(saved_view)
endfunc

Затем вы можете использовать:

:RetabIndents

, чтобы заменить все начальные пробелы в качестве вкладок, но невлиять на вкладки после других символов.Предполагается, что «ts» установлен правильно.Вы можете проделать долгий путь к созданию файлов, которые лучше выровнены, выполнив что-то вроде этого:

:set ts=8     " Or whatever makes the file looks like right
:set et       " Switch to 'space mode'
:retab        " This makes everything spaces
:set noet     " Switch back to 'tab mode'
:RetabIndents " Change indentation (not alignment) to tabs
:set ts=4     " Or whatever your coding convention says it should be

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

Объяснение строки 'exe':

execute '%s@^\( \{'.&ts.'}\)\+@\=repeat("\t", len(submatch(0))/'.&ts.')@'

" Execute the result of joining a few strings together:

%s               " Search and replace over the whole file
@....@....@      " Delimiters for search and replace
^                " Start of line
\(...\)          " Match group
 \{...}          " Match a space the number of times in the curly braces
&ts              " The current value of 'tabstop' option, so:
                 " 'string'.&ts.'string' becomes 'string4string' if tabstop is 4
                 " Thus the bracket bit becomes \( \{4}\)
\+               " Match one or more of the groups of 'tabstop' spaces (so if
                 " tabstop is 4, match 4, 8, 12, 16 etc spaces
@                " The middle delimiter
\=               " Replace with the result of an expression:
repeat(s,c)      " Make a string that is c copies of s, so repeat('xy',4) is 'xyxyxyxy'
"\t"             " String consisting of a single tab character
submatch(0)      " String that was matched by the first part (a number of multiples 
                 " of tabstop spaces)
len(submatch(0)) " The length of the match
/'.&ts.'         " This adds the string "/4" onto the expression (if tabstop is 4),
                 " resulting in len(submatch(0))/4 which gives the number of tabs that
                 " the line has been indented by
)                " The end of the repeat() function call

@                " End delimiter
0 голосов
/ 24 августа 2014

Из моего ответа на этот другой (*) вопрос:

Чтобы решить эту маленькую проблему, я рекомендую поиск вместо retab.

:%s/^\(^I*\)␣␣␣␣/\1^I/g

Этот поиск будет искать во всем файле любые строки, начинающиеся с любое количество знаков табуляции, за которым следуют 4 пробела, и заменить его на любое найденное количество вкладок плюс одна.

Чем нужно повторить поиск с помощью @: или 10@:

Это лучше объяснить в ссылке ниже.

(*) Как мне преобразовать пробелы в табуляции в Vim или Linux?

...