{ lib, pkgs, config, ... }: let cfg = config.reo101.shell; inherit (lib) mkEnableOption mkOption types mkIf optionals optionalString; in { imports = [ ]; options = { reo101.shell = { enable = mkEnableOption "reo101 zsh setup"; username = mkOption { description = "Username to be used in prompt"; type = types.str; default = "${config.home.username}"; }; atuin = mkOption { description = "Integrate with atuin"; type = types.bool; default = true; }; direnv = mkOption { description = "Integrate with direnv"; type = types.bool; default = true; }; zoxide = mkOption { description = "Integrate with zoxide"; type = types.bool; default = true; }; extraConfig = mkOption { description = "Extra zsh config"; type = types.str; default = '' ''; }; }; }; config = mkIf cfg.enable { home.packages = with pkgs; builtins.concatLists [ [ zsh starship ] (optionals cfg.atuin [ atuin ]) (optionals cfg.direnv [ direnv ]) (optionals cfg.zoxide [ zoxide ]) ]; programs.direnv = mkIf cfg.direnv { enable = true; nix-direnv = { enable = true; }; }; programs.zsh = { enable = true; enableCompletion = true; dotDir = ".config/zsh"; shellAliases = { ls = "${pkgs.lsd}/bin/lsd"; cp = "${pkgs.advcpmv}/bin/advcp -rvi"; mv = "${pkgs.advcpmv}/bin/advmv -vi"; mkdir = "mkdir -vp"; }; history = { size = 10000; path = "${config.xdg.dataHome}/zsh/history"; }; initExtra = builtins.concatStringsSep "\n" [ '' rebuild () { ${ let inherit (lib.strings) hasInfix; flake_dir = builtins.toString ../../..; in if hasInfix "nixos" pkgs.system then "sudo nixos-rebuild --flake ${flake_dir}" else if hasInfix "darwin" pkgs.system then "darwin-rebuild --flake ${flake_dir}" else if "aarch64-linux" == pkgs.system then "nix-on-droid --flake ${flake_dir}" else "home-manager --flake ${flake_dir}" } ''${1:-switch} |& nix run nixpkgs#nix-output-monitor } '' (optionalString cfg.atuin '' export ATUIN_NOBIND="true" eval "$(${pkgs.atuin}/bin/atuin init zsh)" function zvm_after_init() { # bindkey "^r" _atuin_search_widget zvm_bindkey viins "^R" _atuin_search_widget } '') # NOTE: done by `programs.direnv` # (optionalString cfg.direnv '' # eval "$(${pkgs.direnv}/bin/direnv hook zsh)" # '') (optionalString cfg.zoxide '' eval "$(${pkgs.zoxide}/bin/zoxide init zsh)" '') cfg.extraConfig ]; plugins = [ { name = "zsh-nix-shell"; file = "nix-shell.plugin.zsh"; src = pkgs.fetchFromGitHub { owner = "chisui"; repo = "zsh-nix-shell"; rev = "v0.7.0"; sha256 = "sha256-oQpYKBt0gmOSBgay2HgbXiDoZo5FoUKwyHSlUrOAP5E="; }; } { name = "fast-syntax-highlighting"; file = "fast-syntax-highlighting.plugin.zsh"; src = pkgs.fetchFromGitHub { owner = "zdharma-continuum"; repo = "fast-syntax-highlighting"; rev = "cf318e06a9b7c9f2219d78f41b46fa6e06011fd9"; sha256 = "sha256-RVX9ZSzjBW3LpFs2W86lKI6vtcvDWP6EPxzeTcRZua4="; }; } { name = "zsh-autosuggestions"; file = "zsh-autosuggestions.plugin.zsh"; src = pkgs.fetchFromGitHub { owner = "zsh-users"; repo = "zsh-autosuggestions"; rev = "a411ef3e0992d4839f0732ebeb9823024afaaaa8"; sha256 = "sha256-KLUYpUu4DHRumQZ3w59m9aTW6TBKMCXl2UcKi4uMd7w="; }; } { name = "zsh-vi-mode"; file = "zsh-vi-mode.plugin.zsh"; src = pkgs.fetchFromGitHub { owner = "jeffreytse"; repo = "zsh-vi-mode"; rev = "1bda23100e8d140a19be0eed67395c64f6a6074c"; sha256 = "sha256-3arAa5EBG+U9cCauChX9K0KF3hkd+t04/trlWKk/gOw="; }; } ]; }; home.file.".config/atuin/config.toml" = mkIf cfg.atuin { text = '' ## where to store your database, default is your system data directory ## mac: ~/Library/Application Support/com.elliehuxtable.atuin/history.db ## linux: ~/.local/share/atuin/history.db # db_path = "~/.history.db" ## where to store your encryption key, default is your system data directory # key_path = "~/.key" ## where to store your auth session token, default is your system data directory # session_path = "~/.key" ## date format used, either "us" or "uk" # dialect = "us" ## enable or disable automatic sync auto_sync = true ## enable or disable automatic update checks update_check = false ## address of the sync server sync_address = "https://naboo.qtrp.org/atuin" ## how often to sync history. note that this is only triggered when a command ## is ran, so sync intervals may well be longer ## set it to 0 to sync after every command sync_frequency = "1m" ## which search mode to use ## possible values: prefix, fulltext, fuzzy, skim # search_mode = "fuzzy" ## which filter mode to use ## possible values: global, host, session, directory filter_mode = "global" # ## which filter mode to use when atuin is invoked from a shell up-key binding # ## the accepted values are identical to those of "filter_mode" # ## leave unspecified to use same mode set in "filter_mode" # filter_mode_shell_up_keybinding = "session" ## which style to use ## possible values: auto, full, compact # style = "auto" ## the maximum number of lines the interface should take up ## set it to 0 to always go full screen # inline_height = 0 ## enable or disable showing a preview of the selected command ## useful when the command is longer than the terminal width and is cut off # show_preview = false ## what to do when the escape key is pressed when searching ## possible values: return-original, return-query # exit_mode = "return-original" ## possible values: emacs, subl # word_jump_mode = "emacs" ## characters that count as a part of a word # word_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ## number of context lines to show when scrolling by pages # scroll_context_lines = 1 ## prevent commands matching any of these regexes from being written to history. ## Note that these regular expressions are unanchored, i.e. if they don't start ## with ^ or end with $, they'll match anywhere in the command. ## For details on the supported regular expression syntax, see ## https://docs.rs/regex/latest/regex/#syntax # history_filter = [ # "^secret-cmd", # "^innocuous-cmd .*--secret=.+" # ] ''; }; programs.starship = { enable = true; settings = { # Get editor completions based on the config schema "$schema" = "https://starship.rs/config-schema.json"; # Use custom format format = '' [╭───────┨](bold green)[${cfg.username}](bright-white)[@](bold yellow)$hostname[┠───────>](bold green)$status$cmd_duration$git_branch$git_status$git_state$git_commit [│](bold green)$time$jobs: $directory$package [╰─](bold green)$character ''; # ${custom.local}\ # ${custom.local_root}\ # ${custom.ssh}\ # ${custom.ssh_root}\ add_newline = true; character = { success_symbol = "[→](bold green)"; error_symbol = "[→](red)"; }; git_branch = { symbol = "🌱 "; truncation_length = 15; truncation_symbol = "…"; # … }; git_commit = { commit_hash_length = 6; tag_symbol = "🔖 "; }; git_state = { format = "[\($state( $progress_current of $progress_total)\)]($style) "; cherry_pick = "[🍒 PICKING](bold red)"; }; git_status = { # conflicted = "🏳"; # ahead = "🏎💨"; # behind = "😰"; # diverged = "😵"; # untracked = "🤷‍"; # stashed = "📦"; # modified = "📝"; # staged = '[++\($count\)](green)'; # renamed = "👅"; # deleted = "🗑"; format = "[\\[$all_status$ahead_behind\\]]($style) "; conflicted = "=[\($count\)](green) "; ahead = "⇡[\($count\)](green) "; behind = "⇣[\($count\)](green) "; diverged = "⇕[\($count\)](green) "; untracked = "?[\($count\)](green) "; stashed = "$[\($count\)](green) "; modified = "![\($count\)](green) "; staged = "+[\($count\)](green) "; renamed = "»[\($count\)](green) "; deleted = "✘[\($count\)](green) "; }; status = { style = "bg:blue fg:red"; symbol = "🔴"; format = "[\[$symbol $common_meaning$signal_name$maybe_int\]]($style) "; map_symbol = true; disabled = false; }; time = { disabled = false; format = "🕙[$time]($style) "; # format = '🕙[\[ $time \]]($style) '; time_format = "%T"; utc_time_offset = "+3"; # time_range = "10:00:00-14:00:00"; }; cmd_duration = { min_time = 2000; # miliseconds # show_notifications = true; min_time_to_notify = 45000; # miliseconds format = "took [$duration](bold yellow) "; }; hostname = { ssh_only = false; format = "[$hostname](bold fg:#CC59B0)"; disabled = false; }; username = { disabled = false; style_user = "white bold"; style_root = "red bold"; format = "[$user]($style)[@](bold yellow)"; show_always = true; }; directory = { read_only = "🔒"; read_only_style = "bold white"; style = "fg:#A7F3E4"; truncate_to_repo = false; truncation_length = 5; truncation_symbol = "…/"; home_symbol = "🏡"; format = "[$read_only]($read_only_style)[$path]($style) "; }; directory.substitutions = { ".config" = " "; "nvim" = ""; "emacs" = "𝓔"; "doom" = "𝓔"; "Projects" = "💻"; "FMI" = "🏫"; "Home" = "🏠"; "CPP" = ""; "Java" = ""; "Python" = ""; }; # Language Environments package = { style = "bold fg:#5E5E5E"; }; python = { style = "bold fg:#5E5E5E"; symbol = "[](bold yellow) "; }; nodejs = { style = "bold fg:#5E5E5E"; symbol = "[⬢](bold green) "; }; # Custom jobs = { format = "[ $symbol$number ]($style)"; style = "bg:#587744 fg:bright-white"; symbol = "⚙"; }; custom.local = { shell = [ "zsh" "-d" "-f" ]; when = '' [ [ -z "$SSH_CLIENT" ] ] && [ [ `whoami` != "root" ] ] ''; format = "[$symbol$output]($style)[@](bold yellow)"; command = "whoami"; style = "fg:bright-white"; symbol = ""; }; custom.local_root = { shell = [ "zsh" "-d" "-f" ]; when = '' [ [ -z "$SSH_CLIENT" ] ] && [ [ `whoami` == "root" ] ] ''; format = "[ $output ]($style)[@](bold yellow)"; command = "whoami"; style = "bg:red fg:bright-white"; }; custom.ssh = { shell = [ "zsh" "-d" "-f" ]; when = '' [ [ -n "$SSH_CLIENT" ] ] && [ [ `whoami` != "root" ] ] ''; format = "[ $symbol$output ]($style)[@](bold yellow)"; command = "whoami"; style = "bg:blue fg:bright-white"; # style = "bg:#FD7208 fg:bright-white"; symbol = "⌁"; }; custom.ssh_root = { shell = [ "zsh" "-d" "-f" ]; when = '' [ [ -n "$SSH_CLIENT" ] ] && [ [ `whoami` == "root" ] ] ''; format = "[ $symbol$output ]($style)[@](bold yellow)"; command = "whoami"; style = "bg:red fg:bright-white"; symbol = "⌁"; }; }; }; }; meta = { maintainers = with lib.maintainers; [ reo101 ]; }; }