Files
chiasson-nix/modules/desktop/shells/dms/home-manager/default.nix
T
Olivier 4ca225ed60 Add DMS plugins and configuration enhancements
- Introduced multiple DMS plugins including ambient sound, calculator, home assistant, dropdown menu, OCR scanner, and more.
- Updated flake.nix to include new plugin URLs and configurations.
- Enhanced the DMS home-manager module to support third-party plugins and their settings.
- Added keybindings for new plugins in the Niri configuration.
- Updated default settings to include new plugins and their visibility options.
2026-06-21 04:18:36 -03:00

780 lines
32 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
inputs,
config,
pkgs,
lib,
osConfig ? { },
...
}: let
home = config.home.homeDirectory;
cfg = config.dms;
gpuTempEnabled = cfg.enableGpuTemp;
hyprlandEnabled = lib.attrByPath [ "chiasson" "desktop" "hyprland" "enable" ] false osConfig;
discordEnabled = lib.attrByPath [ "chiasson" "home" "apps" "discord" "enable" ] false config;
ohMyPoshEnabled = config.programs.oh-my-posh.enable or false;
matugenOutputDirs =
lib.optionals hyprlandEnabled [ "${home}/.config/hypr" ]
++ lib.optionals ohMyPoshEnabled [ "${home}/.config/oh-my-posh" ]
++ lib.optionals discordEnabled [ "${home}/.config/vesktop/themes" ]
++ [
"${home}/.config/qt6ct/colors"
"${home}/.config/qt5ct/colors"
];
ensureMatugenOutputDirsScript = pkgs.writeShellScript "dms-ensure-matugen-output-dirs" ''
set -euo pipefail
${lib.concatStringsSep "\n" (map (dir: "mkdir -p ${lib.escapeShellArg dir}") matugenOutputDirs)}
${lib.optionalString ohMyPoshEnabled ''
dest="$HOME/.config/oh-my-posh/theme.omp.json"
template="$HOME/.config/matugen/templates/ohmyposh-theme.omp.json"
# matugen writes output_path in place; HM symlinks into the store are read-only and go stale.
if [ -L "$dest" ] || { [ -e "$dest" ] && ! [ -f "$dest" ]; }; then
rm -f "$dest"
fi
if [ ! -f "$dest" ]; then
# Seed from our matugen template (same generation closure), not programs.oh-my-posh.package
# which can reference a GC'd store path after profile churn.
cp -L "$template" "$dest"
fi
''}
'';
obsidianSnippetsDir = cfg.obsidianSnippetsDir; # legacy single path
obsidianSnippetDirs =
let
snippetsFromConfigDirs = map (d: "${d}/snippets") cfg.obsidianConfigDirs;
explicitSnippetsDirs =
cfg.obsidianSnippetsDirs
++ lib.optionals (obsidianSnippetsDir != null) [obsidianSnippetsDir];
in
lib.unique (snippetsFromConfigDirs ++ explicitSnippetsDirs);
# Clears Quickshell QML bytecode cache so bar plugins reload (stale *.qmlc keeps old UI).
dmsRestartOnceScript = pkgs.writeShellScript "dms-rbw-plugin-restart-once" ''
set -euo pipefail
rt="''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
exec 9>"$rt/dms-rbw-plugin-restart.lock"
${pkgs.util-linux}/bin/flock -n 9 || exit 0
cache="''${XDG_CACHE_HOME:-''$HOME/.cache}/quickshell/qmlcache"
rm -rf "$cache"
${pkgs.systemd}/bin/systemctl --user try-restart dms.service 2>/dev/null || true
'';
jsonFormat = pkgs.formats.json { };
dmsSeedSettings =
if cfg.defaultSettingsFile != null then
builtins.fromJSON (builtins.readFile cfg.defaultSettingsFile)
else
import ../_private/default-settings.nix {
inherit lib gpuTempEnabled;
extraRightBarWidgets = cfg.extraRightBarWidgets;
};
dmsSeedFile = jsonFormat.generate "dms-settings-seed.json" dmsSeedSettings;
dmsSettingsPath = "${config.xdg.configHome}/DankMaterialShell/settings.json";
# Directory name must match each plugin's `id` in plugin.json.
thirdPartyPlugins = {
dankVault = inputs.dms-plugin-dank-vault;
calculator = inputs.dms-plugin-calculator;
homeAssistantMonitor = inputs.dms-plugin-home-assistant;
dropdownMenu = inputs.dms-plugin-dropdown-menu;
ocrScanner = inputs.dms-plugin-ocr-scanner;
unifiedTaskbar = inputs.dms-plugin-unified-taskbar;
widgetGroup = inputs.dms-plugin-widget-group;
nixPackageRunner = inputs.dms-plugin-nix-package-runner;
ambientSound = inputs.dms-plugin-ambient-sound;
cavaVisualizer = inputs.dms-plugin-cava-visualizer;
emojiLauncher = inputs.dms-plugin-emoji-launcher;
dankDesktopWeather = inputs.dms-plugin-official + "/DankDesktopWeather";
webSearch = inputs.dms-plugin-web-search;
wallpaperCarousel = inputs.dms-plugin-wallpaper-carousel;
ephemera = inputs.dms-plugin-ephemera;
appShortcut = inputs.dms-plugin-app-shortcut;
};
shipThirdPartyPlugin =
id: src:
{
source = src;
onChange = "${dmsRestartOnceScript}";
};
in {
options = {
dms.enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "DMS Home Manager config from this flake.";
};
dms.enableGpuTemp = lib.mkOption {
type = lib.types.bool;
default = true;
description = "GPU temp widget in the bar.";
};
# <vault>/.obsidian/snippets — unset skips Obsidian matugen output
dms.obsidianSnippetsDir = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/home/olivier/Documents/Notes/.obsidian/snippets";
description = "Snippet dir for `matugen.css` (legacy; prefer `obsidianConfigDirs`).";
};
# Each path is a vaults `.obsidian/` — we write `<path>/snippets/matugen.css`.
dms.obsidianConfigDirs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
example = [
"/mnt/zimaos/Obsidian/Home/.obsidian"
];
description = "Vault `.obsidian` dirs for matugen CSS.";
};
# Or pass `.obsidian/snippets` paths yourself.
dms.obsidianSnippetsDirs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
example = [
"/mnt/zimaos/Obsidian/Home/.obsidian/snippets"
];
description = "Explicit snippet directories for matugen CSS.";
};
# Prepended to the bars rightWidgets (shows first).
dms.extraRightBarWidgets = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [];
example = [
{ id = "wvkbdToggle"; enabled = true; }
{ id = "rbwLockToggle"; enabled = true; }
];
description = "Extra `{ id, enabled, … }` widgets merged into the first-run settings seed.";
};
dms.enableWvkbdToggle = lib.mkEnableOption ''
Ship wvkbd-toggle plugin into `~/.config/DankMaterialShell/plugins/` (toggle from NixOS `desktop.shells.dms`).
'';
dms.enableRbwLockToggle = lib.mkEnableOption ''
Ship rbw-lock-toggle into `~/.config/DankMaterialShell/plugins/rbwLockToggle/` (directory name matches plugin id; Bitwarden vault lock/unlock in the bar).
'';
dms.defaultSettingsFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
Host-specific first-run `settings.json` seed. When set, replaces the bundled
`default-settings.nix` template on fresh profiles.
'';
};
dms.bundleThirdPartyPlugins = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Install bundled third-party DMS plugins (DankVault, Calculator, Home Assistant, …)
into `~/.config/DankMaterialShell/plugins/` from flake inputs.
'';
};
};
imports = [
inputs.dms.homeModules.dank-material-shell
inputs.nix-monitor.homeManagerModules.default
];
config = lib.mkIf cfg.enable (lib.mkMerge [
(lib.mkIf cfg.enableWvkbdToggle {
xdg.configFile."DankMaterialShell/plugins/wvkbd-toggle/plugin.json".source =
../plugins/wvkbd-toggle/plugin.json;
xdg.configFile."DankMaterialShell/plugins/wvkbd-toggle/WvkbdToggle.qml".source =
../plugins/wvkbd-toggle/WvkbdToggle.qml;
xdg.configFile."DankMaterialShell/plugins/wvkbd-toggle/WvkbdToggleSettings.qml".source =
../plugins/wvkbd-toggle/WvkbdToggleSettings.qml;
})
(lib.mkIf cfg.enableRbwLockToggle {
# Directory name matches plugin id (same idea as NixMonitor / ideapad wvkbdToggle).
xdg.configFile."DankMaterialShell/plugins/rbwLockToggle/plugin.json" = {
source = ../plugins/rbw-lock-toggle/plugin.json;
onChange = "${dmsRestartOnceScript}";
};
xdg.configFile."DankMaterialShell/plugins/rbwLockToggle/RbwLockToggleSettings.qml" = {
source = ../plugins/rbw-lock-toggle/RbwLockToggleSettings.qml;
onChange = "${dmsRestartOnceScript}";
};
xdg.configFile."DankMaterialShell/plugins/rbwLockToggle/RbwLockToggle.qml" = {
source = ../plugins/rbw-lock-toggle/RbwLockToggle.qml;
onChange = "${dmsRestartOnceScript}";
};
})
(lib.mkIf cfg.bundleThirdPartyPlugins {
xdg.configFile =
lib.mapAttrs (id: src: shipThirdPartyPlugin id src) thirdPartyPlugins;
})
{
# Nix rebuild widget used by DankMaterialShell (via nix-monitor).
# Per-host `rebuildCommand` is set in `modules/hosts/<host>/configuration.nix` (`chiasson.desktop.shells.dms`).
programs.nix-monitor = {
enable = true;
generationsCommand = [
"bash"
"-c"
"readlink /nix/var/nix/profiles/system | cut -d- -f2"
];
};
home.packages = with pkgs; [
kdePackages.qtdeclarative
kdePackages.kirigami.unwrapped
kdePackages.qtmultimedia
kdePackages.sonnet
# ocrScanner DMS plugin — eng/fra/vie and 120+ langs ship in nixpkgs tessdata.
tesseract
# ambientSound DMS plugin — mpv playback + socat IPC to mpv socket.
mpv
socat
# dankVault / emojiLauncher / ephemera — Wayland clipboard.
wl-clipboard
# nixPackageRunner DMS plugin.
jq
# cavaVisualizer DMS plugin.
cava
# ephemera DMS plugin — API requests + optional keyring storage.
curl
libsecret
];
programs.dank-material-shell = {
enable = true;
# homeAssistantMonitor plugin (QtWebSockets) needs QML on DMS's import path, not just home.packages.
package = inputs.dms.packages.${pkgs.stdenv.hostPlatform.system}.dms-shell.override {
extraQtPackages = with pkgs.kdePackages; [ qtwebsockets ];
};
systemd = {
enable = true; # Systemd service for auto-start
restartIfChanged = true; # Auto-restart dms.service when dankMaterialShell changes
};
# Core features
enableSystemMonitoring = true; # System monitoring widgets (dgop)
dgop.package = inputs.dgop.packages.${pkgs.stdenv.hostPlatform.system}.default;
enableVPN = true; # VPN management widget
enableDynamicTheming = true; # Wallpaper-based theming (matugen)
enableAudioWavelength = true; # Audio visualizer (cava)
enableCalendarEvents = false; # Disable calendar integration (khal/ikhal)
# Leave `session` at {} — non-empty makes HM rewrite session.json every switch and nukes wallpaper/session state.
# Leave `settings` at {} — UI-owned settings.json is seeded once on first run (see home.activation below).
settings = { };
session = { };
};
# Detach store symlink so UI edits survive rebuilds; seed defaults only on a fresh profile.
home.activation.dmsMaterializeSettings = lib.hm.dag.entryBefore [ "writeBoundary" ] ''
settingsFile=${lib.escapeShellArg dmsSettingsPath}
if [ -L "$settingsFile" ]; then
mkdir -p "$(dirname "$settingsFile")"
${pkgs.coreutils}/bin/cp --remove-destination -L "$settingsFile" "$settingsFile"
fi
'';
home.activation.dmsSeedSettings = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
settingsFile=${lib.escapeShellArg dmsSettingsPath}
mkdir -p "$(dirname "$settingsFile")"
if [ ! -e "$settingsFile" ]; then
${pkgs.coreutils}/bin/cp ${lib.escapeShellArg dmsSeedFile} "$settingsFile"
chmod u+w "$settingsFile"
fi
'';
# matugen won't create missing output_path parents; run before DMS theme generation.
systemd.user.services.dms.serviceConfig.ExecStartPre =
lib.mkOrder 100 "${ensureMatugenOutputDirsScript}";
# DMS / matugen custom templates.
#
# DMS docs (custom templates): https://danklinux.com/docs/dankmaterialshell/application-themes#custom-matugen-templates
xdg.configFile."matugen/config.toml".text =
''
[config]
''
+ lib.optionalString hyprlandEnabled ''
[templates.hyprland]
input_path = '${home}/.config/matugen/templates/hyprland-colors.conf'
output_path = '${home}/.config/hypr/colors.conf'
''
+ lib.optionalString ohMyPoshEnabled ''
[templates.ohmyposh]
input_path = '${home}/.config/matugen/templates/ohmyposh-theme.omp.json'
output_path = '${home}/.config/oh-my-posh/theme.omp.json'
''
+ lib.optionalString discordEnabled ''
[templates.dank-discord]
input_path = '${home}/.config/matugen/templates/dank-discord.css'
output_path = '${home}/.config/vesktop/themes/dank-discord.css'
''
+ lib.optionalString (obsidianSnippetDirs != []) (
lib.concatStringsSep "\n" (
lib.lists.imap0 (i: snippetDir: ''
[templates.Obsidian${toString i}]
input_path = '${home}/.config/matugen/templates/obsidian-minimal-matugen-colors.css'
output_path = '${snippetDir}/matugen.css'
'') obsidianSnippetDirs
)
)
;
# Obsidian snippet dirs for matugen: mkdir here instead of tmpfiles (no chmod fights on weird mounts).
home.activation.dmsEnsureObsidianSnippetDirs = lib.hm.dag.entryAfter ["writeBoundary"] (
let
snippetDirs = lib.unique obsidianSnippetDirs;
escapedSnippetDirs = map lib.escapeShellArg snippetDirs;
in
''
for snippetDir in ${lib.concatStringsSep " " escapedSnippetDirs}; do
parentDir="$(dirname "$snippetDir")"
if [ -d "$snippetDir" ]; then
continue
fi
if [ ! -d "$parentDir" ] || [ ! -w "$parentDir" ]; then
echo "dms: skipping Obsidian snippet dir '$snippetDir' (parent missing or not writable)" >&2
continue
fi
mkdir -p "$snippetDir"
done
''
);
xdg.configFile."matugen/templates/dank-discord.css".source = ../templates/dank-discord.css;
# matugen template → Hyprland colors file sourced at runtime.
# Your Hyprland module includes: `source = ~/.config/hypr/colors.conf`
# (see `modules/desktop/hyprland/home-manager/appearance.nix`).
xdg.configFile."matugen/templates/hyprland-colors.conf".text = ''
# Hyprland colors generated by DMS/matugen
# Keep `.default` so DMS can swap to `.dark` when "Always use Dark Theme" is enabled.
general {
col.active_border = rgb({{colors.primary.default.hex_stripped}}) rgb({{colors.secondary.default.hex_stripped}}) rgb({{colors.tertiary.default.hex_stripped}})
col.inactive_border = rgba({{colors.surface_variant.default.hex_stripped}}ee)
}
decoration {
shadow {
color = rgba({{colors.shadow.default.hex_stripped}}cc)
}
}
# Hyprbars colors
plugin {
hyprbars {
bar_color = rgba({{colors.surface.default.hex_stripped}}ff)
col.text = rgba({{colors.on_surface.default.hex_stripped}}ff)
}
}
'';
# matugen → Oh My Posh JSON; hex in the base theme swapped for matugen tokens.
xdg.configFile."matugen/templates/ohmyposh-theme.omp.json".text = ''
{
"$schema": "https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json",
"blocks": [
{
"alignment": "left",
"segments": [
{
"background": "#3A456E",
"foreground": "#ffbebc",
"leading_diamond": "\ue0b6",
"style": "diamond",
"template": "\u007B\u007B .UserName \u007D\u007D@\u007B\u007B .HostName \u007D\u007D <#ffffff>on</>",
"type": "session"
},
{
"type": "os",
"style": "diamond",
"background": "#3A456E",
"foreground": "#ffffff",
"trailing_diamond": "\ue0b4",
"template": " \u007B\u007B .Icon \u007D\u007D "
},
{"type": "session",
"style": "diamond",
"background": "#3A456E",
"foreground": "#ffbebc",
"template": "\u007B\u007B if .SSHSession \u007D\u007Dvia SSH\u007B\u007B end \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "session"
},
{
"type": "text",
"style": "diamond",
"background": "#3A456E",
"foreground": "#ffbebc",
"template": "\u007B\u007B if .Env.IN_NIX_SHELL \u007D\u007Din nix-shell\u007B\u007B end \u007D\u007D",
"trailing_diamond": "\ue0b4"
},
{
"background": "#3A456E",
"foreground": "#bc93ff",
"leading_diamond": "\ue0b6",
"properties": {
"time_format": "Monday <#ffffff>at</> 3:04 PM"
},
"style": "diamond",
"trailing_diamond": "\ue0b4",
"template": "\u007B\u007B .CurrentDate | date .Format \u007D\u007D",
"type": "time"
},
{
"background": "#3A456E",
"foreground": "#43CCEA",
"foreground_templates": [
"\u007B\u007B if or (.Working.Changed) (.Staging.Changed) \u007D\u007D#FF9248\u007B\u007B end \u007D\u007D",
"\u007B\u007B if and (gt .Ahead 0) (gt .Behind 0) \u007D\u007D#ff4500\u007B\u007B end \u007D\u007D",
"\u007B\u007B if gt .Ahead 0 \u007D\u007D#B388FF\u007B\u007B end \u007D\u007D",
"\u007B\u007B if gt .Behind 0 \u007D\u007D#B388FF\u007B\u007B end \u007D\u007D"
],
"leading_diamond": " \ue0b6",
"options": {
"branch_template": "\u007B\u007B trunc 25 .Branch \u007D\u007D",
"fetch_status": true,
"fetch_upstream_icon": true
},
"style": "diamond",
"template": " \u007B\u007B .UpstreamIcon \u007D\u007D\u007B\u007B .HEAD \u007D\u007D\u007B\u007Bif .BranchStatus \u007D\u007D \u007B\u007B .BranchStatus \u007D\u007D\u007B\u007B end \u007D\u007D\u007B\u007B if .Working.Changed \u007D\u007D \uf044 \u007B\u007B .Working.String \u007D\u007D\u007B\u007B end \u007D\u007D\u007B\u007B if and (.Working.Changed) (.Staging.Changed) \u007D\u007D |\u007B\u007B end \u007D\u007D\u007B\u007B if .Staging.Changed \u007D\u007D \uf046 \u007B\u007B .Staging.String \u007D\u007D\u007B\u007B end \u007D\u007D\u007B\u007B if gt .StashCount 0 \u007D\u007D \ueb4b \u007B\u007B .StashCount \u007D\u007D\u007B\u007B end \u007D\u007D ",
"trailing_diamond": "\ue0b4",
"type": "git"
},
{
"background": "#3A456E",
"foreground": "#E4F34A",
"leading_diamond": " \ue0b6",
"options": {
"fetch_version": false
},
"style": "diamond",
"template": "\ue235 \u007B\u007B if .Error \u007D\u007D\u007B\u007B .Error \u007D\u007D\u007B\u007B else \u007D\u007D\u007B\u007B if .Venv \u007D\u007D\u007B\u007B .Venv \u007D\u007D \u007B\u007B end \u007D\u007D\u007B\u007B .Full \u007D\u007D\u007B\u007B end \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "python"
},
{
"background": "#3A456E",
"foreground": "#7FD5EA",
"leading_diamond": " \ue0b6",
"options": {
"fetch_version": false
},
"style": "diamond",
"template": "\ue626\u007B\u007B if .Error \u007D\u007D\u007B\u007B .Error \u007D\u007D\u007B\u007B else \u007D\u007D\u007B\u007B .Full \u007D\u007D\u007B\u007B end \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "go"
},
{
"background": "#3A456E",
"foreground": "#42E66C",
"leading_diamond": " \ue0b6",
"options": {
"fetch_version": false
},
"style": "diamond",
"template": "\ue718\u007B\u007B if .PackageManagerIcon \u007D\u007D\u007B\u007B .PackageManagerIcon \u007D\u007D \u007B\u007B end \u007D\u007D\u007B\u007B .Full \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "node"
},
{
"background": "#3A456E",
"foreground": "#E64747",
"leading_diamond": " \ue0b6",
"options": {
"fetch_version": false
},
"style": "diamond",
"template": "\ue791\u007B\u007B if .Error \u007D\u007D\u007B\u007B .Error \u007D\u007D\u007B\u007B else \u007D\u007D\u007B\u007B .Full \u007D\u007D\u007B\u007B end \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "ruby"
},
{
"background": "#3A456E",
"foreground": "#E64747",
"leading_diamond": " \ue0b6",
"options": {
"fetch_version": false
},
"style": "diamond",
"template": "\ue738\u007B\u007B if .Error \u007D\u007D\u007B\u007B .Error \u007D\u007D\u007B\u007B else \u007D\u007D\u007B\u007B .Full \u007D\u007D\u007B\u007B end \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "java"
},
{
"background": "#3A456E",
"foreground": "#9B6BDF",
"leading_diamond": " \ue0b6",
"options": {
"fetch_version": false
},
"style": "diamond",
"template": "\ue624\u007B\u007B if .Error \u007D\u007D\u007B\u007B .Error \u007D\u007D\u007B\u007B else \u007D\u007D\u007B\u007B .Full \u007D\u007D\u007B\u007B end \u007D\u007D ",
"trailing_diamond": "\ue0b4",
"type": "julia"
},
{
"type": "php",
"style": "diamond",
"foreground": "#ffffff",
"background": "#4063D8",
"leading_diamond": " \ue0b6",
"options": {
"fetch_version": false
},
"template": "\ue73d \u007B\u007B .Full \u007D\u007D ",
"trailing_diamond": "\ue0b4"
},
{
"background": "#3A456E",
"foreground": "#9B6BDF",
"foreground_templates": [
"\u007B\u007Bif eq \"Charging\" .State.String\u007D\u007D#40c4ff\u007B\u007Bend\u007D\u007D",
"\u007B\u007Bif eq \"Discharging\" .State.String\u007D\u007D#ff5722\u007B\u007Bend\u007D\u007D",
"\u007B\u007Bif eq \"Full\" .State.String\u007D\u007D#4caf50\u007B\u007Bend\u007D\u007D"
],
"leading_diamond": " \ue0b6",
"options": {
"charged_icon": "• ",
"charging_icon": "\u21e1 ",
"discharging_icon": "\u21e3 "
},
"style": "diamond",
"template": "\u007B\u007B if not .Error \u007D\u007D\u007B\u007B .Icon \u007D\u007D\u007B\u007B .Percentage \u007D\u007D\u007B\u007B end \u007D\u007D\u007B\u007B .Error \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "battery"
}
],
"type": "prompt"
},
{
"alignment": "right",
"segments": [
{
"background": "#3A456E",
"foreground": "#AEA4BF",
"leading_diamond": "\ue0b6",
"options": {
"style": "austin",
"threshold": 150
},
"style": "diamond",
"template": "\u007B\u007B .FormattedMs \u007D\u007D",
"trailing_diamond": "\ue0b4 ",
"type": "executiontime"
}
],
"type": "prompt"
},
{
"alignment": "left",
"newline": true,
"segments": [
{
"background": "#3A456E",
"foreground": "#3EC669",
"leading_diamond": "\ue0b6",
"properties": {
"style": "agnoster_full",
"cycle": [
"#3EC669,#3A456E",
"#43CCEA,#3A456E",
"#E4F34A,#3A456E",
"#9B6BDF,#3A456E"
],
"cycle_folder_separator": true
},
"style": "diamond",
"template": "\ue5ff \u007B\u007B .Path \u007D\u007D",
"trailing_diamond": "\ue0b4",
"type": "path"
},
{
"background": "#3A456E",
"foreground": "#ffbebc",
"leading_diamond": "\ue0b6",
"style": "diamond",
"template": "\ue602",
"trailing_diamond": "\ue0b4",
"type": "text"
}
],
"type": "prompt"
}
],
"final_space": true,
"version": 4
}
'';
# matugen template → Obsidian CSS snippet (Minimal-compatible variables).
#
# Upstream template:
# https://raw.githubusercontent.com/Simorg2002/obsidian-matugen-template/refs/heads/main/obsidian-minimal-matugen-colors.css
xdg.configFile."matugen/templates/obsidian-minimal-matugen-colors.css".text = ''
.theme-dark {
--accent-h:calc({{colors.primary.dark.hue}}/255*360);
--accent-s:calc({{colors.primary.dark.saturation}}/255*100%);
--accent-l:calc({{colors.primary.dark.lightness}}/255*100%);
--text-normal:{{colors.on_surface.dark.hex}};
--text-muted:{{colors.on_surface_variant.dark.hex}};
--text-faint:{{colors.outline.dark.hex}};
--background-primary:{{colors.surface.dark.hex}}; /* editor and right ribbon */
--background-secondary:{{colors.surface_dim.dark.hex}}; /* left ribbon */
--background-modifier-hover:{{colors.secondary_container.dark.hex}};
--background-modifier-active-hover:{{colors.secondary.dark.hex}};
--background-modifier-message:{{colors.surface_dim.dark.hex}};
--background-modifier-form-field:{{colors.primary_container.dark.hex}};
--ribbon-background:{{colors.surface.dark.hex}};
--divider-color:{{colors.secondary_container.dark.hex}};
--scrollbar-thumb-bg:{{colors.on_secondary_container.dark.hex}};
--status-bar-border-color:{{colors.secondary_container.dark.hex}};
--status-bar-background:{{colors.surface.dark.hex}};
--titlebar-background:{{colors.surface.dark.hex}};
--titlebar-text-color:{{colors.on_surface.dark.hex}};
--nav-item-color:{{colors.on_surface_variant.dark.hex}};
--nav-item-color-active:{{colors.on_primary_container.dark.hex}};
--nav-item-background-active:{{colors.primary_container.dark.hex}};
--nav-item-color-hover:{{colors.on_secondary_container.dark.hex}};
--nav-item-background-hover:{{colors.secondary_container.dark.hex}};
--tab-background-active:{{colors.primary_container.dark.hex}};
--tab-text-color-active:{{colors.on_primary_container.dark.hex}};
--tab-text-color:{{colors.on_surface_variant.dark.hex}};
--icon-color:{{colors.on_surface.dark.hex}};
--h1-color:{{colors.primary.dark.hex}};
--h2-color: color-mix(in srgb, {{colors.primary.dark.hex}}, {{colors.tertiary.dark.hex}});
--h3-color:{{colors.tertiary.dark.hex}};
--h4-color: color-mix(in srgb, {{colors.primary.dark.hex}}, {{colors.secondary.dark.hex}});
--h5-color:{{colors.secondary.dark.hex}};
--h6-color: color-mix(in srgb, {{colors.tertiary.dark.hex}}, {{colors.secondary.dark.hex}});
}
/* add parts not accessible without specific selector?*/
.theme-dark .sidebar-toggle-button.mod-left {
color:{{colors.on_surface.dark.hex}};
background:{{colors.surface.dark.hex}};
}
.theme-dark .sidebar-toggle-button.mod-right {
color:{{colors.on_surface.dark.hex}};
background:{{colors.surface.dark.hex}};
}
.theme-dark .workspace-tab-header-container{
background:{{colors.surface.dark.hex}};
}
/* copy for light mode */
.theme-light {
--accent-h:calc({{colors.primary.light.hue}}/255*360);
--accent-s:calc({{colors.primary.light.saturation}}/255*100%);
--accent-l:calc({{colors.primary.light.lightness}}/255*100%);
--text-normal:{{colors.on_surface.light.hex}};
--text-muted:{{colors.on_surface_variant.light.hex}};
--text-faint:{{colors.outline.light.hex}};
--background-primary:{{colors.surface.light.hex}}; /* editor and right ribbon */
--background-secondary:{{colors.surface_dim.light.hex}}; /* left ribbon */
--background-modifier-hover:{{colors.secondary_container.light.hex}};
--background-modifier-active-hover:{{colors.secondary.light.hex}};
--background-modifier-message:{{colors.surface_dim.light.hex}};
--background-modifier-form-field:{{colors.primary_container.light.hex}};
--ribbon-background:{{colors.surface.light.hex}};
--divider-color:{{colors.secondary_container.light.hex}};
--scrollbar-thumb-bg:{{colors.on_secondary_container.light.hex}};
--status-bar-border-color:{{colors.secondary_container.light.hex}};
--status-bar-background:{{colors.surface.light.hex}};
--titlebar-background:{{colors.surface.light.hex}};
--titlebar-text-color:{{colors.on_surface.light.hex}};
--nav-item-color:{{colors.on_surface_variant.light.hex}};
--nav-item-color-active:{{colors.on_primary_container.light.hex}};
--nav-item-background-active:{{colors.primary_container.light.hex}};
--nav-item-color-hover:{{colors.on_secondary_container.light.hex}};
--nav-item-background-hover:{{colors.secondary_container.light.hex}};
--tab-background-active:{{colors.primary_container.light.hex}};
--tab-text-color-active:{{colors.on_primary_container.light.hex}};
--tab-text-color:{{colors.on_surface_variant.light.hex}};
--icon-color:{{colors.on_surface.light.hex}};
--h1-color:{{colors.primary.light.hex}};
--h2-color: color-mix(in srgb, {{colors.primary.light.hex}}, {{colors.tertiary.light.hex}});
--h3-color:{{colors.tertiary.light.hex}};
--h4-color: color-mix(in srgb, {{colors.primary.light.hex}}, {{colors.secondary.light.hex}});
--h5-color:{{colors.secondary.light.hex}};
--h6-color: color-mix(in srgb, {{colors.tertiary.light.hex}}, {{colors.secondary.light.hex}});
}
/* add parts not accessible without specific selector?*/
.theme-light .sidebar-toggle-button.mod-left {
color:{{colors.on_surface.light.hex}};
background:{{colors.surface.light.hex}};
}
.theme-light .sidebar-toggle-button.mod-right {
color:{{colors.on_surface.light.hex}};
background:{{colors.surface.light.hex}};
}
.theme-light .workspace-tab-header-container{
background:{{colors.surface.light.hex}};
}
/* Hide window controls (frameless titlebar buttons) */
div[aria-label="Close window"],
div[aria-label="Minimize"],
div[aria-label="Restore down"],
div[aria-label="Maximize"]{
display: none !important;
}
/* Remove the extra right-side spacing reserved for those buttons */
.is-hidden-frameless:not(.is-fullscreen) .workspace-tabs.mod-top-right-space .workspace-tab-header-container{
padding-right: 0px !important;
}
.is-hidden-frameless:not(.is-fullscreen) .workspace-tabs.mod-top-right-space .workspace-tab-header-container:after{
display: none !important;
}
'';
}
(lib.mkIf ohMyPoshEnabled {
# Same path as matugen `[templates.ohmyposh]`; seeded as a real file by `ensureMatugenOutputDirsScript`.
programs.oh-my-posh = {
useTheme = lib.mkForce null;
configFile = lib.mkForce "${config.xdg.configHome}/oh-my-posh/theme.omp.json";
};
})
]);
}