在可视模式下在vim中创建过滤器但仅适用于选定的列范围?

Posted

技术标签:

【中文标题】在可视模式下在vim中创建过滤器但仅适用于选定的列范围?【英文标题】:Creating a filter in vim in visual mode but only for the selected column range? 【发布时间】:2021-03-13 05:17:13 【问题描述】:

我想做的是使用<ctrl>V 选择一个文本块,然后运行一个对该文本起作用的外部过滤器程序。您可以使用内部 vim cmd 执行此操作,即 ~ 但如果我使用等效的 C 程序尝试它,则处理每个选定行的整行。如果我使用 shell 命令作为过滤器,也会发生同样的事情。

有什么方法可以只处理选定的文本或在 C 代码中提取选定的列范围?

示例 C 代码过滤器:

//File: vis.c 
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int main(int argc, char * argv[],char * envp[])

     char c;
     while(!feof(stdin)) fputc(toupper(fgetc(stdin)),stdout) ;

     return 0;

Vim 命令:

<ctrl>V
:'<,'>!vis

使用 shell cmd 的示例过滤器:

:'<,'>! tr '[:lower:]'  '[:upper:]' 
enter code here

使用 vim 版本 7.4 和 8.1 进行测试

【问题讨论】:

【参考方案1】:

这是不可能用:help :range! 实现的,因为它是一个所谓的 Ex 命令,因此只适用于

整行都传递给外部命令,对此您无能为力,即使在您的范围内使用 `&lt;`&gt; 也不行,无论如何都会被拒绝。 传递给外部命令的文本没有任何元数据可以帮助外部命令确定选择了哪个部分,因此您的外部命令对管道输入的文本执行什么操作是无关紧要的。

由于阻碍者站在 Vim 一边,这就是你必须努力的地方。

在 Vim 中,您必须执行以下操作……

    将可视块选择拉到您选择的寄存器中:

    "by
    

    将该寄存器的内容写入临时文件:

    :let tempfile = tempname()
    :call split(@b, '\n')->writefile(tempfile)
    

    通过您的外部程序运行该文件并将输出抓取到您选择的寄存器中:

    :call system('vis < ' .. tempname)->setreg('o', 'b')
    

    删除临时文件:

    :call delete(tempfile)
    

    重新选择之前选择的块:

    gv
    

    将新文本放在所选内容上:

    "op
    

请注意,这既不是经过测试也不是完整的:您必须自己填写空白。如果不是这样,那乐趣在哪里?

资源:

:help registers
:help tempname()
:help split()
:help writefile()
:help system()
:help setreg()
:help delete()
:help gv

【讨论】:

我很想拥有你的 vimL 专业知识水平,但是将文本块拉入一个新的空临时文件更简单,在那里运行外部命令,拉出文本然后返回并粘贴修改前一个块上的文本(gvp)。我希望有某种方法可以访问我的 C 代码中的范围或限制拾取的内容。显然不是,除非其他人知道不同。 再一次,没有任何元数据添加到传递给过滤器的文本中,因此您的过滤器无法知道 a)它是否来自视觉块选择和 b)该视觉对象的边界-块选择:您的所有过滤器作为输入都是一些带有一堆换行符的文本,所以那里无事可做。正确的解决方案不是手动缓慢地通过大量杂乱的中间步骤来完成,而是编写一个可以正常工作的简短函数并将其映射到某个组合键或将其分配给某个自定义命令。

以上是关于在可视模式下在vim中创建过滤器但仅适用于选定的列范围?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用渐变维度的情况下在维度中创建数据历史记录?

在vim中创建1列中的2列

Tailwind CSS 网格提供 3 行而不是 3 列,但仅适用于 grid-cols-6

如何在报告中创建一个包含所有已检查列名称的列?

如何在可视模式下在外部过滤器命令中使用 vim 变量?

在 Xcode5 中创建 CustomCells