nomad / crop

🌾 A pretty fast text rope
https://crates.io/crates/crop
MIT License
262 stars 13 forks source link

Why does trailing newline not count as a line? #20

Open QnnOkabayashi opened 1 month ago

QnnOkabayashi commented 1 month ago

Hi! This crate is amazing, thank you for your work on it.

I'm curious what the motivation is for having the empty line after a trailing newline not be counted as a line? For context, I'm creating a language server, and when I open an empty document and start writing, the first incremental update I get is roughly "insert X text on line 0". But rope.line(0) on an empty rope just panics, when I would expect it to return an empty RopeSlice.

Is this an outcome of the implementation? Or was Rope created with a specific use case in mind that wanted this behavior?

QnnOkabayashi commented 1 month ago

I realize I can secretly append an extra newline at the end of the rope so it always thinks it has a trailing newline, and then carry on as usual while making sure to never touch the trailing newline. But my question still stands, why is Rope implemented like this?

noib3 commented 1 month ago

That was a deliberate decision to match the behaviour of Rust's String. I kinda regret that now, and changing the trailing newline semantics to match Ropey's has long been on my todo list.

I'd merge a PR if you want to work on it, but keep in mind that Rope{Slice}::line_len(), Rope{Slice}::line() and Lines's {DoubleEnded,Exact}Iterator impls would all have to be changed.

QnnOkabayashi commented 1 month ago

I see, that makes a lot of sense. I wonder if there are any people relying on this behavior? I'll try to send a PR for this soon.