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

byte positions, more information in listener_add #5086

Open
andymass opened this issue Oct 19, 2019 · 4 comments
Open

byte positions, more information in listener_add #5086

andymass opened this issue Oct 19, 2019 · 4 comments

Comments

@andymass
Copy link

Is your feature request related something that is currently hard to do? Please describe.

I'm working with a server utility that needs buffer updates to update its internal model of the text. listener_add callbacks seem designed for this purpose:

    func Listener(bufnr, start, end, added, changes)
        changes = {lnum, end, added, col}	  

However, I can't figure out how to make this work with my use-case, which requires both line/col and byte positions, e.g., an insertion of two chars looks like:

class Edit {
    start_byte = 5, old_end_byte = 5, new_end_byte = 5 + 2,
    start_point = (0, 5), old_end_point = (0, 5), new_end_point = (0, 5 + 2),
}

Column position doesn't much matter so much, I can just use the start/end of lines if necessary. But I can't figure out how to get byte positions at all. It won't work, for instance, to keep track of buffer text before and after because we only have the current buffer's state and there may be numerous disjoint changes in callback Listener. The callback doesn't get text before/after or bytes.

Describe the solution you'd like

It would be helpful to receive byte positions as well as line/column. If the edit is a single-line I would also expect to be able to determine the length byte-wise.

Neovim solved this issue by adding "old_bytecount" to their listener callback:
neovim/neovim@b0e2619

It's possible to determine the new end-byte since you can inspect the buffer. This doesn't work in vim (as far as I know) because the changes are batched up.

Describe alternatives you've considered

I considered taking the changes and forming the smallest enclosing contiguous region, calling this a single edit, and using line2byte. This seems less efficient than using the granular listener changes.

@brammool
Copy link
Contributor

brammool commented Oct 19, 2019 via email

@andymass
Copy link
Author

You don't need the byte offset from the start of the buffer?

Unfortunately, ultimately, I do need absolute byte offsets of start and end of the old and new text. If there were exactly one edit, it would suffice to use line2byte for the start and the end positions, if the callback would supply the old byte count and end position of the affected text.

But since there are multiple changes per callback I think this wouldn't work, thus we would need old and new byte counts of the affected text. Basically the complication is that if you look at partial changes the current buffer state is effective after all of these changes.

@prabirshrestha
Copy link

Curious is there was any solution for this. Was trying to start looking at change listener to add to vim-lsp and faced the same issue. This would impact folks using multi-byte characters and LSP by it self mainly uses utf-16.

@andymass
Copy link
Author

andymass commented May 6, 2020

@prabirshrestha my concern was not utf-16 but keeping track of absolute byte positions. The solution there was to keep an array of byte positions which you update whenever a listener is called. You could probably keep track of utf-16 start-of-line positions in a similar way, assuming you could compute the number of utf-16 encoded bytes in a particular line.

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

No branches or pull requests

3 participants