-
Notifications
You must be signed in to change notification settings - Fork 41
Description
Quoting next vi.stackexchange answer:
Special key combinations, such as
Ctrl+→, are translated into terminal keycodes like^[[1;5C, then into vim keycodes like<C-Right>, and finally into a sequence of bytes starting with 0x80 like<80><fd>V(<80>is 0x80). This is a special case where the vim keycode is different than the terminal keycode.
After assigning the register q like this:
let @q="\<C-Right>"
the sequence of bytes is what's actually saved:
:registers q
Type Name Content
c "q <80><fd>V
Press ENTER or type command to continue
In vim-peekaboo the output is also byted as in :registers command.
But one can overwrite (in command line) a register through user friendly key-strokes (Vim ones as in mapping, not byted). Quoting this:
For readability purpose, it's possible to use the proper key-notation tags such as
<Esc>or<CR>instead of^[or^M
You would need to escape the tag<Esc>with a single\and use double quotes instead of single quotes which would result in"\<Esc>". The following examples are equivalent
:let @e='^[I<e>^[A</e>'
:let @e="\<Esc><e>\<Esc>A</e>"
So my plugin feature request is this. To show the Vim mappings, not the sequence of bytes.
Related to this I tried to make a function, just to (not byte sequence) edit a register quickly in command line. With few easy examples it is working (see screenshot), BUT I did test just easy cases, a lot lot more is TODO. Furthermore, I don't know:
- if is reasonable to translate every byte to user friendly characters (and therefore if my plugin future request is reasonable) or pro Vim users are just used to byte sequences (or find it easily in documentation)
- and if it's reasonable, then I doubt if I make a right approach in my next function (same approach as my feature request could adapt)
- or maybe if in next Vim upgrades are already working on this
Thanks in advance!
[registers_friendly_overwrite__vim.txt](https://github.com/junegunn/vim-peekaboo/files/6511854/registers_friendly_overwrite__vim.txt)
Note: in next pasted code, the bytes sequences are not recognized in github, for example ^[ is transformed to �. Rather download previous file, and change extension to .vim (github neither allows to upload .vim files in comments [banging head on wall emoji]).
nnoremap <leader>z <C-u>:call X_Register_echo('d')<CR>:let @d="<C-r>*"<Left>
fun! X_Register_echo(reg)
" toogle to 1 to debug current function (otherwise 0)
let debug_bool = 0
" use 'a:' before arg input variable to use it https://learnvimscriptthehardway.stevelosh.com/chapters/24.html
" echo a:reg
let regText = getreg(a:reg, 1, 1)
let regTextStr01 = string(regText) " list to string
if strlen(l:regTextStr01) > 0
if debug_bool
echo "regTextStr01 --> "regTextStr01
endif
" check if has substring
" echo stridx(regTextStr, str_match)
" replace <Esc> alike for \<Esc>
" https://stackoverflow.com/questions/2943555/how-to-save-a-vim-macro-that-contains-escape-key-presses
" Ctrl + V-Esc for "�"
" double or tiple value just as one (<Esc><Esc> is equivalent to just <Esc>)
let str_match = "���"
let str_replacement = "�"
let regTextStr01 = substitute(l:regTextStr01, l:str_match, l:str_replacement, "g") " substitute all (flag 'g')
let str_match = "��"
let regTextStr01 = substitute(l:regTextStr01, l:str_match, l:str_replacement, "g") " substitute all (flag 'g')
if debug_bool
echo "regTextStr01 --> "regTextStr01
endif
let str_match = "�"
let str_replacement = '\\<Esc>'
" let str_replacement = "\\\\\<Esc\>"
" https://stackoverflow.com/questions/4864073/using-substitute-on-a-variable
let regTextStr02 = substitute(l:regTextStr01, l:str_match, l:str_replacement, "g") " substitute all (flag 'g')
if debug_bool
echo "regTextStr02 --> "regTextStr02
endif
" remove <fd><80>a alike --> added to macro changing from insert to normal mode (i.e. not always added)
" https://vi.stackexchange.com/questions/19465/whats-the-difference-between-qp-and-c-rc-rq-when-you-store-a-macro
" Opt.A search and remove ( I cannot even find it, so no removing it this way)
" " Ctrl+V u0080 for <80>
" " Ctrl+V u00fd for <fd>
" " let str_match = 'a'
" " let str_match = "�ýa"
" let str_match = '�'
" " let str_match = '<80>'
" " let str_match = '�ý'
" let str_replacement = ''
"
" " not even finding it
" echo stridx(regTextStr02, str_match)
" echo stridx(regTextStr02, '\\�')
"
" " let regTextStr03 = substitute(l:regTextStr02, l:str_match, l:str_replacement, "")
" let regTextStr03 = s:strreplace(l:regTextStr02, l:str_match, l:str_replacement)
" echo "regTextStr03 --> "regTextStr03
" Opt. B: remove next 6 bytes after \<Esc>
" remove ONLY if not already removed before
if l:regTextStr01 == l:regTextStr02
let l:removed_already_bool = 1
else
let l:removed_already_bool = 0
endif
" remove just 1st match:
" if l:removed_already_bool == 0
" let l:match_str ='\<Esc>'
" let l:match_len = strlen(l:match_str)
" let l:match_index = stridx(regTextStr02, match_str) " cannot be -1
" if debug_bool
" echo "regTextStr02 --> "regTextStr02
" echo "removed_already_bool --> "removed_already_bool
" echo "match_index --> "match_index
" endif
" " VimL counts the bytes instead of the characters for indexing --> https://stackoverflow.com/a/64780270/9391770
" let l:match_index += l:match_len -1
" let l:regTextStr03 = regTextStr02[2:match_index] . regTextStr02[match_index+3:]
" if debug_bool
" " echo "n --> "n
" echo "regTextStr03 --> "regTextStr03
" echo "-----------------\n"
" endif
" endif
" previous just remove first <fd><80>a alike
" ... to remove all we shall loop
if l:removed_already_bool == 0
let l:match_str ='\<Esc>'
let l:match_len = strlen(l:match_str)
let l:cnt = 1
let l:regTextStr_shorted = l:regTextStr02
while l:cnt > 0
if debug_bool
echo "regTextStr_shorted --> "regTextStr_shorted
endif
let l:match_index = stridx(regTextStr_shorted, match_str) " cannot be -1 the 1st time
if debug_bool
echo "match_index --> "match_index
endif
let l:match_index_prev = l:match_index
if l:match_index > -1
" it's not always alike: ��<fd><80>a
" ... sometimes is just alike: ��
let l:match_char_after = regTextStr_shorted[match_index+match_len:match_index+match_len]
if debug_bool
echo "match_char_after --> "match_char_after
endif
let l:remove_fd80a_bool = 1
if "qwertyuiopasdfghjklzxcvbnm" =~ l:match_char_after
let l:remove_fd80a_bool = 0
endif
if l:cnt == 1
let l:regTextStr03 = regTextStr_shorted[2:match_index+match_len-1]
else
if l:remove_fd80a_bool
let l:regTextStr03 = l:regTextStr03 . regTextStr_shorted[0:match_index+match_len-1]
else
let l:regTextStr03 = l:regTextStr03 . regTextStr_shorted[1:match_index+match_len-1]
endif
endif
if l:remove_fd80a_bool
let l:regTextStr_shorted = regTextStr_shorted[match_index+match_len+2:]
else
let l:regTextStr_shorted = regTextStr_shorted[match_index+match_len:]
endif
let l:cnt+=1
if l:cnt > 9
" avoid infinite loop debugging
break
endif
else
let l:cnt=0
endif
if debug_bool
echo "regTextStr03 --> "regTextStr03."\n"
endif
endwhile
else
let l:regTextStr03 = l:regTextStr01[1:-3]
endif
" echo "Register '" a:reg "' values: " l:regText
echon "Register "
\ | :echon "'"
\ | :call EchoWarning(a:reg)
\ | :echon "'"
\ | :echon " now values: '"
\ | :call EchoGreen(l:regTextStr03)
\ | :echon "'"
echo "Register "
\ | :echon "'"
\ | :call EchoWarning(a:reg)
\ | :echon "'"
\ | :echon " did value: '"
\ | :call EchoGreen(l:regTextStr01[2:-3])
\ | :echon "'"
echo "Tip: "
\ | :echo "\tRun @@ab to copy reg 'a' into 'b' (if same vim process)"
\ | :echo "\tOR copy inbetween single quotes of previous echo of reg. "
\ | :call EchoWarning(a:reg)
\ | :echon " and execute in other terminal: "
\ | :call EchoBlue(':let @')
\ | :call EchoWarning(a:reg)
\ | :call EchoBlue('="<C-r>+"')
" overwrite register
let [regText, regType] = [getreg(a:reg, 1, 1), getregtype(a:reg)]
if debug_bool
echo "regText --> "regText
endif
" call setreg(a:reg, l:regTextStr03, l:regType)
" setreg() would need double quotes, not single quotes to make \Esc work
" https://stackoverflow.com/a/56506589/9391770
" For readability purpose, it's possible to use the proper key-notation tags such as <Esc> or <CR> instead of ^[ or ^M
" You would need to escape the tag <Esc> with a single \ and use double quotes instead of single quotes which would result in "\<Esc>". The following examples are equivalent
" :let @e='^[I<e>^[A</e>'
" :let @e="\<Esc><e>\<Esc>A</e>"
" alternative:
let l:x_reg_echo_aux = l:regTextStr03
else
let l:x_reg_echo_aux = "empty register"
endif
call setreg('*', l:x_reg_echo_aux, l:regType)
endfun
function! EchoWarning(msg)
echohl WarningMsg
echon a:msg
echohl None
endfunction
" EchoGreen
hi X_ColorGreen guifg=#00ff00 ctermfg=darkgreen
function! EchoGreen(msg)
echohl X_ColorGreen
echon a:msg
echohl None
endfunction
" EchoBlue
hi X_ColorBlue guifg=#00ff00 ctermfg=blue
function! EchoBlue(msg)
echohl X_ColorBlue
echon a:msg
echohl None
endfunction
Btw if anyone is interested, for the @@ab map that I mention in screenshot check this or this:
nnoremap @@ab <C-u>:call CopyRegister('a','b')<cr>
fun! CopyRegister(reg_origin,reg_destiny)
let [regText, regType] = [getreg(a:reg_origin, 1, 1), getregtype(a:reg_origin)]
call setreg(a:reg_destiny, l:regText, l:regType)
" echo "Register '" a:reg_destiny "' changed to value of register'" a:reg_origin "': " l:regText
endfun
