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

Add hidecursorinactive option to indicate status when terminal loses focus #965

Merged
merged 7 commits into from
Dec 26, 2023

Conversation

laktak
Copy link
Contributor

@laktak laktak commented Oct 15, 2022

When hidecursorinactive is enabled, focus events from the terminal will hide/show the cursor when the terminal (or tmux pane) loses/gets focus.

This is similar to how most terminals and tmux hide the cursor in inactive windows/panes.


OLD VERSION - Enable focus events through configuration

Enable focus events through configuration by using focus (option), on-ui-enter/on-ui-exit (events) and echoraw (command).

This enables the same functionality as #861 but stores all escape sequences (both ways) in the configuration.

For example to enable focus events with tmux (I will add this to the wiki if the PR gets merged):

(updated for the current version)

# focus event, sent by the terminal/tmux on focus change
map <a-[>O :set cursoractivefmt ""; set cursorpreviewfmt ""
map <a-[>I :set cursoractivefmt "\033[7m"; set cursorpreviewfmt "\033[38;5;232m\033[48;5;240m"
cmap <a-[>O :set cursoractivefmt ""; set cursorpreviewfmt ""
cmap <a-[>I :set cursoractivefmt "\033[7m"; set cursorpreviewfmt "\033[38;5;232m\033[48;5;240m"

# enable focus reporting
cmd on-ui-enter &{{
    echo -n $'\e[?1004h'
}}

# disable focus reporting
cmd on-ui-exit &{{
    echo -n $'\e[?1004l'
}}

@ilyagr it's still a on/off option at the moment but since focus is now defined as a string option, you should be able implement something like set focus dark-grey on top of this. Please let me know if you need more than that.

ui.go Outdated
@@ -416,7 +416,7 @@ func (win *win) printDir(screen tcell.Screen, dir *dir, selections map[string]in
}
}

if i == dir.pos {
if i == dir.pos && gOpts.focus == "on" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nit: I'm not sure if "focus" is the right name for this option. At this point, it's an option that chooses whether to draw cursors, and the user decides whether that has anything to do with focus.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe instead add a 'cursorfmt' option that takes a format string like 'tagfmt' so you can apply an arbitrary style.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, the name is not ideal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed it back to be a bool since ilyagr does not need it anymore and cursor is not quite right (we already have a text cursor).

@ilyagr
Copy link
Collaborator

ilyagr commented Oct 16, 2022

I actually stopped using focus events in favor of making the tmux background of the active pane slightly darker. Specifically, I use the terminal background "terminal" color for the active pane, and the black color for the inactive pane. The latter is slightly brighter.

I may or may not implement the grey cursors on top of this PR. I'm not sure anybody is using it.

@p-ouellette
Copy link
Contributor

Not a huge fan of this. It adds a lot of commands/options to support an (IMO) pretty minor feature.
I think focus events should be added to tcell first. Then you could add on-focus and on-unfocus special commands.

@laktak
Copy link
Contributor Author

laktak commented Oct 16, 2022

@p-ouellette you got it a bit backwards. The point is not to add this one feature but to make it possible to implement more in user code and to require less code and maintenance in lf.

@p-ouellette
Copy link
Contributor

What's the usecase for on-ui-enter, on-ui-exit, and echoraw outside of supporting focus events? They seem like workarounds for missing tcell focus event support to me.

@laktak
Copy link
Contributor Author

laktak commented Oct 17, 2022

What's the usecase for on-ui-enter, on-ui-exit, and echoraw outside of supporting focus events?

Haven't implemented it yet but I want do use on-ui-enter and on-ui-exit to disable the tmux paste commands. Doesn't happen often but I accidentally pasted a text file into lf ...

echoraw can be used to send terminal commands like it is here. There are lots of use cases for that command alone.

@laktak
Copy link
Contributor Author

laktak commented Oct 25, 2022

I removed the echoraw command because sending it asynchronously had too many side effects.

@laktak
Copy link
Contributor Author

laktak commented Sep 20, 2023

Rebased to current master.

@laktak
Copy link
Contributor Author

laktak commented Sep 21, 2023

@ilyagr Since cursoractivefmt, cursorparentfmt and cursorpreviewfmt are now implemented, how about naming this simply hidecursor or cursorvisible?

@ilyagr
Copy link
Collaborator

ilyagr commented Sep 21, 2023

Setting cursoractivefmt and cursorparentfmt to empty strings should already make the cursor invisible. I hope this makes cursorvisible unnecessary.

If it was necessary, I think I'd go with cursorvisible for now, to keep the pattern going.

@laktak
Copy link
Contributor Author

laktak commented Sep 21, 2023

Setting cursoractivefmt and cursorparentfmt to empty strings should already make the cursor invisible. I hope this makes cursorvisible unnecessary.

Perfect, I hadn't thought of that. That simplifies this PR.

@laktak
Copy link
Contributor Author

laktak commented Sep 28, 2023

@gokcehan @ilyagr @joelim-work this PR has changed a lot as quite a few features are now part of lf and so the implementation is a bit smaller.

  • echoraw and the focus option have been removed
  • on-ui-enter and on-ui-exit are needed to tell the terminal to start/stop sending focus escapes
  • the ^ command is only used internally so that on-ui-enter and on-ui-exit can communicate via escapes with the terminal app or tmux.
  • when focus events are active they are handled by the map and cmap commands. In my example I (at the top) I use it to hide the cursor.
  • on-ui-enter and on-ui-exit are necessary because we need to enable the events when lf starts but we need to pause them whenever another process is processing stdin.

I've been maintaining this for almost a year but it would be great if it could be merged. I'd consider it thoroughly tested ;)

@ilyagr
Copy link
Collaborator

ilyagr commented Sep 29, 2023

I haven't made up my mind on anything, but here are some quick thoughts. @gokcehan @joelim-work , feel free to chime in.

If this PR is about focus events, it could use gdamore/tcell#599 when that's released (if it's not already). Then, instead of map <a-[>O it could be something like map <focusgained>.

Depending on whether the ui-enter event is useful for other purposes (I'm not sure), we could either 1) create a request-focus-events true/false command to replace echo -n $'\e[?1004h' or 2) get rid of the ui-enter event and introduce a request-focus-events option (possibly with a better name).

If we do neither, this feature looks cryptic in the documentation. Perhaps it could link to the wiki where you'd have an explanation of how to use this, but I'd prefer the documentation to be self-sufficient. (Again, this is a preference. I'm not saying this is an absolute requirement, I haven't thought about it enough to have a clear opinion).

@joelim-work
Copy link
Collaborator

@laktak @ilyagr Similar to the above #965 (comment), I am against handling focus events directly in the lf code and exposing such low-level configuration hooks to provide support, especially since tcell now supports it from gdamore/tcell#599 onwards. Merging this change now and introducing these configuration options means they will have to be deprecated later when lf is changed to use the native support provided by tcell. My understanding is that this is not a widely requested feature, and I think it would be better to be patient and wait for the newly added support in tcell to be released before implementing this.

Regarding the design, perhaps it's fine to enable focus reporting by default and provide on-focus-gained/on-focus-lost hook commands that can be customized by the user. Although I haven't given this very much thought and I suppose this can be discussed later.

@laktak
Copy link
Contributor Author

laktak commented Sep 29, 2023

Thanks for the feedback. Handling this via config would give the user a lot more flexibility but if we reduce this to just focus events, then letting tcell handle it (and maintaining it) is a good option.

There is one other use case that I can think of (disabling the tmux paste command when lf has focus) but I don't think that's very important.

I'll wait for the tcell release for now.

@joelim-work
Copy link
Collaborator

Hi @laktak,

I have merged #1533, which upgrades to the new version of tcell. You should be able to use the new focus reporting API now. I did a very brief test and it appears to work on my end.

@laktak
Copy link
Contributor Author

laktak commented Dec 19, 2023

@joelim-work Thanks, works great now!

I've replaced everything with:

## hidecursorinactive (bool) (default false)

Hide the cursor when the terminal or tmux pane loses focus.

app.go Outdated Show resolved Hide resolved
app.go Outdated Show resolved Hide resolved
doc.md Show resolved Hide resolved
gen/doc-with-docker.sh Outdated Show resolved Hide resolved
@joelim-work
Copy link
Collaborator

joelim-work commented Dec 20, 2023

I have left a few comments. Also since this is a new feature with some design considerations, I think it might be better to have @gokcehan / @ilyagr review this as well. I hope you don't mind the delay.

@laktak
Copy link
Contributor Author

laktak commented Dec 20, 2023

At this point, after having added and removed various events in this PR ;), I think adding it as just an option would make the most sense because you don't need to look at the wiki to set it up. I'd even set it as default because that's the standard behavior for a terminal window.

app.go Outdated Show resolved Hide resolved
@joelim-work
Copy link
Collaborator

At this point, after having added and removed various events in this PR ;), I think adding it as just an option would make the most sense because you don't need to look at the wiki to set it up. I'd even set it as default because that's the standard behavior for a terminal window.

After thinking about this some more, I think it might be fine to just have it as a bool option. I suspect there aren't many users who care about focus events, so there is no need to expose hooks, and even if we decide to replace hidecursorinactive with them later on, the breaking change won't be severe.

I am not a fan of changing the default behavior though. The last time something like this happened was changing cursorpreviewfmt in #1258, where a number of users thought it was some kind of bug, and we ended up having to pin the issue for some time.

Also please update the PR title and description to reflect the new status.

@laktak laktak changed the title Enable focus events through configuration Add hidecursorinactive option to indicate status when terminal loses focus Dec 23, 2023
joelim-work
joelim-work previously approved these changes Dec 23, 2023
Copy link
Collaborator

@joelim-work joelim-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the changes now look good to me and I can give my approval. Sorry couple more comments, PR looks much better overall though.


The following is more of a general concern from me and doesn't apply to just this PR:

As a collaborator, I actually do have permission to merge this change, but I'm not sure whether you are in a rush to have this merged or if you want to wait for a second review (I don't know how long this could take). Up until now, as I am not the owner of lf, I have so far taken the conservative approach and merged only minor changes like bug fixes and Dependabot updates. As much as I want to keep the development of lf active, I also have reservations about just 'taking over' the project.


Anyway I do intend to take a break until the new year, so this can be discussed later. In the meantime, thanks once again for the PR and have a good break 🙂.

eval.go Show resolved Hide resolved
ui.go Outdated Show resolved Hide resolved
@joelim-work joelim-work dismissed their stale review December 23, 2023 12:05

Couple more comments

@laktak
Copy link
Contributor Author

laktak commented Dec 23, 2023

IMO it would be a nice PR to handle all boolean option variations in a centralized manner (instead of the no and ! business for each one). Maybe next year :)

Happy holidays!

@gokcehan
Copy link
Owner

It looks good to me. I'm happy to finally see this feature getting merged with an appropriate implementation. Thank you @laktak for the patch and @joelim-work and others for the reviews and feedbacks. Happy holidays.

@gokcehan gokcehan merged commit 075caac into gokcehan:master Dec 26, 2023
4 checks passed
@joelim-work
Copy link
Collaborator

IMO it would be a nice PR to handle all boolean option variations in a centralized manner (instead of the no and ! business for each one). Maybe next year :)

@laktak There actually is such a discussion, see #1552. I doubt you are the only person who is worried about making a typo when copy/pasting the boilerplate code for a new boolean option.

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

Successfully merging this pull request may close these issues.

None yet

5 participants