如何针对逐块视觉模式选择运行命令? [英] How to run commands against block-wise visual mode selection?

查看:20
本文介绍了如何针对逐块视觉模式选择运行命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含内容的测试文件:

var a = fff噗

然后我将光标移动到第 1 行的 f 字符上,ctrl+v 选择了两个 f 在它下面(■ 表示选择).

var a = ■■f■ff

我想把文字改成这样:

var a = "f"噗"噗"

所以我执行了这个命令:

:normal i"ctrl+vEscA"

但是引号被添加到整行中.是否可以仅对逐块视觉选择(而不是整行)进行操作?请注意,此示例仅用于讨论 Vim 技能.我不是想解决任何问题,只是想学习 Vim 技能.

解决方案

问题是所有 :-commands 只能采用 linewise range.回想一下,在可视模式下按 : 后,你得到 :'<,'>_ 这是一个足够强的提示(参见 :h mark-motions 以防您不记得反引号与单引号).

因此您不能直接处理视觉上选择的文本,而必须先将其拉入寄存器.

一种解决方案是将文本猛拉到它自己的行中.然后您可以应用您的命令并将新文本移动到它应该在的位置.

这是在@phd 的评论和链接答案中提到的vis"插件中完成的.但是它又大又臃肿,我们最好自己实现这样的功能.

" 将命令应用于视觉选择" a:cmd - 任何范围"命令" a:mods - :h 命令修饰符" a:trim - 如果我们需要从选择文本中修剪尾随空格,则为 true函数 s:block(cmd, mods, trim) 中止" 保存最后一行 no让 l:last = line('$')" 将选定的文本拖入寄存器 "9"沉默正常!gv"9y" 把它放在缓冲区的末尾调用 append(l:last, getreg(9, 1, 1))" 修剪尾随空格如果:修剪执行 'keepj keepp' l:last..'+,$s/\s\+$//e'万一应用我们的命令" 注意:我们假设该命令永远不会进入可视模式执行 a:mods l:last..'+,$' a:cmd" 将更改后的文本放回寄存器 "9"调用 setreg(9, getline(l:last + 1, '$'), visualmode())"清理调用 deletebufline('%', l:last + 1, '$')" 替换选择" 注意:旧文本进入寄存器1",1"进入2",依此类推." 旧寄存器 "9" 无论如何都丢失了,请参阅 :h v_p沉默正常!gv"9p端功能我们的界面是一个用户命令命令!-bang -range -nargs=1 -complete=command B call s:block(<q-args>, <q-mods>, <bang>0)

现在您可以选择您的块(不要忘记将其扩展到行尾!),然后执行:

:'<,'>B!普通的!我^CA"

注意:^C 代表 Ctrl-VCtrl-C

I have a testing file with the content:

var a = f
        ff
        fff

Then I moved the cursor on the f character in line 1, ctrl+v selected the two f below it (■ means selection).

var a = ■
        ■f
        ■ff

I want to change the text to this:

var a = "f"
        "ff"
        "fff"

So I executed this command:

:normal i"ctrl+vEscA"

But the quotes were added to the whole line. Is it possible to do operations on only block-wise visual selection (not the whole line)? Note that this example was made only for discussing Vim skills. I'm not trying to solving any problems, just want to learn Vim skills.

解决方案

The problem is that all :-commands can take linewise range only. Recall that after pressing : in Visual mode you got :'<,'>_ which is a hint strong enough (see :h mark-motions in case you don't remember about backtick vs. single-quote).

So you can't process visually selected text directly but have to yank it into register first.

One solution is to yank-put the text into the lines of its own. Then you can apply your command(s) and move the new text where it should be.

This is how it's done in that "vis" plugin mentioned in the comment by @phd and the linked answer. But it's so big and bloated that we'd better implement such functionality ourselves.

" apply command to a visual selection
" a:cmd - any "range" command
" a:mods - :h command-modifiers
" a:trim - true if we need to trim trailing spaces from selection text
function s:block(cmd, mods, trim) abort
    " save last line no
    let l:last = line('$')
    " yank selected text into the register "9"
    silent normal! gv"9y
    " put it at buffer's end
    call append(l:last, getreg(9, 1, 1))
    " trim trailing spaces
    if a:trim
        execute 'keepj keepp' l:last..'+,$s/\s\+$//e'
    endif
    " apply our command
    " note: we assume that the command never enters Visual mode
    execute a:mods l:last..'+,$' a:cmd
    " get the changed text back into the register "9"
    call setreg(9, getline(l:last + 1, '$'), visualmode())
    " clean up
    call deletebufline('%', l:last + 1, '$')
    " replace the selection
    " note: the old text goes into the register "1", "1" into "2", and so on.
    " old register "9" is lost anyway, see :h v_p
    silent normal! gv"9p
endfunction

" our interface is a user command
command! -bang -range -nargs=1 -complete=command B call s:block(<q-args>, <q-mods>, <bang>0)

Now you can select your block (do not forget about extending it until lines' ends!), and execute:

:'<,'>B! normal! i"^CA"

Note: ^C stands for Ctrl-VCtrl-C

这篇关于如何针对逐块视觉模式选择运行命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