2011-02-28 60 views

回答

11

以我的经验来做到这一点,最好的方法是使用自定义功能:

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

" Retab spaced file, but only indentation 
func! RetabIndents() 
    let saved_view = winsaveview() 
    execute '%[email protected]^\(\{'.&ts.'}\)\[email protected]\=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 '%[email protected]^\(\{'.&ts.'}\)\[email protected]\=repeat("\t", len(submatch(0))/'.&ts.')@' 

" Execute the result of joining a few strings together: 

%s    " Search and replace over the whole file 
@[email protected]@  " 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

奇妙的答案。我将不得不深入探讨“执行”声明,因为这看起来像是一些深暗的魔法。 – 2011-02-28 16:22:42

+0

很有帮助。我已经添加了对“执行”语句正在做什么的解释。 – DrAl 2011-03-01 08:00:52

+0

我没有成功使用此功能。当我运行它时使用:RetabIndents,我得到:处理函数时检测到错误RetabIndents: 第2行: E486:找不到模式:^ \(\ {4} \)\ + – 2011-03-02 18:57:16

0

从我回答这个其他(*)的问题:

为了解决这个小问题,我建议搜索,而不是retab。

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

此搜索将查找任何行整个文件开始 标签的任何数字,其次是4个空格,并用它替换 任何标签的数量才发现加一。

比你需要与@:[email protected]:

其更好的链接波纹管解释重做搜索。

(*) How can I convert spaces to tabs in Vim or Linux?