Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"g@" does not pass "v:register" to the opfunc when operating on a custom text-object #6374

Open
lacygoill opened this issue Jul 2, 2020 · 2 comments

Comments

@lacygoill
Copy link

Describe the bug

g@ does not pass v:register to the opfunc when operating on a custom text-object.

To Reproduce

Run this shell command:

vim -es -Nu NONE -S <(cat <<'EOF'
    fu Opfunc(...)
        if !a:0
            let &opfunc = 'Opfunc'
            return 'g@'
        endif
        pu=v:register
    endfu
    nno <expr> <c-b> Opfunc()
    xno io iw
    ono io :normal vio<cr>
    call feedkeys('"r'.."\<c-b>"..'io', 'xt') | %p | qa!
EOF
)

It outputs ".

Expected behavior

It outputs r.

Environment

  • Vim version: 8.2 Included patches: 1-1101
  • OS: Ubuntu 16.04.6 LTS
  • Terminal: XTerm(356)

Additional context

It seems inconsistent.

We can use a builtin operator (like d) or a custom one (via g@).
We can use a builtin text-object (like iw) or a custom one.

Therefore, a change can be performed by 4 different types of commands:

  1. builtin operator + builtin text-object
  2. builtin operator + custom text-object
  3. custom operator + builtin text-object
  4. custom operator + custom text-object

All of them correctly handle a register without any special code, except the fourth one.

Test 1:

vim -Nu NONE -i NONE +"pu='word'"

" press:  "rdaw
:reg r
Type Name Content
  c  "r   word

Notice how word was correctly written inside the r register, meaning that daw correctly handled "r.

Test 2:

vim -Nu NONE -i NONE -S <(cat <<'EOF'
    pu='word'
    xno io iw
    ono io :norm vio<cr>
EOF
)

" press:  "rdio
:reg r
Type Name Content
  c  "r   word

Again, notice how word was correctly written inside the r register, meaning that dio correctly handled "r.

Test 3:

vim -Nu NONE -i NONE -S <(cat <<'EOF'
    pu='word'
    fu Opfunc(...)
        if !a:0
            let &opfunc = 'Opfunc'
            return 'g@'
        endif
        pu=v:register
    endfu
    nno <expr> <c-b> Opfunc()
EOF
)

" press:  "r C-b iw

Notice that Vim puts the text r in the buffer, meaning that "r correctly passed the r register to the opfunc.

If Vim is able to correctly handle a register in the first 3 cases (in particular 2.), I would expect it to correctly handle case 4..

@lacygoill
Copy link
Author

One workaround is to pass v:register manually.

When not passing it:

xno io iw
ono io :normal vio<cr>

When passing it:

xno io iw
ono io :normal vio"<c-r>=v:register<cr><cr>
                  ^-------------------^

Test:

vim -es -Nu NONE -S <(cat <<'EOF'
    fu Opfunc(...)
        if !a:0
            let &opfunc = 'Opfunc'
            return 'g@'
        endif
        pu=v:register
    endfu
    nno <expr> <c-b> Opfunc()
    xno io iw
    ono io :normal vio"<c-r>=v:register<cr><cr>
    call feedkeys('"r'.."\<c-b>"..'io', 'xt') | %p | qa!
EOF
)

This correctly outputs r.

It works but it's one more pitfall to be aware of, and fixing this could make existing text-objects provided by third-party plugins more reliable.

@andymass
Copy link

andymass commented Jul 2, 2020

Relevant question; https://vi.stackexchange.com/questions/20322/how-to-pass-vregister-to-custom-operator-when-working-on-custom-text-object/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants