add chrysalis

This commit is contained in:
Kate 2025-08-01 21:13:51 +02:00
parent 9193d6e469
commit 771b662dd7
17 changed files with 1186 additions and 486 deletions

63
XCompose Normal file
View file

@ -0,0 +1,63 @@
include "%L"
# compose 5 = euro
<Multi_key> <5> : "€" U20AC
# general typography
<Multi_key> <period> <period> : "…" U2026 # HORIZONTAL ELLIPSIS
<Multi_key> <v> <period> <period> : "⋮" U22EE # VERTICAL ELLIPSIS
<Multi_key> <c> <period> <period> : "⋯" U22EF # MIDLINE HORIZONTAL ELLIPSIS
# these aren't the cookie
<Multi_key> <equal> <A> : "Ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON
<Multi_key> <equal> <a> : "ā" U0101 # LATIN SMALL LETTER A WITH MACRON
<Multi_key> <equal> <E> : "Ē" U0112 # LATIN CAPITAL LETTER E WITH MACRON
<Multi_key> <equal> <e> : "ē" U0113 # LATIN SMALL LETTER E WITH MACRON
<Multi_key> <equal> <I> : "Ī" U012A # LATIN CAPITAL LETTER I WITH MACRON
<Multi_key> <equal> <i> : "ī" U012B # LATIN SMALL LETTER I WITH MACRON
<Multi_key> <equal> <O> : "Ō" U014C # LATIN CAPITAL LETTER O WITH MACRON
<Multi_key> <equal> <o> : "ō" U014D # LATIN SMALL LETTER O WITH MACRON
<Multi_key> <equal> <U> : "Ū" U016A # LATIN CAPITAL LETTER U WITH MACRON
<Multi_key> <equal> <u> : "ū" U016B # LATIN SMALL LETTER U WITH MACRON
# puck keys
#- 2474;PARENTHESIZED DIGIT ONE;No;0;ON;<compat> 0028 0031 0029;;1;1;N;;;;;
<Multi_key> <parenleft> <period> <1> <parenright> : "⑴" U2474 # PARENTHESIZED DIGIT ONE
#- 2475;PARENTHESIZED DIGIT TWO;No;0;ON;<compat> 0028 0032 0029;;2;2;N;;;;;
<Multi_key> <parenleft> <period> <2> <parenright> : "⑵" U2475 # PARENTHESIZED DIGIT TWO
#- 2476;PARENTHESIZED DIGIT THREE;No;0;ON;<compat> 0028 0033 0029;;3;3;N;;;;;
<Multi_key> <parenleft> <period> <3> <parenright> : "⑶" U2476 # PARENTHESIZED DIGIT THREE
#- 2477;PARENTHESIZED DIGIT FOUR;No;0;ON;<compat> 0028 0034 0029;;4;4;N;;;;;
<Multi_key> <parenleft> <period> <4> <parenright> : "⑷" U2477 # PARENTHESIZED DIGIT FOUR
#- 2478;PARENTHESIZED DIGIT FIVE;No;0;ON;<compat> 0028 0035 0029;;5;5;N;;;;;
<Multi_key> <parenleft> <period> <5> <parenright> : "⑸" U2478 # PARENTHESIZED DIGIT FIVE
#- 2479;PARENTHESIZED DIGIT SIX;No;0;ON;<compat> 0028 0036 0029;;6;6;N;;;;;
<Multi_key> <parenleft> <period> <6> <parenright> : "⑹" U2479 # PARENTHESIZED DIGIT SIX
#- 247A;PARENTHESIZED DIGIT SEVEN;No;0;ON;<compat> 0028 0037 0029;;7;7;N;;;;;
<Multi_key> <parenleft> <period> <7> <parenright> : "⑺" U247A # PARENTHESIZED DIGIT SEVEN
#- 247B;PARENTHESIZED DIGIT EIGHT;No;0;ON;<compat> 0028 0038 0029;;8;8;N;;;;;
<Multi_key> <parenleft> <period> <8> <parenright> : "⑻" U247B # PARENTHESIZED DIGIT EIGHT
#- 247C;PARENTHESIZED DIGIT NINE;No;0;ON;<compat> 0028 0039 0029;;9;9;N;;;;;
<Multi_key> <parenleft> <period> <9> <parenright> : "⑼" U247C # PARENTHESIZED DIGIT NINE
#- 247D;PARENTHESIZED NUMBER TEN;No;0;ON;<compat> 0028 0031 0030 0029;;;10;N;;;;;
<Multi_key> <parenleft> <period> <1> <0> <parenright> : "⑽" U247D # PARENTHESIZED NUMBER TEN
#- 247E;PARENTHESIZED NUMBER ELEVEN;No;0;ON;<compat> 0028 0031 0031 0029;;;11;N;;;;;
<Multi_key> <parenleft> <period> <1> <1> <parenright> : "⑾" U247E # PARENTHESIZED NUMBER ELEVEN
#- 247F;PARENTHESIZED NUMBER TWELVE;No;0;ON;<compat> 0028 0031 0032 0029;;;12;N;;;;;
<Multi_key> <parenleft> <period> <1> <2> <parenright> : "⑿" U247F # PARENTHESIZED NUMBER TWELVE
#- 2480;PARENTHESIZED NUMBER THIRTEEN;No;0;ON;<compat> 0028 0031 0033 0029;;;13;N;;;;;
<Multi_key> <parenleft> <period> <1> <3> <parenright> : "⒀" U2480 # PARENTHESIZED NUMBER THIRTEEN
#- 2481;PARENTHESIZED NUMBER FOURTEEN;No;0;ON;<compat> 0028 0031 0034 0029;;;14;N;;;;;
<Multi_key> <parenleft> <period> <1> <4> <parenright> : "⒁" U2481 # PARENTHESIZED NUMBER FOURTEEN
#- 2482;PARENTHESIZED NUMBER FIFTEEN;No;0;ON;<compat> 0028 0031 0035 0029;;;15;N;;;;;
<Multi_key> <parenleft> <period> <1> <5> <parenright> : "⒂" U2482 # PARENTHESIZED NUMBER FIFTEEN
#- 2483;PARENTHESIZED NUMBER SIXTEEN;No;0;ON;<compat> 0028 0031 0036 0029;;;16;N;;;;;
<Multi_key> <parenleft> <period> <1> <6> <parenright> : "⒃" U2483 # PARENTHESIZED NUMBER SIXTEEN
#- 2484;PARENTHESIZED NUMBER SEVENTEEN;No;0;ON;<compat> 0028 0031 0037 0029;;;17;N;;;;;
<Multi_key> <parenleft> <period> <1> <7> <parenright> : "⒄" U2484 # PARENTHESIZED NUMBER SEVENTEEN
#- 2485;PARENTHESIZED NUMBER EIGHTEEN;No;0;ON;<compat> 0028 0031 0038 0029;;;18;N;;;;;
<Multi_key> <parenleft> <period> <1> <8> <parenright> : "⒅" U2485 # PARENTHESIZED NUMBER EIGHTEEN
#- 2486;PARENTHESIZED NUMBER NINETEEN;No;0;ON;<compat> 0028 0031 0039 0029;;;19;N;;;;;
<Multi_key> <parenleft> <period> <1> <9> <parenright> : "⒆" U2486 # PARENTHESIZED NUMBER NINETEEN
#- 2487;PARENTHESIZED NUMBER TWENTY;No;0;ON;<compat> 0028 0032 0030 0029;;;20;N;;;;;
<Multi_key> <parenleft> <period> <2> <0> <parenright> : "⒇" U2487 # PARENTHESIZED NUMBER TWENTY

