danth / stylix

System-wide colorscheming and typography for NixOS
https://stylix.danth.me/
MIT License
1.23k stars 157 forks source link

add support for LS_COLORS #560

Open i-am-logger opened 2 months ago

i-am-logger commented 2 months ago

to generate something like this

  programs.bash.initExtra = ''
      export LS_COLORS="${generateLsColors config.lib.stylix.colors}"
    '';
  };
trueNAHO commented 2 months ago

Is LS_COLORS not is specifically for ls? AFAIK, ls can take the terminal colors, which Stylix should already apply in (nearly?) all cases.

i-am-logger commented 2 months ago

some utillities like lsd rely on LS_COLORS

I've implemented it this way which works

{ config, lib, pkgs, ... }:

with lib;

let
  cfg = config.stylix.ls-colors;

  # This function generates LS_COLORS based on Stylix colors
  generateLsColors = colors: ''
    di=${colors.base0D}  # directory
    fi=${colors.base05}  # file
    ln=${colors.base0C}  # symlink
    ex=${colors.base0A}  # executable
    bd=${colors.base0E}  # block device
    cd=${colors.base0E}  # character device
    so=${colors.base0E}  # socket
    pi=${colors.base0E}  # pipe
    or=${colors.base08}  # orphan symlink
    mi=${colors.base08}  # missing file
    su=${colors.base0B}  # setuid
    sg=${colors.base0B}  # setgid
    tw=${colors.base0A}  # sticky other writable
    ow=${colors.base0A}  # other writable
    st=${colors.base0E}  # sticky
    *.tar=${colors.base08}
    *.tgz=${colors.base08}
    *.zip=${colors.base08}
    *.gz=${colors.base08}
    *.bz2=${colors.base08}
    *.rpm=${colors.base08}
    *.deb=${colors.base08}
    *.jpg=${colors.base0D}
    *.jpeg=${colors.base0D}
    *.gif=${colors.base0D}
    *.png=${colors.base0D}
    *.svg=${colors.base0D}
    *.mp3=${colors.base0C}
    *.mp4=${colors.base0C}
    *.flac=${colors.base0C}
    *.wav=${colors.base0C}
    *.ogg=${colors.base0C}
    *.pdf=${colors.base08}
    *.doc=${colors.base08}
    *.docx=${colors.base08}
    *.odt=${colors.base08}
    *.txt=${colors.base05}
    *.md=${colors.base05}
    *.xml=${colors.base05}
    *.json=${colors.base05}
    *.yml=${colors.base05}
    *.yaml=${colors.base05}
    *.ini=${colors.base05}
    *.cfg=${colors.base05}
    *.conf=${colors.base05}
    *.py=${colors.base0E}
    *.rb=${colors.base0E}
    *.js=${colors.base0E}
    *.ts=${colors.base0E}
    *.sh=${colors.base0E}
    *.bash=${colors.base0E}
    *.zsh=${colors.base0E}
    *.nix=${colors.base0E}
    *.vim=${colors.base0E}
    *.lua=${colors.base0E}
    *.cpp=${colors.base0E}
    *.c=${colors.base0E}
    *.h=${colors.base0E}
    *.rs=${colors.base0E}
    *.go=${colors.base0E}
    *.java=${colors.base0E}
    *.class=${colors.base0E}
    *.cs=${colors.base0E}
    *.html=${colors.base09}
    *.css=${colors.base09}
    *.scss=${colors.base09}
    *.less=${colors.base09}
    *.sql=${colors.base09}
  '';

in
{
  options.stylix.ls-colors = {
    enable = mkEnableOption "Stylix-based LS_COLORS";
  };

  config = mkIf cfg.enable {
    environment.sessionVariables = {
      LS_COLORS = generateLsColors config.lib.stylix.colors;
    };

    environment.extraInit = ''
      export LS_COLORS="${generateLsColors config.lib.stylix.colors}"
    '';
    programs.bash.interactiveShellInit = ''
      export LS_COLORS="${generateLsColors config.lib.stylix.colors}"
    '';
    programs.zsh.interactiveShellInit = mkIf config.programs.zsh.enable ''
      export LS_COLORS="${generateLsColors config.lib.stylix.colors}"
    '';
    programs.fish.interactiveShellInit = mkIf config.programs.fish.enable ''
      set -gx LS_COLORS "${generateLsColors config.lib.stylix.colors}"
    '';
  };
}
i-am-logger commented 2 months ago

sorry, that script was old version

... }:

with lib;

let
  cfg = config.stylix.ls-colors;

  hexDigitToInt = c:
    let
      hexChars = "0123456789abcdef";
    in
    stringLength (head (splitString c (toLower hexChars)));

  hexToRgb = hexColor:
    let
      r = substring 0 2 hexColor;
      g = substring 2 2 hexColor;
      b = substring 4 2 hexColor;
      toDecimal = hex: hexDigitToInt (substring 0 1 hex) * 16 + hexDigitToInt (substring 1 1 hex);
    in
    "${toString (toDecimal r)};${toString (toDecimal g)};${toString (toDecimal b)}";

  generateLsColors = colors:
    let
      mkColor = color: "38;2;${hexToRgb color}";
      colorMap = {
        # Special files and directories
        di = mkColor colors.base0D; # directory
        fi = mkColor colors.base05; # regular file
        ln = mkColor colors.base0C; # symbolic link
        ex = mkColor colors.base0A; # executable file
        bd = mkColor colors.base0E; # block device
        cd = mkColor colors.base0E; # character device
        so = mkColor colors.base0E; # socket
        pi = mkColor colors.base0E; # named pipe (FIFO)
        or = mkColor colors.base08; # orphaned symlink
        mi = mkColor colors.base08; # missing file
        su = mkColor colors.base0B; # file that is setuid (u+s)
        sg = mkColor colors.base0B; # file that is setgid (g+s)
        ca = mkColor colors.base0B; # file with capability
        tw = mkColor colors.base0A; # directory that is sticky and other-writable (+t,o+w)
        ow = mkColor colors.base0A; # directory that is other-writable (o+w) and not sticky
        st = mkColor colors.base0E; # directory with sticky bit set (+t) and not other-writable
        ee = mkColor colors.base05; # empty file (arrow for classifyAlt)
        no = mkColor colors.base05; # normal non-filename text
        rs = mkColor colors.base05; # reset to no color
        mh = mkColor colors.base05; # multi-hardlink
        lc = mkColor colors.base05; # left code (opening part of color sequence)
        rc = mkColor colors.base05; # right code (closing part of color sequence)
        ec = mkColor colors.base05; # end code (for non-filename text)
        # File extensions
        "*.bash" = mkColor colors.base0D;
        "*.bz2" = mkColor colors.base08;
        "*.c" = mkColor colors.base0D;
        "*.cfg" = mkColor colors.base05;
        "*.class" = mkColor colors.base0D;
        "*.conf" = mkColor colors.base05;
        "*.cpp" = mkColor colors.base0D;
        "*.cs" = mkColor colors.base0D;
        "*.css" = mkColor colors.base09;
        "*.deb" = mkColor colors.base08;
        "*.doc" = mkColor colors.base08;
        "*.docx" = mkColor colors.base08;
        "*.flac" = mkColor colors.base0C;
        "*.gif" = mkColor colors.base0D;
        "*.go" = mkColor colors.base0D;
        "*.gz" = mkColor colors.base08;
        "*.h" = mkColor colors.base0D;
        "*.html" = mkColor colors.base09;
        "*.ini" = mkColor colors.base05;
        "*.java" = mkColor colors.base0D;
        "*.jpeg" = mkColor colors.base0D;
        "*.jpg" = mkColor colors.base0D;
        "*.js" = mkColor colors.base0D;
        "*.json" = mkColor colors.base05;
        "*.less" = mkColor colors.base09;
        "*.lua" = mkColor colors.base0D;
        "*.md" = mkColor colors.base05;
        "*.mp3" = mkColor colors.base0C;
        "*.mp4" = mkColor colors.base0C;
        "*.nix" = mkColor colors.base0D;
        "*.odt" = mkColor colors.base08;
        "*.ogg" = mkColor colors.base0C;
        "*.pdf" = mkColor colors.base08;
        "*.png" = mkColor colors.base0D;
        "*.py" = mkColor colors.base0D;
        "*.rb" = mkColor colors.base0D;
        "*.rpm" = mkColor colors.base08;
        "*.rs" = mkColor colors.base0D;
        "*.scss" = mkColor colors.base09;
        "*.sh" = mkColor colors.base0D;
        "*.sql" = mkColor colors.base09;
        "*.svg" = mkColor colors.base0D;
        "*.tar" = mkColor colors.base08;
        "*.tgz" = mkColor colors.base08;
        "*.ts" = mkColor colors.base0D;
        "*.txt" = mkColor colors.base05;
        "*.vim" = mkColor colors.base0D;
        "*.wav" = mkColor colors.base0C;
        "*.xml" = mkColor colors.base05;
        "*.yaml" = mkColor colors.base05;
        "*.yml" = mkColor colors.base05;
        "*.zip" = mkColor colors.base08;
        "*.zsh" = mkColor colors.base0D;
      };
    in
    concatStringsSep ":" (mapAttrsToList (k: v: "${k}=${v}") colorMap);

in
{
  options.stylix.ls-colors = {
    enable = mkEnableOption "Stylix-based LS_COLORS";
  };

  config = mkIf cfg.enable {
    environment.sessionVariables = {
      LS_COLORS = generateLsColors config.lib.stylix.colors;
    };

    environment.extraInit = ''
      export LS_COLORS="${generateLsColors config.lib.stylix.colors}"
    '';

    programs.bash.interactiveShellInit = ''
      export LS_COLORS="${generateLsColors config.lib.stylix.colors}"
    '';

    programs.zsh.interactiveShellInit = mkIf config.programs.zsh.enable ''
      export LS_COLORS="${generateLsColors config.lib.stylix.colors}"
    '';

    programs.fish.interactiveShellInit = mkIf config.programs.fish.enable ''
      set -gx LS_COLORS "${generateLsColors config.lib.stylix.colors}"
    '';
  };
}
danth commented 2 months ago

Please could you submit this as a pull request so that we can more easily review the changes?

jeanlucthumm commented 1 month ago

For nushell add:

  programs.nushell.environmentVariables = {
    LS_COLORS = ''${generateLsColors config.lib.stylix.colors}'';
  };
arunoruto commented 3 weeks ago

One can also use vivid for this. I am currently always setting my LS_COLORS with $(vivid generate <theme>). The command will be evaluated on shell startup and the LS_COLORS is set. Stylix just needs to create the config for vivid and make sure it is installed in home-manager. I already created a base16 repo for vivid, so feel free to make changes and/or PRs :D

Maybe it wouldn't be a bad idea to have it home-manager as an option with appropriate options, so stylix doesn't have to do the heavy lifting here. EDIT I created a PR for this: https://github.com/nix-community/home-manager/pull/6045

trueNAHO commented 2 weeks ago

One can also use vivid for this. I am currently always setting my LS_COLORS with $(vivid generate <theme>).

Great suggestion! Using this tool would delegate some of Stylix's responsibilities.

The command will be evaluated on shell startup and the LS_COLORS is set. Stylix just needs to create the config for vivid and make sure it is installed in home-manager.

To improve runtime performance, the vivid generate <theme> output could be injected at Nix build time.

I already created a base16 repo for vivid, so feel free to make changes and/or PRs :D

Maybe it wouldn't be a bad idea to have it home-manager as an option with appropriate options, so stylix doesn't have to do the heavy lifting here. EDIT I created a PR for this: nix-community/home-manager#6045

Let's wait for this PR to get merged.