sxyazi / yazi

💥 Blazing fast terminal file manager written in Rust, based on async I/O.
https://yazi-rs.github.io
MIT License
15.24k stars 345 forks source link

Enable live update of flavor through Lua plugin API #988

Closed markmacode closed 2 weeks ago

markmacode commented 5 months ago

Please describe the problem you're trying to solve

Currently it appears that I can not make a plugin for Yazi that would allow me to automatically change the flavor that Yazi is using. The only way to change a Yazi flavor is to update the config, then close and re-open Yazi. I would like to make a plugin in the future (or contribute a built-in feature) that can automatically switch between light and dark themes based on the system theme.

Automatically switching between light and dark themes is important for me as I try to view light mode during day time and dark mode at night. There is many eye-care and sleep benefits for this but GitHub this issue isn't the place to expand that 😃

Would you be willing to contribute this feature?

Describe the solution you'd like

A Lua function that could set the flavor of Yazi and update its appearance without needing to close and re-open Yazi (live update).

The name of the function, and the name of top level Lua module (config or theme) is something that I have no strong opinion over. But it would be good to have the field names follow the general configuration file spec: Within our "config", there is a "theme.toml" file where you can set the flavor.use entry, so my suggestion would follow this terminology.

If it has not been explored yet then I would suggest something possibly generic to the config, rather than specific to flavors:

config.apply({ theme.flavor.use = 'theme-name' })

Or if you would rather something specific for updating the theme config -- then maybe we could have something like:

theme.apply({ flavor.use = 'theme-name' })

These approaches seem to be expandable to applying other config values, so this solution wouldn't be specific just to updating flavors only.

Additional context

I understand that this may be something already planned as the config section of the plugin docs is under "TODO" https://yazi-rs.github.io/docs/plugins/config. So there may be a broader discussion needed before deciding on implementing my suggested approach, as you may want to approach applying config changes to Yazi in a different way that my proposed solution wouldn't be compatible with.

sxyazi commented 5 months ago

I like the idea, but I think it should be a built-in feature provided to users rather than a plugin API.

When Yazi starts up, it should send a CSI sequence request to the terminal for its colors, and based on the response color values, calculate whether the user's terminal is light or dark, and apply the corresponding flavor. Maybe we could have:

[flavor]

light = "atom-one-light"
dark  = "atom-one-dark"
markmacode commented 5 months ago

I like the idea, but I think it should be a built-in feature provided to users rather than a plugin API.

Well if you are willing to add to the current flavor config spec then I like that idea more.

When Yazi starts up, it should send a CSI sequence request to the terminal for its colors, and based on the response color values, calculate whether the user's terminal is light or dark, and apply the corresponding flavor

My end goal would is swap the colors automatically while Yazi is running. If I swap the terminal colors, could Yazi listen for that event and automatically update its colors to the corresponding light or dark theme?

sxyazi commented 5 months ago

If I swap the terminal colors, could Yazi listen for that event and automatically update its colors to the corresponding light or dark theme?

The crossterm crate (which Yazi uses) doesn't support terminal color response events, so it's not possible to detect it at runtime and I can only manually implement it before crossterm initializes during program startup.

I don't think crossterm will support it in the short term; it's currently in a state of lacking maintenance. My PR for detecting terminal size has been pending for a long time without being merged, so I've given up on directly adding it to crossterm...

markmacode commented 5 months ago

The crossterm crate (which Yazi uses) doesn't support terminal color response events

I understand, that's unfortunate. Is this just the listening for a color change event? Or does crossterm not have the ability to manually update the colors of the interface while the app is running?

If it's just the event: then what I'm imagining is that we could create our own event listener that executes a simple shell command every second to check the system theme (there are various ways to do this in each OS) -- if it changes from the last call then update the colors of Yazi.

So our own make-shift event listener, then call crossterm to change the colors, would this be something that's possible?

sxyazi commented 5 months ago

I understand, that's unfortunate. Is this just the listening for a color change event? Or does crossterm not have the ability to manually update the colors of the interface while the app is running?

crossterm does not support parsing OSI 11 responses into its internal events and does not provide the ability to extend it externally. OSI 11 is a sequence for querying terminal colors, and most terminals support it, see https://github.com/Canop/terminal-light/tree/main?tab=readme-ov-file#dynamic-colors-osc-escape-sequence-strategy for details.

then what I'm imagining is that we could create our own event listener that executes a simple shell command every second to check the system theme (there are various ways to do this in each OS)

I don't think it makes sense for the following reasons:

markmacode commented 5 months ago

I don't think it makes sense for the following reasons:

Yes I have noticed that all TUI's I use don't have a feature to swap themes based on the OS theme. Although some can be extended through plugins which was my original motivation, to enable the ability for such functionality to be implemented as a plugin so that Yazi can keep its hands clean of this messy stuff. I currently have Wezterm, Neovim, and Tmux responding to system theme changes, this is done through plugins or scripting 'hacks'.

So lets ditch the idea that Yazi should natively support syncing a light/dark theme with the OS.

sxyazi commented 2 weeks ago

Tracked by https://github.com/sxyazi/yazi/issues/1644