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

Ability to define second theme to sync with OS #2158

Closed
domhel opened this issue Apr 18, 2022 · 29 comments
Closed

Ability to define second theme to sync with OS #2158

domhel opened this issue Apr 18, 2022 · 29 comments
Labels
C-enhancement Category: Improvements R-wontfix Not planned: Won't fix

Comments

@domhel
Copy link

domhel commented Apr 18, 2022

Describe your feature request

My OS is in light mode during day time and dark mode at night.
I like to code in the sun but in order to see anything I have to use a light theme.

My request is to define a light theme and a dark theme and the theme chosen depends on the OS's theme.
Low priority though.

@domhel domhel added the C-enhancement Category: Improvements label Apr 18, 2022
@thomas-profitt
Copy link

thomas-profitt commented Apr 18, 2022

To work around this, you could have your configured theme be a symlink to another theme, and use your OS's task scheduling utility (e.g. systemd timers) to run a task every evening to replace the symlink with one pointing to the dark theme, and another to switch it to the light theme in the morning.

But this is an excellent feature for a plugin to implement, once Helix has an interface for plugins.

@johalun
Copy link

johalun commented Apr 19, 2022

+1 for this on macOS

@archseer
Copy link
Member

This is better suited to either solving with symlinks or via scripting once we support it. Querying OS themes would introduce a bunch of platform specific code.

@EpocSquadron
Copy link
Contributor

Is it possible to define a theme like base16 that inherits purely from the terminal's color scheme? I know for example wezterm supports switching theme based on light/dark switch in the OS (macos and Linux gnome). It would be cool if such a theme literally just output references to the terminal's foreground, background, so it would automatically change with the terminal.

@sudormrfbin
Copy link
Member

It's possible, simply specify the colors as red, yellow, etc without defining a palette or hex colors. There's a section on it in the theme docs.

@EpocSquadron
Copy link
Contributor

But is "background" and "foreground" a thing? Otherwise you end up specifying "black" as the background which gains nothing in responding to terminal theme change.

@aral
Copy link
Contributor

aral commented Aug 1, 2022

Just came over to open an issue on this also. New terminal apps like Black Box do an excellent job of integrating with the operating system’s (ok, desktop environment’s) colour scheme. It’s a joy to see my terminal go from light mode to dark mode as my whole system does but sad to see Helix Editor stick out like a sore thumb when it launches in Dracula in the middle of a light scheme. Vampires don’t like the light and all that… :)

(Beyond vanity and mere aesthetics, this has implications for legibility/readability and, thus, accessibility.)

@archseer
Copy link
Member

archseer commented Aug 1, 2022

I'll reiterate: there's no built-in terminal way to detect this. We'd need to do a bunch of platform-specific hacks and probably link directly against a bunch of GTK-specific libraries to be able to read this on Linux+GTK.

See here for example: a nvim plugin that has to speak the dbus protocol (plus continually poll) to detect this: https://github.com/Sewdohe/Nvim-Adapt/blob/main/lua/nvim-adapt.lua

You could script this by doing the dbus interaction externally to helix, then swap the config files. To deal with running instances we'd need to add support for reloading the config on USR1 signal, but that's fairly easy to add.

@aral
Copy link
Contributor

aral commented Aug 1, 2022

To deal with running instances we'd need to add support for reloading the config on USR1 signal, but that's fairly easy to add.

Ah, this was what I was just about to ask :)

Scripting this for GNOME has been no effort at all. I’ll share my own script in a second once I’m happy it’s working properly. The ability to update running instances is the only thing it’s missing right now.

@aral
Copy link
Contributor

aral commented Aug 1, 2022

OK, sorry for the delay, life got in the way. So, here’s one way to synchronise Helix with the system colour scheme on GNOME:

Prerequisites

Make sure your Helix configuration is at ~/.config/helix/config.toml (or change the paths in the scripts accordingly) and that you have a line in it that sets the theme. What it’s set to is not as important as the line being there so it can be changed by the update script.

theme = "something"

The scripts

First, create a folder to hold the scripts:

mkdir -p ~/.config/helix/scripts/synchronise-with-system-colour-scheme

Then create the following scripts and ensure they’re executable (chmod +x <name-of-file>):

monitor.sh

#!/usr/bin/env bash

