在vim中粘贴期间转义字符 < >我将输出缓冲区中的内容复制到VIM中正在处理的C++代码中。 通常,此输出会卡在字符串中。如果能够自动转义所有的控制字符,而不是返回并手动编辑粘贴的片段,那就太好了

在vim中粘贴期间转义字符 < >我将输出缓冲区中的内容复制到VIM中正在处理的C++代码中。 通常,此输出会卡在字符串中。如果能够自动转义所有的控制字符,而不是返回并手动编辑粘贴的片段,那就太好了,vim,Vim,举个例子,我可以复制如下内容: error in file "foo.dat" 需要把它放进这样的东西里 std::string expected_error = "error in file \"foo.dat\"" 我认为可以使用最后一次粘贴的开始和结束标记将替换函数应用于最后一次粘贴的主体,但我不确定如何使其运行 更新: Joey Mazzarelli建议使用 `[v`]h:%s/\%V"/\\"/g 在一次粘贴之后 由于没有解释这是怎么回事,我最初觉得有点简练,但很难在评论中解释,

举个例子,我可以复制如下内容:

error in file "foo.dat"
需要把它放进这样的东西里

std::string expected_error = "error in file \"foo.dat\""
我认为可以使用最后一次粘贴的开始和结束标记将替换函数应用于最后一次粘贴的主体,但我不确定如何使其运行

更新:

Joey Mazzarelli建议使用

`[v`]h:%s/\%V"/\\"/g
在一次粘贴之后

由于没有解释这是怎么回事,我最初觉得有点简练,但很难在评论中解释,我想我应该在这里解释一下我认为它的作用:

`[  : Move to start of last paste
v   : Start visual mode
`]  : Move to end of last paste
h   : adjust cursor one position left
:%  : apply on the lines of the selection
s/  : replace
\%V : within the visual area
"   : "
/   : with
\\" : \"
/g  : all occurrences

这似乎是一个很好的方法,但只处理一个字符“,我希望它能处理换行符、制表符和其他可能出现在文本中的内容。(可能不是通用的unicode)。我知道这可能在问题定义中并不清楚。

这至少可以让您开始

粘贴后:

`[v`]h:%s/\%V"/\\"/g

显然,您可以将其映射到更易于键入的内容。

虽然Joey的解决方案看起来可以扩展到我需要的所有情况,但我认为我应该使用vims-python集成来共享我的部分解决方案(因为我对python比vim脚本更熟悉)

然后在我的.vimrc或其他conf文件中

# FILE cpp.vim
python import tocstring
# C-Escape and paste the currently yanked content
nmap <Leader>P :python tocstring.convertToCString("@","z")<CR>"zP
# C-Escape and paste the current visual selection
vmap <Leader>P "zd:python tocstring.convertToCString("z","z")<CR>"zP
#文件cpp.vim
python导入字符串
#C-Escape并粘贴当前拖动的内容
nmap:python tocstring.convertToCString(“@”,“z”)“zP
#C-退出并粘贴当前视觉选择
vmap P“zd:python tocstring.convertToCString(“z”,“z”)”zP
如果我可以使用第一个函数,使“a\p”粘贴“a”寄存器的转换内容,那就太好了,我假设使用v:register可以做到这一点,但我没有意识到这一点

这一版本的工作原理与Joey的解决方案相同,可以按照以下方式制作:

nmap <Leader>P `[v`]"zd:python tocstring.convertToCString("z","z")<CR>"zP
nmap`[v`]”zd:python-tocstring.convertToCString(“z”,“z”)“zP

