wez / wezterm

A GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust
https://wezfurlong.org/wezterm/
Other
17.17k stars 774 forks source link

Smart selection, select everything between brackets #4464

Open JeanMertz opened 11 months ago

JeanMertz commented 11 months ago

this is a copy/paste of an issue I raised on Alacritty almost 5 years ago (time flies 😱), see https://github.com/alacritty/alacritty/issues/2014

In Terminal.app, you can double-click a starting bracket (for example, {), or the closing one, to select it and everything up to and including the bracket pair:

terminal

I believe this behaviour is different (but not exclusive) to the already existing "smart selection" functionality.

I use this functionality a lot when dealing with large (log) outputs that include JSON for example, to quickly see where an object starts and ends. It serves as a quick visual aid to limit the scope in which I have to search for some key.

I know this use case can also be tackled by using less or grep or some other way, but it's not always obvious when I run a command that I need to find a needle in a haystack, so in Terminal.app I could use this handy functionality to quickly find what I'm looking for, instead of having to execute the command again with some extra commands piped onto it, to achieve the same result.


there are more details in the implementation PR here: https://github.com/alacritty/alacritty/pull/2022

Back to raising this for Wezterm:

I've been using Wezterm for a few years now, and love its performance, extensibility and general workflows. This is a feature that I've missed for a while now, though, and today was the day I finally decided to raise an issue.

I'm not sure if this can already be done with some other abstract feature, I tried a few different search terms, but wasn't able to find it.

Also, somewhat related, which I might as well add here, while I'm at it: I regularly notice that my double click doesn't actually select a piece of text at all. At first, I thought it was a bug, but upon actually debugging it (by trying it manually and seeing when it works or doesn't work), I realized it's actually user error that causes this, as I sometimes very slightly move my mouse when I try to double-click somewhere (might be a nerve issue, or whatever). I assume there's some piece of code somewhere that determines a double click to be two consecutive mouse clicks, without any other mouse event in-between. It might be worth building in some leeway to allow the mouse to move slightly in-between those clicks, and still register it as a double click.

JeanMertz commented 8 months ago

@wez any thoughts on this? Are you open to supporting a feature like this?

wez commented 8 months ago

Yeah, I'm open to seeing it added. I don't have time to implement it though.

JeanMertz commented 8 months ago

Alright, I can see about finding some time in the coming weeks. Any pointers on where/how you'd like to see this implemented?

wez commented 8 months ago

in terms of configuration, there should probably be a config option something like "(){}[]" that lists pairs of open/close characters so that you can determine whether a character has a matching closing character. There may be unicode properties that can tell you this, but making a string list them out feels easier for the user to control an/or mildly abuse for unusual/unexpected alternative use cases.

Also, I think that this behavior should be explicitly configured by adding a SelectionMode for it:

https://github.com/wez/wezterm/blob/925568a21505a8b7299663a7b2db962fa0baa9f8/config/src/keyassignment.rs#L102-L109

I'd suggest starting with the word selection logic to get a sense of the code you'd want to write; it shows how to peek into lines: https://github.com/wez/wezterm/blob/925568a21505a8b7299663a7b2db962fa0baa9f8/wezterm-gui/src/selection.rs#L240-L241

that is called from over here: https://github.com/wez/wezterm/blob/925568a21505a8b7299663a7b2db962fa0baa9f8/wezterm-gui/src/termwindow/selection.rs#L257-L264

wez commented 8 months ago

there are probably also follow ups from there: eg: how to make a double click mix different selection behaviors together based on context? We don't have good answers for that today, which is why we have somewhat unwieldy stuff like https://wezfurlong.org/wezterm/config/lua/keyassignment/CompleteSelectionOrOpenLinkAtMouseCursor.html

JeanMertz commented 8 months ago

there are probably also follow ups from there: eg: how to make a double click mix different selection behaviors together based on context? We don't have good answers for that today, which is why we have somewhat unwieldy stuff like wezfurlong.org/wezterm/config/lua/keyassignment/CompleteSelectionOrOpenLinkAtMouseCursor.html

Agreed. This was the first thing I stumbled upon as I was perusing through the code.

We might want to introduce a new Semantic mode (although the name does somewhat collide with the existing SemanticZone mode), which "does the right thing" based on the context. That mode could replace the current Word mode mapped to double-click.

Semantic selection would be (for starters):

  1. If the character under the cursor is one of the "pair" characters, then "pair selection mode" is triggered.
  2. Otherwise, regular "word selection mode" is triggered.

This could be expanded upon in the future if there are alternative double-click selection modes we want.

I'm open to alternative strategies, though.

wez commented 8 months ago

half-baked thought here, but I think for this to be composable and configurable to the degree that wezterm users are likely to demand that there should probably be a little bit of an overhaul to the available mouse (and perhaps also key) assignment actions so that they can configure eg: double click to be a list of possibilities, listed in order of preference/precedence:

What I think might help facilitate this is having a notional return value from these actions to indicate if they did something. Then the user can configure the list in the order that makes sense to them, with the parameters that make sense to them. The dispatcher will stop going through the list when one of the entries signals that it did what it was supposed to do.

Today, the key and mouse assignments are partially asynchronous; processing has no way to await the outcome because of the nature of how the action dispatcher works. I don't think it will be simple to change that for all possible actions, but maybe there can be a targeted subset of "semantic selection compatible" actions that be defined so that they can signal their results appropriately.

gegoune commented 8 months ago

Alternative idea, or maybe different feature(?), is some sort of incremental selection. Could be triggered by mapping, like control-double click, selecting (from configurable list), say starting with Word, then expanding to within-quotes on following C-click, next onto within parentheses, etc, line, paragraph, semantic zone.

(Treesitrer plugin for neovim provides such functionality.)