[vim/vim] can not restore registers content properly (#2345)

25 zobrazení
Přeskočit na první nepřečtenou zprávu

ramele

nepřečteno,
17. 11. 2017 23:12:3417.11.17
komu: vim/vim, Subscribed

Sometimes, there is a need for a mapping to yank something without a trace so it has to save and restore the relevant registers.
The problem is that there is no way to set register " without modifying register 0. So if, for example, we have the following:
:reg 01"
--- Registers ---
"" deleted text^J
"0 yanked text^J
"1 deleted text^J

Now we want to do a yank as part of a mapping, this mapping will have to restore register " with the deleted text. But now the original content of register 0 (the yanked text) is lost.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub

Tony Mechelynck

nepřečteno,
17. 11. 2017 23:37:1417.11.17
komu: vim/vim, Subscribed

Have you tried saving and restoring with the :let command, by means of an auxiliary variable (possibly a script-local variable)? (see :help script-variable, :help let-register and :help expr-register)

Best regards,
Tony.

ramele

nepřečteno,
18. 11. 2017 0:32:4418.11.17
komu: vim/vim, Subscribed

If you meant :let @"='text', then yes -after this register 0 contains the same text.

Christian Brabandt

nepřečteno,
18. 11. 2017 11:05:3418.11.17
komu: vim/vim, Subscribed

I think this has been discussed before, but I don't find it. I think I even made a patch back then, but Bram didn't want to change this behaviour, as this might have unexpected results.

Nikolay Aleksandrovich Pavlov

nepřečteno,
18. 11. 2017 11:27:3718.11.17
komu: vim_dev, reply+00b1d1987b17efcd2a06c29468c6e33e8b13e8e...@reply.github.com, vim/vim, Subscribed
2017-11-18 7:37 GMT+03:00 Tony Mechelynck <vim-dev...@256bit.org>:
> Have you tried saving and restoring with the :let command, by means of an
> auxiliary variable (possibly a script-local variable)? (see :help
> script-variable, :help let-register and :help expr-register)

You can’t do that: `:let @x` is not going to work correctly if you
yanked NUL byte, or if you yanked a block selection. For
saving/restoring registers one must use getreg()/setreg(), but this is
only good as long as registers are internal to Vim and you have an
idea of what registers your command have touched: @", @0..@9 and @-
have a habit of being auto-populated under different circumstances.

If register is not internal to Vim (i.e. @* or @+, @" with some
&clipboard values) it is completely impossible to restore it correctly
because of

1. In X11 there is no register contents to restore at all, accessing a
register yields a call to the owner and Vim can only make himself the
owner and not restore the original app as such.
2. System clipboard does not necessary contain only text, but Vim is
completely unable to “restore” anything, but text.

So what you need to save/restore registers correctly is something like

function RExe(s)
let clipboard_save = &clipboard
let &clipboard = ''
let registers_save = []
for r in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '"']
call add(registers_save, [r, getreg(r, 1, 1), getregtype(r)])
endfor
try
execute a:s
finally
for reg in registers_save
call call('setreg', reg)
endfor
let &clipboard = clipboard_save
endtry
endfunction

>
> Best regards,
> Tony.
>
> —
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
>
> --
> --
> You received this message from the "vim_dev" maillist.
> Do not top-post! Type your reply below the text you are replying to.
> For more information, visit http://www.vim.org/maillist.php
>
> ---
> You received this message because you are subscribed to the Google Groups
> "vim_dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to vim_dev+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

vim-dev ML

nepřečteno,
18. 11. 2017 11:28:3218.11.17
komu: vim/vim, vim-dev ML, Your activity
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly, view it on GitHub
>
> --
> --
> You received this message from the "vim_dev" maillist.
> Do not top-post! Type your reply below the text you are replying to.
> For more information, visit http://www.vim.org/maillist.php
>
> ---
> You received this message because you are subscribed to the Google Groups
> "vim_dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to vim_dev+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Nikolai Aleksandrovich Pavlov

nepřečteno,
18. 11. 2017 11:43:3718.11.17
komu: vim/vim, vim-dev ML, Comment

And getreg() fails to fix the problem as well: whether I have '"' or '0' at the end, the result is the same value in both.


You are receiving this because you commented.

Nikolai Aleksandrovich Pavlov

nepřečteno,
18. 11. 2017 12:06:2618.11.17
komu: vim/vim, vim-dev ML, Comment

By the way, I once written a function which may serve as a replacement to normal! gvy followed by getreg('"', 1, 1): https://gist.github.com/fa35a5128886c0ecbca8f7c14fbcdde1. Usage to just yank is

let data = selection#modrange('b', 42, getpos("'<"), getpos("'>"), 0)

You may see there that handling blockwise selection is tricky and you will need to somehow get width, and while just y equivalent which is not using any registers for characterwise selection is easy, handle replacement is not so.


You are receiving this because you commented.

lacygoill

nepřečteno,
22. 6. 2020 18:16:5522.06.20
komu: vim/vim, vim-dev ML, Comment

Fixed by 8.2.0924 which provides the getreginfo() function.
The latter outputs a dictionary providing everything 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

Before the patch, you could try (and fail because it didn't point back to the same register) to save/restore it like this:

let save = ['"', getreg('"', 1, 1), getregtype('"')]
" do something which alters the unnamed register
call call('setreg', save)

Now, you can do it like this:

let save = getreginfo('"')
" do something which alters the unnamed register
call setreg('"', save)

Broken code before the patch:

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 = ['"', getreg('"', 1, 1), getregtype('"')]
        norm! 2Gdd
        call 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   deleted text^J
  l  "1   line deleted by mapping^J

Working code after the patch:

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


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.

Christian Brabandt

nepřečteno,
23. 6. 2020 2:33:2923.06.20
komu: vim/vim, vim-dev ML, Comment

Closed #2345.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.

Odpovědět všem
Odpověď autorovi
Přeposlat
0 nových zpráv