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

feat: Getregion function #13998

Closed
wants to merge 68 commits into from
Closed

feat: Getregion function #13998

wants to merge 68 commits into from

Conversation

Shougo
Copy link
Contributor

@Shougo Shougo commented Feb 9, 2024

Continues of #11579

It is not only for visual mode.

runtime/doc/builtin.txt Outdated Show resolved Hide resolved
@chrisbra
Copy link
Member

chrisbra commented Feb 9, 2024

I think this is a nice addition. I think we should call it getline_region() so that it comes close to the description of the getline() function.

However, we need tests here. Including testing what happens with invalid positions, multibyte character support, tab handling, and testing failure modes if possible.

@chrisbra chrisbra added the needs more work used for a pull request that isn't ready to include (other than needing a test) label Feb 9, 2024
src/evalfunc.c Outdated Show resolved Hide resolved
@Shougo
Copy link
Contributor Author

Shougo commented Feb 10, 2024

I think this is a nice addition. I think we should call it getline_region() so that it comes close to the description of the getline() function.

Well, the rename is needed?

However, we need tests here. Including testing what happens with invalid positions, multibyte character support, tab handling, and testing failure modes if possible.

Yes. The tests are needed...

@chrisbra chrisbra closed this in 3f905ab Feb 20, 2024
@habamax
Copy link
Contributor

habamax commented Feb 20, 2024

Thank you @Shougo and the rest who helped!

@Shougo Shougo deleted the getregion branch February 21, 2024 01:21
zeertzjq added a commit to zeertzjq/neovim that referenced this pull request Feb 22, 2024
Problem:  hard to get visual region using Vim script
Solution: Add getregion() Vim script function
          (Shougo Matsushita, Jakub Łuczyński)

closes: vim/vim#13998
closes: vim/vim#11579

vim/vim@3f905ab

Cherry-pick changes from patch 9.1.0122, with :echom instead of :echow.

Co-authored-by: Shougo Matsushita <[email protected]>
Co-authored-by: Jakub Łuczyński <[email protected]>
zeertzjq added a commit to zeertzjq/neovim that referenced this pull request Feb 22, 2024
Problem:  hard to get visual region using Vim script
Solution: Add getregion() Vim script function
          (Shougo Matsushita, Jakub Łuczyński)

closes: vim/vim#13998
closes: vim/vim#11579

vim/vim@3f905ab

Cherry-pick changes from patch 9.1.0122, with :echom instead of :echow.

Co-authored-by: Shougo Matsushita <[email protected]>
Co-authored-by: Jakub Łuczyński <[email protected]>
zeertzjq added a commit to zeertzjq/neovim that referenced this pull request Feb 22, 2024
Problem:  hard to get visual region using Vim script
Solution: Add getregion() Vim script function
          (Shougo Matsushita, Jakub Łuczyński)

closes: vim/vim#13998
closes: vim/vim#11579

vim/vim@3f905ab

Cherry-pick changes from patch 9.1.0122, with :echom instead of :echow.

Co-authored-by: Shougo Matsushita <[email protected]>
Co-authored-by: Jakub Łuczyński <[email protected]>
@Shougo Shougo mentioned this pull request Feb 25, 2024
@justinmk
Copy link
Contributor

justinmk commented Apr 20, 2024

Why doesn't this return a list of positions? Return text is the least useful part about a region. How can plugin authors get the positions that correspond to a visual block region (for example)? That is still an unsolved problem.

getregion() yet it doesn't return a position structure, which means that plugins still have to manually figure out the part of a buffer that corresponds to a region.

@chrisbra
Copy link
Member

chrisbra commented Apr 20, 2024

Why doesn't this return a list of positions? Return text is the least useful part about a region.

The functionality of this function was to be to get the buffer content of whatever those positions would define. Au contraire, getting the buffer content was an unsolved problem before, positions would need to be known before hand so I fail to see how this would be "more useful".

How can plugin authors get the positions that correspond to a visual block region (for example)? That is still an unsolved problem.

You can use getpos() of those positions already. Don't see why this is a problem.

@zeertzjq
Copy link
Member

For blockwise Visual selection it'll probably need a combination of getpos(), virtcol() and virtcol2col().

@chrisbra
Copy link
Member

correct and visualmode()

@justinmk
Copy link
Contributor

You can use getpos() of those positions already. Don't see why this is a problem.

You cannot easily get the dimensions of the buffer text that is described by a region. This is the code that is currently required to do that: https://github.com/neovim/neovim/blob/d35a8a9bbe385daf808984ba0fc7f07f51a96da0/runtime/lua/vim/_editor.lua#L509-L578

