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

Suggestion for tracking lines does not work #12

Open
p-e-w opened this issue Feb 26, 2020 · 2 comments
Open

Suggestion for tracking lines does not work #12

p-e-w opened this issue Feb 26, 2020 · 2 comments

Comments

@p-e-w
Copy link

p-e-w commented Feb 26, 2020

On the subject of "How do I keep track of row, col information?", the README suggests:

The best way is to use a linebuffer data structure in conjunction with the Rope:

type Foo struct{
	*skiprope.Rope
	linebuf []int
}

The linebuf is essentially a list of offsets to a newline character.

This doesn't work. More precisely, it technically works, but doing this negates the advantages of using a rope in the first place. The reason is that maintaining the linebuf array when the rope is modified is an O(n) operation in the average case, where n is the number of lines. Under standard assumptions (bounded line length), this makes inserting into and deleting from the rope an O(n) operation in the length of the text – and we are back to zero. At this point, the "rope" is just a very complicated string.

Rope implementations designed for line-based editing store line count information directly in the binary tree's nodes, in addition to the fragment length. This allows for line operations with a complexity of O(log(n)). Of course, instead of a line array as suggested, one could use a binary tree to externally track lines, but that would entail mirroring the rope's internal structure outside of it, which is extremely ugly.

It appears, then, that the correct answer to the question "How do I keep track of row, col information?" is currently "Use a different package", which is rather unfortunate because all other rope implementations written in Go that I am aware of suffer from the same shortcoming (unlike e.g. ropey, which gets this right).

@chewxy
Copy link
Owner

chewxy commented Feb 26, 2020

Rope implementations designed for line-based editing store line count information directly in the binary tree's nodes, in addition to the fragment length. This allows for line operations with a complexity of O(log(n)).

So this issue is solvable with a bit of sacrifice to heap mem? Would you like to put a PR in?

@p-e-w
Copy link
Author

p-e-w commented Mar 1, 2020

I have since found a more suitable solution for my original problem than using a rope, so I won't be adding this myself. But I did think about it some more and realized that because this package is built around a skip list rather than a binary tree, line tracking might not be as straightforward as it is for conventional rope implementations. It's unclear how storing line counts in the skip node hierarchy would provide the same guarantees as doing so with tree nodes. I'm sure it's still possible somehow, but not necessarily easy.

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