Inital commit

This commit is contained in:
Daniel Thwaites 2020-12-20 18:30:22 +00:00
commit f9daee029e
No known key found for this signature in database
GPG key ID: D8AFC4BF05670F9D
7 changed files with 237 additions and 0 deletions

5
default.nix Normal file
View file

@ -0,0 +1,5 @@
{
imports = [
./stylix/default.nix
];
}

5
flake.nix Normal file
View file

@ -0,0 +1,5 @@
{
outputs = inputs: {
nixosModules.stylix = import ./default.nix;
};
}

27
stylix/colors.nix Normal file
View file

@ -0,0 +1,27 @@
{ pkgs, lib, config, ... }:
with lib;
let
cfg = config.stylix;
# TODO: This Python library should be included in Nixpkgs
colorgram = with pkgs.python3Packages; buildPythonPackage rec {
pname = "colorgram.py";
version = "1.2.0";
src = fetchPypi {
inherit pname version;
sha256 = "1gzxgcmg3ndra2j4dg73x8q9dw6b0akj474gxyyhfwnyz6jncxz7";
};
propagatedBuildInputs = [ pillow ];
};
colorgramPython = pkgs.python3.withPackages (ps: [ colorgram ]);
# Pass the wallpaper to ./colors.py and return a JSON file containing the
# generated colorscheme
colorsJSON = pkgs.runCommand "stylix-colors" {}
"${colorgramPython}/bin/python ${./colors.py} ${cfg.image} > $out";
in {
config.lib.stylix.colors = importJSON colorsJSON;
}

85
stylix/colors.py Normal file
View file

@ -0,0 +1,85 @@
import json
import sys
import colorgram
import colorsys
# Select 9 colors from the image passed on the command line
colors = colorgram.extract(sys.argv[1], 9)
# Extract the most dominant color to use as the background
colors.sort(key=lambda c: c.proportion)
dominant_color = colors.pop(0)
# Decide whether to generate a light or dark scheme based
# on the lightness of the dominant color
if dominant_color.hsl.l >= 128:
def scale(i):
scale = 0.8 - (0.1 * i)
return scale * 255
def clamp(l):
return min(l, 100)
else:
def scale(i):
scale = 0.1 + (0.1 * i)
return scale * 255
def clamp(l):
return max(l, 155)
def int_to_base(i):
return "base{0:02X}".format(i)
scheme = {}
# base00 to base07 use the dominant color's hue and saturation,
# lightness is a linear scale
for i in range(8):
scheme[int_to_base(i)] = (
dominant_color.hsl.h,
dominant_color.hsl.s,
scale(i),
)
# base08 to base0A use the remaining 8 colors from the image,
# with their lightness clamped to enforce adequate contrast
colors.sort(key=lambda c: c.hsl.h) # sort by hue
for i in range(8, 16):
color = colors[i-8]
scheme[int_to_base(i)] = (
color.hsl.h,
color.hsl.s,
clamp(color.hsl.l),
)
data = {}
for key, color in scheme.items():
r, g, b = colorsys.hls_to_rgb(
# Function wants HLS, stored as HSL
color[0] / 255,
color[2] / 255,
color[1] / 255,
)
data[key + "-dec-r"] = r
data[key + "-dec-g"] = g
data[key + "-dec-b"] = b
data[key + "-rgb-r"] = r * 255
data[key + "-rgb-g"] = g * 255
data[key + "-rgb-b"] = b * 255
hex_color = "{0:02x}{1:02x}{2:02x}".format(
round(r * 255),
round(g * 255),
round(b * 255),
)
data[key + "-hex"] = hex_color
data[key + "-hex-r"] = hex_color[0:2]
data[key + "-hex-g"] = hex_color[2:4]
data[key + "-hex-b"] = hex_color[4:6]
json.dump(data, sys.stdout)

16
stylix/default.nix Normal file
View file

@ -0,0 +1,16 @@
{ lib, ... }:
with lib;
{
imports = [
./colors.nix
./fonts.nix
./home-manager.nix
];
options.stylix.image = mkOption {
type = types.package;
description = "Wallpaper image.";
};
}

74
stylix/fonts.nix Normal file
View file

@ -0,0 +1,74 @@
{ pkgs, config, lib, ... }:
with lib;
let
cfg = config.stylix.fonts;
fontType = types.submodule { options = {
package = mkOption {
description = "Package providing the font.";
type = types.package;
};
name = mkOption {
description = "Name of the font within the package.";
type = types.str;
};
}; };
in {
options.stylix.fonts = {
serif = mkOption {
description = "Serif font.";
type = fontType;
default = {
package = pkgs.dejavu_fonts;
name = "DejaVu Serif";
};
};
sansSerif = mkOption {
description = "Sans-serif font.";
type = fontType;
default = {
package = pkgs.dejavu_fonts;
name = "DejaVu Sans";
};
};
monospace = mkOption {
description = "Monospace font.";
type = fontType;
default = {
package = pkgs.dejavu_fonts;
name = "DejaVu Sans Mono";
};
};
emoji = mkOption {
description = "Emoji font.";
type = fontType;
default = {
package = pkgs.noto-fonts-emoji;
name = "Noto Color Emoji";
};
};
};
config.fonts = {
fonts = [
cfg.monospace.package
cfg.serif.package
cfg.sansSerif.package
cfg.emoji.package
];
fontconfig.defaultFonts = {
monospace = [ cfg.monospace.name ];
serif = [ cfg.serif.name ];
sansSerif = [ cfg.sansSerif.name ];
emoji = [ cfg.emoji.name ];
};
};
}

25
stylix/home-manager.nix Normal file
View file

@ -0,0 +1,25 @@
{ lib, config, ... }:
with lib;
let
cfg = config.stylix;
in {
options.stylix = {
homeManagerUsers = mkOption {
type = types.listOf types.str;
description = "Users for which to enable Home Manager integration.";
default = [];
};
homeModule = mkOption {
internal = true;
description = "Home Manager module to apply for all users.";
};
};
config = {
home-manager.users = genAttrs cfg.homeManagerUsers (user: cfg.homeModule);
};
}