If your Vim contains the patch 8.2.0924, then try to use getreginfo()
:
function Foo()
let save_cb = &cb
let regInfo = getreginfo('"')
try
norm! y{motion}
do something
finally
let &cb = save_cb
call setreg('"', regInfo)
endtry
endfunction
The latter function returns a dictionary providing all the info you need to save and restore the unnamed register:
- its contents as a list (which allows you to not lose NULs) via the
regcontents
key
- its type via the
regtype
key
- the name of the register it points to via the
points_to
key
getreginfo()
is the only way to restore the register to which the unnamed register pointed to originally.
You can test it like this:
vim -es -Nu NONE -i NONE -S <(cat <<'EOF'
call setline(1, ['yanked text', 'deleted text', 'line deleted by mapping'])
norm! yyjdd
pu=['registers before mapping'] + [execute('reg \"01')]
nno cd :call Func()<cr>
fu Func()
let save = getreginfo('"')
norm! 2Gdd
call setreg('"', save)
endfu
au VimEnter * call feedkeys('cd', 'xt')
\ | $pu=['', 'registers after mapping'] + [execute('reg \"01')]
\ | exe 'g/^registers/t.|norm! Vr='
\ | 2,$p | qa!
EOF
)
registers before mapping
========================
Type Name Content
l "" deleted text^J
l "0 yanked text^J
l "1 deleted text^J
registers after mapping
=======================
Type Name Content
l "" deleted text^J
l "0 yanked text^J
l "1 deleted text^J
Note that if your Vim doesn't support getreginfo()
, you should ask getreg()
to give you the contents of a register as a list instead of a string, by passing it a third non-zero argument:
let [regText, regType] = [getreg('"'), getregtype('"')]
^---------^
✘
let [regText, regType] = [getreg('"', 1, 1), getregtype('"')]
^---------------^
✔
That's the only way to correctly handle possible NULs. See :h getreg()
:
If {list} is present and |TRUE|, the result type is changed
to |List|. Each list item is one text line. Use it if you care
about zero bytes possibly present inside register: without
third argument both NLs and zero bytes are represented as NLs
(see |NL-used-for-Nul|).
I don't think you need to temporarily remove the y
flag from 'cpo'
. The dot command keeps its original behavior after your function is finished:
set cpo+=y
norm! dd
fu Func()
norm! yy
endfu
call Func()
norm! .
" dot keeps removing the current line
See :h function-search-undo
.
As for the dot register, it contains the last inserted text (see :h quote_.
). But a yank does not insert any text, so it can't alter the register, regardless of whether y
is in 'cpo'
. And even if it did, it would probably not matter.
"ay{motion}
sets in the"
(unnamed register) as well asa
?"
point toa
, check:h quotequote
.