helix-editor / helix

A post-modern modal text editor.
https://helix-editor.com
Mozilla Public License 2.0
31.84k stars 2.35k forks source link

Line-wise extend mode #356

Closed CBenoit closed 3 years ago

CBenoit commented 3 years ago

Description

A new line-wise extend mode similar to (neo)vim's line-wise visual mode that we can enter by pressing V.

Aside

As mentioned in this issue I would like it to replace current line selection using x.

Current x (kakoune's x) has a few pain points:

For more background, see this kakoune issue.

Line-wise extend mode fixes the above pain points and can also do more:

cessen commented 3 years ago

An empty line is always fully selected (selection is at least one character, in this case the newline character), so when pressing x the next line is selected in addition to the current line. This totally makes sense, but makes the behavior somewhat feeling weird. We could use a new state just for that, but that's not very elegant.

I discuss that as one of the motivating examples in #362. IMO it's potentially solvable in an elegant way that doesn't involve any special state, depending on your definitions.

Having said that, I also like vim's line-wise extend mode, ha ha. :-)

CBenoit commented 3 years ago

Very good points you made in #362! :smile:

I see the current plan is to keep the current behavior but get an internal refactoring to use gap indexing instead:

I'm a bit unsure on the approach to cursors, so I think we should start by enforcing that ranges are always at least 1-width. I don't think there's a good approach to solve this in the terminal (it makes i/a behavior a bit more confusing because it looks like you're over a character but you're positioned right before it, both i and a will insert in the same spot), but it would be interesting in a proper UI because we could render 0-width cursors.

So I guess this wouldn't fix x immediately, right?

cessen commented 3 years ago

Correct, it won't fix x immediately, but it will open the door to possibly fixing it later, depending on how we decide we want Helix to work in general around cursors/selections.

(Edit: I'm personally pretty optimistic. I think there are very likely to be good ways to make everything work intuitively with zero-width cursors, even in a terminal. But I think it will be easier to demonstrate and convince people with a prototype, which will be a lot easier to whip up after switching to gap indexing anyway.)

CBenoit commented 3 years ago

(Edit: I'm personally pretty optimistic. I think there are very likely to be good ways to make everything work intuitively with zero-width cursors, even in a terminal. But I think it will be easier to demonstrate and convince people with a prototype, which will be a lot easier to whip up after switching to gap indexing anyway.)

(I'm very enthusiastic about this approach, I'll will be following that!)

archseer commented 3 years ago

I wonder if simply implementing X as "extend selection to line bounds" might be enough? You could make a selection then press X to have it cover all the selected lines.

pickfire commented 3 years ago

Or vx if we don't want to hold shift for X.

CBenoit commented 3 years ago

I wonder if simply implementing X as "extend selection to line bounds" might be enough? You could make a selection then press X to have it cover all the selected lines.

I think it's enough albeit a bit less efficient

archseer commented 3 years ago

I've implemented X in https://github.com/helix-editor/helix/commit/a4e28c6927e59cf08d056e9c9a74be095eae5f29

https://asciinema.org/a/THZeT7YLA2izb9lNviGuMg5PL

CBenoit commented 3 years ago

Looks good, thank you! :slightly_smiling_face: It seems to me the issue can be closed so I'll go ahead!

Possible plugin-provided implementation for VIM-like line-wise extend mode : add a hook on selection change to call extend_to_line_bounds

dpc commented 2 years ago

Hi, I've been trying hx and I've been one of the vocal kakoune users in https://github.com/mawww/kakoune/issues/2590 , the the point where I still use my custom fork that changes x behavior.

I was also prototyping https://github.com/dpc/breeze , which is kakoune inspired editor with 0-width cursor as a base mode of operation, also in Rust. Since you kind of work on a very similar thing though far more featureful already I thought I might point to it just as an inspiration.

In it I used gap-cursor from the start, and I represent an unselected empty line as []\n and selected one as [\n] (where [] is the selection/cursor). Note: since in breeze, the cursor (the vertical line is displayed separately from the selection), that means there's the difference looks like this:

line NOT considered fully selected:

Screenshot from 2021-08-05 23-47-59

line considered fully selected:

Screenshot from 2021-08-05 23-48-05

That little arrow is a marker of a selected newline. You might want to try it yourself, run breeze, open some file and see how it feels.

cessen commented 2 years ago

@dpc Although I would certainly prefer vertical-line cursors, there are a couple of hurdles:

  1. Many terminals don't support vertical-line cursors, so it's not very portable.
  2. Even terminals that do support vertical-line cursors only support a single such cursor, but Helix is a multi-cursor editor. So even in those terminals we still can't display our cursors that way.

I would still like to experiment with approaches to indicate/visualize zero-width cursors within the limitations of terminals, but I don't think vertical-line cursors is a workable solution in the current terminal landscape, unfortunately.

sudormrfbin commented 2 years ago

FWIW I made a working prototype some time ago to change cursor shape on mode change (#323) and this is what I ended up with:

We can show an I beam for the primary cursor (given that the terminal supports it) but that's about it. For multiple cursors we'll have to fall back to block cursors in the terminal.

dpc commented 2 years ago

(...) I don't think vertical-line cursors is a workable solution in the current terminal landscape, unfortunately.

I thought about it myself, and my conclusion was:

Why would anyone go so out of their way to use some super niche text editor... and then plan to use it with some legacy underpowered terminal emulator, instead of one of the fast modern featureful ones?

And:

Given such a dominance of "mainstream" CLI modal text editors like Neovim Emacs, why would anyone bother with some weird new one? An editor like this MUST do something far, far better than existing ones and provide substantially better experience to have people stick around and suffer through some other pain points like smaller ecosystem.

For both legacy & multi-cursor, I was planing to display a normal 1-width cursor fallback.

cessen commented 2 years ago

(Before I go any further, I just want to make sure anyone stumbling on this understands: I am not the primary author of Helix. I sometimes write with an authoritative voice, but I'm only speaking for myself here.)

Why would anyone go so out of their way to use some super niche text editor... and then plan to use it with some legacy underpowered terminal emulator, instead of one of the fast modern featureful ones?

I mostly agree with you here (with some minor quibbles). But the main issue still remains: even the modern terminal emulators don't support multiple vertical-line cursors. If it were a reasonably common feature among modern terminal emulators I think I'd be right there with you. But I don't know of any terminal emulator that supports this, even among modern ones. That doesn't mean one doesn't exist, of course. But the point is that it's definitely not something we can rely on, even on a modern system.

I think our best option for accommodating vertical-line cursors is to support them in a GUI version of Helix. Then we can draw things however we want.

Okay... so having said all of that, I want to come back to what I think is the more pertinent point: editor behavior.

Even if we can't display vertical-line cursors, that doesn't necessarily mean we can't support zero-width cursor behavior. I had some ideas about that in #362. Basically, if we make a distinction between "cursors" and "selections" (the former being zero-width, the latter being anything > zero-width), then we can make a visual distinction between the two by e.g. display cursors with a different color. I think as long as we made this a front-and-center concept in Helix, it could work well.

But I also think it needs some prototyping and experimentation to see if it actually works well in practice, and to explore/discover other possible solutions that might work even better. Since implementing #376 that kind of experimentation should be much easier to do.

Given such a dominance of "mainstream" CLI modal text editors like Neovim Emacs, why would anyone bother with some weird new one? An editor like this MUST do something far, far better than existing ones and provide substantially better experience to have people stick around and suffer through some other pain points like smaller ecosystem.

Independent of the substance of this discussion, I see people making this kind of argument a lot when trying to convince open source projects to change what they're doing. For some projects that's reasonable, due to their nature. But for many others (I think including Helix) I find this kind of reasoning odd, and it kind of comes across as "Cm'on kid, don'cha wanna be famous?"

I don't think many of us are developing Helix specifically because we're trying to make it popular. We're developing Helix because we personally want to use it as our editor. So I think it's best to focus the discussion on the actual pros and cons of the available approaches rather than on what would attract more people to the project.

dpc commented 2 years ago

even the modern terminal emulators don't support multiple vertical-line cursors

As a kakoune user, I find that I rarely use multiple selections and usually miss the simplicity of :g/foo/bar/. When I do use them, 90% of the time the edits I'm making are so far apart that I still see only one at the time anyway, so I have completely different problems. So I while agree that some handling of it is needed, I am confidence it will be good enough in practice.

then we can make a visual distinction between the two by e.g. display cursors with a different color.

:+1:

cessen commented 2 years ago

As a kakoune user, I find that I rarely use multiple selections and usually miss the simplicity of :g/foo/bar/.

Ah, interesting. Coming from Sublime, it's a primary workflow for me. It's certainly a little trickier to use effectively in Helix right now with the available selection commands (and I suspect that's true in Kakoune as well...?). But after higher priority things have been addressed, that's something I want to tackle. Assuming no one else gets to it first.

musjj commented 9 months ago

Can this issue potentially be re-opened? The OP seems satisfied with the current solution, but IMO extend_to_line_bounds is not really a true line-wise mode. You can test this by pressing vX, then k. You can see that the previous line is now no longer fully selected.

kladd commented 8 months ago

Second.

pascalkuthe commented 8 months ago

You just got it the wrong way around. You enter insertmode with v and move around, then you can press X last to extend to linebounds.

Just like kakoune we have no plan to add a linewise selection mode.