-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathpaste_into_c_string.vim
90 lines (71 loc) · 2.82 KB
/
paste_into_c_string.vim
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
" paste_into_c_string.vim
"
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>
" end paste_into_c_string.vim