View file

@ -277,17 +277,15 @@
];
};
# Valere (powerful laptop).
nixosConfigurations.valere = nixpkgs.lib.nixosSystem rec {
# Chrysalis (powerful Framework 13 laptop).
nixosConfigurations.chrysalis = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
specialArgs = mkSpecialArgs system;
modules = linuxOfflineGuiModules [
./nixos/hosts/valere
./nixos/configs/steam.nix
./nixos/configs/virt-host.nix
./nixos/configs/power-saving.nix
./nixos/configs/looking-glass.nix
./nixos/hosts/chrysalis
./nixos/configs/power-saving-amd.nix
#./nixos/configs/vmware.nix
];
};

View file

@ -165,7 +165,6 @@ UseIn=niri'')
# Also enable plasma, for when we need to use X11 for e.g. Talon.
services.xserver.enable = true;
services.desktopManager.plasma6.enable = true;
services.power-profiles-daemon.enable = lib.mkForce false;
# Enable sound with pipewire.
services.pulseaudio.enable = false;

View file

@ -168,9 +168,9 @@ in
accel-profile = "flat";
};
keyboard = {
keyboard.xkb = {
# Make caps lock a second escape, and ralt a compose.
xkb.options = "caps:escape,compose:ralt";
options = "caps:escape,compose:ralt";
};
};

View file

@ -10,465 +10,466 @@
}:
let
hostname = config.networking.hostName;
isAmd = config.hardware.cpu.amd.updateMicrocode;
isSmallScreen = (hostname == "utol");
cfg = config.deprekated.waybar;
in
{
options.deprekated.waybar = {
# Pull in some dependencies for our bar.
environment.systemPackages = with pkgs; [ networkmanagerapplet ];
# Enable the yubikey touch detector, for our icon.
programs.yubikey-touch-detector.enable = true;
#
# Set up our waybar configuration in home-manager.
#
home-manager.users.deprekated =
{ pkgs, config, ... }:
let
icons = rec {
calendar = "󰃭 ";
clock = " ";
puclock = "󱑆";
cpu = "";
ram = "";
battery.charging = "󱐋";
battery.horizontal = [
" "
" "
" "
" "
" "
];
battery.vertical = [
"󰁺"
"󰁻"
"󰁼"
"󰁽"
"󰁾"
"󰁿"
"󰂀"
"󰂁"
"󰂂"
"󰁹"
];
battery.levels = battery.vertical;
network.disconnected = "󰤮 ";
network.ethernet = "󰈀 ";
network.strength = [
"󰤟 "
"󰤢 "
"󰤥 "
"󰤨 "
];
bluetooth.on = "󰂯";
bluetooth.off = "󰂲";
bluetooth.battery = "󰥉";
volume.source = "󱄠";
volume.muted = "󰝟";
volume.levels = [
"󰕿"
"󰖀"
"󰕾"
];
idle = {
on = "<span color='#${colors.red}'>󰅶</span>";
off = "󰾪";
};
vpn = "󰌆 ";
music = {
playing = "";
paused = "";
stopped = "";
missing = "󰌙";
};
speed = {
slow = "󰾆";
medium = "󰾅";
fast = "󰓅";
};
};
colors = config.lib.stylix.colors;
# From the Waybar wiki.
waybar-events = pkgs.writeScriptBin "waybar-events" ''
#!${pkgs.python3}/bin/python3
import calendar
import subprocess
import datetime
import json
import html
import sys
data = {}
today = datetime.date.today().strftime("%Y-%m-%d")
next_week = (datetime.date.today() +
datetime.timedelta(days=10)).strftime("%Y-%m-%d")
tomorrow = (datetime.date.today() +
datetime.timedelta(days=1)).strftime("%Y-%m-%d")
human_events = subprocess.check_output('khal list now ' + next_week, shell=True).decode('utf-8')
machine_events = subprocess.check_output('khal list now ' + next_week + ' -d "Holidays in United States" --once -f "{title}|{start-date}|{start-time}" -df ""', shell=True).decode('utf-8')
if not machine_events:
sys.exit(0)
next_event = machine_events.split("\n")[0]
event, date, time = next_event.split('|')
# Generate our hover-over text.
lines = human_events.split("\n")
new_lines = []
for line in lines:
if line.startswith("To hide observances") or (line == ""):
continue
clean_line = html.escape(line).split(" ::")[0]
if len(clean_line) and not clean_line[0] in ['0', '1', '2']:
clean_line = "\n<b><span color='#${colors.blue}'>"+clean_line+"</span></b>" if (',' in clean_line) else clean_line
new_lines.append(clean_line)
tooltip = "\n".join(new_lines).strip()
if tomorrow in date:
date = "tomorrow"
else:
weekday = datetime.datetime.fromisoformat(date).weekday()
date = calendar.day_name[weekday].lower()
# Add time suffixes when appropriate.
time_suffix = ""
if time:
time_suffix = " @ " + time
date_suffix = ""
if today not in date:
date_suffix = ", " + date
# In the typical case, display the next event.
data['text'] = html.escape(" " + event[0:30] + date_suffix + time_suffix)
# Display our nice, human-readable event ouptut on hover.
data['tooltip'] = tooltip
# Finally, send the data to Waybar.
print(json.dumps(data))
'';
waybar-title = pkgs.writeScriptBin "waybar-title" ''
#!${pkgs.bash}/bin/bash
niri msg --json focused-window | jq -c '{text: (if ((.title | length) > 40) then (.title[:38] + "") else .title end), tooltip: .app_id}' | sed 's/&[ $]/\&amp; /g'
'';
waybar-puck-countdown = pkgs.writeScriptBin "waybar-puck-countdown" ''
#!${pkgs.python3}/bin/python3
import json
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
puck_day = "2024-12-11 13:30:00-07:00"
puck_time = datetime.fromisoformat(puck_day)
until = puck_time - now
response = {
"text": f" 󰧒 {until.days}d {until.seconds // 60 // 60}h",
"tooltip": f"days until {puck_day}"
hostSpecificCss = lib.mkOption {
type = lib.types.str;
default = "";
example = ''
window#waybar {
padding-left: 8px;
padding-right: 8px;
}
print(json.dumps(response))
'';
description = ''
CSS to add to our waybar config on this system.
'';
};
};
in
{
#
# Core Waybar settings.
#
programs.waybar = {
enable = true;
#systemd.enable = true;
};
config = {
programs.waybar.settings.mainBar = {
layer = "top";
#mode = "overlay";
# Pull in some dependencies for our bar.
environment.systemPackages = with pkgs; [ networkmanagerapplet ];
modules-left = [
"clock"
"clock#otherzone"
"mpris"
];
modules-center = [
"custom/title"
"wlr/taskbar"
];
modules-right = [
"tray"
"custom/events"
"privacy"
"custom/yubikey"
"wireplumber"
"battery"
];
# Enable the yubikey touch detector, for our icon.
programs.yubikey-touch-detector.enable = true;
battery = {
interval = 5;
format = "{icon} {capacity}%";
format-charging = "{icon} {capacity}% ${icons.battery.charging}";
format-icons = icons.battery.levels;
states.warning = 30;
states.critical = 15;
};
#
# Set up our waybar configuration in home-manager.
#
home-manager.users.deprekated =
{ pkgs, config, ... }:
let
cpu = {
format = "${icons.cpu} {usage}% @ {avg_frequency:0.1f}GHz";
};
memory = {
format = "${icons.ram} {used:0.1f}G / {total:0.1f}G";
};
clock = {
interval = 1;
format = "${icons.clock} {:%H:%M %A, %B %d %Z}";
tooltip-format = "<tt>${icons.calendar}<u><b> {:%a, %Y-%m-%d}</b></u>\n\n{calendar}</tt>";
calendar = {
mode = "month";
format = {
weeks = "<b>W{}</b>";
months = "<span color='#${colors.magenta}'><b>{}</b></span>";
days = "<span color='#${colors.blue}'><b>{}</b></span>";
weekdays = "<span color='#${colors.cyan}'><b>{}</b></span>";
today = "<span color='#${colors.green}'><b>{}</b></span>";
};
};
};
"clock#otherzone" = {
interval = 1;
format = "${icons.puclock} {:%H:%M %Z}";
timezone = "America/Denver";
tooltip-format = ''
<b><u>Homosexuality Statistics</u></b>
Homosexuality is <b><span color='#${colors.green}'>online</span></b>.
Homosexuality levels are <b><span color='#${colors.red}'>CRITICAL</span></b>.
'';
};
network = {
on-click = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor";
tooltip = false;
format-disconnected = icons.network.disconnected;
format-ethernet = "${icons.network.ethernet}";
format-wifi = "{icon} {essid}";
format-icons = icons.network.strength;
};
bluetooth = {
format = "{icon}";
format-disabled = "{icon}";
format-icons = {
inherit (icons.bluetooth) on off;
connected = icons.bluetooth.on;
};
format-connected = "{icon} {device_alias}";
};
"bluetooth#battery" = {
format = "";
format-connected-battery = "${icons.bluetooth.battery} {device_battery_percentage}%";
};
wireplumber = {
on-click = "${pkgs.pavucontrol}/bin/pavucontrol -t 1";
format = "{icon} {volume}%";
tooltip-format = "${icons.volume.source}";
format-muted = "${icons.volume.muted}";
format-icons = icons.volume.levels;
reverse-scrolling = 1;
};
# Displays an icon when our yubikey is waiting for touch.
"custom/yubikey" = {
exec = ./waybar-yubikey.sh;
return-type = "json";
};
"custom/events" = {
exec = "${waybar-events}/bin/waybar-events";
format = "{}";
tooltip = true;
return-type = "json";
interval = 60;
on-click = "${pkgs.wezterm}/bin/wezterm start ikhal";
};
"custom/title" = {
exec = "${waybar-title}/bin/waybar-title";
format = "{}";
tooltip = true;
return-type = "json";
interval = 1;
};
"custom/puckdown" = {
exec = "${waybar-puck-countdown}/bin/waybar-puck-countdown";
format = "{}";
tooltip = true;
return-type = "json";
interval = 60 * 5;
};
"wlr/taskbar" = {
format = "{icon}";
tooltip-format = "{app_id}";
on-click = "activate";
};
tray = {
icon-size = 21;
spacing = 10;
};
# Display indicators when we're sharing video or audio.
privacy = {
icon-spacing = 4;
icon-size = 18;
transition-duration = 250;
modules = [
{
type = "screenshare";
tooltip = false;
tooltip-icon-size = 24;
}
{
type = "audio-out";
tooltip = false;
tooltip-icon-size = 24;
}
{
type = "audio-in";
tooltip = false;
tooltip-icon-size = 24;
}
icons = rec {
calendar = "󰃭 ";
clock = " ";
puclock = "󱑆";
cpu = "";
ram = "";
battery.charging = "󱐋";
battery.horizontal = [
" "
" "
" "
" "
" "
];
};
mpris = {
format = "${icons.music.playing} {artist} - {title}";
format-paused = "${icons.music.paused} {artist} - {title}";
format-stopped = "";
format-disconnected = "${icons.music.missing}";
tooltip-format = "${icons.music.playing} {artist} - {title}";
max-length = 60;
};
idle_inhibitor = {
format = "{icon}";
format-icons = {
activated = icons.idle.on;
deactivated = icons.idle.off;
battery.vertical = [
"󰁺"
"󰁻"
"󰁼"
"󰁽"
"󰁾"
"󰁿"
"󰂀"
"󰂁"
"󰂂"
"󰁹"
];
battery.levels = battery.vertical;
network.disconnected = "󰤮 ";
network.ethernet = "󰈀 ";
network.strength = [
"󰤟 "
"󰤢 "
"󰤥 "
"󰤨 "
];
bluetooth.on = "󰂯";
bluetooth.off = "󰂲";
bluetooth.battery = "󰥉";
volume.source = "󱄠";
volume.muted = "󰝟";
volume.levels = [
"󰕿"
"󰖀"
"󰕾"
];
idle = {
on = "<span color='#${colors.red}'>󰅶</span>";
off = "󰾪";
};
vpn = "󰌆 ";
music = {
playing = "";
paused = "";
stopped = "";
missing = "󰌙";
};
tooltip-format-activated = "System <span color='#${colors.orange}'><b>blocked</b></span> from going idle.";
tooltip-format-deactivated = "System <span color='#${colors.green}'><b>allowed</b></span> to go idle.";
speed = {
slow = "󰾆";
medium = "󰾅";
fast = "󰓅";
};
};
};
stylix.targets.waybar.enable = false;
programs.waybar.style =
let
colors = config.lib.stylix.colors;
modules = s: "${s ".modules-left"}, ${s ".modules-center"}, ${s ".modules-right"}";
module = s: modules (m: "${m} > ${s} > *");
in
''
* {
border: none;
font-family: ${config.stylix.fonts.monospace.name};
font-weight: 400;
font-size: ${if isSmallScreen then "17" else toString config.stylix.fonts.sizes.desktop}px;
color: #${colors.base06};
}
colors = config.lib.stylix.colors;
window#waybar {
background: #${colors.base00};
}
# From the Waybar wiki.
waybar-events = pkgs.writeScriptBin "waybar-events" ''
#!${pkgs.python3}/bin/python3
#taskbar button {
padding: 0 0.4em;
}
import calendar
import subprocess
import datetime
import json
import html
import sys
#taskbar button.active {
background: #${colors.base01};
}
data = {}
#tray image,
#taskbar image {
-gtk-icon-transform: scale(0.75);
margin: -5px -4px;
padding: 0px 2px;
}
today = datetime.date.today().strftime("%Y-%m-%d")
next_week = (datetime.date.today() +
datetime.timedelta(days=10)).strftime("%Y-%m-%d")
tomorrow = (datetime.date.today() +
datetime.timedelta(days=1)).strftime("%Y-%m-%d")
${modules lib.id} {
margin: 0;
}
human_events = subprocess.check_output('khal list now ' + next_week, shell=True).decode('utf-8')
machine_events = subprocess.check_output('khal list now ' + next_week + ' -d "Holidays in United States" --once -f "{title}|{start-date}|{start-time}" -df ""', shell=True).decode('utf-8')
${module "*"} {
padding: 0 5px;
margin: 0;
font-size: 75%;
}
if not machine_events:
sys.exit(0)
${module ":not(:first-child)"} {
border-left: 1px solid #${colors.base01};
}
next_event = machine_events.split("\n")[0]
event, date, time = next_event.split('|')
${module ":not(:last-child)"} {
border-right: 1px solid #${colors.base01};
}
# Generate our hover-over text.
lines = human_events.split("\n")
new_lines = []
for line in lines:
if line.startswith("To hide observances") or (line == ""):
continue
#battery.charging {
color: #${colors.green};
}
clean_line = html.escape(line).split(" ::")[0]
if len(clean_line) and not clean_line[0] in ['0', '1', '2']:
clean_line = "\n<b><span color='#${colors.blue}'>"+clean_line+"</span></b>" if (',' in clean_line) else clean_line
#battery.warning:not(.charging) {
color: #${colors.yellow};
}
new_lines.append(clean_line)
tooltip = "\n".join(new_lines).strip()
#battery.critical:not(.charging) {
animation: critical-blink steps(8) 1s infinite alternate;
}
if tomorrow in date:
date = "tomorrow"
else:
weekday = datetime.datetime.fromisoformat(date).weekday()
date = calendar.day_name[weekday].lower()
@keyframes critical-blink {
to {
color: #${colors.red};
}
}
# Add time suffixes when appropriate.
time_suffix = ""
if time:
time_suffix = " @ " + time
date_suffix = ""
if today not in date:
date_suffix = ", " + date
# In the typical case, display the next event.
data['text'] = html.escape(" " + event[0:30] + date_suffix + time_suffix)
# Display our nice, human-readable event ouptut on hover.
data['tooltip'] = tooltip
# Finally, send the data to Waybar.
print(json.dumps(data))
'';
#
# Restart waybar when niri starts.
#
programs.niri.settings.spawn-at-startup = [
{
command = [
"systemctl"
"--user"
"restart"
"waybar"
];
}
{ command = [ "nm-applet" ]; }
];
};
waybar-title = pkgs.writeScriptBin "waybar-title" ''
#!${pkgs.bash}/bin/bash
niri msg --json focused-window | jq -c '{text: (if ((.title | length) > 40) then (.title[:38] + "") else .title end), tooltip: .app_id}' | sed 's/&[ $]/\&amp; /g'
'';
in
{
#
# Core Waybar settings.
#
programs.waybar = {
enable = true;
#systemd.enable = true;
};
programs.waybar.settings.mainBar =
{
layer = "top";
#mode = "overlay";
modules-left = [
"clock"
"mpris"
];
modules-center = [
"custom/title"
"wlr/taskbar"
];
modules-right = [
"tray"
"custom/events"
"privacy"
"custom/yubikey"
"wireplumber"
"battery"
] ++ (if isAmd then [ "power-profiles-daemon" ] else [ ]);
battery = {
interval = 5;
format = "{icon} {capacity}%";
format-charging = "{icon} {capacity}% ${icons.battery.charging}";
format-icons = icons.battery.levels;
states.warning = 30;
states.critical = 15;
};
cpu = {
format = "${icons.cpu} {usage}% @ {avg_frequency:0.1f}GHz";
};
memory = {
format = "${icons.ram} {used:0.1f}G / {total:0.1f}G";
};
clock = {
interval = 1;
format = "${icons.clock} {:%H:%M %A, %B %d %Z}";
tooltip-format = "<tt>${icons.calendar}<u><b> {:%a, %Y-%m-%d}</b></u>\n\n{calendar}</tt>";
calendar = {
mode = "month";
format = {
weeks = "<b>W{}</b>";
months = "<span color='#${colors.magenta}'><b>{}</b></span>";
days = "<span color='#${colors.blue}'><b>{}</b></span>";
weekdays = "<span color='#${colors.cyan}'><b>{}</b></span>";
today = "<span color='#${colors.green}'><b>{}</b></span>";
};
};
};
network = {
on-click = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor";
tooltip = false;
format-disconnected = icons.network.disconnected;
format-ethernet = "${icons.network.ethernet}";
format-wifi = "{icon} {essid}";
format-icons = icons.network.strength;
};
bluetooth = {
format = "{icon}";
format-disabled = "{icon}";
format-icons = {
inherit (icons.bluetooth) on off;
connected = icons.bluetooth.on;
};
format-connected = "{icon} {device_alias}";
};
"bluetooth#battery" = {
format = "";
format-connected-battery = "${icons.bluetooth.battery} {device_battery_percentage}%";
};
wireplumber = {
on-click = "${pkgs.pavucontrol}/bin/pavucontrol -t 1";
format = "{icon} {volume}%";
tooltip-format = "${icons.volume.source}";
format-muted = "${icons.volume.muted}";
format-icons = icons.volume.levels;
reverse-scrolling = 1;
};
# Displays an icon when our yubikey is waiting for touch.
"custom/yubikey" = {
exec = ./waybar-yubikey.sh;
return-type = "json";
};
"custom/events" = {
exec = "${waybar-events}/bin/waybar-events";
format = "{}";
tooltip = true;
return-type = "json";
interval = 60;
on-click = "${pkgs.wezterm}/bin/wezterm start ikhal";
};
"custom/title" = {
exec = "${waybar-title}/bin/waybar-title";
format = "{}";
tooltip = true;
return-type = "json";
interval = 1;
};
"wlr/taskbar" = {
format = "{icon}";
tooltip-format = "{app_id}";
on-click = "activate";
};
tray = {
icon-size = 21;
spacing = 10;
};
# Display indicators when we're sharing video or audio.
privacy = {
icon-spacing = 4;
icon-size = 18;
transition-duration = 250;
modules = [
{
type = "screenshare";
tooltip = false;
tooltip-icon-size = 24;
}
{
type = "audio-out";
tooltip = false;
tooltip-icon-size = 24;
}
{
type = "audio-in";
tooltip = false;
tooltip-icon-size = 24;
}
];
};
mpris = {
format = "${icons.music.playing} {artist} - {title}";
format-paused = "${icons.music.paused} {artist} - {title}";
format-stopped = "";
format-disconnected = "${icons.music.missing}";
tooltip-format = "${icons.music.playing} {artist} - {title}";
max-length = 60;
};
idle_inhibitor = {
format = "{icon}";
format-icons = {
activated = icons.idle.on;
deactivated = icons.idle.off;
};
tooltip-format-activated = "System <span color='#${colors.orange}'><b>blocked</b></span> from going idle.";
tooltip-format-deactivated = "System <span color='#${colors.green}'><b>allowed</b></span> to go idle.";
};
}
// (
# Support PPD on AMD.
if isAmd then
{
power-profiles-daemon = {
format = "{icon} ";
tooltip-format = "Power profile: {profile}nDriver: {driver}";
tooltip = true;
format-icons = {
default = "";
performance = "";
balanced = "";
power-saver = "";
};
};
}
else
{ }
);
stylix.targets.waybar.enable = false;
programs.waybar.style =
let
colors = config.lib.stylix.colors;
modules = s: "${s ".modules-left"}, ${s ".modules-center"}, ${s ".modules-right"}";
module = s: modules (m: "${m} > ${s} > *");
in
''
* {
border: none;
font-family: ${config.stylix.fonts.monospace.name};
font-weight: 400;
font-size: ${if isSmallScreen then "17" else toString config.stylix.fonts.sizes.desktop}px;
color: #${colors.base06};
}
${cfg.hostSpecificCss}
window#waybar {
background: #${colors.base00};
}
#taskbar button {
padding: 0 0.4em;
}
#taskbar button.active {
background: #${colors.base01};
}
#tray image,
#taskbar image {
-gtk-icon-transform: scale(0.75);
margin: -5px -4px;
padding: 0px 2px;
}
${modules lib.id} {
margin: 0;
}
${module "*"} {
padding: 0 5px;
margin: 0;
font-size: 75%;
}
${module ":not(:first-child)"} {
border-left: 1px solid #${colors.base01};
}
${module ":not(:last-child)"} {
border-right: 1px solid #${colors.base01};
}
#battery.charging {
color: #${colors.green};
}
#battery.warning:not(.charging) {
color: #${colors.yellow};
}
#battery.critical:not(.charging) {
animation: critical-blink steps(8) 1s infinite alternate;
}
@keyframes critical-blink {
to {
color: #${colors.red};
}
}
'';
#
# Restart waybar when niri starts.
#
programs.niri.settings.spawn-at-startup = [
{
command = [
"systemctl"
"--user"
"restart"
"waybar"
];
}
{ command = [ "nm-applet" ]; }
];
};
};
}

View file

@ -0,0 +1,22 @@
#
# Laptop power-saving configuration.
#
# vim: et:ts=2:sw=2:
#
{ lib, pkgs, ... }:
let
powerprofilesctl = "${pkgs.power-profiles-daemon}/bin/powerprofilesctl";
in
{
# Set up a power saving policy manager.
services.power-profiles-daemon.enable = lib.mkForce true;
# Profile its CLI.
environment.systemPackages = [ pkgs.power-profiles-daemon ];
# Automatically switch power profile on AC plug/unplug.
services.udev.extraRules = ''
SUBSYSTEM=="power_supply", ATTR{online}=="1", RUN+="${powerprofilesctl} set performance"
SUBSYSTEM=="power_supply", ATTR{online}=="0", RUN+="${powerprofilesctl} set power-saver"
'';
}

View file

@ -9,6 +9,7 @@
services.thermald.enable = !pkgs.stdenv.isAarch64;
# Set up a power saving policy manager.
# We use TLP on intel...
services.tlp = {
enable = true;
settings = {

View file

@ -17,6 +17,9 @@
# xonsh
xdg.configFile.xonsh.source = ../../xonsh;
# XCompose
xdg.configFile."XCompose".source = ../../XCompose;
# zellij
xdg.configFile.zellij.source = ../../zellij;

View file

@ -0,0 +1,391 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.hardware.framework.laptop13.audioEnhancement;
in
{
options = {
hardware.framework.laptop13.audioEnhancement = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Create a new audio device called "Framework Speakers",
which applies sound tuning before sending the audio out to the speakers.
This option requires PipeWire and WirePlumber.
The filter chain includes the following:
- Psychoacoustic bass enhancement
- Loudness compensation
- Equalizer
- Slight compression
This option has been optimised for the Framework Laptop 13 AMD 7040 series, but should work on all models.
Before applying, ensure the speakers are set to 100%,
because the volumes compound and the raw speaker device will be hidden by default.
You might also need to re-select the default output device.
In some cases, the added bass will vibrate the keyboard cable leading to a rattling sound,
a piece of foam can be used to mitigate this.
'';
};
hideRawDevice = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Hide the raw speaker device.
This option is enabled by default, because keeping the raw speaker device can lead to volume conflicts.
'';
};
rawDeviceName = lib.mkOption {
type = lib.types.str;
example = "alsa_output.pci-0000_c1_00.6.analog-stereo";
description = ''
The name of the raw speaker device. This will vary by device.
You can get this by running `pw-dump | grep -C 20 pci-0000`.
'';
};
};
};
config = lib.mkIf cfg.enable (
let
outputName = cfg.rawDeviceName;
prettyName = "Framework Speakers";
# These are pre-made decibel to linear value conversions, since Nix doesn't have pow().
# Use the formula `10 ** (db / 20)` to calculate.
db = {
"-18.1" = 0.1244514611771385;
"-5.48" = 0.5321082592667942;
"-4.76" = 0.5780960474057181;
"8.1" = 2.5409727055493048;
"-36" = 1.5848931924611134e-2;
};
json = pkgs.formats.json { };
# The filter chain, heavily inspired by the asahi-audio project: https://github.com/AsahiLinux/asahi-audio
filter-chain = json.generate "filter-chain.json" {
"node.description" = prettyName;
"media.name" = prettyName;
"filter.graph" = {
nodes = [
# Psychoacoustic bass extension,
# it creates harmonics of the missing bass to fool our ears into hearing it.
{
type = "lv2";
plugin = "https://chadmed.au/bankstown";
name = "bassex";
control = {
bypass = 0;
amt = 1.2;
sat_second = 1.3;
sat_third = 2.5;
blend = 1.0;
ceil = 200.0;
floor = 20.0;
};
}
# Loudness compensation,
# it ensures that the sound profile stays consistent across different volumes.
{
type = "lv2";
plugin = "http://lsp-plug.in/plugins/lv2/loud_comp_stereo";
name = "el";
control = {
enabled = 1;
input = 1.0;
fft = 4;
};
}
# 8-band equalizer,
# it tries to lessen frequencies where the laptop might resonate,
# and tries to make the frequency curve more pleasing;
# this is the "Lappy McTopface" profile (https://github.com/ceiphr/ee-framework-presets)
# further tuned for the Framework Laptop 13 AMD 7040 series
# and might need some tuning on other models.
{
type = "lv2";
plugin = "http://lsp-plug.in/plugins/lv2/para_equalizer_x8_lr";
name = "fw13eq";
control = {
mode = 0;
react = 0.2;
zoom = db."-36";
fl_0 = 101.0;
fml_0 = 0;
ftl_0 = 5;
gl_0 = db."-18.1";
huel_0 = 0.0;
ql_0 = 4.36;
sl_0 = 0;
wl_0 = 4.0;
fl_1 = 451.0;
fml_1 = 0;
ftl_1 = 1;
gl_1 = db."-5.48";
huel_1 = 3.125e-2;
ql_1 = 2.46;
sl_1 = 0;
wl_1 = 4.0;
fl_2 = 918.0;
fml_2 = 0;
ftl_2 = 1;
gl_2 = db."-4.76";
huel_2 = 6.25e-2;
ql_2 = 2.44;
sl_2 = 0;
wl_2 = 4.0;
fl_3 = 9700.0;
fml_3 = 0;
ftl_3 = 1;
gl_3 = db."8.1";
huel_3 = 9.375e-2;
ql_3 = 2.0;
sl_3 = 0;
wl_3 = 4.0;
fr_0 = 101.0;
fmr_0 = 0;
ftr_0 = 5;
gr_0 = db."-18.1";
huer_0 = 0.0;
qr_0 = 4.36;
sr_0 = 0;
wr_0 = 4.0;
fr_1 = 451.0;
fmr_1 = 0;
ftr_1 = 1;
gr_1 = db."-5.48";
huer_1 = 3.125e-2;
qr_1 = 2.46;
sr_1 = 0;
wr_1 = 4.0;
fr_2 = 918.0;
fmr_2 = 0;
ftr_2 = 1;
gr_2 = db."-4.76";
huer_2 = 6.25e-2;
qr_2 = 2.44;
sr_2 = 0;
wr_2 = 4.0;
fr_3 = 9700.0;
fmr_3 = 0;
ftr_3 = 1;
gr_3 = db."8.1";
huer_3 = 9.375e-2;
qr_3 = 2.0;
sr_3 = 0;
wr_3 = 4.0;
};
}
# Compressors. The settings were taken from the asahi-audio project.
{
type = "lv2";
plugin = "http://lsp-plug.in/plugins/lv2/mb_compressor_stereo";
name = "woofer_bp";
control = {
mode = 0;
ce_0 = 1;
sla_0 = 5.0;
cr_0 = 1.75;
al_0 = 0.725;
at_0 = 1.0;
rt_0 = 100;
kn_0 = 0.125;
cbe_1 = 1;
sf_1 = 200.0;
ce_1 = 0;
cbe_2 = 0;
ce_2 = 0;
cbe_3 = 0;
ce_3 = 0;
cbe_4 = 0;
ce_4 = 0;
cbe_5 = 0;
ce_5 = 0;
cbe_6 = 0;
ce_6 = 0;
};
}
{
type = "lv2";
plugin = "http://lsp-plug.in/plugins/lv2/compressor_stereo";
name = "woofer_lim";
control = {
sla = 5.0;
al = 1.0;
at = 1.0;
rt = 100.0;
cr = 15.0;
kn = 0.5;
};
}
];
# Now, we're chaining together the modules instantiated above.
links = [
{
output = "bassex:out_l";
input = "el:in_l";
}
{
output = "bassex:out_r";
input = "el:in_r";
}
{
output = "el:out_l";
input = "fw13eq:in_l";
}
{
output = "el:out_r";
input = "fw13eq:in_r";
}
{
output = "fw13eq:out_l";
input = "woofer_bp:in_l";
}
{
output = "fw13eq:out_r";
input = "woofer_bp:in_r";
}
{
output = "woofer_bp:out_l";
input = "woofer_lim:in_l";
}
{
output = "woofer_bp:out_r";
input = "woofer_lim:in_r";
}
];
inputs = [
"bassex:in_l"
"bassex:in_r"
];
outputs = [
"woofer_lim:out_l"
"woofer_lim:out_r"
];
# This makes pipewire's volume control actually control the loudness comp module
"capture.volumes" = [
{
control = "el:volume";
min = -47.5;
max = 0.0;
scale = "cubic";
}
];
};
"capture.props" = {
"node.name" = "audio_effect.laptop-convolver";
"media.class" = "Audio/Sink";
"audio.channels" = "2";
"audio.position" = [
"FL"
"FR"
];
"audio.allowed-rates" = [
44100
48000
88200
96000
176400
192000
];
"device.api" = "dsp";
"node.virtual" = "false";
# Lower seems to mean "more preferred",
# bluetooth devices seem to be ~1000, speakers seem to be ~2000
# since this is between the two, bluetooth devices take over when they connect,
# and hand over to this instead of the speakers when they disconnect.
"priority.session" = 1500;
"priority.driver" = 1500;
"state.default-volume" = 0.343;
"device.icon-name" = "audio-card-analog-pci";
};
"playback.props" = {
"node.name" = "audio_effect.laptop-convolver";
"target.object" = outputName;
"node.passive" = "true";
"audio.channels" = "2";
"audio.allowed-rates" = [
44100
48000
88200
96000
176400
192000
];
"audio.position" = [
"FL"
"FR"
];
"device.icon-name" = "audio-card-analog-pci";
};
};
configPackage =
(pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/99-laptop.conf" ''
monitor.alsa.rules = [
{
matches = [{ node.name = "${outputName}" }]
actions = {
update-props = {
audio.allowed-rates = [44100, 48000, 88200, 96000, 176400, 192000]
}
}
}
]
node.software-dsp.rules = [
{
matches = [{ node.name = "${outputName}" }]
actions = {
create-filter = {
filter-path = "${filter-chain}"
hide-parent = ${lib.boolToString cfg.hideRawDevice}
}
}
}
]
wireplumber.profiles = {
main = { node.software-dsp = "required" }
}
'')
// {
passthru.requiredLv2Packages = with pkgs; [
lsp-plugins
bankstown-lv2
];
};
in
{
services.pipewire.wireplumber.configPackages = [ configPackage ];
# Pipewire is needed for this.
services.pipewire.enable = lib.mkDefault true;
}
);
}