gsettings monitor org.gnome.desktop.interface color-scheme \
  | xargs -L1 bash -c "source ${HOME}/.config/helix/scripts/synchronise-with-system-colour-scheme/update.sh"

update.sh

#!/usr/bin/env bash

# Fail early, fail often.
set -eu -o pipefail

if [[ "$1" == "default" ]]; then
  # Update Helix Editor config to use light theme.
  sed -i 's/theme = ".*"/theme = "serika-light"/' ${HOME}/.config/helix/config.toml
else
  # Update Helix Editor config to use dark theme.
  sed -i 's/theme = ".*"/theme = "dracula"/' ${HOME}/.config/helix/config.toml
fi

Edit the script to change the light and dark themes to the ones you want. You can see the ones available on your system using the :theme command in Helix.

You need to keep the monitor script running in the background for this to work. You can do this by simply running ./monitor.sh &, or (recommended), you can run it as a systemd user service.

Before creating the systemd service, create two more helper scripts to enable and disable it:

enable.sh

#!/usr/bin/env bash

# Enables the service to start on boot and also starts it up immediately.
systemctl --user enable helix-system-colour-scheme-synchronisation.service
systemctl --user start helix-system-colour-scheme-synchronisation.service

disable.sh

#!/usr/bin/env bash

# Stop the service immediately and disables it from starting on boot.
systemctl --user stop helix-system-colour-scheme-synchronisation.service
systemctl --user disable helix-system-colour-scheme-synchronisation.service

And, finally, create the systemd user service (in _~/.config/systemd/user and make sure it is executable.)

helix-system-colour-scheme-synchronisation.service

[Unit]
Description=Helix System Colour Scheme Synchronisation Service
Documentation=https://github.com/helix-editor/helix/issues/2158
After=gnome-session.target

[Service]
Type=simple
RestartSec=5
Restart=always
ExecStart=%h/.config/helix/scripts/synchronise-with-system-colour-scheme/monitor.sh

[Install]
WantedBy=gnome-session.target

That’s it.

Run: ./enable in your scripts folder to enable the service and ./disable to disable it.

Helix currently doesn’t automatically reload its configuration when it changes so you’ll have to restart existing instances manually.

I look forward to the day when we can see a smooth fade from a light theme to a dark theme and back when the system theme changes ;)

Hope you find this useful :)

@aral
Copy link
Contributor

aral commented Sep 5, 2022

@archeer, @the-mikedavis, et al., Just a quick heads up that I’ve now released a simple tool called Lipstick on a Pig (https://codeberg.org/small-tech/lipstick/#lipstick-on-a-pig) that handles the theme switches on GNOME-based systems.

All you have to do is install it and it does its thing automatically.

It currently also has support for the bat and delta tools (which are two I use daily) and you can easily add support for any other CLI app that supports colour themes by providing a simple plugin: https://codeberg.org/small-tech/lipstick/src/branch/main/src/lipstick-apps

(For Helix, you currently need a restart but the moment we have some sort of functionality to reload the config when it detects a change, this should be automatic. How neat would it be if it actually fade/transitioned along with everything else?) :)

Enjoy! 💕

@Siilwyn
Copy link
Contributor

Siilwyn commented Oct 5, 2022

👋 I recently worked on something similar, how about adding linux support for this using the dbus freedesktop portal? It'll work on all distros that follow this standard and the only new dependency this would introduce is zbus & zvariant. I'm down to adding this to helix if the maintainers agree.

@the-mikedavis
Copy link
Member

Now that we reload configuration when we receive the USR1 signal, I don't see any reason to build this directly into Helix, especially if it requires new dependencies.

@Siilwyn
Copy link
Contributor

Siilwyn commented Oct 6, 2022

@the-mikedavis ah that's a pity, it would really make the editor 'complete' for me. Let me know if anything changes your mind!

@aral
Copy link
Contributor

aral commented Oct 9, 2022

@the-mikedavis That’s great news. I just updated Lipstick on a Pig so it now sends the USR1 signal to Helix. This is what it looks like when you switch between light/dark themes on Fedora Silverblue with Helix Editor running under Black Box terminal and switching between the One Light and Dracula themes.

lipstick-on-a-pig-helix-editor.mp4

@lukepighetti
Copy link

lukepighetti commented Feb 7, 2023

I have played around with rust-dark-light on macOS and it seems to work well. This would be a great feature. https://github.com/frewsxcv/rust-dark-light

