From 1010e8150f5f8cda1d9a007043bef414f51f1e33 Mon Sep 17 00:00:00 2001 From: Nickolaj Jepsen Date: Sun, 11 Jan 2026 23:00:26 +0100 Subject: [PATCH] wip: zsh --- modules/programs/default.nix | 1 + modules/programs/zsh/abbrs.nix | 104 ++++++++++++++++++++++++++ modules/programs/zsh/autocomplete.zsh | 22 ++++++ modules/programs/zsh/default.nix | 99 ++++++++++++++++++++++++ modules/programs/zsh/k8s.zsh | 49 ++++++++++++ modules/programs/zsh/starship.toml | 70 +++++++++++++++++ modules/programs/zsh/theme.zsh | 31 ++++++++ 7 files changed, 376 insertions(+) create mode 100644 modules/programs/zsh/abbrs.nix create mode 100644 modules/programs/zsh/autocomplete.zsh create mode 100644 modules/programs/zsh/default.nix create mode 100644 modules/programs/zsh/k8s.zsh create mode 100644 modules/programs/zsh/starship.toml create mode 100644 modules/programs/zsh/theme.zsh diff --git a/modules/programs/default.nix b/modules/programs/default.nix index b863bab..b41f8ca 100644 --- a/modules/programs/default.nix +++ b/modules/programs/default.nix @@ -6,6 +6,7 @@ imports = [ ./fish/default.nix + ./zsh/default.nix ./claude.nix ./comma.nix ./core.nix diff --git a/modules/programs/zsh/abbrs.nix b/modules/programs/zsh/abbrs.nix new file mode 100644 index 0000000..fa66772 --- /dev/null +++ b/modules/programs/zsh/abbrs.nix @@ -0,0 +1,104 @@ +{lib, ...}: let + kube_verbs = [ + { + s = "g"; + v = "get"; + } + { + s = "d"; + v = "describe"; + } + { + s = "rm"; + v = "delete"; + } + { + s = "e"; + v = "edit"; + } + ]; + kube_resources = [ + { + s = "p"; + r = "pods"; + } + { + s = "d"; + r = "deployments"; + } + { + s = "s"; + r = "services"; + } + { + s = "i"; + r = "ingresses"; + } + { + s = "c"; + r = "configmaps"; + } + { + s = "ds"; + r = "daemonsets"; + } + { + s = "ss"; + r = "statefulsets"; + } + { + s = "n"; + r = "namespace"; + } + { + s = "ns"; + r = "namespace"; + } + ]; + + # Generate dynamic k8s abbreviations + kube_abbrs = lib.listToAttrs ( + lib.concatMap (verb: + [ + { + name = "k${verb.s}"; + value = "kubectl ${verb.v}"; + } + ] + ++ (map (res: { + name = "k${verb.s}${res.s}"; + value = "kubectl ${verb.v} ${res.r}"; + }) + kube_resources)) + kube_verbs + ); + + static_kube_abbrs = { + k = "kubectl"; + kl = "kubectl logs -f"; + kgl = "kubectl logs -f"; + kaf = "kubectl apply -f"; + kr = "kubectl rollout"; + krs = "kubectl rollout status"; + krr = "kubectl rollout restart"; + kt = "kubectl top"; + ktp = "kubectl top pods"; + ktn = "kubectl top nodes"; + kpf = "kubectl port-forward"; + kfp = "kubectl port-forward"; + ksns = "kubectl config set-context --current --namespace"; + ksc = "kubectl config set-context"; + }; + + general_abbrs = { + # General + gs = "git status"; + gc = "git commit"; + gp = "git push"; + gl = "git pull"; + gco = "git checkout"; + gd = "git diff"; + ll = "ls -la"; + }; +in + general_abbrs // static_kube_abbrs // kube_abbrs diff --git a/modules/programs/zsh/autocomplete.zsh b/modules/programs/zsh/autocomplete.zsh new file mode 100644 index 0000000..cf464d6 --- /dev/null +++ b/modules/programs/zsh/autocomplete.zsh @@ -0,0 +1,22 @@ +# ds autocomplete (if installed) +if command -v ds &> /dev/null; then + eval "$(_DS_COMPLETE=zsh_source ds)" +fi + +# Additional tool completions + +# fzf integration for better history search (fish-like experience) +if command -v fzf &> /dev/null; then + # Use fzf for Ctrl+R history search + source <(fzf --zsh 2>/dev/null || true) +fi + +# direnv integration +if command -v direnv &> /dev/null; then + eval "$(direnv hook zsh)" +fi + +# zoxide integration (if installed, provides better cd) +if command -v zoxide &> /dev/null; then + eval "$(zoxide init zsh)" +fi diff --git a/modules/programs/zsh/default.nix b/modules/programs/zsh/default.nix new file mode 100644 index 0000000..40c177f --- /dev/null +++ b/modules/programs/zsh/default.nix @@ -0,0 +1,99 @@ +{ + config, + pkgs, + lib, + ... +}: let + inherit (config.fireproof) username; +in { + config = { + programs.zsh.enable = true; + # Keep fish as default shell for now (as requested) + # users.users.${username}.shell = pkgs.zsh; + + fireproof.home-manager.programs.zsh = { + enable = true; + enableCompletion = true; + autocd = true; + autosuggestion.enable = true; + syntaxHighlighting.enable = true; + zsh-abbr = { + enable = true; + abbreviations = import ./abbrs.nix {inherit lib;}; + }; + + # History settings (similar to fish behavior) + history = { + size = 10000; + save = 10000; + ignoreDups = true; + ignoreAllDups = true; + ignoreSpace = true; + share = true; + extended = true; + }; + + initContent = '' + # Source theme and configs + ${builtins.readFile ./theme.zsh} + ${builtins.readFile ./k8s.zsh} + ${builtins.readFile ./autocomplete.zsh} + + # nix-your-shell for proper nix shell integration + eval "$(${pkgs.nix-your-shell}/bin/nix-your-shell zsh)" + + # Completion settings (fish-like behavior) + setopt COMPLETE_IN_WORD # Complete from both ends of a word + setopt ALWAYS_TO_END # Move cursor to end after completion + setopt MENU_COMPLETE # Autoselect first completion entry + + # Enable colors in completion + zstyle ':completion:*' list-colors ''${(s.:.)LS_COLORS} + zstyle ':completion:*' menu select + zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # Case insensitive + + # Key bindings for history search (fish-like) + bindkey '^[[A' history-search-backward # Up arrow + bindkey '^[[B' history-search-forward # Down arrow + bindkey '^R' history-incremental-search-backward + ''; + + # Plugins + plugins = [ + { + name = "zsh-autopair"; + src = pkgs.fetchFromGitHub { + owner = "hlissner"; + repo = "zsh-autopair"; + rev = "396c38a7468458ba29011f2ad4112e4fd35f78e6"; + sha256 = "sha256-PXHxPxFeoYXYMOC29YQKDdMnqTO0toyA7eJTSCV6PGE="; + }; + } + ]; + + # Shell aliases (equivalent to fish abbreviations) + shellAliases = { + # General + ls = "ls --color=auto"; + ll = "ls -la"; + la = "ls -a"; + ".." = "cd .."; + "..." = "cd ../.."; + "~" = "cd ~"; + }; + }; + + # Starship prompt + fireproof.home-manager.programs.starship = { + enable = true; + enableZshIntegration = true; + enableFishIntegration = false; + settings = builtins.fromTOML (builtins.readFile ./starship.toml); + }; + + # Install additional packages for zsh + environment.systemPackages = with pkgs; [ + fzf # For better history search + ]; + }; +} diff --git a/modules/programs/zsh/k8s.zsh b/modules/programs/zsh/k8s.zsh new file mode 100644 index 0000000..f7d1e4b --- /dev/null +++ b/modules/programs/zsh/k8s.zsh @@ -0,0 +1,49 @@ +# Kubernetes functions and completion (migrated from fish) + +if command -v kubectl &> /dev/null; then + # Namespace functions + kns() { + kubectl config view --minify --output 'jsonpath={..namespace}' + } + + # kexec function (equivalent to fish __echo_kubeexec) + kexec() { + local _flag_namespace + _flag_namespace=$(kubectl config view --minify --output 'jsonpath={..namespace}') + if [[ -z "$_flag_namespace" ]]; then + _flag_namespace="default" + fi + + local _flag_pod="shop" + local POD + POD=$(kubectl get pods --namespace "$_flag_namespace" 2>/dev/null | grep "^$_flag_pod" | grep Running | head -n1 | awk '{ print $1 }') + + if [[ -z "$POD" ]]; then + echo "kubectl exec --namespace $_flag_namespace -it" + return + fi + echo "kubectl exec --namespace $_flag_namespace -it $POD --" + } + + # kmanage function (equivalent to fish __echo_kubemanage) + kmanage() { + local _flag_namespace + _flag_namespace=$(kubectl config view --minify --output 'jsonpath={..namespace}') + if [[ -z "$_flag_namespace" ]]; then + _flag_namespace="default" + fi + + local _flag_pod="shop" + local POD + POD=$(kubectl get pods --namespace "$_flag_namespace" 2>/dev/null | grep "^$_flag_pod" | grep Running | head -n1 | awk '{ print $1 }') + + if [[ -z "$POD" ]]; then + echo "kubectl exec --namespace $_flag_namespace -it" + return + fi + echo "kubectl exec --namespace $_flag_namespace -it $POD -- python3 /src/lib/manage.py" + } + + # Kubectl completion + source <(kubectl completion zsh) +fi diff --git a/modules/programs/zsh/starship.toml b/modules/programs/zsh/starship.toml new file mode 100644 index 0000000..40ab200 --- /dev/null +++ b/modules/programs/zsh/starship.toml @@ -0,0 +1,70 @@ +# Starship prompt configuration +# https://starship.rs/config/ +"$schema" = 'https://starship.rs/config-schema.json' + +format = """ +$status\ +$directory\ +[](fg:prev_bg bg:color_bg) +""" +right_format = """ +$cmd_duration\ +$time +""" + +palette = 'fireproof' + +[palettes.fireproof] +color_bg = '#1C1B1A' +color_bg_alt = '#282726' +color_fg = '#DAD8CE' +color_fg_alt = '#B7B5AC' +color_muted = '#878580' +color_ui = '#343331' +color_ui_alt = '#403E3C' +color_black = '#100F0F' +color_accent = '#CF6A4C' +color_red = '#D14D41' +color_red_alt = '#AF3029' +color_orange = '#DA702C' +color_orange_alt = '#BC5215' +color_yellow = '#D0A215' +color_yellow_alt = '#AD8301' +color_green = '#879A39' +color_green_alt = '#66800B' +color_cyan = '#3AA99F' +color_cyan_alt = '#24837B' +color_blue = '#4385BE' +color_blue_alt = '#205EA6' +color_purple = '#8B7EC8' +color_purple_alt = '#5E409D' +color_magenta = '#CE5D97' +color_magenta_alt = '#A02F6F' +color_white = '#DAD8CE' +color_white_alt = '#F2F0E5' + +[status] +disabled = false +symbol = "!" +not_executable_symbol = "X" +not_found_symbol = "?" +sigint_symbol = "%" +style = "bold bg:color_fg fg:color_red" +format = "[ $symbol ]($style)[](fg:color_fg bg:color_black)" + +[directory] +style = "bold fg:color_fg bg:color_black" +format = "[ $path ]($style)" + +[cmd_duration] +disabled = false +format = "[$duration - ]($style)" +style = "fg:color_muted" + +[time] +disabled = false +format = "[$time]($style)" +style = "fg:color_muted" + +[line_break] +disabled = false diff --git a/modules/programs/zsh/theme.zsh b/modules/programs/zsh/theme.zsh new file mode 100644 index 0000000..9110066 --- /dev/null +++ b/modules/programs/zsh/theme.zsh @@ -0,0 +1,31 @@ +# Zsh theme configuration +# Starship prompt is configured via starship.toml + +# Syntax highlighting colors (fish-like) +typeset -gA ZSH_HIGHLIGHT_STYLES +ZSH_HIGHLIGHT_STYLES[default]='none' +ZSH_HIGHLIGHT_STYLES[unknown-token]='fg=red,bold' +ZSH_HIGHLIGHT_STYLES[reserved-word]='fg=green' +ZSH_HIGHLIGHT_STYLES[alias]='fg=blue' +ZSH_HIGHLIGHT_STYLES[builtin]='fg=blue' +ZSH_HIGHLIGHT_STYLES[function]='fg=blue' +ZSH_HIGHLIGHT_STYLES[command]='fg=blue' +ZSH_HIGHLIGHT_STYLES[precommand]='fg=blue,underline' +ZSH_HIGHLIGHT_STYLES[commandseparator]='fg=green' +ZSH_HIGHLIGHT_STYLES[hashed-command]='fg=blue' +ZSH_HIGHLIGHT_STYLES[path]='underline' +ZSH_HIGHLIGHT_STYLES[path_prefix]='underline' +ZSH_HIGHLIGHT_STYLES[globbing]='fg=cyan' +ZSH_HIGHLIGHT_STYLES[history-expansion]='fg=cyan' +ZSH_HIGHLIGHT_STYLES[single-hyphen-option]='fg=cyan' +ZSH_HIGHLIGHT_STYLES[double-hyphen-option]='fg=cyan' +ZSH_HIGHLIGHT_STYLES[back-quoted-argument]='fg=magenta' +ZSH_HIGHLIGHT_STYLES[single-quoted-argument]='fg=yellow' +ZSH_HIGHLIGHT_STYLES[double-quoted-argument]='fg=yellow' +ZSH_HIGHLIGHT_STYLES[dollar-quoted-argument]='fg=yellow' +ZSH_HIGHLIGHT_STYLES[dollar-double-quoted-argument]='fg=cyan' +ZSH_HIGHLIGHT_STYLES[back-double-quoted-argument]='fg=cyan' +ZSH_HIGHLIGHT_STYLES[back-dollar-quoted-argument]='fg=cyan' +ZSH_HIGHLIGHT_STYLES[redirection]='fg=cyan,bold' +ZSH_HIGHLIGHT_STYLES[comment]='fg=red' +ZSH_HIGHLIGHT_STYLES[arg0]='fg=blue'