View file

@ -0,0 +1,176 @@
#
# Per-system configuration.
#
# vim: et:ts=2:sw=2:
#
{
config,
lib,
pkgs,
deprekages,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
./audio.nix
./ec_kmod.nix
];
# Bootloader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# Networking.
networking.hostName = "chrysalis";
networking.networkmanager = {
enable = true;
wifi.backend = "iwd";
};
networking.firewall.enable = false;
# This is a local machine, rather than our typical network-accesed ones.
# Run an ssh-agent locally.
programs.ssh.startAgent = true;
# Support our fingerprint reader.
services.fprintd.enable = true;
# Support framework updates.
services.fwupd.enable = true;
# Tools for the framework EC.
environment.systemPackages = [
pkgs.framework-tool
deprekages.framework-13-icm
];
#
# Niri configuration for our monitors.
#
home-manager.users.deprekated.programs.niri.settings = {
outputs."eDP-1".scale = 1.5;
};
# Override stylix font sizes.
stylix.fonts.sizes.desktop = lib.mkForce 16;
# Accomodate the curved screen top by moving things in just a little.
deprekated.waybar.hostSpecificCss = ''
.modules-left > :first-child > * {
padding-left: 3ex;
}
.modules-right > :last-child > * {
padding-right: 3ex;
}
'';
# Provide memtest86, since that's nice.
boot.loader.systemd-boot.memtest86.enable = true;
#
# Hardware config.
#
# Use the latest kernel, and our patches, until the Dell+Alienware stuff makes it into
# more mainline kernels. We'll include ccache so we can iterate sanely.
boot.kernelPackages = pkgs.linuxPackages_latest;
boot.extraModprobeConfig = ''
# Ensure we have a regulatory domain set for our wifi.
options cfg80211 ieee80211_regdom=NL
# Support microphones via the TRRS jack.
options snd-hda-intel model=dell-headset-multi
'';
boot.initrd.availableKernelModules = [
"xhci_pci"
"thunderbolt"
"vmd"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [
"thunderbolt"
];
boot.kernelParams = [
# Bluetooth stability tweaks.
"mt7925e.disable_aspm=1"
# N.b. if we start experiencing GPU stalls, disabling PSR can help.
#"amdgpu.dcdebugmask=0x10"
];
# Allow use of our brightness sensor for screen auto-leveling.
hardware.sensor.iio.enable = lib.mkDefault true;
# Fix suspend with the ethernet expansion card.
services.udev.extraRules = ''
# Ethernet expansion card support
ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="0bda", ATTR{idProduct}=="8156", ATTR{power/autosuspend}="20"
'';
# Support ICC color profiles.
services.colord.enable = true;
# Support thunderbolt.
services.hardware.bolt.enable = true;
# Enable audio DSP filtering.
hardware.framework.laptop13.audioEnhancement = {
enable = true;
rawDeviceName = "alsa_output.pci-0000_c1_00.6.analog-stereo";
};
# Support the framework EC from sysfs.
hardware.framework.enableKmod = true;
# Support bluetooth.
hardware.bluetooth = {
enable = true;
powerOnBoot = false;
settings = {
General = {
# Support A2DP.
Enable = "Source,Sink,Media,Socket";
# Enable experimental featurees, like reading device battery levels.
Experimental = true;
};
};
};
fileSystems."/" = {
device = "/dev/disk/by-uuid/bb880b80-992f-4e56-bb80-c5c4df0ddd72";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/5B37-C691";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
swapDevices = [ { device = "/dev/disk/by-uuid/50f20263-9632-439d-b57d-b9ee8f13d62b"; } ];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = true;
}

View file

@ -0,0 +1,56 @@
{
config,
lib,
pkgs,
...
}:
let
kernel_version_compatible = lib.versionAtLeast config.boot.kernelPackages.kernel.version "6.10";
in
{
options.hardware.framework.enableKmod =
(lib.mkEnableOption "Enable the community created Framework kernel module that allows interacting with the embedded controller from sysfs.")
// {
# enable by default on NixOS >= 24.05 and kernel >= 6.10
default = lib.and (lib.versionAtLeast (lib.versions.majorMinor lib.version) "24.05") kernel_version_compatible;
defaultText = "enabled by default on NixOS >= 24.05 and kernel >= 6.10";
};
config.boot = lib.mkIf config.hardware.framework.enableKmod {
extraModulePackages = with config.boot.kernelPackages; [
framework-laptop-kmod
];
# https://github.com/DHowett/framework-laptop-kmod?tab=readme-ov-file#usage
kernelModules = [
"cros_ec"
"cros_ec_lpcs"
];
# add required patch if enabled on kernel <6.10
kernelPatches = lib.mkIf (!kernel_version_compatible) [
rec {
name = "platform/chrome: cros_ec_lpc: add support for AMD Framework Laptops";
msgid = "20240403004713.130365-1-dustin@howett.net";
version = "3";
hash = "sha256-aQSyys8CMzlj9EdNhg8vtp76fg1qEwUVeJL0E+8w5HU=";
patch =
pkgs.runCommandLocal "patch-${msgid}"
{
nativeBuildInputs = with pkgs; [
b4
git
cacert
];
SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
outputHash = hash;
}
''
export HOME="$TMP"
PYTHONHASHSEED=0 ${pkgs.b4}/bin/b4 -n am -C -T -v ${version} -o- "${msgid}" > "$out"
'';
}
];
};
}

View file

@ -71,48 +71,6 @@
services.blueman.enable = true;
# Allow the NFC reader on the trackpoint to be used as a smartcard reader.
hardware.nfc-nci.enable = true;
#
# Niri configuration for our monitors.
#
#
home-manager.users.deprekated = {
programs.niri.settings = {
# Left monitor.
outputs."DP-3" = {
position = {
x = 0;
y = 0;
};
scale = 1.0;
};
# Laptop screen.
outputs."eDP-1" = {
position = {
x = 1920;
y = 0;
};
scale = 1.0;
};
# Right monitor.
outputs."DP-1" = {
position = {
x = 1920 * 2;
y = 0;
};
scale = 1.0;
};
};
# Also position waybar on only one monitor.
programs.waybar.settings.mainBar.output = "eDP-1";
};
# Override stylix font sizes.
stylix.fonts.sizes.desktop = lib.mkForce 16;
@ -163,5 +121,5 @@
# networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -111,6 +111,9 @@ flake-utils.lib.eachDefaultSystem (
hantek-udev-rules = callPackage ./hantek-udev-rules { };
linux-nfc-lenovo-udev-rules = callPackage ./linux-nfc-lenovo/udev.nix { };
# color profiles
framework-13-icm = callPackage ./framework-13-icm { };
# weechat
weechat-discord = callPackage ./weechat-discord { };

Binary file not shown.

View file

@ -0,0 +1,13 @@
{ stdenv, ... }:
stdenv.mkDerivation (finalAttrs: {
pname = "framework-13-icm";
version = "0.0.1";
src = ./color-profile.icm;
dontUnpack = true;
installPhase = ''
mkdir -p $out/share/color/icc/colord/
cp ${finalAttrs.src} $out/share/color/icc/colord/framework-13.icm
'';
})

View file

@ -89,7 +89,7 @@ config = {
font_overrides = {
miko = 10,
hinata = 15,
valere = 12,
chrysalis = 12,
utol = 13,
trailblazer = 11,
kanbaru = 12,

16
xonsh/chrysalis.xsh Normal file
View file

@ -0,0 +1,16 @@
#
# Dotfile specifics for this host.
#
# Path
# Note: lower in the list = higher priority
PATH_ADDS = [
"/run/current-system/sw/bin"
"/run/wrappers/bin"
]
# SSH key management.
try_source("includes/add-ssh-keys")
# NixOS compatibility.
try_source("includes/nixos")