@sadamczyk-eos
Copy link

For GNOME you can use the Night Theme Switcher extension.

Sunrise

Set the following command for Sunrise: ~/.scripts/sunrise.sh (or wherever you keep these kinds of scripts)

#!/usr/bin/env sh
# Shell commands to run when GNOME Night Theme Switcher switches to day
set -e

# Update Helix Editor config to use light theme
sed -i 's/theme = ".*"/theme = "solarized_light"/' ${HOME}/.config/helix/config.toml
pkill -USR1 hx

# Other programs, like e.g. kitty:
kitty +kitten themes --reload-in=all Solarized Light

Sunset

Set the following command for Sunset: ~/.scripts/sunset.sh (or wherever you keep these kinds of scripts)

#!/usr/bin/env sh
# Shell commands to run when GNOME Night Theme Switcher switches to night
set -e

# Update Helix Editor config to use dark theme
sed -i 's/theme = ".*"/theme = "solarized_dark"/' ${HOME}/.config/helix/config.toml
pkill -USR1 hx

# Other programs, like e.g. kitty:
kitty +kitten themes --reload-in=all Solarized Dark

I took the commands to update and reload the helix config from @aral's tool. Thanks for providing them.

@dessalines
Copy link

Another easy way to do this, is to use darkman. Then you can create scripts in ~/.local/share/dark-mode.d and light-mode.dwith the following:

sed -i 's/theme = ".*"/theme = "solarized_light"/' ${HOME}/.config/helix/config.toml
pkill -USR1 helix

@kirawi kirawi added the R-wontfix Not planned: Won't fix label Jun 10, 2023
@dvic
Copy link
Contributor

dvic commented Jun 15, 2023

I've also successfully used the darklight rust crate to come up with a workaround that should work across platforms, I've posted the simpel binary with instructions here: https://github.com/qdentity/darklight.

I see that a wontfix label was added but maybe this can be reconsidered if we just implement the feature in a simple way by justing checking on startup and config reload? (using the darklight rust crate)

VScode already has and the next version iTerm will also have this feature so I thought it would be nice if we can also have it :) I would be willing to dive in the code and work a PR :)

@lukepighetti
Copy link

I definitely think there should be a canonical way to have auto light/dark theme in Helix. I don't really have an opinion on what that should be, but the quickest I can think of is using one of the system brightness crates and adding dark/light theme settings in config

@Siilwyn
Copy link
Contributor

Siilwyn commented Jul 4, 2023

I've started with this because I really miss this feature and in the hope that it'll be reconsidered, I'm willing to maintain it too once it's merged. In the meantime my branch could be useful for some people, also open to any feedback!

@jokeyrhyme
Copy link

If it were possible to set the theme (and/or all settings) via command-line flag or environment variable, then that would allow us to control it at launch time without needing to modify the configuration files

That wouldn't be the same as having it change on-the-fly, but it'd be enough for workflows where the light/dark decision is made once per terminal session

@swsnr
Copy link

swsnr commented Sep 18, 2023

You can switch the helix editor theme on the fly by editing the configuration file (e.g. with sed) and sending SIGUSR1 to all helix processes, or, if you'd like to avoid editing the config file, by pointing theme to a symlink, updating the symlink target, and sending SIGUSR1 to all helix processes afterwards, see https://github.com/swsnr/dotfiles/blob/5bc53b1357debfeafe0804059c000511d73cc344/bin/color-scheme-hook#L64

@zoedsoupe
Copy link

You can switch the helix editor theme on the fly by editing the configuration file (e.g. with sed) and sending SIGUSR1 to all helix processes, or, if you'd like to avoid editing the config file, by pointing theme to a symlink, updating the symlink target, and sending SIGUSR1 to all helix processes afterwards, see https://github.com/swsnr/dotfiles/blob/5bc53b1357debfeafe0804059c000511d73cc344/bin/color-scheme-hook#L64

That's a possibility but it breaks the contract and become unavailable on declarative build system as Nix and Guix as those make config files read only and isn't suitable to change dynamically the declaration of the config.

@ModProg
Copy link

ModProg commented Nov 1, 2023

As helix is a terminal editor, it could also try querying the background color with OSC 4 and switch based on that.

@vwkd
Copy link
Contributor

vwkd commented Nov 3, 2023

Some terminals like iTerm212 send a SIGWINCH signal when the system color scheme changes.

