mirror of
https://codeberg.org/muon/home.git
synced 2026-07-03 23:49:35 +00:00
Compare commits
No commits in common. "0cda38f25b91138831fb01fc2e0c31183239e308" and "86c3dbfa88904ae86745a476b3d67ed2b63e0ae3" have entirely different histories.
0cda38f25b
...
86c3dbfa88
10 changed files with 199 additions and 626 deletions
59
flake.nix
59
flake.nix
|
|
@ -46,31 +46,48 @@
|
|||
};
|
||||
|
||||
utils = import ./utils.nix {inherit inputs system sources;};
|
||||
|
||||
# Discover hosts: all subdirectories of hosts/
|
||||
hosts = builtins.attrNames (nixpkgs.lib.filterAttrs
|
||||
(_: type: type == "directory")
|
||||
(builtins.readDir ./hosts));
|
||||
|
||||
nixosConfigs = builtins.listToAttrs (map (host: {
|
||||
name = host;
|
||||
value = utils.mkHost ./hosts/${host}/configuration.nix;
|
||||
}) hosts);
|
||||
in {
|
||||
nixosConfigurations = nixosConfigs;
|
||||
nixosConfigurations = {
|
||||
# desktop
|
||||
muon = utils.mkHost ./hosts/muon/configuration.nix;
|
||||
|
||||
# laptop
|
||||
muop = utils.mkHost ./hosts/muop/configuration.nix;
|
||||
|
||||
# server
|
||||
muho = utils.mkHost ./hosts/muho/configuration.nix;
|
||||
|
||||
# vps
|
||||
mups = utils.mkHost ./hosts/mups/configuration.nix;
|
||||
|
||||
# vm
|
||||
muvm = utils.mkHost ./hosts/muvm/configuration.nix;
|
||||
|
||||
# work
|
||||
murk = utils.mkHost ./hosts/murk/configuration.nix;
|
||||
|
||||
# work desktop
|
||||
musk = utils.mkHost ./hosts/musk/configuration.nix;
|
||||
|
||||
# lenovo
|
||||
muvo = utils.mkHost ./hosts/muvo/configuration.nix;
|
||||
|
||||
# installer
|
||||
muin = utils.mkHost ./hosts/muin/configuration.nix;
|
||||
};
|
||||
|
||||
homeManagerModules.default = ./modules/home;
|
||||
|
||||
# Standalone HM configurations — one per host.
|
||||
# osConfig is injected so all modules using it continue to work.
|
||||
# Use: home-manager switch --flake '.#muon@<host>'
|
||||
homeConfigurations = builtins.listToAttrs (map (host: {
|
||||
name = "muon@${host}";
|
||||
value = utils.mkHome {
|
||||
hostConfig = nixosConfigs.${host};
|
||||
homeFile = ./hosts/${host}/home.nix;
|
||||
};
|
||||
}) hosts);
|
||||
# Expose each host's HM activation package so `home-manager switch --flake .#muon@<host>`
|
||||
# works without a full NixOS rebuild. Extracted from the already-evaluated
|
||||
# nixosConfiguration, so osConfig remains fully populated.
|
||||
homeConfigurations = nixpkgs.lib.mapAttrs' (host: nixos:
|
||||
nixpkgs.lib.nameValuePair "muon@${host}" {
|
||||
activationPackage = nixos.config.home-manager.users.muon.home.activationPackage;
|
||||
}
|
||||
) (nixpkgs.lib.filterAttrs
|
||||
(_: nixos: nixos.config.home-manager.users ? muon)
|
||||
inputs.self.outputs.nixosConfigurations);
|
||||
|
||||
colmena = {
|
||||
meta = {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ in {
|
|||
mods.server.ntfy.enable = true;
|
||||
mods.server.lemmy.enable = true;
|
||||
mods.server.audio.enable = true;
|
||||
mods.server.murmur.enable = true;
|
||||
mods.server.atuin.enable = true;
|
||||
mods.server.seedbox.enable = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ in {
|
|||
mods.xdg.enable = true;
|
||||
mods.social.enable = false;
|
||||
mods.i3.enable = false;
|
||||
mods.terminal.wezterm.enable = true;
|
||||
mods.terminal.nushell.enable = true;
|
||||
mods.terminal.zsh.enable = true;
|
||||
mods.terminal.emulator.enable = false;
|
||||
mods.terminal.development.enable = true;
|
||||
|
|
|
|||
|
|
@ -5,97 +5,22 @@
|
|||
osConfig,
|
||||
...
|
||||
}: let
|
||||
# Bootstrap script that runs as the first program inside a new wezterm window.
|
||||
# It sets up the three tabs synchronously before the shell prompt appears,
|
||||
# so by the time the window is visible the layout is already complete.
|
||||
# Receives the project path as $1.
|
||||
wezterm-zmenu-init = pkgs.writeShellApplication {
|
||||
name = "wezterm-zmenu-init";
|
||||
runtimeInputs = [pkgs.wezterm pkgs.zsh];
|
||||
text = ''
|
||||
ZPATH=$1
|
||||
WIN=$(wezterm cli list --format json 2>/dev/null \
|
||||
| tr ',' '\n' \
|
||||
| awk -v pane="$WEZTERM_PANE" '
|
||||
/window_id/ { gsub(/.*: */,""); w=int($0) }
|
||||
/pane_id/ { gsub(/.*: */,""); if (int($0)==pane) { print w; exit } }')
|
||||
P1=$(wezterm cli spawn --window-id "$WIN" --cwd "$ZPATH" -- direnv exec . nvim)
|
||||
wezterm cli spawn --window-id "$WIN" --cwd "$ZPATH" > /dev/null
|
||||
wezterm cli spawn --window-id "$WIN" --cwd "$ZPATH" -- lazygit > /dev/null
|
||||
wezterm cli activate-tab --tab-index 0 --pane-id "$P1" 2>/dev/null
|
||||
'';
|
||||
};
|
||||
|
||||
zmenu = with pkgs;
|
||||
writeShellApplication {
|
||||
name = "zmenu";
|
||||
runtimeInputs =
|
||||
[zoxide wmctrl i3 rofi zsh]
|
||||
++ lib.optionals config.mods.terminal.wezterm.enable [wezterm]
|
||||
++ lib.optionals (!config.mods.terminal.wezterm.enable) [zellij alacritty];
|
||||
text =
|
||||
if config.mods.terminal.wezterm.enable
|
||||
then ''
|
||||
ZPATH=$(zoxide query -l | sed -e "s|$HOME/||g" | rofi -dmenu)
|
||||
[[ -z "$ZPATH" ]] && exit
|
||||
ZSESH=$(echo "$ZPATH" | tr / -)
|
||||
|
||||
# Per-workspace socket registry so we can focus existing workspaces.
|
||||
SOCKDIR="$XDG_RUNTIME_DIR/zmenu-wez"
|
||||
mkdir -p "$SOCKDIR"
|
||||
SOCKFILE="$SOCKDIR/$ZSESH"
|
||||
|
||||
SOCK=""
|
||||
if [[ -f "$SOCKFILE" ]]; then
|
||||
SOCK=$(cat "$SOCKFILE")
|
||||
# Extract the PID from the socket path (gui-sock-<pid>) and check
|
||||
# if the process is still alive. Dead sockets linger on disk.
|
||||
SOCK_PID=''${SOCK##*-}
|
||||
if ! kill -0 "$SOCK_PID" 2>/dev/null; then
|
||||
rm -f "$SOCKFILE"
|
||||
SOCK=""
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$SOCK" ]]; then
|
||||
# Workspace open: raise its window by matching the wezterm PID in
|
||||
# wmctrl's process list, then activate a pane to ensure focus.
|
||||
SOCK_PID=''${SOCK##*-}
|
||||
WIN_HEX=$(wmctrl -lp | awk -v pid="$SOCK_PID" '$3==pid {print $1; exit}')
|
||||
wmctrl -i -a "$WIN_HEX"
|
||||
PANE=$(WEZTERM_UNIX_SOCKET="$SOCK" wezterm cli list --format json 2>/dev/null \
|
||||
| tr ',' '\n' \
|
||||
| awk '/pane_id/{gsub(/.*: */,""); print int($0); exit}')
|
||||
WEZTERM_UNIX_SOCKET="$SOCK" wezterm cli activate-pane --pane-id "$PANE" 2>/dev/null
|
||||
else
|
||||
# Not open: the init script runs as the first program inside the new
|
||||
# window. It sets up all tabs synchronously before the shell prompt
|
||||
# appears, so the layout is complete before anything is visible.
|
||||
wezterm start --always-new-process \
|
||||
--workspace "$ZSESH" --cwd "$HOME/$ZPATH" \
|
||||
-- ${lib.getExe wezterm-zmenu-init} "$HOME/$ZPATH" &
|
||||
WEZ_PID=$!
|
||||
|
||||
# Record the socket for future focus calls.
|
||||
for _ in $(seq 50); do
|
||||
sleep 0.1
|
||||
[[ -S /run/user/$UID/wezterm/gui-sock-$WEZ_PID ]] && break
|
||||
done
|
||||
echo "/run/user/$UID/wezterm/gui-sock-$WEZ_PID" > "$SOCKFILE"
|
||||
fi
|
||||
''
|
||||
else ''
|
||||
ZPATH=$(zoxide query -l | sed -e "s|$HOME/||g" | rofi -dmenu)
|
||||
[[ -z "$ZPATH" ]] && exit
|
||||
ZSESH=$(echo "$ZPATH" | tr / -)
|
||||
ZWIND=$(wmctrl -l | grep "$ZSESH$" || echo "")
|
||||
cd "$HOME/$ZPATH"
|
||||
if [[ -z "$ZWIND" ]]; then
|
||||
alacritty -T "$ZSESH" -e zsh -c "zellij -s $ZSESH -n dev || zellij a $ZSESH"
|
||||
else
|
||||
wmctrl -a "$ZSESH"
|
||||
fi
|
||||
'';
|
||||
runtimeInputs = [zellij zoxide wmctrl i3 rofi alacritty zsh];
|
||||
text = ''
|
||||
ZPATH=$(zoxide query -l | sed -e "s|$HOME/||g" | rofi -dmenu)
|
||||
[[ -z "$ZPATH" ]] && exit
|
||||
ZSESH=$(echo "$ZPATH" | tr / -)
|
||||
ZWIND=$(wmctrl -l | grep "$ZSESH$" || echo "")
|
||||
cd "$ZPATH"
|
||||
if [[ -z "$ZWIND" ]]; then
|
||||
alacritty -T "$ZSESH" -e zsh -c "zellij -s $ZSESH -n dev || zellij a $ZSESH"
|
||||
else
|
||||
wmctrl -a "$ZSESH"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
in
|
||||
with lib; {
|
||||
|
|
@ -169,10 +94,7 @@ in
|
|||
enable = true;
|
||||
config = {
|
||||
modifier = modifier;
|
||||
terminal =
|
||||
if config.mods.terminal.wezterm.enable
|
||||
then "wezterm"
|
||||
else "alacritty";
|
||||
terminal = "alacritty";
|
||||
menu = "rofi -show drun";
|
||||
|
||||
window = {
|
||||
|
|
|
|||
|
|
@ -23,43 +23,35 @@ in {
|
|||
|
||||
shellAliases = aliases;
|
||||
|
||||
# vi mode + sensible defaults via flat assignments (avoids clobbering other modules)
|
||||
settings = {
|
||||
show_banner = false;
|
||||
edit_mode = "vi";
|
||||
cursor_shape = {
|
||||
vi_insert = "line";
|
||||
vi_normal = "block";
|
||||
};
|
||||
history = {
|
||||
max_size = 2097152;
|
||||
sync_on_enter = true;
|
||||
file_format = "sqlite";
|
||||
isolation = false;
|
||||
};
|
||||
completions = {
|
||||
case_sensitive = false;
|
||||
quick = true;
|
||||
partial = true;
|
||||
algorithm = "fuzzy";
|
||||
};
|
||||
table.mode = "rounded";
|
||||
};
|
||||
# vi mode + sensible defaults
|
||||
extraConfig = ''
|
||||
$env.config = {
|
||||
show_banner: false
|
||||
edit_mode: vi
|
||||
|
||||
# Append the / keybinding after all integrations (including atuin) are sourced,
|
||||
# so _atuin_search_cmd is defined when this runs.
|
||||
extraConfig = lib.mkAfter ''
|
||||
$env.config = (
|
||||
$env.config | upsert keybindings (
|
||||
$env.config.keybindings | append {
|
||||
name: atuin_search_vi_normal
|
||||
modifier: none
|
||||
keycode: char_/
|
||||
mode: vi_normal
|
||||
event: { send: executehostcommand cmd: (_atuin_search_cmd) }
|
||||
}
|
||||
)
|
||||
)
|
||||
cursor_shape: {
|
||||
vi_insert: line
|
||||
vi_normal: block
|
||||
}
|
||||
|
||||
history: {
|
||||
max_size: 2097152
|
||||
sync_on_enter: true
|
||||
file_format: "sqlite"
|
||||
isolation: false
|
||||
}
|
||||
|
||||
completions: {
|
||||
case_sensitive: false
|
||||
quick: true
|
||||
partial: true
|
||||
algorithm: "fuzzy"
|
||||
}
|
||||
|
||||
table: {
|
||||
mode: rounded
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
# Carry over zsh session variables
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ in
|
|||
atuin = {
|
||||
enable = true;
|
||||
enableZshIntegration = true;
|
||||
enableNushellIntegration = true;
|
||||
flags = ["--disable-up-arrow"];
|
||||
settings = {
|
||||
sync_frequency = "5m";
|
||||
|
|
|
|||
|
|
@ -28,155 +28,70 @@
|
|||
|
||||
# vi directions: key, arrow alias, wezterm direction name
|
||||
viDirs = [
|
||||
{
|
||||
key = "h";
|
||||
arrow = "LeftArrow";
|
||||
dir = "Left";
|
||||
}
|
||||
{
|
||||
key = "j";
|
||||
arrow = "DownArrow";
|
||||
dir = "Down";
|
||||
}
|
||||
{
|
||||
key = "k";
|
||||
arrow = "UpArrow";
|
||||
dir = "Up";
|
||||
}
|
||||
{
|
||||
key = "l";
|
||||
arrow = "RightArrow";
|
||||
dir = "Right";
|
||||
}
|
||||
{key = "h"; arrow = "LeftArrow"; dir = "Left";}
|
||||
{key = "j"; arrow = "DownArrow"; dir = "Down";}
|
||||
{key = "k"; arrow = "UpArrow"; dir = "Up";}
|
||||
{key = "l"; arrow = "RightArrow"; dir = "Right";}
|
||||
];
|
||||
|
||||
# hjkl + arrow equivalents; mkAction :: dir -> lua-action-string
|
||||
viDirKeys = {
|
||||
mods ? null,
|
||||
indent ? " ",
|
||||
mkAction,
|
||||
}:
|
||||
viDirKeys = {mods ? null, indent ? " ", mkAction}:
|
||||
lib.concatMapStrings (d:
|
||||
luaKey {
|
||||
inherit mods indent;
|
||||
key = d.key;
|
||||
action = mkAction d.dir;
|
||||
}
|
||||
+ luaKey {
|
||||
inherit mods indent;
|
||||
key = d.arrow;
|
||||
action = mkAction d.dir;
|
||||
})
|
||||
luaKey {inherit mods indent; key = d.key; action = mkAction d.dir;} +
|
||||
luaKey {inherit mods indent; key = d.arrow; action = mkAction d.dir;})
|
||||
viDirs;
|
||||
|
||||
# 1-9 tab-jump bindings
|
||||
tabJumpKeys = {
|
||||
mods ? null,
|
||||
indent ? " ",
|
||||
}:
|
||||
tabJumpKeys = {mods ? null, indent ? " "}:
|
||||
lib.concatStrings (builtins.genList (i:
|
||||
luaKey {
|
||||
inherit mods indent;
|
||||
key = toString (i + 1);
|
||||
key = toString (i + 1);
|
||||
action = "act.ActivateTab(${toString i})";
|
||||
})
|
||||
9);
|
||||
|
||||
# hjkl + arrows for AdjustPaneSize at a given step
|
||||
resizeDirKeys = {
|
||||
step,
|
||||
indent ? " ",
|
||||
}:
|
||||
resizeDirKeys = {step, indent ? " "}:
|
||||
lib.concatMapStrings (d:
|
||||
luaKey {
|
||||
inherit indent;
|
||||
key = d.key;
|
||||
action = "act.AdjustPaneSize({ \"${d.dir}\", ${toString step} })";
|
||||
}
|
||||
+ luaKey {
|
||||
inherit indent;
|
||||
key = d.arrow;
|
||||
action = "act.AdjustPaneSize({ \"${d.dir}\", ${toString step} })";
|
||||
})
|
||||
luaKey {inherit indent; key = d.key; action = "act.AdjustPaneSize({ \"${d.dir}\", ${toString step} })";} +
|
||||
luaKey {inherit indent; key = d.arrow; action = "act.AdjustPaneSize({ \"${d.dir}\", ${toString step} })";})
|
||||
viDirs;
|
||||
|
||||
# Uppercase HJKL fine-tune resize
|
||||
resizeShiftKeys = {
|
||||
step,
|
||||
indent ? " ",
|
||||
}:
|
||||
resizeShiftKeys = {step, indent ? " "}:
|
||||
lib.concatMapStrings (d:
|
||||
luaKey {
|
||||
inherit indent;
|
||||
key = lib.toUpper d.key;
|
||||
action = "act.AdjustPaneSize({ \"${d.dir}\", ${toString step} })";
|
||||
})
|
||||
luaKey {inherit indent; key = lib.toUpper d.key; action = "act.AdjustPaneSize({ \"${d.dir}\", ${toString step} })";})
|
||||
viDirs;
|
||||
|
||||
# Wrap a lua action string so it also pops the key table (return to locked)
|
||||
andPop = action: "act.Multiple({ ${action}, act.PopKeyTable })";
|
||||
|
||||
# Standard exit bindings, given the mode's own pop key
|
||||
exitKeys = {
|
||||
selfKey,
|
||||
indent ? " ",
|
||||
}:
|
||||
exitKeys = {selfKey, indent ? " "}:
|
||||
lib.concatStrings [
|
||||
(luaKey {
|
||||
inherit indent;
|
||||
key = selfKey;
|
||||
action = "act.PopKeyTable";
|
||||
})
|
||||
(luaKey {
|
||||
inherit indent;
|
||||
key = "Escape";
|
||||
action = "act.PopKeyTable";
|
||||
})
|
||||
(luaKey {
|
||||
inherit indent;
|
||||
key = "Enter";
|
||||
action = "act.PopKeyTable";
|
||||
})
|
||||
(luaKey {
|
||||
inherit indent;
|
||||
key = "Space";
|
||||
mods = "ALT";
|
||||
action = "act.PopKeyTable";
|
||||
})
|
||||
(luaKey {inherit indent; key = selfKey; action = "act.PopKeyTable";})
|
||||
(luaKey {inherit indent; key = "Escape"; action = "act.PopKeyTable";})
|
||||
(luaKey {inherit indent; key = "Enter"; action = "act.PopKeyTable";})
|
||||
(luaKey {inherit indent; key = "Space"; mods = "ALT"; action = "act.PopKeyTable";})
|
||||
];
|
||||
|
||||
# ── Status bar ───────────────────────────────────────────────────────────────
|
||||
|
||||
# Per-mode accent colour (base16) and hint string shown in the status bar
|
||||
# Hints use nerd font glyphs: separators, icons, key labels
|
||||
# Per-mode accent colour (base16) and hint string shown on the left status bar
|
||||
modes = {
|
||||
locked = {
|
||||
fg = color.base03;
|
||||
hint = "⌥: ⌥hl: ^ud: ⌥1-9: ⌥n: ⌥s: ⌥w: ⌥t: ⌥p:";
|
||||
};
|
||||
normal = {
|
||||
fg = color.base0D;
|
||||
hint = "t: x: r: c: s: esc:";
|
||||
};
|
||||
resize = {
|
||||
fg = color.base0A;
|
||||
hint = "hjkl: HJKL: esc:";
|
||||
};
|
||||
copy_mode = {
|
||||
fg = color.base0E;
|
||||
hint = "hjkl: v: V: ^v: y: /: n/p: esc:";
|
||||
};
|
||||
search_mode = {
|
||||
fg = color.base08;
|
||||
hint = "type: ^n/^p: ^r: ↵/esc:";
|
||||
};
|
||||
locked = {fg = color.base03; hint = "Alt+Space:enter Alt+hl:focus/tab Alt+1-9:tab Alt+n:split C-ud:scroll";};
|
||||
normal = {fg = color.base0D; hint = "p:pane t:tab r:resize s:scroll n:split Esc:exit";};
|
||||
pane = {fg = color.base0B; hint = "hjkl:focus n/r:split→ d:split↓ f:zoom x:close Esc:exit";};
|
||||
tab = {fg = color.base0C; hint = "hjkl:prev/next 1-9:jump n:new x:close r:rename Esc:exit";};
|
||||
resize = {fg = color.base0A; hint = "hjkl:+5 HJKL:+1 Esc:exit";};
|
||||
scroll = {fg = color.base0E; hint = "jk:line ud:half hl:page f:search Esc:exit";};
|
||||
};
|
||||
|
||||
# Lua table literal mapping mode name -> { fg, hint }
|
||||
modeTableEntries = lib.concatStringsSep "\n " (lib.mapAttrsToList (name: m: ''
|
||||
["${name}"] = { fg = "${m.fg}", hint = "${m.hint}" },
|
||||
'')
|
||||
modes);
|
||||
["${name}"] = { fg = "${m.fg}", hint = "${m.hint}" },
|
||||
'') modes);
|
||||
in {
|
||||
options.mods.terminal.wezterm.enable = lib.mkEnableOption "enables wezterm";
|
||||
|
||||
|
|
@ -207,51 +122,6 @@ in {
|
|||
end)
|
||||
end
|
||||
|
||||
-- scroll_or_passthrough: Ctrl+key scrolls at the shell prompt but passes
|
||||
-- the key through when a program has taken the alt screen (vim, less, fzf…).
|
||||
local function scroll_or_passthrough(key, pages)
|
||||
return wezterm.action_callback(function(window, pane)
|
||||
if pane:is_alt_screen_active() then
|
||||
window:perform_action(act.SendKey({ key = key, mods = "CTRL" }), pane)
|
||||
else
|
||||
window:perform_action(act.ScrollByPage(pages), pane)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- tab_is_zoomed: true if any pane in the current tab is zoomed.
|
||||
-- Used by move_vertical to decide whether to carry zoom forward.
|
||||
local function tab_is_zoomed(pane)
|
||||
for _, info in ipairs(pane:tab():panes_with_info()) do
|
||||
if info.is_zoomed then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- move_vertical: move focus Up/Down.
|
||||
-- If any pane in the tab is currently zoomed (zoom-mode is "on" for this
|
||||
-- tab), zoom the destination pane too — stacked-panel behaviour.
|
||||
-- Otherwise just move focus plainly.
|
||||
local function move_vertical(direction)
|
||||
return wezterm.action_callback(function(window, pane)
|
||||
local neighbour = pane:tab():get_pane_direction(direction)
|
||||
if neighbour == nil then return end
|
||||
if tab_is_zoomed(pane) then
|
||||
-- unzoom_on_switch_pane unzooms the current pane when we move;
|
||||
-- then SetPaneZoomState(true) zooms the newly active pane.
|
||||
window:perform_action(
|
||||
act.Multiple({
|
||||
act.ActivatePaneDirection(direction),
|
||||
act.SetPaneZoomState(true),
|
||||
}),
|
||||
pane
|
||||
)
|
||||
else
|
||||
window:perform_action(act.ActivatePaneDirection(direction), pane)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- ─── Status bar ────────────────────────────────────────────────────────────
|
||||
|
||||
-- Per-mode accent colour and hint text, generated from Nix/stylix palette
|
||||
|
|
@ -261,107 +131,27 @@ in {
|
|||
|
||||
local bg_bar = "${color.base01}"
|
||||
local fg_text = "${color.base05}"
|
||||
local fg_dim = "${color.base03}"
|
||||
local bg_main = "${color.base00}"
|
||||
|
||||
-- Render hints with the key in the mode accent colour and the icon dimmed.
|
||||
-- Each hint token is "key:icon"; we colour them individually.
|
||||
local function render_hints(hint, accent)
|
||||
local cells = {}
|
||||
for token in hint:gmatch("%S+") do
|
||||
local key, icon = token:match("^(.-):(.)$")
|
||||
if key and icon then
|
||||
table.insert(cells, { Background = { Color = bg_bar } })
|
||||
table.insert(cells, { Foreground = { Color = accent } })
|
||||
table.insert(cells, { Text = key })
|
||||
table.insert(cells, { Foreground = { Color = fg_text } })
|
||||
table.insert(cells, { Text = ":" .. icon .. " " })
|
||||
else
|
||||
table.insert(cells, { Background = { Color = bg_bar } })
|
||||
table.insert(cells, { Foreground = { Color = fg_dim } })
|
||||
table.insert(cells, { Text = token .. " " })
|
||||
end
|
||||
end
|
||||
return cells
|
||||
end
|
||||
|
||||
wezterm.on("format-window-title", function(tab, _pane, _tabs, _panes, _config)
|
||||
local ok, win = pcall(function() return wezterm.mux.get_window(tab.window_id) end)
|
||||
if ok and win then
|
||||
local ws = win:get_workspace()
|
||||
if ws ~= "default" then
|
||||
return ws .. " — " .. tab.active_pane.title
|
||||
end
|
||||
end
|
||||
return tab.active_pane.title
|
||||
end)
|
||||
|
||||
-- format-tab-title: show "rank/total title" when the active tab is in
|
||||
-- stacked (zoom) mode; otherwise show plain " title ".
|
||||
-- Returning a cell table gives us explicit padding and colours;
|
||||
-- returning a plain string loses the retro tab bar's built-in spacing.
|
||||
local tab_bg_active = "${color.base0D}"
|
||||
local tab_fg_active = "${color.base00}"
|
||||
local tab_bg_inactive = "${color.base01}"
|
||||
local tab_fg_inactive = "${color.base03}"
|
||||
|
||||
wezterm.on("format-tab-title", function(tab, _tabs, panes, _config, _hover, _max_width)
|
||||
local title = (tab.tab_title and tab.tab_title ~= "") and tab.tab_title or tab.active_pane.title
|
||||
local bg = tab.is_active and tab_bg_active or tab_bg_inactive
|
||||
local fg = tab.is_active and tab_fg_active or tab_fg_inactive
|
||||
|
||||
-- Only compute stack position for the active tab.
|
||||
-- The `panes` event parameter only contains the active pane snapshot
|
||||
-- and lacks `top`, so we use wezterm.mux.get_tab():panes_with_info()
|
||||
-- which returns full PaneInformation including top/is_zoomed/is_active.
|
||||
if tab.is_active then
|
||||
local mux_tab = wezterm.mux.get_tab(tab.tab_id)
|
||||
if mux_tab then
|
||||
local infos = mux_tab:panes_with_info()
|
||||
table.sort(infos, function(a, b) return a.top < b.top end)
|
||||
|
||||
local any_zoomed = false
|
||||
local active_rank, total = 0, 0
|
||||
for _, p in ipairs(infos) do
|
||||
total = total + 1
|
||||
if p.is_active then active_rank = total end
|
||||
if p.is_zoomed then any_zoomed = true end
|
||||
end
|
||||
|
||||
if any_zoomed and total > 1 and active_rank > 0 then
|
||||
title = active_rank .. "/" .. total .. " " .. title
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
{ Background = { Color = bg } },
|
||||
{ Foreground = { Color = fg } },
|
||||
{ Text = " " .. title .. " " },
|
||||
}
|
||||
end)
|
||||
|
||||
wezterm.on("update-status", function(window, _pane)
|
||||
local kt = window:active_key_table()
|
||||
local mode = kt or "locked"
|
||||
local info = mode_info[mode] or mode_info["locked"]
|
||||
|
||||
window:set_left_status("")
|
||||
-- Left: coloured mode badge + hint line
|
||||
window:set_left_status(wezterm.format({
|
||||
{ Background = { Color = info.fg } },
|
||||
{ Foreground = { Color = bg_main } },
|
||||
{ Attribute = { Intensity = "Bold" } },
|
||||
{ Text = " " .. mode:upper() .. " " },
|
||||
"ResetAttributes",
|
||||
{ Background = { Color = bg_bar } },
|
||||
{ Foreground = { Color = fg_text } },
|
||||
{ Text = " " .. info.hint .. " " },
|
||||
"ResetAttributes",
|
||||
}))
|
||||
|
||||
-- Right: coloured hints then mode badge
|
||||
local cells = { { Text = " " } }
|
||||
for _, c in ipairs(render_hints(info.hint, info.fg)) do
|
||||
table.insert(cells, c)
|
||||
end
|
||||
table.insert(cells, "ResetAttributes")
|
||||
table.insert(cells, { Background = { Color = info.fg } })
|
||||
table.insert(cells, { Foreground = { Color = bg_bar } })
|
||||
table.insert(cells, { Text = "" })
|
||||
table.insert(cells, { Foreground = { Color = bg_main } })
|
||||
table.insert(cells, { Attribute = { Intensity = "Bold" } })
|
||||
table.insert(cells, { Text = " " .. mode:upper() .. " " })
|
||||
table.insert(cells, "ResetAttributes")
|
||||
window:set_right_status(wezterm.format(cells))
|
||||
window:set_right_status("")
|
||||
end)
|
||||
|
||||
-- ─── Appearance ────────────────────────────────────────────────────────────
|
||||
|
|
@ -380,29 +170,7 @@ in {
|
|||
config.default_cursor_style = "BlinkingBar"
|
||||
config.hide_tab_bar_if_only_one_tab = false
|
||||
config.use_fancy_tab_bar = false
|
||||
config.tab_max_width = 24
|
||||
|
||||
config.colors = {
|
||||
tab_bar = {
|
||||
background = "${color.base01}",
|
||||
active_tab = { bg_color = "${color.base0D}", fg_color = "${color.base00}", intensity = "Bold" },
|
||||
inactive_tab = { bg_color = "${color.base01}", fg_color = "${color.base03}" },
|
||||
inactive_tab_hover = { bg_color = "${color.base02}", fg_color = "${color.base04}" },
|
||||
new_tab = { bg_color = "${color.base01}", fg_color = "${color.base03}" },
|
||||
new_tab_hover = { bg_color = "${color.base02}", fg_color = "${color.base04}" },
|
||||
},
|
||||
}
|
||||
config.tab_bar_at_bottom = false
|
||||
|
||||
-- ─── SSH Domains ───────────────────────────────────────────────────────────
|
||||
|
||||
config.ssh_domains = {
|
||||
{
|
||||
name = "muho",
|
||||
remote_address = "muho",
|
||||
username = "muon",
|
||||
},
|
||||
}
|
||||
config.tab_bar_at_bottom = true
|
||||
|
||||
-- ─── Shell ─────────────────────────────────────────────────────────────────
|
||||
|
||||
|
|
@ -414,53 +182,30 @@ in {
|
|||
|
||||
config.scrollback_lines = 10000
|
||||
|
||||
-- ─── Stacked panes ─────────────────────────────────────────────────────────
|
||||
-- When switching away from a zoomed pane, unzoom it automatically.
|
||||
-- Paired with stack_focus (Alt+j/k) this gives Zellij-style stacked panels.
|
||||
config.unzoom_on_switch_pane = true
|
||||
|
||||
-- ─── Key bindings ──────────────────────────────────────────────────────────
|
||||
--
|
||||
-- Default mode = "locked" (all keys pass through to the shell).
|
||||
-- Alt+Space enters "normal" mode.
|
||||
-- From normal: t→new tab x→close tab p/n→split r→resize mode
|
||||
-- Alt+Space enters "normal" mode (like Zellij).
|
||||
-- From normal: p→pane t→tab r→resize s→scroll
|
||||
-- Esc / Enter / Alt+Space → back to locked from any mode.
|
||||
|
||||
config.disable_default_key_bindings = true
|
||||
|
||||
config.keys = {
|
||||
-- Alt+h/l: move focus or switch tab at edge (Zellij MoveFocusOrTab)
|
||||
-- Alt+j/k: initial bindings (overridden below by stacked-focus variants)
|
||||
-- Alt+j/k: move focus between panes
|
||||
${viDirKeys {
|
||||
mods = "ALT";
|
||||
indent = " ";
|
||||
mkAction = d:
|
||||
if d == "Left" || d == "Right"
|
||||
then "move_focus_or_tab(\"${d}\")"
|
||||
else "act.ActivatePaneDirection(\"${d}\")";
|
||||
}}
|
||||
mods = "ALT";
|
||||
indent = " ";
|
||||
mkAction = d:
|
||||
if d == "Left" || d == "Right"
|
||||
then "move_focus_or_tab(\"${d}\")"
|
||||
else "act.ActivatePaneDirection(\"${d}\")";
|
||||
}}
|
||||
-- Alt+1-9: jump to tab by number
|
||||
${tabJumpKeys {
|
||||
mods = "ALT";
|
||||
indent = " ";
|
||||
}}
|
||||
${tabJumpKeys {mods = "ALT"; indent = " ";}}
|
||||
-- Alt+n: new pane (split right)
|
||||
{ key = "n", mods = "ALT", action = act.SplitHorizontal({ domain = "CurrentPaneDomain" }) },
|
||||
-- Alt+s: split below, then zoom the new pane so stacked mode starts.
|
||||
-- Two separate perform_action calls: the split runs first and focuses
|
||||
-- the new pane, then the second call zooms window:active_pane() which
|
||||
-- is now the new pane (not the original `pane` argument).
|
||||
{ key = "s", mods = "ALT", action = wezterm.action_callback(function(window, pane)
|
||||
window:perform_action(act.SplitVertical({ domain = "CurrentPaneDomain" }), pane)
|
||||
window:perform_action(act.SetPaneZoomState(true), window:active_pane())
|
||||
end)
|
||||
},
|
||||
-- Alt+j/k: move_vertical — plain focus move normally, stacked zoom
|
||||
-- when any pane in the tab is already zoomed (mirrors Alt+f state).
|
||||
{ key = "j", mods = "ALT", action = move_vertical("Down") },
|
||||
{ key = "k", mods = "ALT", action = move_vertical("Up") },
|
||||
{ key = "DownArrow", mods = "ALT", action = move_vertical("Down") },
|
||||
{ key = "UpArrow", mods = "ALT", action = move_vertical("Up") },
|
||||
-- Alt+f: toggle zoom
|
||||
{ key = "f", mods = "ALT", action = act.TogglePaneZoomState },
|
||||
-- Alt+[/]: rotate panes
|
||||
|
|
@ -473,31 +218,11 @@ in {
|
|||
-- Alt+i/o: reorder tabs
|
||||
{ key = "i", mods = "ALT", action = act.MoveTabRelative(-1) },
|
||||
{ key = "o", mods = "ALT", action = act.MoveTabRelative(1) },
|
||||
-- Alt+w: close current pane; if tab was in stacked (zoom) mode, re-zoom
|
||||
-- the new active pane so zoom mode persists across close.
|
||||
-- confirm=false because the callback must run synchronously after close;
|
||||
-- a confirm dialog would make the zoom fire before the user answers.
|
||||
-- Guard: only re-zoom when there will still be panes left after close.
|
||||
{ key = "w", mods = "ALT", action = wezterm.action_callback(function(window, pane)
|
||||
local panes = pane:tab():panes()
|
||||
local was_zoomed = tab_is_zoomed(pane)
|
||||
window:perform_action(act.CloseCurrentPane({ confirm = false }), pane)
|
||||
if was_zoomed and #panes > 1 then
|
||||
window:perform_action(act.SetPaneZoomState(true), window:active_pane())
|
||||
end
|
||||
end)
|
||||
},
|
||||
-- Alt+p: command palette
|
||||
{ key = "p", mods = "ALT", action = act.ActivateCommandPalette },
|
||||
-- Alt+t: tab navigator (searchable tab list)
|
||||
{ key = "t", mods = "ALT", action = act.ShowTabNavigator },
|
||||
-- Alt+q: quit
|
||||
{ key = "q", mods = "ALT", action = act.QuitApplication },
|
||||
-- Ctrl+U/D: scroll half page when at the shell prompt; pass through
|
||||
-- to the running program when it is using the alt screen (vim, less,
|
||||
-- fzf, etc. switch to the alt screen and need the raw key).
|
||||
{ key = "u", mods = "CTRL", action = scroll_or_passthrough("u", -0.5) },
|
||||
{ key = "d", mods = "CTRL", action = scroll_or_passthrough("d", 0.5) },
|
||||
-- Ctrl+U/D: scroll half page (matches Alacritty)
|
||||
{ key = "u", mods = "CTRL", action = act.ScrollByPage(-0.5) },
|
||||
{ key = "d", mods = "CTRL", action = act.ScrollByPage(0.5) },
|
||||
-- Copy / paste
|
||||
{ key = "c", mods = "CTRL|SHIFT", action = act.CopyTo("Clipboard") },
|
||||
{ key = "v", mods = "CTRL|SHIFT", action = act.PasteFrom("Clipboard") },
|
||||
|
|
@ -509,86 +234,77 @@ in {
|
|||
|
||||
-- ── NORMAL ─────────────────────────────────────────────────────────────
|
||||
normal = {
|
||||
{ key = "t", action = ${andPop "act.SpawnTab(\"CurrentPaneDomain\")"} },
|
||||
{ key = "x", action = ${andPop "act.CloseCurrentTab({ confirm = true })"} },
|
||||
{ key = "p", action = act.ActivateKeyTable({ name = "pane", one_shot = false }) },
|
||||
{ key = "t", action = act.ActivateKeyTable({ name = "tab", one_shot = false }) },
|
||||
{ key = "r", action = act.ActivateKeyTable({ name = "resize", one_shot = false }) },
|
||||
{ key = "c", action = ${andPop "act.ActivateCopyMode"} },
|
||||
{ key = "s", action = ${andPop "act.Search({ CaseSensitiveString = \"\" })"} },
|
||||
{ key = "s", action = act.ActivateKeyTable({ name = "scroll", one_shot = false }) },
|
||||
{ key = "n", action = ${andPop "act.SplitHorizontal({ domain = \"CurrentPaneDomain\" })"} },
|
||||
${exitKeys {selfKey = "Escape";}} },
|
||||
|
||||
-- ── PANE ───────────────────────────────────────────────────────────────
|
||||
pane = {
|
||||
${viDirKeys {
|
||||
mkAction = d:
|
||||
if d == "Left" || d == "Right"
|
||||
then "move_focus_or_tab(\"${d}\")"
|
||||
else "act.ActivatePaneDirection(\"${d}\")";
|
||||
}}
|
||||
{ key = "n", action = ${andPop "act.SplitHorizontal({ domain = \"CurrentPaneDomain\" })"} },
|
||||
{ key = "r", action = ${andPop "act.SplitHorizontal({ domain = \"CurrentPaneDomain\" })"} },
|
||||
{ key = "d", action = ${andPop "act.SplitVertical({ domain = \"CurrentPaneDomain\" })"} },
|
||||
{ key = "f", action = ${andPop "act.TogglePaneZoomState"} },
|
||||
{ key = "z", action = ${andPop "act.TogglePaneZoomState"} },
|
||||
{ key = "x", action = ${andPop "act.CloseCurrentPane({ confirm = true })"} },
|
||||
{ key = "Tab", action = act.ActivatePaneDirection("Next") },
|
||||
${exitKeys {selfKey = "p";}} },
|
||||
|
||||
-- ── TAB ────────────────────────────────────────────────────────────────
|
||||
tab = {
|
||||
{ key = "h", action = act.ActivateTabRelative(-1) },
|
||||
{ key = "k", action = act.ActivateTabRelative(-1) },
|
||||
{ key = "j", action = act.ActivateTabRelative(1) },
|
||||
{ key = "l", action = act.ActivateTabRelative(1) },
|
||||
{ key = "LeftArrow", action = act.ActivateTabRelative(-1) },
|
||||
{ key = "UpArrow", action = act.ActivateTabRelative(-1) },
|
||||
{ key = "RightArrow", action = act.ActivateTabRelative(1) },
|
||||
{ key = "DownArrow", action = act.ActivateTabRelative(1) },
|
||||
{ key = "Tab", action = act.ActivateTabRelative(1) },
|
||||
${tabJumpKeys {}}
|
||||
{ key = "n", action = ${andPop "act.SpawnTab(\"CurrentPaneDomain\")"} },
|
||||
{ key = "x", action = ${andPop "act.CloseCurrentTab({ confirm = true })"} },
|
||||
{ key = "r", action = act.PromptInputLine({
|
||||
description = "Rename tab",
|
||||
action = wezterm.action_callback(function(window, _, line)
|
||||
if line then window:active_tab():set_title(line) end
|
||||
window:perform_action(act.PopKeyTable, window:active_pane())
|
||||
end),
|
||||
})
|
||||
},
|
||||
${exitKeys {selfKey = "t";}} },
|
||||
|
||||
-- ── RESIZE ─────────────────────────────────────────────────────────────
|
||||
resize = {
|
||||
${resizeDirKeys {step = 5;}}${resizeShiftKeys {step = 1;}}
|
||||
${resizeDirKeys {step = 5;}}${resizeShiftKeys {step = 1;}}
|
||||
{ key = "+", action = act.AdjustPaneSize({ "Right", 5 }) },
|
||||
{ key = "-", action = act.AdjustPaneSize({ "Left", 5 }) },
|
||||
{ key = "=", action = act.AdjustPaneSize({ "Right", 5 }) },
|
||||
${exitKeys {selfKey = "r";}} },
|
||||
|
||||
-- ── COPY MODE ──────────────────────────────────────────────────────────
|
||||
copy_mode = {
|
||||
-- movement
|
||||
{ key = "h", action = act.CopyMode("MoveLeft") },
|
||||
{ key = "j", action = act.CopyMode("MoveDown") },
|
||||
{ key = "k", action = act.CopyMode("MoveUp") },
|
||||
{ key = "l", action = act.CopyMode("MoveRight") },
|
||||
{ key = "LeftArrow", action = act.CopyMode("MoveLeft") },
|
||||
{ key = "DownArrow", action = act.CopyMode("MoveDown") },
|
||||
{ key = "UpArrow", action = act.CopyMode("MoveUp") },
|
||||
{ key = "RightArrow", action = act.CopyMode("MoveRight") },
|
||||
{ key = "w", action = act.CopyMode("MoveForwardWord") },
|
||||
{ key = "b", action = act.CopyMode("MoveBackwardWord") },
|
||||
{ key = "e", action = act.CopyMode("MoveForwardWordEnd") },
|
||||
{ key = "0", action = act.CopyMode("MoveToStartOfLine") },
|
||||
{ key = "^", action = act.CopyMode("MoveToStartOfLineContent") },
|
||||
{ key = "$", action = act.CopyMode("MoveToEndOfLineContent") },
|
||||
{ key = "g", action = act.CopyMode("MoveToScrollbackTop") },
|
||||
{ key = "G", action = act.CopyMode("MoveToScrollbackBottom") },
|
||||
{ key = "Enter", action = act.CopyMode("MoveToStartOfNextLine") },
|
||||
{ key = "u", mods = "CTRL", action = act.CopyMode({ MoveByPage = -0.5 }) },
|
||||
{ key = "d", mods = "CTRL", action = act.CopyMode({ MoveByPage = 0.5 }) },
|
||||
{ key = "b", mods = "CTRL", action = act.CopyMode("PageUp") },
|
||||
{ key = "f", mods = "CTRL", action = act.CopyMode("PageDown") },
|
||||
{ key = "PageUp", action = act.CopyMode("PageUp") },
|
||||
{ key = "PageDown", action = act.CopyMode("PageDown") },
|
||||
-- selection
|
||||
{ key = "v", action = act.CopyMode({ SetSelectionMode = "Cell" }) },
|
||||
{ key = "V", action = act.CopyMode({ SetSelectionMode = "Line" }) },
|
||||
{ key = "v", mods = "CTRL", action = act.CopyMode({ SetSelectionMode = "Block" }) },
|
||||
{ key = "o", action = act.CopyMode("MoveToSelectionOtherEnd") },
|
||||
{ key = "O", action = act.CopyMode("MoveToSelectionOtherEndHoriz") },
|
||||
-- yank and exit
|
||||
{ key = "y", action = act.Multiple({
|
||||
act.CopyTo("ClipboardAndPrimarySelection"),
|
||||
act.Multiple({ act.ScrollToBottom, act.CopyMode("Close") }),
|
||||
})
|
||||
},
|
||||
-- search within copy mode
|
||||
{ key = "/", action = act.Search({ CaseSensitiveString = "" }) },
|
||||
{ key = "n", action = act.CopyMode("NextMatch") },
|
||||
{ key = "p", action = act.CopyMode("PriorMatch") },
|
||||
-- exit
|
||||
{ key = "q", action = act.Multiple({ act.ScrollToBottom, act.CopyMode("Close") }) },
|
||||
{ key = "Escape", action = act.Multiple({ act.ScrollToBottom, act.CopyMode("Close") }) },
|
||||
{ key = "c", mods = "CTRL", action = act.Multiple({ act.ScrollToBottom, act.CopyMode("Close") }) },
|
||||
},
|
||||
|
||||
-- ── SEARCH MODE ────────────────────────────────────────────────────────
|
||||
search_mode = {
|
||||
-- navigate matches
|
||||
{ key = "Enter", action = act.CopyMode("AcceptPattern") },
|
||||
{ key = "n", mods = "CTRL", action = act.CopyMode("NextMatch") },
|
||||
{ key = "p", mods = "CTRL", action = act.CopyMode("PriorMatch") },
|
||||
{ key = "PageUp", action = act.CopyMode("PriorMatchPage") },
|
||||
{ key = "PageDown", action = act.CopyMode("NextMatchPage") },
|
||||
{ key = "UpArrow", action = act.CopyMode("PriorMatch") },
|
||||
{ key = "DownArrow", action = act.CopyMode("NextMatch") },
|
||||
-- cycle match type (case-sensitive / insensitive / regex)
|
||||
{ key = "r", mods = "CTRL", action = act.CopyMode("CycleMatchType") },
|
||||
-- clear search input
|
||||
{ key = "u", mods = "CTRL", action = act.CopyMode("ClearPattern") },
|
||||
-- Escape: dismiss search bar, return to copy mode at current match
|
||||
{ key = "Escape", action = act.CopyMode("AcceptPattern") },
|
||||
},
|
||||
-- ── SCROLL ─────────────────────────────────────────────────────────────
|
||||
scroll = {
|
||||
{ key = "j", action = act.ScrollByLine(1) },
|
||||
{ key = "k", action = act.ScrollByLine(-1) },
|
||||
{ key = "d", action = act.ScrollByPage(0.5) },
|
||||
{ key = "u", action = act.ScrollByPage(-0.5) },
|
||||
{ key = "h", action = act.ScrollByPage(-1) },
|
||||
{ key = "l", action = act.ScrollByPage(1) },
|
||||
{ key = "DownArrow", action = act.ScrollByLine(1) },
|
||||
{ key = "UpArrow", action = act.ScrollByLine(-1) },
|
||||
{ key = "PageDown", action = act.ScrollByPage(1) },
|
||||
{ key = "PageUp", action = act.ScrollByPage(-1) },
|
||||
{ key = "f", action = act.Search({ CaseSensitiveString = "" }) },
|
||||
{ key = "c", mods = "CTRL", action = act.ScrollToBottom },
|
||||
${exitKeys {selfKey = "s";}} },
|
||||
}
|
||||
|
||||
return config
|
||||
|
|
|
|||
|
|
@ -1,8 +1,4 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
{ pkgs, lib, ... }: {
|
||||
imports = [
|
||||
./containers
|
||||
./gaming
|
||||
|
|
@ -29,6 +25,5 @@
|
|||
./lemmy.nix
|
||||
./audio.nix
|
||||
./atuin.nix
|
||||
./murmur.nix
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}: let
|
||||
cfg = config.mods.server.murmur;
|
||||
in
|
||||
with lib; {
|
||||
options.mods.server = {
|
||||
murmur = {
|
||||
enable = mkEnableOption {
|
||||
default = false;
|
||||
description = "enables murmur server";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.murmur = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
42
utils.nix
42
utils.nix
|
|
@ -1,7 +1,4 @@
|
|||
{ inputs, system, sources, ... }:
|
||||
let
|
||||
pkgs = import inputs.nixpkgs { inherit system; };
|
||||
in {
|
||||
{ inputs, system, sources, ... }: {
|
||||
mkHost = host:
|
||||
inputs.nixpkgs.lib.nixosSystem {
|
||||
specialArgs = { inherit inputs system sources; };
|
||||
|
|
@ -14,41 +11,4 @@ in {
|
|||
inputs.impermanence.nixosModules.impermanence
|
||||
];
|
||||
};
|
||||
|
||||
# Build a standalone HM configuration for a given host NixOS config and
|
||||
# home.nix file. osConfig is injected as a specialArg so all modules that
|
||||
# reference it continue to work.
|
||||
mkHome = { hostConfig, homeFile, username ? "muon" }:
|
||||
inputs.home-manager.lib.homeManagerConfiguration {
|
||||
inherit pkgs;
|
||||
extraSpecialArgs = {
|
||||
inherit inputs system sources;
|
||||
osConfig = hostConfig.config;
|
||||
};
|
||||
modules = [
|
||||
homeFile
|
||||
inputs.self.outputs.homeManagerModules.default
|
||||
inputs.stylix.homeManagerModules.stylix
|
||||
({ osConfig, ... }: {
|
||||
home.username = username;
|
||||
home.homeDirectory = "/home/${username}";
|
||||
# Mirror the stylix settings from the NixOS config so the standalone
|
||||
# HM build has the same theme without re-declaring it.
|
||||
stylix = {
|
||||
enable = osConfig.stylix.enable;
|
||||
autoEnable = osConfig.stylix.autoEnable;
|
||||
base16Scheme = osConfig.stylix.base16Scheme;
|
||||
image = osConfig.stylix.image;
|
||||
cursor = osConfig.stylix.cursor;
|
||||
# Forward individual font options; stylix derives fonts.packages
|
||||
# internally as read-only so we must not forward that attr.
|
||||
fonts.monospace = osConfig.stylix.fonts.monospace;
|
||||
fonts.sansSerif = osConfig.stylix.fonts.sansSerif;
|
||||
fonts.serif = osConfig.stylix.fonts.serif;
|
||||
fonts.emoji = osConfig.stylix.fonts.emoji;
|
||||
fonts.sizes = osConfig.stylix.fonts.sizes;
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue