nix-community / home-manager

Manage a user environment using Nix [maintainer=@rycee]
https://nix-community.github.io/home-manager/
MIT License
6.56k stars 1.73k forks source link

Color scheme switcher #361

Closed NefixEstrada closed 3 years ago

NefixEstrada commented 6 years ago

It would be nice if there was an option to store different color schemes (+ background directories) and have the ability to switch between them. No idea how to implement it though.

I have something like this in mind:

The themes would be stored in a file called themes.nix and would be referenced from the home.nix

Not sure if that was clear, let's hope it was!

bsima commented 5 years ago

I think this is a great idea. Right now I just store my theme config in a separate file, and append onto the main config file. Here's an example:

https://github.com/bsima/config/blob/master/home.nix#L46-L47

So, the general mechanism is simply "append theme.nix to the main config", which seems simple enough to generalize across multiple modules.

On 08.28..03.51, Néfix Estrada wrote:

It would be nice if there was an option to store different color schemes (+ background directories) and have the ability to switch between them. No idea how to implement it though.

I have something like this in mind:

  • Being able to choose the theme when switching: home-manager switch --theme="nature"
  • Having a configuration option where you specify the theme
  • ...

The themes would be stored in a file called themes.nix and would be referenced from the home.nix

Not sure if that was clear, let's hope it was!

-- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/rycee/home-manager/issues/361

rycee commented 5 years ago

Yeah, I've been thinking about adding some form of theming support for a long time but haven't yet thought of a solution I would be happy with. The main difficulty is the wide variety of how programs and widget toolkits do their theming.

It most likely would end up with the programs and toolkits modules having their own theming options (e.g., like the gtk and gnome-terminal modules do today). Then it would be possible for people to create themes under some themes option name space. This should be quite possible today, just create your own mytheme.nix file as a Home Manager module, publish it somewhere, and convince people to put

imports = [ https://.../mytheme.nix ];

in their Home Manager configuration. Clearly there are security aspects to consider here since a module can do pretty much anything but in principle it works.

NefixEstrada commented 5 years ago

I was thinking more in something like having different color palettes and being able to switch between them easily (not sure if I've understood you). Right now, I handle my theming in the following way:

{ pkgs, ... }:

let

  ...

  # Colors
  color0 = "#04020b";
  color1 = "#2e3568";
  color2 = "#47346a";
  color3 = "#90327a";
  color4 = "#384f87";
  color5 = "#4e6897";
  color6 = "#c228b6";
  color7 = "#a4bdcf";
  color8 = "#728490";
  color9 = "#2e3568";
  color10 = "#47346a";
  color11 = "#90327a";
  color12 = "#384f87";
  color13 = "#4e6897";
  color14 = "#c228b6";
  color15 = "#a4bdcf";
  background = "#04020b";
  foreground = "#a4bdcf";
  cursorColor = "#a4bdcf";
in
...

But I'm sure there's a better way to do that. The thing is that I can't switch between color schemes easily

rycee commented 5 years ago

Sorry for the long delay.

In your case I think you could just make a simple module for it. For example, create a file colors.nix containing

{ lib, ... }:

with lib;

{
  options.colors =
    let
      mkColorOption = name: {
        inherit name;
        value = mkOption {
          type = types.strMatching "#[a-fA-F0-9]{6}";
          description = "Color ${name}.";
        };
      };
    in
      listToAttrs (map mkColorOption [
        "background" "foreground" "cursor" "color0" "color1" "color2"
        "color3" "color4" "color5" "color6" "color7" "color8" "color9"
        "color10" "color11" "color12" "color13" "color14" "color15"
      ]);
}

Then you can create mycolors0.nix, mycolors1.nix, etc. that may contain something like

{
  imports = [ ./colors.nix ];

  colors = {
    color0 = "#04020b";
    color1 = "#2e3568";
    color2 = "#47346a";
    color3 = "#90327a";
    color4 = "#384f87";
    color5 = "#4e6897";
    color6 = "#c228b6";
    color7 = "#a4bdcf";
    color8 = "#728490";
    color9 = "#2e3568";
    color10 = "#47346a";
    color11 = "#90327a";
    color12 = "#384f87";
    color13 = "#4e6897";
    color14 = "#c228b6";
    color15 = "#a4bdcf";
    background = "#04020b";
    foreground = "#a4bdcf";
    cursor = "#a4bdcf";
  };
}

Finally you can use this in a HM configuration. For example,

{
  imports = [ ./mycolors0.nix ];
  home.file."foo".text = "foreground is ${config.colors.foreground}\n";
}

where you can relatively easily switch colors by changing the imports line.

If you insist on being able to change the color theme directly from the home-manager command then that is also possible. If you instead have

{
  imports = [ <color-theme> ];
  home.file."foo".text = "foreground is ${config.colors.foreground}\n";
}

then you can, for example, say

$ home-manager -I color-theme=$HOME/dotfiles/mycolors0.nix switch
balsoft commented 5 years ago

I am working on some "theme translators" - currently I have QT theme figured out, as well as themes for i3, dunst, polybar (although only my custom config), VSCode, kate, konsole, kdevelop and some other stuff that I've forgotten about already. All of the themes are generated from single color list. I am not yet ready to show it to the world, though, as it's very bad code style and not polished enough. (Also, it's currently made with breeze-dark in mind and you can just change fg colours; I am not sure if bg changes will work correctly)

dustinlacewell commented 5 years ago

You all may be interested in https://github.com/dylanaraps/pywal https://github.com/deviantfero/wpgtk/ https://www.youtube.com/watch?v=sVHlYcKVerE and https://github.com/dustinlacewell/dotfiles/blob/master/modules/home/linux/workstation/pywal/default.nix

aakropotkin commented 5 years ago

I implemented something similar to this. Here's my modules: https://gist.github.com/alexameen/15d07005112d1808bb9271f122f40989

This will give you Xresources colors and add a ton of shell variables filled with hex codes that could be used in a variety of progams. This is easily extended to add support for more programs in the config itself.

I included an example color-scheme, the modules, and a snipped of my home.nix with the relevant bits.

I wrote the options so that you could snag someones Xresources lists which are commonly shared online and easily convert it to a theme by replacing all : with = and wrapping all values in "<value>"; without hassling with renaming things too much.

feijoas commented 4 years ago

I am using the module from @balsoft with success: https://github.com/balsoft/nixos-config/blob/master/modules/themes.nix

balsoft commented 4 years ago

@feijoas cool! Can I look at the way you are using it?

stellarhoof commented 4 years ago

I've been using this https://github.com/stellarhoof/furnisher/blob/master/lib/colors.nix with my configuration and it works quite well. Here are usage examples:

Nadrieril commented 4 years ago

You may all be interested in https://github.com/chriskempson/base16 . They have a lot of templates to apply a colorscheme to various apps. This might be partially nix-able.

rycee commented 4 years ago

FWIW I have some half-baked base16-inspired module in my NUR.

There is a bit of documentation if you search for "base16" in https://rycee.gitlab.io/nur-expressions/hm-options.html and the configuration I use is public.

nixos-discourse commented 3 years ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/switching-theme-across-programs-with-home-manager/10880/2

stale[bot] commented 3 years ago

Thank you for your contribution! I marked this issue as stale due to inactivity. If this remains inactive for another 7 days, I will close this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

If you have nothing of substance to add, please refrain from commenting and allow the bot close the issue. Also, don't be afraid to manually close an issue, even if it holds valuable information.

Closed issues stay in the system for people to search, read, cross-reference, or even reopen--nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

stale[bot] commented 3 years ago

Thank you for your contribution! I marked this issue as stale due to inactivity. If this remains inactive for another 7 days, I will close this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

If you have nothing of substance to add, please refrain from commenting and allow the bot close the issue. Also, don't be afraid to manually close an issue, even if it holds valuable information.

Closed issues stay in the system for people to search, read, cross-reference, or even reopen--nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

i-am-logger commented 1 year ago

I was looking into something like that. I know the issue is closed but worth mentioning this work: https://github.com/SenchoPens/base16.nix and https://github.com/danth/stylix

zeorin commented 1 year ago

I had some thoughts around this… I wondered whether it would be possible to generate more than one profile from a home.nix file, but to only activate one, and then to later be able to activate a different one without re-evaluating the home.nix file again. I'm imagining a home-manager switch --variant $foo that would take relatively little time to execute, but it would switch around symlinks, restart services, etc. as a normal activation, without actually having to change anything in home.nix itself.

rycee commented 1 year ago

@zeorin Sounds like you are describing the specialization module.

I use it in my configuration to have quick access to a light theme for each generation.

fufexan commented 8 months ago

@rycee I've been using specialisations to do theming for the past 2 months or so, but I feel like they're overkill for theming, because it takes roughly twice the time to evaluate and build the config for 2 specialisations.

What I think would be a better approach would be to have each program's config or settings or whatever defined as a submodule of themes, which HM would eval and build all at once, and switch at runtime using home-manager --theme <theme> as previously said.

e.g For gtk we could have

gtk.theme = {
  light = {
    name = "Catppuccin-Latte-Compact-Flamingo-Light";
    package = pkgs.catppuccin-gtk.override {
      accents = ["flamingo"];
      size = "compact";
      variant = "latte";
    };
  };
  dark = {
    name = "Catppuccin-Mocha-Compact-Flamingo-Dark";
    package = pkgs.catppuccin-gtk.override {
      accents = ["flamingo"];
      size = "compact";
      variant = "mocha";
    };
  };
};

It would take a lot of module rewriting unless a general solution can be found.

Cu3PO42 commented 8 months ago

@fufexan I am actually working on something like this for my config. I am trying to re-use functionality from upstream modules as much as possible, but I'm still writing a new module for each program I want to support. Some of them are fairly short and easy (like Kitty) and others are a decent chunk of work. I think so far GTK is by far the worst offender, for which I actually needed to copy/paste some code from upstream. (I am also evaluating building partial configs including only the themed settings using an approach similar to specializations, but I'm not sure if that's here to stay yet.)

A "theme" in my framework consists of (at most) one theme for each supported application. If you omit it, there is built-in fallback functionality. For example, here is my Catppuccin Latte theme. Themes are activated by running chromactl activate-theme <name>, which switches the symlink at ~/.config/chroma/active to the new theme and runs a generated activation script. I configure each application to include a config file from there wherever possible. If the program doesn't support importing other configuration, I symlink the whole configuration file, e.g., ~/.config/gtk-3.0 is symlinked to ~/.config/chroma/active/gtk/gtk-3.0.

This is all very much a work in progress, but it has been working well for me so far. If you'd like to check it out, it's here. All theming code is on that branch exclusively (and at the time of writing I squashed everything into one commit). It's not ready for use by others quite yet (mostly because there is no documentation and I am likely to change the API in parts), but I do plan to make it as easy to use and integrate into your own config as possible.