使用Python在Vim中获取可视选择范围内的字符串

7
Here is some text
here is line two of text

我在 Vim 中通过视觉选择从 isis:(括号表示视觉选择 [ ]

Here [is some text
here is] line two of text

使用Python,我可以获取所选内容的范围元组:
function! GetRange()
python << EOF

import vim

buf   = vim.current.buffer # the buffer
start = buf.mark('<')      # start selection tuple: (1,5)
end   = buf.mark('>')      # end selection tuple: (2,7)

EOF
endfunction

我使用以下命令找到这个文件::so %,然后用鼠标选择文本,并运行命令 :<,'>call GetRange()
现在我有了(1,5)(2,7)。在Python中,如何编译以下字符串: is some text\nhere is 想要实现以下功能:
  1. 获取此字符串以备将来操作
  2. 使用更新/操作后的字符串替换所选范围

1
需要用Python来做这件事吗?我在下面留了一个只有Vimscript的答案。重新阅读问题,我不确定这对您是否可接受,但我现在先把它留在那里。 - FDinoff
1
如何在 VimScript 中获取可视选择文本 中有许多有用的 Vim 脚本答案。 - glts
3个回答

8

试试这个:

fun! GetRange()
python << EOF

import vim

buf = vim.current.buffer
(lnum1, col1) = buf.mark('<')
(lnum2, col2) = buf.mark('>')
lines = vim.eval('getline({}, {})'.format(lnum1, lnum2))
lines[0] = lines[0][col1:]
lines[-1] = lines[-1][:col2]
print "\n".join(lines)

EOF
endfun

您可以使用vim.eval获取Vim函数和变量的Python值。

2
我认为 line[-1][:col2+1] 更方便。 - qed
如果可视标记范围跨越多行,则假定iiuc。 如果lnum1 = lnum2,则在替换中lines[-1] = lines[-1][:col2]col2不会在原始列处截断。(请参见Andrew Magee的补丁)。 - pseyfert

4
如果使用纯vimscript,则可能会起作用。
function! GetRange()
    let @" = substitute(@", '\n', '\\n', 'g')
endfunction

vnoremap ,r y:call GetRange()<CR>gvp

这将把可视选择中的所有换行符转换为\n,并用该字符串替换选择。

这个映射将选择复制到寄存器"中。调用函数(实际上不是必需的,因为它只有一个命令)。然后使用gv重新选择可视选择,然后将引号寄存器粘贴回所选区域。

注意:在vimscript中,所有用户定义的函数都必须以大写字母开头。


3

这是基于Conner的答案的另一种版本。我采纳了qed的建议,并添加了一个修复选区完全在一行内的情况的解决方案。

import vim

def GetRange():
    buf = vim.current.buffer
    (lnum1, col1) = buf.mark('<')
    (lnum2, col2) = buf.mark('>')
    lines = vim.eval('getline({}, {})'.format(lnum1, lnum2))
    if len(lines) == 1:
        lines[0] = lines[0][col1:col2 + 1]
    else:
        lines[0] = lines[0][col1:]
        lines[-1] = lines[-1][:col2 + 1]
    return "\n".join(lines)

如果在可视块模式下选择文本会怎样?该函数似乎无法正确处理它。 - Meow
对我来说,似乎工作正常... 对你来说它在做什么? - Andrew Magee

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