如何基于Vim中光标下的字符在函数中执行某些操作?

如何基于Vim中光标下的字符在函数中执行某些操作?,vim,cursor,Vim,Cursor,我正在写一个函数,它在LaTeX中编辑特定的环境 环境基本上如下所示: \begin{quicktikz} ...some stuff... \end{quicktikz} \begin*{quicktikz} ...some stuff... \end{quicktikz} 或者像这样: \begin{quicktikz} ...some stuff... \end{quicktikz} \begin*{quicktikz} ...some stuff..

我正在写一个函数,它在LaTeX中编辑特定的环境

环境基本上如下所示:

\begin{quicktikz}
    ...some stuff...
\end{quicktikz}
\begin*{quicktikz}
    ...some stuff...
\end{quicktikz}
或者像这样:

\begin{quicktikz}
    ...some stuff...
\end{quicktikz}
\begin*{quicktikz}
    ...some stuff...
\end{quicktikz}
我想写一个函数,当从环境中调用时,可以在两者之间切换。因为我对Vim的了解还不够,所以我提出了一个简单的解决方案:

  • 使用
    让save\u cursor=getpos(“.”)获取光标位置
  • 向后搜索
    \begin{quicktikz}
    使用:
    ?\\begin{quicktikz}\\\\\begin\*{quicktikz}
  • 搜索
    {
    并使用:
    normal 0f{h
    向左移动
  • 检查光标下的项目是否等于
    *
    • 如果是,则执行
      normal x
    • 如果没有,请执行
      普通a*
  • 使用
    调用setpos('.',保存光标)
    恢复光标位置
  • 除了步骤3,我知道如何执行所有这些操作。如何检查光标下的字符是否等于
    *


    如果你知道一种更好的方法,欢迎分享。

    我认为检索光标下的字符最简单的方法是:

    getline(".")[col(".")-1]
    
    或者,您可以使用
    strpart()


    第一个表达式首先调用传递为“的函数 参数表示将返回光标所在的行。 然后,我们使用所谓的expr8或expr-[](请参阅)来检索 单个字符。传递的数字来自另一个函数, 返回当前游标列。当索引从0开始时,将减去1

    你可以像这样使用它

    if getline(".")[col(".")-1] == '*'
            ...
    

    让我为您描述的技术提出一个替代实现

    :?\\begin\>\zs\*\=?s//\='*'[submatch(0)!='']/|norm!``
    
    上述命令由两个单独的命令组成,这些命令与
    |
    链接在一起(请参见
    :help:bar
    )在一行中。第一行是替换(请参见
    :help:s
    ) 对指定范围内的每一行执行

    ?\\begin\>\zs\*\=?
    
    根据范围语法(请参见
    :help:range
    ),此范围指定 只有一行,即
    \\begin\>\zs\*\=
    模式所在的前一行 匹配单词
    begin
    ,前面加反斜杠,后面加可选字符 星号字符.1模式各部分之间的
    \zs
    原子 匹配
    \begin
    *
    设置匹配的开始。因此,匹配 整个图案的一部分为空或包含单星字符 对于指定范围内的行不是必需的,它有助于重用 后面在
    :substitute
    命令中使用相同的模式,其中只有该星号 应替换字符或其空白位置。有关 模式的语法请参见
    :help/\>
    :help/\=
    :help/\zs

    替代品本身

    s//\='*'[submatch(0)!='']/
    
    替换最后一个搜索模式(由 使用表达式所指向的字符串在范围内进行反向搜索
    “*”[submatch(0)!=”
    求值(请参见
    :help sub replace-\=
    )。作为模式 仅匹配空字符串或星号字符,子表达式
    子匹配(0)!=''如果
    \begin
    之后没有星号,则计算结果为零,或者 否则为1。字符串
    “*”
    中的零下标将导致子字符串 包含该字符串的第一个字符。索引1为 等于字符串的长度,因此下标结果为空 因此,当
    \begin
    后面有星号时,它将被替换为 空字符串,当不存在星号时,紧接着是零宽度间隔
    \begin
    替换为
    *

    第二个命令,

    :norm!``
    
    利用
    :substitute
    命令存储当前 光标在实际开始替换之前的位置。
    `
    移动 命令跳回最近一次跳转之前的位置(发生在 前面提到的替换命令)恢复 光标2


    1搜索时要小心,因为在范围内,它会像往常一样 在文件末尾,当启用
    wrapscan
    选项时(该选项已启用) 默认情况下)

    2不要将
    `
    与移动 将光标移到
    最新的跳跃。

    现在我正在寻找一种更好的方法来解决你的问题……另外,你能给我解释一下语法的每一部分吗?我正在尝试学习vim!抱歉@romeovs,我刚刚编辑了答案。第二个表达式很容易用一点:h:-)来解释,但是如果你有任何问题,请告诉我。@sidyll:有趣的用法of
    strpart()
    function!顺便问一下,您知道一种从Unicode字符串中通过索引(以字符为单位,而不是字节索引)提取字符的简单方法吗?类似于
    substitute(s),^.\{7}\(.\).*$,'\1','')
    ?@sidyll:关于一种更好的方法,我试图解决的不是将角色放在光标下的问题,而是整个问题。因此,我遇到了一个有趣的Vim功能组合,这些功能在这个问题上会聚在一起。是的,我将其更改为更完美的。请告诉我这个解决方案是否有效很好。子匹配(0)=“*”?:“*”
    只长了两个字符,但是这个想法是+1。不过,为什么要使用
    :exe
    ?@Benoit:事实上,我已经用一个表达式部分将替换部分缩短了一个字符。:-)无论如何,你是对的,这个表达式也是合理的。@Benoit:在以前版本的答案的命令中使用
    :exe
    是由于在执行
    :global
    命令后需要恢复准确的光标位置而导致的。如果没有
    :exe
    ,光标将跳到命令行的第一个非空字符