Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Support dark and light themes and syncing theme to system setting, a la window decorations #809

Closed
sloane-shark opened this issue Nov 3, 2023 · 17 comments

Comments

@sloane-shark
Copy link
Collaborator

Several other popular terminals support the ability to configure independent themes for dark and light mode, which will then be automatically selected according to the system's dark or light mode setting. Ghostty already supports syncing the light or dark value of the window decorations with the system setting, so I imagine we could leverage the same logic for themes.

For a little bikeshedding, since themes are just configurations, I think it would probably make sense to introduce light-config-file and dark-config-file for arbitrary configuration files that are loaded and unloaded according to the system setting. This would allow adjusting other settings if desired, such as fonts or transparency.

@rockorager
Copy link
Collaborator

Contour has written a VT extension to notify applications using escape sequences that a color scheme change occurred. Would be good to include this reporting as part of this feature

Reference

@mitchellh
Copy link
Contributor

Contour has written a VT extension to notify applications using escape sequences that a color scheme change occurred. Would be good to include this reporting as part of this feature

I would like to keep these separate and focus this issue on the process of configuring Ghostty with theme-specific configurations. I agree with supporting this once it has settled a bit though.

@mitchellh mitchellh added the core label Nov 4, 2023
@mitchellh
Copy link
Contributor

mitchellh commented Nov 4, 2023

Sharing some prior thinking I've had on this. None of this is set in stone, its not a mandate. Just thoughts.

From a design perspective, I think its important that Ghostty retains the property that the CLI arguments and configuration format is isomorphic. I've personally always enjoyed it when software has had that property, because its easy to move stuff around between files and scripts. For those unaware, every Ghostty configuration key is also a valid CLI flag, and the format is identical. The config lines just don't have the -- prefix a CLI flag has.

So, I'd like to retain that property.

I think the suggestion OP has around light-config-file and dark-config-file is not bad, because it does retain that to some extent, but one issue is that you can then only set themed configurations within files, not directly on the CLI.

An approach I was trying to consider was the ability to annotate any config key with a condition in which it is active. For example: background = FF0000 [theme=dark]. This is just an example, not literal proposed syntax. Then in the CLI you could do --background="FF0000 [theme=dark]". I don't love that syntax but the idea I think is more important. This approach would also still enable the dark/light config file because you could do config-file = my-dark-config [theme=dark].

The condition proposal also would let us introduce other conditions. For example, I share my identical Ghostty config between macOS and Linux, and I'd love to have some Linux-specific keybindings. It'd be nice to do keybind = something [os=linux] or whatever.

The condition proposal could also easily extend into AND, OR conditions, although there is no need to introduce that complexity today. I'm merely pointing out the framework allows for it.

🚲🏠 (Bikeshed): We could also bake the condition into the key, i.e. background[theme=dark] = FF0000. This becomes clunkier on the CLI because you'd have to quote the entire thing including the --. Perhaps there are other approaches.

@erf
Copy link
Collaborator

erf commented Nov 4, 2023

Regarding themes, Wezterm ships 700+ iTerm2 themes, is this something Ghostty will do too (or can be inspired by) ?

@mitchellh
Copy link
Contributor

Regarding themes, Wezterm ships 700+ iTerm2 themes, is this something Ghostty will do too (or can be inspired by) ?

Again, I'd like to not make that a focus of this issue, but we could definitely ship those as part of the resources directory. There are already over 250 Ghostty themes available here: https://github.com/mbadolato/iTerm2-Color-Schemes (Ghostty being one of the formats available)

@mitchellh
Copy link
Contributor

Note with #942 we now have built-in themes set with theme. (Not merged at the time of writing this comment because I'm waiting on an upstream PR but I expect that'll happen soon) This configuration will fit very nicely with the ideas proposed in this issue.

@sloane-shark
Copy link
Collaborator Author

i've been meaning to sit down and hash out some alternate syntax proposals for this, but have been busy. re your latest bikeshed method, i'm not sure we WOULD have to quote so aggressively, at least in all cases... i think most shell parsers would let us get away with something like --[mode=dark]theme=my-theme on the CLI, we would just have to implement the splitting by hand. i think that might already be what is done, anyway?

@mitchellh
Copy link
Contributor

i think that might already be what is done, anyway?

Yep!

Happy to hear more bikeshed ideas, I think I've enumerated my constraints/desires clearly above but feel free to ask any Qs.

@adamcstephens
Copy link
Collaborator

I've used external scripts with kitty to provide light/dark toggling. Kitty has a subcommand to set individual colors, or it can load them from a file (e.g. a theme file).

The subcommand even has other options for targeting all windows, how new windows are handled, etc. For my purposes I've been happy with just sending the theme change to all terminals.

Adding concepts for light and dark are nice, but maybe just on-the-fly loading of a theme file could go a long way towards enabling that.

Usage: kitten @ set-colors COLOR_OR_FILE ...

Set the terminal colors for the specified windows/tabs (defaults to active
window). You can either specify the path to a conf file (in the same format as
kitty.conf) to read the colors from or you can specify individual colors, for
example::


kitten @ set-colors foreground=red background=white

