По моему опыту, лучший способ сделать это с помощью пользовательской функции:
" 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