在vim中粘贴时转义字符

Mic*_*son 7 vim

我将输出缓冲区中的东西复制到我正在使用的C++代码中.通常这个输出会陷入字符串.能够自动转义所有控制字符而不是返回并手动编辑粘贴的片段是很好的.

作为一个例子,我可能会复制这样的东西:

error in file "foo.dat"
Run Code Online (Sandbox Code Playgroud)

并且需要把它变成这样的东西

std::string expected_error = "error in file \"foo.dat\""
Run Code Online (Sandbox Code Playgroud)

我认为可以使用最后一个粘贴的开始和结束标记将替换功能应用于最后一个粘贴的主体,但我不确定如何使其飞行.

更新:

Joey Mazzarelli使用sugested

`[v`]h:%s/\%V"/\\"/g
Run Code Online (Sandbox Code Playgroud)

粘贴后.

由于没有给出任何解释,我最初发现它有点简洁,但很难在评论中解释我认为我会解释我认为在这里做的事情:

`[  : 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
Run Code Online (Sandbox Code Playgroud)

这似乎是一个很好的方法,但只处理一个字符,"我希望它能够处理新行,标签和其他可能会出现在文本中的东西.(可能不是一般的unicode)我明白可能问题定义中没有明确的.

Bil*_*dom 5

这里有几个vimscript函数可以做你想要的.

  • EscapeText()将任意文本转换为C转义的等价物.它将ne​​wline转换为\n,tab 转换为\t,Control + G转换为\a等,并\o032为没有友好名称的特殊字符生成八进制转义符(如).

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

还包含一些关键映射,以便PasteEscapedRegister()易于交互使用.<Leader>P粘贴转移到光标位置之前的寄存器内容,然后<Leader>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>
Run Code Online (Sandbox Code Playgroud)