@gagbo
Copy link
Collaborator

gagbo commented May 14, 2024

Adding concepts for light and dark are nice, but maybe just on-the-fly loading of a theme file could go a long way towards enabling that.

I think I’d prefer that as well, I don’t know how easier/harder it would be to configure. My sole usecase for "quick theme switching" is actually runtime cursor color switching. When I switch my editor from light to dark theme, I’d like to have a quick command (shelling out is ok) to change the cursor color from dark to bright.

(Bear with my slow typing in the small demo)

Enregistrement.de.l.ecran.2024-05-14.a.12.02.36.mov

@roguesherlock
Copy link
Collaborator

Adding concepts for light and dark are nice, but maybe just on-the-fly loading of a theme file could go a long way towards enabling that.

I think I’d prefer that as well, I don’t know how easier/harder it would be to configure. My sole usecase for "quick theme switching" is actually runtime cursor color switching. When I switch my editor from light to dark theme, I’d like to have a quick command (shelling out is ok) to change the cursor color from dark to bright.

(Bear with my slow typing in the small demo)

Enregistrement.de.l.ecran.2024-05-14.a.12.02.36.mov

I have this autocommand in my neovim config which switches the ghostty theme. I just have to then press cmd+shift+, to reload. Thought I'd share in case it's helpful until we have proper theme syncing,

vim.api.nvim_create_autocmd("ColorScheme", {
  pattern = "*",
  callback = function()
    if vim.o.background == "light" then
      if term == "xterm-kitty" then
        vim.fn.system("kitty +kitten themes " .. M.terminal_theme_light)
      elseif term == "xterm-ghostty" then
        vim.fn.system(
          "sed -i'.bak' 's/theme = .*/theme = "
            .. M.terminal_theme_light
            .. "/' (readlink ~/.config/ghostty/config)"
        )
      end
    elseif vim.o.background == "dark" then
      if term == "xterm-kitty" then
        vim.fn.system("kitty +kitten themes " .. M.terminal_theme_dark)
      elseif term == "xterm-ghostty" then
        vim.fn.system(
          "sed -i'.bak' 's/theme = .*/theme = "
            .. M.terminal_theme_dark
            .. "/' (readlink ~/.config/ghostty/config)"
        )
      end
    end
  end
})

@i-am-linja
Copy link
Contributor

I think, given we have built-in themes, an MVP would be separate theme-light and theme-dark options, and automatic switching. Reactive config loading is nice, but seems overkill if it's just for colours.

@net
Copy link

net commented Aug 19, 2024

Unless I'm missing something, themes are built into the release, so theme-light and theme-dark wouldn't work for user themes.

@i-am-linja
Copy link
Contributor

Unless I'm missing something, themes are built into the release, so theme-light and theme-dark wouldn't work for user themes.

Under the current system, they would not. However, the current system is a bad fit for theme switching anyway: see above, where an entirely separate config seems like a sensible solution. Ideally we would have theme = ./user-theme-file, but that's a separate idea which does not block the MVP.

@mitchellh
Copy link
Contributor

mitchellh commented Aug 19, 2024

Since #2089, users can provide custom themes. This doesn't fix this issue at all but I'm just noting this as response based on the previous comments.

@gpanders
Copy link
Member

Brainstorming another idea for conditional configuration directives (see this comment):

Zig's build-exe command configures module options by first using the -M flag, which starts a new set of module options, followed by a set of module-specific flags like -target, -O, etc. So for building multiple modules, the usage would look roughly like zig build-exe -Mfoo=foo.zig -O Debug -fstrip -Mbar=bar.zig -O ReleaseSmall.

Ghostty could do something similar, which would allow it to work for both the command line and config file. Essentially, rather than annotating individual options, options are grouped based on a condition. Hypothetical example:

Command line

ghostty \
    --if=os=linux \
    --command=/usr/local/bin/fish \
    --keybind=alt+left_bracket=goto_split:previous \
    --keybind=alt+right_bracket=goto_split:next \
    --if=os=macos \
    --command=/opt/homebrew/bin/fish \
    --if=theme=dark \
    --background=#ff0000 \
    --if=theme=light \
    --background=#00ff00

Config file

if = os=linux
command = /usr/local/bin/fish
keybind = alt+left_bracket=goto_split:previous
keybind = alt+right_bracket=goto_split:next

if = os=macos
command = /opt/homebrew/bin/fish

if = theme=dark
background = #ff0000

if = theme=light
background = #00ff00

And the conditions to if could be combined:

if = os=linux,theme=dark

background = #ff0000

if = os=macos,theme=dark

background = #fff000

It's admittedly a little unusual, but it at least solves the constraint of keeping the config file and command line isomorphic 😅

@melMass
Copy link
Collaborator

melMass commented Oct 1, 2024

What would be the guidelines for proposing such a PR? I'm willing to look into it given I also have the need but don't want to waste anyones (myself included) time going in the wrong direction

@ghostty-org ghostty-org locked and limited conversation to collaborators Oct 2, 2024
@mitchellh mitchellh converted this issue into discussion #2356 Oct 2, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests