vim / vim

The official Vim repository
https://www.vim.org
Vim License
36.62k stars 5.46k forks source link

Block selection to-EOL is possible with cursor not at EOL, to-EOL state of block selection is not exposed to scripts #15587

Open Diomendius opened 2 months ago

Diomendius commented 2 months ago

Steps to reproduce

  1. Create these mappings

    map <f2> <cmd>echom $"'< = {getpos("'<")}, '> = {getpos("'>")}"<cr>
    xmap <f2> <cmd>echom $"v = {getpos("v")}, . = {getpos(".")}"<cr>

    Optionally, :set noshowmode to prevent the mode indicator from hiding these messages in visual mode. Otherwise, :messages is necessary to see them.

  2. Create a buffer with this text

    abcde
    fgh
    ijkl
  3. Place cursor on b

  4. Type <C-V>G$

  5. Press <f2> and observe the message v = [0, 1, 2, 0], . = [0, 3, 5, 0]

  6. Exit visual mode, press <f2> and observe the message '< = [0, 1, 2, 0], '> = [0, 3, 5, 0]

  7. Type hm>, then <f2> and observe the message '< = [0, 1, 2, 0], '> = [0, 3, 3, 0]

  8. Type gv and observe that the blockwise selection includes all the text in column 2 and beyond

    • The cursor, however, is on line 3, column 3, which is not normally possible, given the displayed blockwise region.
    • The only cursor positions matching the displayed region are:
      • Line 1, column 6 (one past the end)
      • Line 3, column 5 (one past the end)
    • Because o in blockwise visual mode disables to-EOL selection (which is surprising but probably not a bug), neither of these positions are valid:
      • Line 1, column 2
      • Line 3, column 2
  9. Type <f2> and observe the message v = [0, 1, 2, 0], . = [0, 3, 3, 0]

  10. Exit visual mode, press <f2> and observe the message '< = [0, 1, 2, 0], '> = [0, 3, 3, 0]

  11. Type gvd and observe that all text in column 2 and beyond is deleted

    • This matches the displayed selection, but not the range specified by '< and '>, or v and ..

The '[ and '] marks are also ambiguous when the last change affected a blockwise region.

Expected behaviour

There's room for interpretation, but probably:

Version of Vim

9.1.0697

Environment

Arch Linux x86_64 up-to-date as of 2024-08-23 Alacritty 0.13.2 (bb8ea18e) $TERM = alacritty zsh 5.9

Logs and stack traces

No response

Diomendius commented 2 months ago

I presume blockwise to-EOL-ness is a specific flag in the state of the visual selection, but I don't believe this is ever exposed to scripts directly. Apart from it being very weird to be able to have a blockwise selection with the cursor not on any of the corners of the selection, this means it is difficult for a script to:

One workaround for scripts would be to yank the selection, then add the left column of the selection to the width specified in getreginfo(reg).regtype. This is unwieldy and requires saving and restoring the used register to avoid visible side effects. It also doesn't distinguish between a to-EOL selection and one where the boundary happens to be on the last column within the region.

Another workaround is to execute gv and call getcurpos(), where curswant is v:maxcol if the selection is to-EOL, but this only works if '> has not been set manually. This is probably the best workaround I can think of, but it's still awkward.