确认:这使用来自的代码与来自vims python的寄存器进行交互。这里有几个vimscript函数,它们可以完成您想要的功能

  • EscapeText()
    将任意文本转换为C-转义等效文本。它将换行符转换为
    \n
    ,将制表符转换为
    \t
    ,将Control+G转换为
    \a
    ,等等,并为没有友好名称的特殊字符生成八进制转义(如
    \o032

  • PasteEscapedRegister()
    转义名为
    v:register
    的寄存器的内容,然后将其插入当前缓冲区。(当函数返回时,寄存器会恢复,因此可以重复调用函数,而无需多次转义寄存器内容。)

还包括两个键映射,以使
PasteEscapedRegister()
易于交互使用。
p
将转义寄存器内容粘贴在光标位置之前,而
p
粘贴在光标位置之后。两者都可以以寄存器规范作为前缀,如
”a\P
粘贴寄存器a的转义内容

代码如下:

function! EscapeText(text)

    let l:escaped_text = a:text

    " Map characters to named C backslash escapes. Normally, single-quoted
    " strings don't require double-backslashing, but these are necessary
    " to make the substitute() call below work properly.
    "
    let l:charmap = {
    \   '"'     : '\\"',
    \   "'"     : '\\''',
    \   "\n"    : '\\n',
    \   "\r"    : '\\r',
    \   "\b"    : '\\b',
    \   "\t"    : '\\t',
    \   "\x07"  : '\\a',
    \   "\x0B"  : '\\v',
    \   "\f"    : '\\f',
    \   }

    " Escape any existing backslashes in the text first, before
    " generating new ones. (Vim dictionaries iterate in arbitrary order,
    " so this step can't be combined with the items() loop below.)
    "
    let l:escaped_text = substitute(l:escaped_text, "\\", '\\\', 'g')

    " Replace actual returns, newlines, tabs, etc., with their escaped
    " representations.
    "
    for [original, escaped] in items(charmap)
        let l:escaped_text = substitute(l:escaped_text, original, escaped, 'g')
    endfor

    " Replace any other character that isn't a letter, number,
    " punctuation, or space with a 3-digit octal escape sequence. (Octal
    " is used instead of hex, since octal escapes terminate after 3
    " digits. C allows hex escapes of any length, so it's possible for
    " them to run up against subsequent characters that might be valid
    " hex digits.)
    "
    let l:escaped_text = substitute(l:escaped_text,
    \   '\([^[:alnum:][:punct:] ]\)',
    \   '\="\\o" . printf("%03o",char2nr(submatch(1)))',
    \   'g')

    return l:escaped_text

endfunction


function! PasteEscapedRegister(where)

    " Remember current register name, contents, and type,
    " so they can be restored once we're done.
    "
    let l:save_reg_name     = v:register
    let l:save_reg_contents = getreg(l:save_reg_name, 1)
    let l:save_reg_type     = getregtype(l:save_reg_name)

    echo "register: [" . l:save_reg_name . "] type: [" . l:save_reg_type . "]"

    " Replace the contents of the register with the escaped text, and set the
    " type to characterwise (so pasting into an existing double-quoted string,
    " for example, will work as expected).
    " 
    call setreg(l:save_reg_name, EscapeText(getreg(l:save_reg_name)), "c")

    " Build the appropriate normal-mode paste command.
    " 
    let l:cmd = 'normal "' . l:save_reg_name . (a:where == "before" ? "P" : "p")

    " Insert the escaped register contents.
    "
    exec l:cmd

    " Restore the register to its original value and type.
    " 
    call setreg(l:save_reg_name, l:save_reg_contents, l:save_reg_type)

endfunction

" Define keymaps to paste escaped text before or after the cursor.
"
nmap <Leader>P :call PasteEscapedRegister("before")<cr>
nmap <Leader>p :call PasteEscapedRegister("after")<cr>
函数!转义文本(文本)
设l:EXCAPED_text=a:text
将字符映射到命名的C反斜杠转义。通常为单引号
“字符串不需要双重反斜杠,但这是必要的
“使下面的substitute()调用正常工作。
"
设l:charmap={
\   '"'     : '\\"',
\   "'"     : '\\''',
\“\n”:“\\n”,
\“\r”:“\\r”,
\“\b”:“\\b”,
\“\t”:“\\t”,
\“\x07”:“\\a”,
\“\x0B”:“\\v”,
\“\f”:“\\f”,
\   }
“先转义文本中的任何现有反斜杠,然后
“生成新的。(Vim字典以任意顺序迭代,
“因此,此步骤不能与下面的items()循环结合使用。)
"
设l:escape\u text=替换(l:escape\u text,“\\”,“\\\”,“g”)
“将实际返回、换行符、制表符等替换为转义项
“陈述。
"
对于项目中的[原始,转义](charmap)
设l:转义文本=替换(l:转义文本,原始,转义,'g')
外循环
替换不是字母、数字的任何其他字符,
标点符号,或带有三位八进制转义序列的空格
“用于代替十六进制,因为八进制转义在3之后终止
“数字.C允许任何长度的十六进制转义,因此
“让它们与可能有效的后续字符相遇
“十六进制数字。)
"
设l:转义文本=替换(l:转义文本,
\“\([^[:alnum:][:punct:][]\)”,
\“\=”\\o.printf(“%03o”,char2nr(子匹配(1))”,
\"g")
返回l:转义的_文本
端功能
功能!粘贴转义寄存器(其中)
记住当前寄存器的名称、内容和类型,
“这样,一旦我们完成,它们就可以恢复。
"
让l:save_reg_name=v:register
让l:save_reg_contents=getreg(l:save_reg_name,1)
让l:save_reg_type=getregtype(l:save_reg_name)
echo“register:[”.l:save_reg_name.]type:[”.l:save_reg_type.]
用转义文本替换寄存器的内容,并设置
“键入字符(因此粘贴到现有的双引号字符串中,
“例如,将按预期工作)。
" 
调用setreg(l:save_reg_name,EscapeText(getreg(l:save_reg_name)),“c”)
“生成适当的正常模式粘贴命令。
" 
设l:cmd='normal'。l:保存注册名称。(a:其中==“在”?“P”之前”:“P”)
“插入转义寄存器内容。
"
执行官l:cmd
“将寄存器恢复为其原始值和类型。
" 
调用setreg(l:save_reg_name,l:save_reg_contents,l:save_reg_ty
function! EscapeText(text)

    let l:escaped_text = a:text

    " Map characters to named C backslash escapes. Normally, single-quoted
    " strings don't require double-backslashing, but these are necessary
    " to make the substitute() call below work properly.
    "
    let l:charmap = {
    \   '"'     : '\\"',
    \   "'"     : '\\''',
    \   "\n"    : '\\n',
    \   "\r"    : '\\r',
    \   "\b"    : '\\b',
    \   "\t"    : '\\t',
    \   "\x07"  : '\\a',
    \   "\x0B"  : '\\v',
    \   "\f"    : '\\f',
    \   }

    " Escape any existing backslashes in the text first, before
    " generating new ones. (Vim dictionaries iterate in arbitrary order,
    " so this step can't be combined with the items() loop below.)
    "
    let l:escaped_text = substitute(l:escaped_text, "\\", '\\\', 'g')

    " Replace actual returns, newlines, tabs, etc., with their escaped
    " representations.
    "
    for [original, escaped] in items(charmap)
        let l:escaped_text = substitute(l:escaped_text, original, escaped, 'g')
    endfor

    " Replace any other character that isn't a letter, number,
    " punctuation, or space with a 3-digit octal escape sequence. (Octal
    " is used instead of hex, since octal escapes terminate after 3
    " digits. C allows hex escapes of any length, so it's possible for
    " them to run up against subsequent characters that might be valid
    " hex digits.)
    "
    let l:escaped_text = substitute(l:escaped_text,
    \   '\([^[:alnum:][:punct:] ]\)',
    \   '\="\\o" . printf("%03o",char2nr(submatch(1)))',
    \   'g')

    return l:escaped_text

endfunction


function! PasteEscapedRegister(where)

    " Remember current register name, contents, and type,
    " so they can be restored once we're done.
    "
    let l:save_reg_name     = v:register
    let l:save_reg_contents = getreg(l:save_reg_name, 1)
    let l:save_reg_type     = getregtype(l:save_reg_name)

    echo "register: [" . l:save_reg_name . "] type: [" . l:save_reg_type . "]"

    " Replace the contents of the register with the escaped text, and set the
    " type to characterwise (so pasting into an existing double-quoted string,
    " for example, will work as expected).
    " 
    call setreg(l:save_reg_name, EscapeText(getreg(l:save_reg_name)), "c")

    " Build the appropriate normal-mode paste command.
    " 
    let l:cmd = 'normal "' . l:save_reg_name . (a:where == "before" ? "P" : "p")

    " Insert the escaped register contents.
    "
    exec l:cmd

    " Restore the register to its original value and type.
    " 
    call setreg(l:save_reg_name, l:save_reg_contents, l:save_reg_type)

endfunction

" Define keymaps to paste escaped text before or after the cursor.
"
nmap <Leader>P :call PasteEscapedRegister("before")<cr>
nmap <Leader>p :call PasteEscapedRegister("after")<cr>
nmap <leader>jp :call setreg('e', json_encode(@+))\| normal "ep<CR>