强制Vi/Vim仅在retab上使用前导卡舌!

强制Vi/Vim仅在retab上使用前导卡舌!,vim,vi,Vim,Vi,有没有办法强迫vim使用制表符进行初始缩进,但在运行retab时!命令不使用制表符替换内部单词间距?根据我的经验,最好的方法是使用自定义函数: " Retab spaced file, but only indentation command! RetabIndents call RetabIndents() " Retab spaced file, but only indentation func! RetabIndents() let saved_view = winsavevi

有没有办法强迫vim使用制表符进行初始缩进,但在运行retab时!命令不使用制表符替换内部单词间距?

根据我的经验,最好的方法是使用自定义函数:

" 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

根据我对另一个(*)问题的回答:

为了解决这个小问题,我建议进行搜索,而不是重新搜索

:%s/^\(^I*\)␣␣␣␣/\1^I/g
此搜索将在整个文件中查找以开头的任何行 任意数量的制表符,后跟4个空格,并将其替换为 无论找到多少个标签,再加上一个

然后您需要使用
@:
10@:

下面的链接可以更好地解释这一点

(*)

回答得太好了。我将不得不深入研究那个“执行”语句,因为它看起来像是一些深沉的黑暗魔法。很高兴它有用。我已经添加了一个关于“execute”语句的解释。我没有成功使用这个函数。当我使用:RetabIndents运行它时,在处理函数RetabIndents:line 2:E486:Pattern not found:^(\{4})时检测到:错误\+