@clason
Copy link
Contributor

clason commented Apr 20, 2024

(Note that this is not as trivial as it seems once you add multibyte and ambiwidth unicode characters to the mix -- which that code can't handle fully, despite its complexity)

@zeertzjq
Copy link
Member

zeertzjq commented Apr 20, 2024

Also ref neovim/neovim#21115 the initial discussion and implementation of this function. For getting text the interface is easy, but when it comes to getting buffer positions the interface gets complicated when 'virtualedit' is concerned.

@Shougo
Copy link
Contributor Author

Shougo commented Apr 21, 2024

Well, I should add the option to return the range feature?

@kuuote
Copy link
Contributor

kuuote commented Apr 21, 2024

I think range feature is good. but shouldn't add to getregion().
Should split entry point to another function because determine return type by arguments is hard to understand.

@chrisbra
Copy link
Member

chrisbra commented Apr 21, 2024

correct, there was a single purpose for the getregion() function, which was to retrieve the selected text between 2 different (start and end) positions. Now the discussion moves away to a different usecase. That should be a new vimscript function. However, I still don't understand the need for it:

We are giving already positions to the getrange() function. You are talking about dimensions of positions, which I don't understand. What exactly do you mean by that? Can you please give concrete examples? Why exactly are start and end positions not enough? Can you spell out the help documentation for what this function should do?

@justinmk
Copy link
Contributor

justinmk commented Apr 21, 2024

We are giving already positions to the getrange() function. You are talking about dimensions of positions, which I don't understand

For a give region defined by 2 opposite "corners", the actual buffer text bounded by those corners, depends on (1) the buffer text itself, (2) inclusive/exclusive, (3) selection type (v/V/^v), (4) multibyte. Mapping a region to buffer text is non-trivial.

Perhaps name it getregionpos() ?

@chrisbra
Copy link
Member

Yes, but you already have those positions. So where do those positions come then from? In other words if you already have the positions, why do you need to use getregionpos()?

BTW: I have for years used a similar approach to this in one of my plugins. Set the marks '< and '> to those positions and then set the selection type. Use norm! gv to reselect those regions. Has worked quite well.

@clason
Copy link
Contributor

clason commented Apr 21, 2024

Yes, but you already have those positions. So where do those positions come then from?

No we don't; that's exactly what we're asking from here. (We have a hack that works in some situations, but not enough.)

@chrisbra
Copy link
Member

Then it's even more curious why you mention it here in the PR for getregion(), since that function already receives the position. Can you please create a new issue with whathever you like to have? Please also mention what the help description should explain.

@clason
Copy link
Contributor

clason commented Apr 21, 2024

(To be clear, I'm not the one complaining here; just trying to provide some additional context.)

@chrisbra
Copy link
Member

sure understood and thanks. (And to be clear, I am just trying to understand the missing pieces)

@clason
Copy link
Contributor

clason commented Apr 21, 2024

Basically, given a pair of positions (which could be '< and '> -- the main use case, in fact) return an array of positions { line1 = {col_start, col_end}, line2 = {col_start, col_end}} that respects

  • setreg-style selection type (char/line/block)
  • whether ending column is inclusive/exclusive
  • 'virtualedit'
  • works with double-width (flag emoji) and amiwidth (thai) unicode
  • ...

Basically, convert a visual-block selection to an array of line-wise selections to then, say, apply highlights to. (Main use case here: highlight-on-yank as in https://github.com/machakann/vim-highlightedyank.) Especially the last points basically rely on Vim internals to be guaranteed to be correct

@justinmk
Copy link
Contributor

justinmk commented Apr 21, 2024

Basically, convert a visual-block selection to an array of line-wise selections to then, say, apply highlights to.

"to char-wise", right?

(Main use case here: highlight-on-yank as in https://github.com/machakann/vim-highlightedyank.)

To @chrisbra 's point, if nvim_buf_set_extmark accepted {pos1}, {pos2}, {regtype}, {inclusive} parameters, then we wouldn't need getregionpos() for that particular case.

This raises the more general question about how a buffer region is described. Currently in Vim, a buffer region is described by those 4 parameters. So we have 2 choices:

  • every API that accepts a "region" has those 4 parameters
  • introduce a getregionpos() which returns a list of start/end positions, and then APIs only need to accept start/end parameters, because the caller can use getregionpos() and feed its result into any such API.

Created #14609

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs more work used for a pull request that isn't ready to include (other than needing a test)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants