VIM: 如何将光标移动到文本块的最后一行而不改变列?

4

往往我想以相同的方式编辑文本块中的每一行,所以我会键入

<C-V>}

这样可以选择整个块,但不幸的是它会超过该块的最后一行并改变光标位置。然后我必须按下 k 键,然后输入任何序列来更正光标位置。通常情况下,我发现只需按下 j 直到我到达最后一行更容易。有没有更简单的方法来实现这个目标呢?

示例:我想将以下内容更改为

std::cerr << "abc::blah " << std::endl;
std::cerr << "def::text " << std::endl;
std::cerr << "ggg::something " << std::endl;
std::cerr << "xyz::else " << std::endl;
std::cerr << "qrs::random " << std::endl;

to:

std::cerr << "Foo::blah " << std::endl;
std::cerr << "Foo::text " << std::endl;
std::cerr << "Foo::something " << std::endl;
std::cerr << "Foo::else " << std::endl;
std::cerr << "Foo::random " << std::endl;

我发现自己将光标放在第一行的第一个a上,然后键入<C-V>jjjjecFoo<ESC>

有没有一种方法可以将光标移动到块的末尾,而不会超过它或更改列,即某种等效于按j直到块的最后一行的方式?


1
这个插件 https://github.com/vim-utils/vim-vertical-move 看起来可以实现你想要的功能(不过我个人还没有尝试过)。很遗憾,目前我无法想到一种不使用插件的方法来实现这个功能(除非使用/计算行号,但这基本上就是你的解决方案,只是使用 4j 代替 jjjj)。 - Marth
是的,那看起来像是我要寻找的! - willpnw
2个回答

1
据我所知,Vim内置并没有这个功能,但是你可以定义一个自定义映射(g} 看起来比较合适),具体可以参考 vi.stackexchange.com上的这篇回答
vnoremap <silent> g} :<C-U>call cursor(line("'}")-1,col("'>"))<CR>`<1v``

这种方法唯一的问题是当段落的最后一行也是缓冲区的最后一行时,它无法正常工作,但是添加一个额外的 j 将修复选择。

1
it doesn't work when the last line of the paragraph is also the last line of the buffer As it was mentioned in my answer, to address this case one needs: :<C-U>call cursor(line("'}")-empty(getline(line("'}"))),col("'>"))<CR><1v``` - Matt

0

您可以定义一个自定义:help :map-operator,它仅使用移动的行号,但保留当前列:

"<Leader>gl{motion} Jump to the line at the end of {motion}; keep the
"           current column.
function! s:SetCursor( lnum, virtcol )
    call cursor(a:lnum, 0)
    execute 'normal!' a:virtcol . '|'
endfunction
function! OnlyLineJumpOperator( type ) abort
    call s:SetCursor(line("']"), virtcol('.'))
endfunction
function! OnlyLineJumpVisual( type ) abort
    normal! gv
    call OnlyLineJumpOperator(a:type)
endfunction
function! s:OnlyOneCoordinateJumpExpression( what, mode ) abort
    let &opfunc = printf('Only%sJump%s', a:what, a:mode)
    return (a:mode ==# 'Visual' ? "\<C-\>\<C-n>" : '') . 'g@'
endfunction
nnoremap <expr> <Leader>gl     <SID>OnlyOneCoordinateJumpExpression('Line', 'Operator')
xnoremap <expr> <Leader>gl     <SID>OnlyOneCoordinateJumpExpression('Line', 'Visual')

有了这个,您的用例将变为<C-v><Leader>gl}ecFoo<Esc>

奖励

为完整起见,您还可以添加相反的映射(仅保留行并更改列):

"<Leader>g|{motion} Jump to the column at the end of {motion}; keep the
"           current line.
function! OnlyColumnJumpOperator( type ) abort
    execute 'normal!' virtcol("']") . '|'
endfunction
function! OnlyColumnJumpVisual( type ) abort
    normal! gv
    call OnlyColumnJumpOperator(a:type)
endfunction
nnoremap <expr> <Leader>g<Bar> <SID>OnlyOneCoordinateJumpExpression('Column', 'Operator')
xnoremap <expr> <Leader>g<Bar> <SID>OnlyOneCoordinateJumpExpression('Column', 'Visual')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接