vim 如何将前导空格转换为制表符?

js4nwp54  于 2022-11-11  发布在  其他
关注(0)|答案(4)|浏览(177)

很多人使用空格而不是制表符。我两个都用。制表符在行首,空格从第一个非空白字符开始。开始新文档没有问题,万一我不得不修改一个更好地适应使用格式。但有时我需要修复空格问题无论如何。
根据Search and replace,我可以只做:%s/spaces_for_tab/tab/g。它很简单,适用于很多情况。无论如何,我只想重构行首的空格。

ztyzrc3y

ztyzrc3y1#

这更像是一个 regex 问题。要在行首锚,请使用插入符号,例如:

s/^        /\t/

或者使用Vim的内置功能:

:set tabstop=4  "four spaces will make up for one tab
:set noexpandtab  "tell vim to keep tabs instead of inserting spaces
:retab            "let vim handle your case

顺便说一句,我也喜欢用制表符来缩进,用空格来对齐。不幸的是,vim doesn't handle this well(我不知道其他编辑器是怎么做的),所以我主要使用:set expandtab(也许可以参见:set softtabstop)。

nhhxz33t

nhhxz33t2#

我已经写了一个简单的函数。无论如何,它将只为4空格制表符工作。

fu! Fixspaces()
        while search('^\t* \{4}') != 0
                execute ':%s/^\t*\zs \{4}/\t/g'
        endwhile
endfu

你可以建议更好的解决方案,如果存在的话,我会很高兴地使用它。问题是这个func也会替换字符串中的空格。

ssgvzors

ssgvzors3#

大卫的回答非常优雅,但它没有解决混合了制表符和空格的前导空格。例如,要转换如下行:

<SPACE><SPACE><TAB>something...

你必须知道制表符的位置,以确定需要多少空格来替换<TAB>并到达下一个制表位。我下面的解决方案,虽然没有大卫的那么简洁,但解决了这个问题。它还允许我选择使用前导空格的方式,而不依赖于&expandtab。我将感谢任何改进我的代码的建议...

function! TabsToSpaces(...)
  let ts = &tabstop
  let pos = getpos('.')
  while search('^ *\zs\t', "w") != 0
    let l:curpos = getcharpos('.')
    " The number of spaces needed depends upon the position of the <TAB>
    let numsp = 1 + ts - ( curpos[2] % ts )
    if numsp == 9
      let numsp = 1
    endif
    silent execute ':s/^ *\zs\t/'.repeat(' ', numsp).'/'
  endwhile
  if a:0 == 0
    echo 'Changed leading tabs to spaces'
  endif
  call setpos('.', pos)
endfunction

function! SpacesToTabs(...)
  let ts = &tabstop
  let pos = getpos('.')
  " First normalize all tabs to spaces
  call TabsToSpaces("quiet")
  while search('^\t* \{'.ts.'}') != 0
    silent execute ':%s/^\t*\zs \{'.ts.'}/\t/g'
  endwhile
  if a:0 == 0
    echo 'Changed leading spaces to tabs'
  endif
  call setpos('.', pos)                                                          
endfunction                                                                      

" Some keystrokes to implement the spaces/tabs functions
nmap <Leader>st :execute SpacesToTabs()<CR>
nmap <Leader>ts :execute TabsToSpaces()<CR>
sigwle7e

sigwle7e4#

如果有人感兴趣的话,我把马丁的答案改进了一下:

function Fixspaces()
  let ts = &tabstop
  let pos = getpos('.')

  if &expandtab
    while search('^ *\t') != 0
      silent execute ':%s/^ *\zs\t/'.repeat(' ', ts).'/g'
    endwhile

    echo 'Changed tabs to spaces'
  else
    while search('^\t* \{'.ts.'}') != 0
      silent execute ':%s/^\t*\zs \{'.ts.'}/\t/g'
    endwhile

    echo 'Changed spaces to tabs'
  endif

  call setpos('.', pos)
endfunction

此函数根据expandtabtabstop设置的值执行相应的操作,并记住光标的位置。

相关问题