If helix could specify commands in the config that are run in reaction to a signal, it would allow to automatically change the theme. There seems to be a plugin3 for neovim that does that.

This would eliminate the need to run a separate watcher script in the background that modifies the helix config in place and reloads it in active helix processes by sending them a SIGUSR1 signal.

Footnotes

  1. https://gitlab.com/gnachman/iterm2/-/issues/7943

  2. https://gitlab.com/gnachman/iterm2/-/issues/9855

  3. https://github.com/will/bgwinch.nvim

@webdev23
Copy link

To solve or palliate this and many other issues, I do recommend to add:

  • The ability to load a theme from the command line
  • pkill -USR1 hx (reload config) <= that one is implemented already
  • pkill -USR2 hx (reload theme)
  • pkill -USR3 hx (reload all files)

@vwkd
Copy link
Contributor

vwkd commented Feb 4, 2024

Since maintainers don’t seem interested in a better solution, here’s one way to set up automatic theme switching using iTerm2 (3.4) on macOS.

The helix script modifies a custom theme instead of the config.toml directly to avoid accidentally overwriting configuration. It’s called from a iTerm2 script which waits until the system theme changes. It also changes the iTerm2 theme which could become obsolete if iTerm2 3.5 adds automatic theme switching.


~/.config/helix/config.toml

theme = "adaptive"
# ...

~/.config/helix/themes/adaptive.toml

inherits = "github_dark"

~/.config/helix/switch_theme.sh

#!/usr/bin/env bash

set -e -u -o pipefail

THEME_LIGHT="github_light"
THEME_DARK="github_dark"
THEME_FILEPATH="${HOME}/.config/helix/themes/adaptive.toml"

if [[ $# -eq 0 ]]; then
  echo "Error: Missing theme argument." >&2
  exit 1
fi

if [[ $1 == "light" ]]; then
  sed -i '' -E "s/^inherits = \"$THEME_DARK\"$/inherits = \"$THEME_LIGHT\"/" "$THEME_FILEPATH"
elif [[ $1 == "dark" ]]; then
  sed -i '' -E "s/^inherits = \"$THEME_LIGHT\"$/inherits = \"$THEME_DARK\"/" "$THEME_FILEPATH"
else
  echo "Error: Invalid theme '$1'. Expected 'light' or 'dark'." >&2
  exit 1
fi

pkill -USR1 hx || true

~/Library/Application\ Support/iTerm2/Scripts/AutoLaunch/switch_theme.py

#!/usr/bin/env python3

# adapted from https://iterm2.com/python-api/examples/theme.html

import os
import subprocess
import iterm2

THEME_LIGHT = "Light Background"
THEME_DARK = "Dark Background"
HELIX_SWITCH_THEME_PATH = os.path.expanduser("~/.config/helix/switch_theme.sh")

async def update(connection, theme):
    parts = theme.split(" ")
    if "dark" in parts:
        preset = await iterm2.ColorPreset.async_get(connection, THEME_DARK)
        subprocess.run([HELIX_SWITCH_THEME_PATH, "dark"], check=True)
    else:
        preset = await iterm2.ColorPreset.async_get(connection, THEME_LIGHT)
        subprocess.run([HELIX_SWITCH_THEME_PATH, "light"], check=True)

    profiles=await iterm2.PartialProfile.async_query(connection)
    for partial in profiles:
        profile = await partial.async_get_full_profile()
        await profile.async_set_color_preset(preset)

async def main(connection):
    app = await iterm2.async_get_app(connection)
    await update(connection, await app.async_get_variable("effectiveTheme"))
    async with iterm2.VariableMonitor(connection, iterm2.VariableScopes.APP, "effectiveTheme", None) as mon:
        while True:
            theme = await mon.async_get()
            await update(connection, theme)

iterm2.run_forever(main)

@aral
Copy link
Contributor

aral commented Feb 5, 2024

I wrote/use Lipstick on a Pig a little while ago to do this for Helix and a few other apps.

In case it’s easier: https://codeberg.org/small-tech/lipstick

@helix-editor helix-editor locked and limited conversation to collaborators Apr 8, 2024
@pascalkuthe pascalkuthe converted this issue into discussion #10281 Apr 8, 2024

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
C-enhancement Category: Improvements R-wontfix Not planned: Won't fix
Projects
None yet
Development

No branches or pull requests