refactor(modules): organize module tree

This commit was merged in pull request #72.
This commit is contained in:
2026-08-28 08:40:15 -04:00
parent f767b613a0
commit abac67afb4
41 changed files with 133 additions and 140 deletions

View File

@@ -0,0 +1,23 @@
# vi-style modal editing on the command line.
set -g fish_key_bindings fish_vi_key_bindings
set -gx EDITOR nvim
set -gx VISUAL nvim
# Render man pages through bat.
set -x MANROFFOPT "-c"
set -x MANPAGER "sh -c 'col -bx | bat -l man -p'"
# Tune the done plugin: only notify for commands past 10s, at low urgency.
set -g __done_min_cmd_duration 10000
set -g __done_notification_urgency_level low
# Prepend ~/.local/bin to PATH when it exists.
if test -d ~/.local/bin
fish_add_path ~/.local/bin
end
# Apply fish-compatible profile overrides if present.
if test -f ~/.fish_profile
source ~/.fish_profile
end

106
modules/shell/fish/fish.nix Normal file
View File

@@ -0,0 +1,106 @@
{
config,
lib,
pkgs,
...
}:
# fish for the primary user, configured through home-manager.
let
cfg = config.modules.shell.fish;
user = config.user.name;
shortcuts = config.registry.shell-shortcut.${config.networking.hostName};
commandsOf = shortcuts: lib.mapAttrs (_name: shortcut: shortcut.command) shortcuts;
in
{
options.modules.shell.fish = {
enable = lib.mkEnableOption "fish as the user's shell, configured via home-manager";
defaultShell = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Set fish as the user's default login shell.";
};
};
config = lib.mkIf cfg.enable {
# System-level fish registers it in /etc/shells and installs vendor completions.
programs.fish.enable = true;
users.users.${user}.shell = lib.mkIf cfg.defaultShell pkgs.fish;
home-manager.users.${user} = {
home.packages = with pkgs; [
bat # backs the manpager
fastfetch # the shell greeting
];
programs.fish = {
enable = true;
preferAbbrs = true;
plugins = [
# Notify when a long command finishes.
{
name = "done";
src = pkgs.fishPlugins.done.src;
}
# Restore the !! and !$ history bindings.
{
name = "bang-bang";
src = pkgs.fishPlugins.bang-bang.src;
}
];
shellAliases = commandsOf (lib.filterAttrs (_name: shortcut: !shortcut.abbreviation) shortcuts);
shellAbbrs = commandsOf (lib.filterAttrs (_name: shortcut: shortcut.abbreviation) shortcuts);
functions = {
# Pick the logo that fits the terminal so the greeting never wraps.
# The full logo needs about 118 columns beside the info block, the
# compact one about 89, the info block alone about 71.
fish_greeting = ''
if test "$COLUMNS" -ge 118
fastfetch
else if test "$COLUMNS" -ge 89
fastfetch --logo NixOS_small
else
fastfetch --logo none
end
'';
# vi insert mode omits the emacs ctrl-f and ctrl-r bindings, so restore both.
# ctrl-f accepts an autosuggestion and ctrl-r opens the history pager.
# vi normal mode keeps its ctrl-r redo, since only insert mode is bound.
fish_user_key_bindings = ''
bind -M insert ctrl-f forward-char
bind -M insert ctrl-r history-pager
'';
history = {
description = "Show command history with timestamps";
body = "builtin history --show-time='%F %T '";
};
backup = {
description = "Copy <file> to <file>.bak";
argumentNames = "filename";
body = "cp $filename $filename.bak";
};
copy = {
description = "Copy a file, or recursively copy a source directory into a destination";
body = builtins.readFile ./functions/copy.fish;
};
deploy-to = {
description = "Deploy the current dotfiles branch to a host through target-local nixos-rebuild";
body = builtins.readFile ./functions/deploy-to.fish;
};
};
# Rendered by home-manager into ~/.config/fish/config.fish.
interactiveShellInit = builtins.readFile ./config.fish;
};
};
};
}

View File

@@ -0,0 +1,8 @@
set count (count $argv | tr -d \n)
if test "$count" = 2; and test -d "$argv[1]"
set from (echo $argv[1] | trim-right /)
set to (echo $argv[2])
command cp -r $from $to
else
command cp $argv
end

View File

@@ -0,0 +1,53 @@
if test (count $argv) -lt 1; or test (count $argv) -gt 2
echo "usage: deploy-to <host> [branch]" >&2
return 2
end
set host $argv[1]
set branch $argv[2]
if test -z "$branch"
set branch (git branch --show-current)
end
if test -z "$branch"
echo "deploy-to: could not determine the current branch" >&2
return 2
end
git rev-parse --show-toplevel >/dev/null 2>&1
or begin
echo "deploy-to: run this from a git checkout" >&2
return 2
end
set dirty_lines (git status --porcelain)
if test (count $dirty_lines) -gt 0
echo "deploy-to: refusing to deploy with a dirty local worktree" >&2
return 1
end
git fetch origin
or return $status
set remote_ref refs/remotes/origin/$branch
git rev-parse --verify --quiet $remote_ref >/dev/null
or begin
echo "deploy-to: origin/$branch does not exist" >&2
return 1
end
set local_head (git rev-parse HEAD)
set remote_head (git rev-parse $remote_ref)
if test "$local_head" != "$remote_head"
echo "deploy-to: local HEAD differs from origin/$branch" >&2
echo "deploy-to: push or reset the branch before deploying" >&2
return 1
end
set escaped_branch (string escape -- $branch)
set escaped_host (string escape -- $host)
set remote_command "cd ~/wrk/dotfiles && git fetch origin && git switch -- $escaped_branch && git reset --hard origin/$escaped_branch && sudo nixos-rebuild switch --flake .#$escaped_host --print-build-logs"
ssh -t $host $remote_command