在自定义命令/函数检查当前缓冲区是否有“已选择”的文本(v/ v/ C-v)

时间:2021-08-01 23:28:38

I am having a custom command, in the command a function would be called.

我有一个自定义命令,在命令中会调用一个函数。

I want to make sure that, the command is executed only if current buffer is in VISUAL mode (v, V or C-V). or, say, the function is executed only if some text in current buffer is currently selected.

我要确保,只有在当前缓冲区处于可视模式(v、v或C-V)时才执行命令。或者,比方说,只有在当前缓冲区中的某些文本当前被选中时,才执行该函数。

  • visualmode() I cannot use, because it gives the last visual mode type.
  • 我不能使用visualmode(),因为它提供了最后的可视模式类型。
  • I tried putting echo mode() in the function, it gives always n.
  • 我尝试在函数中加入echo模式(),它总是给出n。
  • and I am not sure, if I selected something, and press : it has already entered command mode, how can I check if the buffer has something in selection right now?
  • 我不确定,如果我选择了什么,然后按:它已经进入命令模式,我怎么能检查缓冲区现在是否有选择的东西?

The solution could be easy, but I am stuck here.... can someone shed me some light? thank you.

解决方案可能是容易的,但我在这里困....有人能给我点灯吗?谢谢你!

2 个解决方案

#1


1  

If you want that kind of functionality, you have to use a mapping (or two different mappings for normal and visual mode).

如果您想要这种功能,您必须使用一个映射(或两个不同的映射用于普通模式和可视模式)。

As you said, as soon as you press :, visual mode is left for command-line mode. However, as the :'<,'> range is automatically inserted, you can pass that range to your function and operate on that. That would allow use from normal mode via an explicit range, too, but this is just sensible and consistent with the built-in commands.

正如您所说的,一旦您按下:,可视模式将被保留为命令行模式。但是,作为:'<,' '>范围是自动插入的,您可以将该范围传递到您的函数并对其进行操作。这将允许通过显式范围使用普通模式,但这只是合理的,与内置命令一致。

#2


1  

I've been trying to figure out the same problem myself, and I came up with this.

我自己也试着找出同样的问题,我想出了这个。

With this autocmd:

用这个autocmd:

autocmd CursorMoved * let s:Mode = mode()

A command like the following that also uses range option -range=0 that alters the <count> argument (0 when no range is passed, other wise the same number as the line the command is called on):

如下所示的命令也使用range选项-range=0修改 参数(当没有传递范围时,为0,否则与命令调用的行相同):

command! -range=0 CmdName call FuncName(<count>, <line1>, <line2>)

Then with logic like this you can check for either a visual selection, a normal range being passed, and no range passed at all:

然后用这样的逻辑,你可以检查一个视觉选择,一个正常的范围被通过,没有任何范围被通过:

function! FuncName(count, firstLine, lastLine)
    if a:count == 0 "no range given 
            "do stuff for no given range
    else
        if s:Mode  =~ '\vV|v|'  "range was given
            "do stuff for visual selection
        else 
            "do stuff for normal range
            " w/ a:firstLine & a:lastLine 
        endif
    endif
endfunction

NOTES:

注:

  • Known Problem - The only case I have found this doesn't work is when a visual selection is only one character ( the cursor wasn't moved), but for most cases this shouldn't be an issue.

    已知的问题——我发现这个问题的唯一原因是当一个视觉选择仅仅是一个字符(光标没有移动),但是对于大多数情况来说,这不是一个问题。

  • Command Note - You have to pass and as arguments rather than using the before call, so a invalid range isn't passed.

    命令注意-您必须传递和作为参数,而不是使用之前的调用,所以无效的范围没有通过。

#1


1  

If you want that kind of functionality, you have to use a mapping (or two different mappings for normal and visual mode).

如果您想要这种功能,您必须使用一个映射(或两个不同的映射用于普通模式和可视模式)。

As you said, as soon as you press :, visual mode is left for command-line mode. However, as the :'<,'> range is automatically inserted, you can pass that range to your function and operate on that. That would allow use from normal mode via an explicit range, too, but this is just sensible and consistent with the built-in commands.

正如您所说的,一旦您按下:,可视模式将被保留为命令行模式。但是,作为:'<,' '>范围是自动插入的,您可以将该范围传递到您的函数并对其进行操作。这将允许通过显式范围使用普通模式,但这只是合理的,与内置命令一致。

#2


1  

I've been trying to figure out the same problem myself, and I came up with this.

我自己也试着找出同样的问题,我想出了这个。

With this autocmd:

用这个autocmd:

autocmd CursorMoved * let s:Mode = mode()

A command like the following that also uses range option -range=0 that alters the <count> argument (0 when no range is passed, other wise the same number as the line the command is called on):

如下所示的命令也使用range选项-range=0修改 参数(当没有传递范围时,为0,否则与命令调用的行相同):

command! -range=0 CmdName call FuncName(<count>, <line1>, <line2>)

Then with logic like this you can check for either a visual selection, a normal range being passed, and no range passed at all:

然后用这样的逻辑,你可以检查一个视觉选择,一个正常的范围被通过,没有任何范围被通过:

function! FuncName(count, firstLine, lastLine)
    if a:count == 0 "no range given 
            "do stuff for no given range
    else
        if s:Mode  =~ '\vV|v|'  "range was given
            "do stuff for visual selection
        else 
            "do stuff for normal range
            " w/ a:firstLine & a:lastLine 
        endif
    endif
endfunction

NOTES:

注:

  • Known Problem - The only case I have found this doesn't work is when a visual selection is only one character ( the cursor wasn't moved), but for most cases this shouldn't be an issue.

    已知的问题——我发现这个问题的唯一原因是当一个视觉选择仅仅是一个字符(光标没有移动),但是对于大多数情况来说,这不是一个问题。

  • Command Note - You have to pass and as arguments rather than using the before call, so a invalid range isn't passed.

    命令注意-您必须传递和作为参数,而不是使用之前的调用,所以无效的范围没有通过。