refactor!: switch to dendritic pattern

BREAKING CHANGE: complete reorganization of the repository
This commit is contained in:
2026-09-30 18:36:06 +02:00
parent 12684b4e9c
commit 5f4a7a4a42
323 changed files with 7117 additions and 7380 deletions
+60
View File
@@ -0,0 +1,60 @@
{
flake.modules.homeManager.bash = {
config,
lib,
...
}:
with lib; let
cfg = config.home.shell.bash;
in {
options.home.shell.bash = {
enable = mkEnableOption "Enables bash";
aliases = mkOption {
type = types.attrsOf types.str;
default = {};
example = {
cp = "cp -i";
lns = "ln -si";
};
};
autocompletion = mkOption {
type = types.bool;
default = config.home.shell.autocompletion;
example = true;
};
eatIntegration = mkEnableOption "Enable Emacs Eat integration";
bashrcExtra = mkOption {
type = types.lines;
default = "";
};
};
config = mkIf cfg.enable {
programs.bash = {
enable = true;
# inherit (cfg) bashrcExtra;
bashrcExtra =
concatLines
[
(strings.optionalString cfg.eatIntegration ''[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && source "$EAT_SHELL_INTEGRATION_DIR/bash"'')
(strings.optionalString config.home.dev.vcs.jj.shellCompletion "source <(jj util completion bash)")
cfg.bashrcExtra
];
enableCompletion = cfg.autocompletion;
shellAliases = cfg.aliases;
shellOptions = [
"histappend"
"cmdhist"
"lithist"
"checkwinsize"
"extglob"
"globstar"
"checkjobs"
"autocd"
"cdspell"
"dirspell"
];
};
};
};
}
+92
View File
@@ -0,0 +1,92 @@
{
flake.modules.homeManager.fish = {
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.home.shell.fish;
in {
options.home.shell.fish = {
enable = lib.mkEnableOption "enables fish";
abbrs = lib.mkOption {
type = types.attrsOf types.str;
default = {};
example = {
cp = "cp -i";
lns = "ln -si";
};
};
autocompletion = mkOption {
type = types.bool;
default = config.home.shell.autocompletion;
example = true;
};
extraShellInit = mkOption {
type = types.lines;
default = "";
};
};
config = lib.mkIf cfg.enable {
programs.fish = {
enable = true;
generateCompletions = cfg.autocompletion;
shellAbbrs = cfg.abbrs;
preferAbbrs = true;
shellInit = with lib;
concatLines [
''
function fish_command_not_found
__fish_default_command_not_found_handler $argv
end
''
(strings.optionalString config.home.dev.vcs.jj.shellCompletion "jj util completion fish | source")
cfg.extraShellInit
];
plugins = [
{
name = "bass";
inherit (pkgs.fishPlugins.bass) src;
# src = pkgs.fishPlugins.bass.src;
}
{
name = "colored-man-pages";
inherit (pkgs.fishPlugins.colored-man-pages) src;
}
{
name = "done";
inherit (pkgs.fishPlugins.done) src;
}
{
name = "fzf";
inherit (pkgs.fishPlugins.fzf) src;
}
{
name = "pisces";
inherit (pkgs.fishPlugins.pisces) src;
}
{
name = "getopts.fish";
src = pkgs.fetchFromGitHub {
owner = "jorgebucaran";
repo = "getopts.fish";
rev = "4b74206725c3e11d739675dc2bb84c77d893e901";
sha256 = "9hRFBmjrCgIUNHuOJZvOufyLsfreJfkeS6XDcCPesvw=";
};
}
{
name = "replay.fish";
src = pkgs.fetchFromGitHub {
owner = "jorgebucaran";
repo = "replay.fish";
rev = "d2ecacd3fe7126e822ce8918389f3ad93b14c86c";
sha256 = "TzQ97h9tBRUg+A7DSKeTBWLQuThicbu19DHMwkmUXdg=";
};
}
];
};
};
};
}
+116
View File
@@ -0,0 +1,116 @@
{config, ...}: let
m = config.flake.modules.homeManager;
in {
flake.modules.homeManager.shell = {
config,
lib,
...
}:
with lib; let
defaultAliases = {
df = "df -H";
diskspace = "sudo df -h | grep -E \"sd|lv|Size\"";
du = "du -ch";
meminfo = "free -m -l -t";
gpumeminfo = "grep -i --color memory /var/log/Xorg.0.log";
cpuinfo = "lscpu";
pscpu = "ps auxf | sort -nr -k 3";
pscpu10 = "ps auxf | sort -nr -k 3 | head -10";
psmem = "ps auxf | sort -nr -k 4";
psmem10 = "ps auxf | sort -nr -k 4 | head -10";
s = "systemctl";
ss = "systemctl status";
sst = "systemctl stop";
sr = "systemctl restart";
sre = "systemctl reload";
se = "systemctl enable";
sen = "systemctl enable --now";
su = "systemctl --user";
sus = "systemctl --user status";
sust = "systemctl --user stop";
sur = "systemctl --user restart";
sure = "systemctl --user reload";
sue = "systemctl --user enable";
suen = "systemctl --user enable --now";
dc = "docker compose";
dcd = "docker compose down";
dcl = "docker compose logs";
dclf = "docker compose logs -f";
dcp = "docker compose pull";
dcu = "docker compose up";
dcud = "docker compose up -d";
dcudp = "docker compose up -d --pull=always";
dcr = "docker compose restart";
pc = "podman compose";
pcd = "podman compose down";
pcl = "podman compose logs";
pclf = "podman compose logs -f";
pcp = "podman compose pull";
pcu = "podman compose up";
pcud = "podman compose up -d";
pcudp = "podman compose up -d --pull=always";
pcr = "podman compose restart";
enw = "emacsclient -nw";
e = "emacsclient -n -c";
cp = "cp -i";
rsync = "rsync -Pa --progress";
ln = "ln -i";
lns = "ln -si";
mv = "mv -i";
rm = "rm -Iv";
rmd = "rm --preserve-root -Irv";
rmdf = "rm --preserve-root -Irfv";
rmf = "rm --preserve-root -Ifv";
chgrp = "chgrp --preserve-root -v";
chmod = "chmod --preserve-root -v";
chown = "chown --preserve-root -v";
lsl = "eza -halg@ --group-directories-first --git";
flac = "yt-dlp -x --audio-format flac --audio-quality 0 o \"~/Music/%(uploader)s/%(title)s.%(ext)s\"";
please = "sudo -A";
wget = "wget --hsts-file=\"$XDG_DATA_HOME/wget-hsts\" -c";
};
cfg = config.home.shell;
in {
imports = [
m.bash
m.fish
m.starship
m.tmux
m.zellij
m.zsh
m.zoxide
];
options.home.shell = {
fullDesktop = mkEnableOption "Enable all shells";
aliases = mkOption {
type = types.attrsOf types.str;
default = {};
example = {la = "ls -a";};
};
autocompletion = mkOption {
type = types.bool;
default = true;
};
};
config.home.shell = {
enableShellIntegration = cfg.bash.enable or cfg.zsh.enable or cfg.fish.enable;
bash = {
aliases = defaultAliases // cfg.aliases;
enable = mkDefault cfg.fullDesktop;
};
fish = {
abbrs = defaultAliases // cfg.aliases;
enable = mkDefault cfg.fullDesktop;
};
zsh = {
abbrs = defaultAliases // cfg.aliases;
enable = mkDefault cfg.fullDesktop;
};
};
};
}
+79
View File
@@ -0,0 +1,79 @@
{
flake.modules.homeManager.starship = {
config,
lib,
...
}:
with lib; let
cfg = config.home.shell.starship;
in {
options.home.shell.starship = {
enable = mkEnableOption "Enables the starship prompt.";
jjIntegration = mkOption {
description = "Enable Jujutsu integration in starship";
default = config.programs.jujutsu.enable;
type = types.bool;
};
};
config.programs.starship = mkIf cfg.enable {
inherit (cfg) enable;
enableTransience = true;
settings = mkIf cfg.jjIntegration {
# Disabling these so they can be enabled conditionally
# See https://github.com/jj-vcs/jj/wiki/Starship
git_status.disabled = true;
git_commit.disabled = true;
git_metrics.disabled = true;
git_branch.disabled = true;
custom = let
when = "! jj --ignore-working-copy-root";
description = "Only show if we’re not in a jj repository";
style = "";
in {
git_status = {
inherit when description style;
command = "starship module git_status";
};
git_commit = {
inherit when description style;
command = "starship module git_commit";
};
git_metrics = {
inherit when description style;
command = "starship module git_metrics";
};
git_branch = {
inherit when description style;
command = "starship module git_branch";
};
jj = {
description = "The current jj status";
detect_folders = [".jj"];
symbol = "🥋 ";
command = ''
jj log --revisions @ --no-graph --ignore-working-copy --color always --limit 1 --template '
separate(" ",
change_id.shortest(4),
bookmarks,
"|",
concat(
if(conflict, "💥"),
if(divergent, "🚧"),
if(hidden, "👻"),
if(immutable, "🔒"),
),
raw_escape_sequence("\x1b[1;32m") ++ if(empty, "(empty)"),
raw_escape_sequence("\x1b[1;32m") ++ coalesce(
truncate_end(29, description.first_line(), "…"),
"(no description set)",
) ++ raw_escape_sequence("\x1b[0m"),
)
'
'';
};
};
};
};
};
}
+83
View File
@@ -0,0 +1,83 @@
{
flake.modules.homeManager.tmux = {
pkgs,
lib,
config,
...
}:
with lib; let
cfg = config.home.shell.tmux;
keyType = types.submodule {
options = {
key = mkOption {
type = types.str;
example = "C-b";
};
action = mkOption {
type = types.str;
example = "resize-pane -Z";
};
};
};
in {
options.home.shell.tmux = with types; {
enable = mkEnableOption "Enable tmux";
bind = mkOption {
type = attrsOf (listOf keyType);
default = {};
example = {
"prefix" = [
{
key = "C-r";
action = "resize-pane -R";
}
];
};
};
unbind = mkOption {
type = listOf (either str (attrsOf (listOf str)));
default = [];
};
extraConfig = mkOption {
type = types.lines;
default = "";
};
};
config.programs.tmux = mkIf cfg.enable {
inherit (cfg) enable;
baseIndex = 1;
clock24 = true;
customPaneNavigationAndResize = true;
keyMode = "vi";
mouse = true;
newSession = true;
prefix = "M-space";
plugins = with pkgs.tmuxPlugins; [
cpu
nord
prefix-highlight
resurrect
sensible
yank
];
extraConfig = let
generateBinds = concatLines (
mapAttrsToList (table: keys: concatMapStrings (key: "bind -T ${table} ${key.key} ${key.action}\n") keys) cfg.bind
);
generateUnbind =
concatMapStrings (
entry:
if builtins.isString entry
then "unbind ${entry}\n"
else concatStrings (mapAttrsToList (table: keys: concatMapStrings (key: "unbind -T ${table} ${key}\n") keys) entry)
)
cfg.unbind;
in ''
${cfg.extraConfig}
${generateUnbind}
${generateBinds}
'';
};
};
}
+175
View File
@@ -0,0 +1,175 @@
{
flake.modules.homeManager.zellij = {
pkgs,
lib,
config,
...
}:
with lib; let
cfg = config.home.shell.zellij;
isEmpty = list: list == [];
keybind = {
options = {
bind = mkOption {
type = types.either types.str (types.listOf types.str);
example = "Alt j";
description = "Value used as a string after `bind` in zellij config";
};
actions = mkOption {
type = with types; let
allowed = oneOf [int str];
in
attrsOf (either (listOf allowed) allowed);
default = {};
example = {
SwitchToMode = ["normal"];
SwitchFocus = [];
PaneNameInput = [0];
};
};
useUnlockFirst = mkOption {
type = types.bool;
default = false;
description = ''
Go back to locked mode after the actions are done.
Only works when `config.home.shell.zellij.useUnlockFirst` is true.
'';
};
};
};
convertBind = item: {
bind = let
useUnlockFirst = cfg.useUnlockFirst && item.useUnlockFirst;
children =
mapAttrsToList (action: args: let
actualArgs =
if isEmpty args
then {}
else {_args = lists.toList args;};
in {"${action}" = actualArgs;})
(item.actions
// (
if useUnlockFirst
then {SwitchToMode = ["locked"];}
else {}
));
in {
_args = lists.toList item.bind;
_children = children;
};
};
keybindsModule = {
options = mergeAttrsList (forEach [
"normal"
"locked"
"resize"
"pane"
"move"
"tab"
"scroll"
"search"
"entersearch"
"renametab"
"renamepane"
"session"
"tmux"
]
(x: {
"${x}" = mkOption {
type = types.listOf (types.submodule keybind);
default = [];
};
}));
};
makeKeybinds = keybinds: let
values =
attrsets.concatMapAttrs (
mode: binds:
if (isEmpty binds)
then {}
else {
"${mode}"._children = lists.forEach binds convertBind;
}
)
keybinds;
in
if values == {}
then {}
else {
keybinds = values;
};
in {
options.home.shell.zellij = let
jsonFormat = pkgs.formats.yaml {};
in {
enable = mkEnableOption "Enable Zellij";
clearDefaultKeybinds = mkEnableOption "Clear default keybinds";
settings = mkOption {
inherit (jsonFormat) type;
default = {};
};
layouts = mkOption {
inherit (jsonFormat) type;
default = {};
};
extraSettings = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration lines to add to `$XDG_CONFIG_HOME/zellij/config.kdl`
'';
};
useUnlockFirst = mkEnableOption "Use Unlock-First (non-colliding) behaviour by default";
plugins = mkOption {
type = types.listOf (types.submodule plugin);
default = {};
example = [
{name = "about";}
{
name = "filepicker";
location = "zellij:strider";
options = {
cwd = "/";
};
}
];
};
keybinds = mkOption {
type = types.submodule keybindsModule;
default = {};
example = {
pane = [
{
bind = "c";
actions = [
{
action = "SwitchToMode";
args = ["renamepane"];
}
{
action = "PaneNameInput";
args = [0];
}
];
}
];
};
};
};
config.programs.zellij = mkIf cfg.enable {
inherit (cfg) enable layouts;
extraConfig = cfg.extraSettings;
settings = let
resetKeybinds =
if cfg.clearDefaultKeybinds
then {
keybinds._props.clear-defaults = true;
}
else {};
keybinds = makeKeybinds cfg.keybinds;
in
cfg.settings // (lib.recursiveUpdate resetKeybinds keybinds);
};
};
}
+21
View File
@@ -0,0 +1,21 @@
{
flake.modules.homeManager.zoxide = {
lib,
config,
...
}:
with lib; let
cfg = config.home.shell.zoxide;
in {
options.home.shell.zoxide = {
enable = mkEnableOption "Enable zoxide";
replaceCd = mkEnableOption "Replace cd with zoxide";
};
config.programs.zoxide = mkIf cfg.enable {
inherit (cfg) enable;
options = mkIf cfg.replaceCd [
"--cmd cd"
];
};
};
}
+108
View File
@@ -0,0 +1,108 @@
{
flake.modules.homeManager.zsh = {
config,
lib,
pkgs,
...
}:
with lib; let
cfg = config.home.shell.zsh;
in {
options.home.shell.zsh = {
enable = lib.mkEnableOption "Enables zsh";
abbrs = lib.mkOption {
type = types.attrsOf types.str;
default = {};
example = {
cp = "cp -i";
lns = "ln -si";
};
};
autocompletion = mkOption {
type = types.bool;
default = config.home.shell.autocompletion;
example = true;
};
eatIntegration = mkEnableOption "Enable Emacs Eat integration";
zshrcExtra = lib.mkOption {
type = types.lines;
default = "";
};
};
config = lib.mkIf cfg.enable {
programs.zsh = {
enable = true;
autocd = true;
autosuggestion = {
enable = true;
strategy = ["match_prev_cmd" "completion"];
};
enableCompletion = cfg.autocompletion;
enableVteIntegration = true;
history = {
findNoDups = true;
ignoreAllDups = true;
ignoreDups = true;
ignoreSpace = true;
path = "${config.xdg.dataHome}/zsh/zsh_history";
saveNoDups = true;
};
historySubstringSearch.enable = true;
initContent = with lib;
concatLines [
''
bindkey -e
bindkey '^p' history-search-backward
bindkey '^n' history-search-forward
# Completion styling
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Za-z}'
zstyle ':completion:*' list-colors "''${(s.:.)LS_COLORS}"
zstyle ':completion:*' menu no
zstyle ':fzf-tab:complete:cd:*' fzf-preview '${pkgs.eza}/bin/eza $realpath'
''
(strings.optionalString cfg.eatIntegration ''[ -n "$EAT_SHELL_INTEGRATION_DIR" ] && source "$EAT_SHELL_INTEGRATION_DIR/zsh"'')
(strings.optionalString config.home.dev.vcs.jj.shellCompletion ''
autoload -U compinit
compinit
source <(jj util completion zsh)
'')
cfg.zshrcExtra
];
oh-my-zsh = {
enable = true;
plugins = [
"dirhistory"
"sudo"
];
};
plugins = [
{
name = "fzf-tab";
src = pkgs.fetchFromGitHub {
owner = "Aloxaf";
repo = "fzf-tab";
rev = "v1.2.0";
sha256 = "sha256-q26XVS/LcyZPRqDNwKKA9exgBByE0muyuNb0Bbar2lY=";
};
}
{
name = "zsh-autopair";
src = pkgs.fetchFromGitHub {
owner = "hlissner";
repo = "zsh-autopair";
rev = "449a7c3d095bc8f3d78cf37b9549f8bb4c383f3d";
sha256 = "sha256-3zvOgIi+q7+sTXrT+r/4v98qjeiEL4Wh64rxBYnwJvQ=";
};
}
];
syntaxHighlighting.enable = true;
zsh-abbr = {
enable = true;
abbreviations = cfg.abbrs;
};
};
};
};
}