This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

tools: restructure into folders with autoimport

- Convert all tool .nix files into folders with flake-module.nix
- Add autoimport functionality to flake.nix
- Remove empty zed directory
- Tools are now automatically discovered from subdirectories

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

author
lassulus
co-author
Claude
date (Jun 14, 2025, 11:22 PM CEST) commit bb6693d7 parent 258e5c72
+757 -757
+9 -9
flake.nix
··· 126 126 "x86_64-darwin" 127 127 ]; 128 128 imports = [ 129 - ./tools/nvim.nix 130 - ./tools/astronvim/flake-module.nix 131 - ./tools/zsh.nix 132 - ./tools/wifi-qr.nix 133 - ./tools/get-spora-hosts.nix 134 - ./tools/pass.nix 135 - ./tools/menu.nix 136 - ./tools/passmenu.nix 137 129 ./formatter.nix 138 - ]; 130 + ] ++ ( 131 + # Auto-import all flake-module.nix files from tools subdirectories 132 + let 133 + toolDirs = builtins.attrNames (nixpkgs.lib.filterAttrs 134 + (_: type: type == "directory") 135 + (builtins.readDir ./tools)); 136 + in 137 + map (dir: ./tools + "/${dir}/flake-module.nix") toolDirs 138 + ); 139 139 flake.nixosConfigurations = clan.nixosConfigurations; 140 140 flake.clanInternals = clan.clanInternals; 141 141 perSystem =
-22
tools/get-spora-hosts.nix
··· 1 - { self, ... }: 2 - { 3 - perSystem = 4 - { system, pkgs, ... }: 5 - { 6 - packages.get-spora-hosts = pkgs.writeScriptBin "get-spora-hosts" '' 7 - set -eu 8 - set -o pipefail 9 - set -x 10 - OUTDIR=$1 11 - for host in ${self}/machines/*; do 12 - if test -e "$host"/facts/mycelium_pubkey; then 13 - if ! test -e "$OUTDIR"/"$(basename "$host")".json; then 14 - ${ 15 - self.packages.${pkgs.system}.mycelium 16 - }/bin/mycelium inspect "$(cat "$host"/facts/mycelium_pubkey)" --json > "$OUTDIR/$(basename "$host").json" 17 - fi 18 - fi 19 - done 20 - ''; 21 - }; 22 - }
-102
tools/menu.nix
··· 1 - { ... }: 2 - { 3 - perSystem = 4 - { pkgs, ... }: 5 - { 6 - packages.menu = 7 - if pkgs.stdenv.hostPlatform.isDarwin then 8 - (pkgs.writeShellApplication { 9 - name = "menu"; 10 - runtimeInputs = [ 11 - pkgs.choose-gui 12 - pkgs.fzf 13 - ]; 14 - text = '' 15 - set -efu 16 - 17 - # Create temporary files for input and output 18 - TEMP_DIR=$(mktemp -d) 19 - INPUT_FILE="$TEMP_DIR/input" 20 - OUTPUT_FILE="$TEMP_DIR/output" 21 - 22 - # Set up trap to clean up temp dir on exit 23 - trap 'rm -rf "$TEMP_DIR"' EXIT 24 - 25 - # Save stdin to file 26 - cat > "$INPUT_FILE" 27 - 28 - # Try fzf first with terminal UI - explicitly store exit code 29 - # This avoids issues with losing the exit code in a pipe 30 - set +e 31 - fzf "$@" < "$INPUT_FILE" > "$OUTPUT_FILE" 2>/dev/null 32 - FZF_EXIT=$? 33 - set -e 34 - 35 - # Handle fzf results based on exit code 36 - if [ $FZF_EXIT -eq 0 ]; then 37 - # Success - output result and exit 38 - cat "$OUTPUT_FILE" 39 - exit 0 40 - elif [ $FZF_EXIT -eq 130 ]; then 41 - # User pressed Escape - honor the cancellation 42 - exit 130 43 - fi 44 - 45 - # If we get here, fzf failed with error (not cancellation) 46 - 47 - # Fall back to GUI 48 - choose "$@" < "$INPUT_FILE" 49 - ''; 50 - }) 51 - else if pkgs.stdenv.hostPlatform.isLinux then 52 - (pkgs.writeShellApplication { 53 - name = "menu"; 54 - runtimeInputs = [ 55 - pkgs.rofi 56 - pkgs.wofi 57 - pkgs.fzf 58 - ]; 59 - text = '' 60 - set -efu 61 - # Create temporary files for input and output 62 - TEMP_DIR=$(mktemp -d) 63 - INPUT_FILE="$TEMP_DIR/input" 64 - OUTPUT_FILE="$TEMP_DIR/output" 65 - 66 - # Save stdin to file 67 - cat > "$INPUT_FILE" 68 - 69 - # Try fzf first with terminal UI - explicitly store exit code 70 - # This avoids issues with losing the exit code in a pipe 71 - set +e 72 - fzf "$@" < "$INPUT_FILE" > "$OUTPUT_FILE" 2>/dev/null 73 - FZF_EXIT=$? 74 - set -e 75 - 76 - # Handle fzf results based on exit code 77 - if [ $FZF_EXIT -eq 0 ]; then 78 - # Success - output result and exit 79 - cat "$OUTPUT_FILE" 80 - exit 0 81 - elif [ $FZF_EXIT -eq 130 ]; then 82 - # User pressed Escape - honor the cancellation 83 - exit 130 84 - fi 85 - 86 - # If we get here, fzf failed with error (not cancellation) 87 - 88 - # Fall back to GUI based on available display environment 89 - if [ -n "''${WAYLAND_DISPLAY:-}" ]; then 90 - wofi -d "$@" < "$INPUT_FILE" 91 - elif [ -n "''${DISPLAY:-}" ]; then 92 - rofi -dmenu "$@" < "$INPUT_FILE" 93 - else 94 - echo "Error: No suitable display environment available" >&2 95 - exit 1 96 - fi 97 - ''; 98 - }) 99 - else 100 - throw "unsupported system"; 101 - }; 102 - }
-309
tools/nvim.nix
··· 1 - { inputs, ... }: 2 - { 3 - perSystem = 4 - { system, pkgs, ... }: 5 - { 6 - packages.nvim = inputs.nixvim.legacyPackages.${system}.makeNixvim { 7 - vimAlias = true; 8 - colorschemes = { 9 - ayu = { 10 - enable = true; 11 - settings.overrides = { 12 - EoLSpace = { 13 - bg = "#883333"; 14 - }; 15 - }; 16 - }; 17 - everforest = { 18 - enable = true; 19 - settings.overrides = { 20 - EoLSpace = { 21 - bg = "#FF2222"; # doesn't work 22 - }; 23 - }; 24 - }; 25 - }; 26 - globals = { 27 - mapleader = " "; 28 - lumen_light_colorscheme = "everforest"; 29 - lumen_dark_colorscheme = "ayu"; 30 - }; 31 - opts = { 32 - mouse = "a"; 33 - number = true; 34 - shiftwidth = 2; 35 - clipboard = "unnamedplus"; 36 - # undo stuff 37 - undofile = true; 38 - undolevels = 10000; 39 - undoreload = 10000; 40 - listchars = "tab:⇥ ,extends:❯,precedes:❮,nbsp:␣,trail:·,eol:↲"; 41 - }; 42 - extraConfigVim = '' 43 - set et 44 - 45 - " show special characters 46 - set list 47 - 48 - " match trailing whitespace 49 - match EoLSpace /\s\+$/ 50 - 51 - " need to use lua to expand $HOME 52 - lua vim.o.undodir = vim.fs.normalize('$HOME/.vim/undodir') 53 - ''; 54 - extraPackages = [ 55 - pkgs.glib # for vim-lumen 56 - ]; 57 - extraPlugins = [ 58 - pkgs.vimPlugins.vim-fetch 59 - (pkgs.vimUtils.buildVimPlugin { 60 - name = "vim-lumen"; 61 - src = pkgs.fetchFromGitHub { 62 - owner = "vimpostor"; 63 - repo = "vim-lumen"; 64 - rev = "ac13c32c3e309f6c6a84ff6cad8dbb135e75f0e4"; 65 - hash = "sha256-rsDUDI9lh4CEX1upMBjeyBOm99GAXWGPQ9vSCN8cmFo="; 66 - }; 67 - }) 68 - ]; 69 - # not ready yet, we are waiting for none-ls to get updated 70 - # extraConfigLua = '' 71 - # local null_ls = require("null-ls") 72 - # null_ls.register(null_ls.builtins.formatting.nix_flake_fmt) 73 - # ''; 74 - keymaps = [ 75 - { 76 - mode = "i"; 77 - key = "<C-p>"; 78 - action = "<Nop>"; 79 - } 80 - { 81 - mode = "i"; 82 - key = "<C-n>"; 83 - action = "<Nop>"; 84 - } 85 - { 86 - mode = "n"; 87 - key = "<C-c>"; 88 - action = ":q<cr>"; 89 - } 90 - { 91 - mode = "n"; 92 - key = "<Space>"; 93 - action = "<Nop>"; 94 - } 95 - { 96 - mode = "n"; 97 - key = "<leader>sd"; 98 - action = ":colorscheme ayu-dark<cr>"; 99 - } 100 - { 101 - mode = "n"; 102 - key = "<leader>sw"; 103 - action = ":colorscheme ayu-light<cr>"; 104 - } 105 - { 106 - mode = [ 107 - "n" 108 - "v" 109 - ]; 110 - key = "<leader>cc"; 111 - action = ":CopilotChatOpen<cr>"; 112 - } 113 - { 114 - mode = [ 115 - "n" 116 - "v" 117 - ]; 118 - key = "<leader>ce"; 119 - action = ":CopilotChatExplain<cr>"; 120 - } 121 - { 122 - mode = [ 123 - "n" 124 - "v" 125 - ]; 126 - key = "<leader>cr"; 127 - action = ":CopilotChatReview<cr>"; 128 - } 129 - { 130 - mode = [ 131 - "n" 132 - "v" 133 - ]; 134 - key = "<leader>cf"; 135 - action = ":CopilotChatFix<cr>"; 136 - } 137 - { 138 - mode = [ 139 - "n" 140 - "v" 141 - ]; 142 - key = "<leader>cd"; 143 - action = ":CopilotChatDocs<cr>"; 144 - } 145 - { 146 - mode = [ 147 - "n" 148 - "x" 149 - ]; 150 - key = "p"; 151 - action = "<Plug>(YankyPutAfter)"; 152 - } 153 - { 154 - mode = [ 155 - "n" 156 - "x" 157 - ]; 158 - key = "P"; 159 - action = "<Plug>(YankyPutBefore)"; 160 - } 161 - { 162 - mode = [ 163 - "c" 164 - "i" 165 - "n" 166 - "x" 167 - ]; 168 - key = "<M-CR>"; 169 - action = ":lua vim.lsp.buf.code_action()<CR>"; 170 - } 171 - { 172 - mode = [ 173 - "n" 174 - ]; 175 - key = "gd"; 176 - action = ":lua vim.lsp.buf.definition()<CR>"; 177 - } 178 - { 179 - mode = [ 180 - "n" 181 - ]; 182 - key = "gD"; 183 - action = ":lua vim.lsp.buf.declaration()<CR>"; 184 - } 185 - ]; 186 - # autoCmd = [ 187 - # { 188 - # event = "BufWritePost"; 189 - # desc = "run treefmt on save"; 190 - # # https://stackoverflow.com/questions/77466697/how-to-automatically-format-on-save 191 - # callback.__raw = '' 192 - # function() 193 - # vim.cmd("silent !treefmt %") 194 - # vim.cmd("edit") 195 - # end 196 - # ''; 197 - # } 198 - # ]; 199 - plugins.none-ls = { 200 - enable = true; 201 - # sources.formatting.treefmt = { 202 - # enable = true; 203 - # package = pkgs.emptyDirectory; 204 - # }; 205 - # package = pkgs.vimPlugins.none-ls-nvim.overrideAttrs (_old: { 206 - # src = pkgs.fetchFromGitHub { 207 - # owner = "lassulus"; 208 - # repo = "none-ls.nvim"; 209 - # rev = "292c2b5eadea0a097b9a01804aea70f5c8125200"; 210 - # sha256 = "sha256-nbzqXsxmYfxngdJH3NXMLmGgygh6reSEnruoc6l8t/s="; 211 - # }; 212 - # }); 213 - sources.formatting.nix_flake_fmt.enable = true; 214 - }; 215 - plugins.web-devicons.enable = true; 216 - plugins.telescope.extensions.undo.enable = true; 217 - plugins.telescope = { 218 - enable = true; 219 - keymaps = { 220 - "<leader>b" = "buffers"; 221 - "<leader>u" = "undo"; 222 - "<leader>ff" = "find_files"; 223 - "<leader>fg" = "live_grep"; 224 - "<leader>fh" = "help_tags"; 225 - "<leader>fp" = "yank_history"; 226 - }; 227 - }; 228 - plugins.lsp-format.enable = true; 229 - plugins.lsp-lines.enable = true; 230 - plugins.lsp = { 231 - enable = true; 232 - servers = { 233 - bashls.enable = true; # bash 234 - nixd = { 235 - enable = true; # nix 236 - extraOptions.offset_encoding = "utf-8"; # workaround https://github.com/nix-community/nixvim/issues/2390#issuecomment-2408101568 237 - }; 238 - ruff.enable = true; # python 239 - pyright.enable = true; # python 240 - jsonls.enable = true; # json 241 - }; 242 - }; 243 - plugins.treesitter.enable = true; 244 - plugins.copilot-cmp.enable = true; 245 - plugins.copilot-lua.settings.panel.enabled = false; 246 - plugins.copilot-lua.settings.suggestion.enabled = false; 247 - plugins.cmp_yanky.enable = true; 248 - plugins.cmp = { 249 - enable = true; 250 - autoEnableSources = true; 251 - settings = { 252 - experimental = { 253 - ghost_text = true; 254 - }; 255 - sources = [ 256 - { name = "nvim_lsp"; } 257 - { name = "emoji"; } 258 - { 259 - name = "buffer"; # text within current buffer 260 - option.get_bufnrs.__raw = "vim.api.nvim_list_bufs"; 261 - keywordLength = 2; 262 - } 263 - { 264 - name = "copilot"; # enable copilot 265 - } 266 - { 267 - name = "path"; # file system paths 268 - keywordLength = 3; 269 - } 270 - { name = "cmp_yanky"; } 271 - ]; 272 - 273 - mapping = { 274 - "<Tab>" = "cmp.mapping.select_next_item()"; 275 - "<S-Tab>" = "cmp.mapping.select_prev_item()"; 276 - "<C-n>" = "cmp.mapping.select_next_item()"; 277 - "<C-p>" = "cmp.mapping.select_prev_item()"; 278 - "<C-e>" = "cmp.mapping.abort()"; 279 - "<C-b>" = "cmp.mapping.scroll_docs(-4)"; 280 - "<C-f>" = "cmp.mapping.scroll_docs(4)"; 281 - "<CR>" = '' 282 - cmp.mapping({ 283 - i = function(fallback) 284 - if cmp.visible() and cmp.get_active_entry() then 285 - cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }) 286 - else 287 - fallback() 288 - end 289 - end, 290 - s = cmp.mapping.confirm({ select = true }), 291 - c = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true }), 292 - }) 293 - ''; 294 - }; 295 - }; 296 - }; 297 - plugins.bufferline.enable = true; 298 - plugins.which-key.enable = true; 299 - plugins.yanky = { 300 - enable = true; 301 - enableTelescope = true; 302 - }; 303 - plugins.comment.enable = true; 304 - plugins.copilot-chat.enable = true; 305 - plugins.undotree.enable = true; # seems to be needed for undo history in telescope 306 - plugins.gitsigns.enable = true; 307 - }; 308 - }; 309 - }
-26
tools/pass.nix
··· 1 - { self, ... }: 2 - { 3 - perSystem = 4 - { pkgs, ... }: 5 - { 6 - packages.pass = pkgs.symlinkJoin { 7 - name = "pass"; 8 - paths = [ 9 - (pkgs.writeShellApplication { 10 - name = "pass"; 11 - runtimeInputs = [ 12 - (pkgs.pass.withExtensions (ext: [ ext.pass-otp ])) 13 - pkgs.gnupg 14 - ]; 15 - text = '' 16 - set -efu 17 - gpg --import ${self.keys.pgp.yubi.key} &>/dev/null 18 - echo '${self.keys.pgp.yubi.id}:6:' | gpg --import-ownertrust &>/dev/null 19 - pass "$@" 20 - ''; 21 - }) 22 - (pkgs.pass.withExtensions (ext: [ ext.pass-otp ])) 23 - ]; 24 - }; 25 - }; 26 - }
-67
tools/passmenu.nix
··· 1 - { self, ... }: 2 - { 3 - perSystem = 4 - { pkgs, ... }: 5 - { 6 - packages.passmenu = pkgs.writeShellApplication { 7 - name = "passmenu"; 8 - runtimeInputs = with pkgs; [ 9 - self.packages.${pkgs.system}.menu 10 - self.packages.${pkgs.system}.pass 11 - ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ 12 - wtype 13 - xdotool 14 - ]; 15 - text = '' 16 - set -eu 17 - shopt -s nullglob globstar 18 - 19 - typeit=0 20 - if [[ $# -gt 0 && $1 == "--type" ]]; then 21 - typeit=1 22 - shift 23 - fi 24 - 25 - prefix=''${PASSWORD_STORE_DIR-~/.password-store} 26 - password_files=( "$prefix"/**/*.gpg ) 27 - password_files=( "''${password_files[@]#"$prefix"/}" ) 28 - password_files=( "''${password_files[@]%.gpg}" ) 29 - 30 - password=$(printf '%s\n' "''${password_files[@]}" | menu "$@") 31 - 32 - filename=$(basename "$password") 33 - if [[ "$filename" == "otp" ]]; then 34 - if [[ $typeit -eq 1 ]]; then 35 - # Type OTP code 36 - otp_code=$(pass otp "$password" | tr -d '\n') 37 - if [[ "$(uname)" == "Darwin" ]]; then 38 - # On macOS, use osascript to type the code 39 - osascript -e "tell application \"System Events\" to keystroke \"$otp_code\"" 2>/dev/null 40 - elif [[ -n "$WAYLAND_DISPLAY" ]]; then 41 - echo -n "$otp_code" | wtype -d 10 -s 400 - 42 - else 43 - echo -n "$otp_code" | xdotool type --clearmodifiers --file - 44 - fi 45 - else 46 - pass otp --clip "$password" 2>/dev/null 47 - fi 48 - else 49 - if [[ $typeit -eq 1 ]]; then 50 - # Type password 51 - pw=$(pass show "$password" | head -n1 | tr -d '\n') 52 - if [[ "$(uname)" == "Darwin" ]]; then 53 - # On macOS, use osascript to type the password 54 - osascript -e "tell application \"System Events\" to keystroke \"$pw\"" 2>/dev/null 55 - elif [[ -n "$WAYLAND_DISPLAY" ]]; then 56 - echo -n "$pw" | wtype -d 10 -s 400 - 57 - else 58 - echo -n "$pw" | xdotool type --clearmodifiers --file - 59 - fi 60 - else 61 - pass show --clip "$password" 2>/dev/null 62 - fi 63 - fi 64 - ''; 65 - }; 66 - }; 67 - }
-21
tools/wifi-qr.nix
··· 1 - 2 - { ... }: 3 - { 4 - perSystem = 5 - { pkgs, ... }: { 6 - packages.wifi-qr = pkgs.writeShellApplication { 7 - name = "wifi-qr"; 8 - runtimeInputs = [ 9 - pkgs.zbar 10 - pkgs.gawk 11 - ]; 12 - text = '' 13 - QR_CODE=$(zbarcam --raw --oneshot) 14 - SSID=$(echo "$QR_CODE" | awk -F 'S:' '{print $2}' | awk -F ';' '{print $1}') 15 - PW=$(echo "$QR_CODE" | awk -F 'P:' '{print $2}' | awk -F ';' '{print $1}') 16 - nmcli dev wifi rescan 17 - nmcli dev wifi connect "$SSID" password "$PW" 18 - ''; 19 - }; 20 - }; 21 - }
-201
tools/zsh.nix
··· 1 - { ... }: 2 - { 3 - perSystem = 4 - { pkgs, ... }: 5 - let 6 - zshrc = '' 7 - autoload -U compinit && compinit 8 - 9 - # Setup custom interactive shell init stuff. 10 - # Bind gpg-agent to this TTY if gpg commands are used. 11 - export GPG_TTY=$(tty) 12 - 13 - # show how long a command takes 14 - ZSH_COMMAND_TIME_MIN_SECONDS=3 15 - ZSH_COMMAND_TIME_EXCLUDE=(vim) 16 - ZSH_COMMAND_TIME_MSG="took: %s sec" 17 - source ${ 18 - pkgs.fetchFromGitHub { 19 - owner = "popstas"; 20 - repo = "zsh-command-time"; 21 - rev = "803d26eef526bff1494d1a584e46a6e08d25d918"; 22 - hash = "sha256-ndHVFcz+XmUW0zwFq7pBXygdRKyPLjDZNmTelhd5bv8="; 23 - } 24 - }/command-time.plugin.zsh 25 - 26 - unsetopt nomatch # no matches found urls 27 - setopt autocd extendedglob 28 - bindkey -e 29 - 30 - #C-x C-e open line in editor 31 - autoload -z edit-command-line 32 - zle -N edit-command-line 33 - bindkey "^X^E" edit-command-line 34 - 35 - #fzf inclusion 36 - source ${pkgs.fzf}/share/fzf/completion.zsh 37 - source ${pkgs.fzf}/share/fzf/key-bindings.zsh 38 - 39 - # atuin distributed shell history 40 - if type -p atuin >/dev/null; then 41 - export ATUIN_CONFIG_DIR=${pkgs.writeTextDir "/config.toml" '' 42 - auto_sync = true 43 - update_check = false 44 - sync_address = "http://green.r:8888" 45 - sync_frequency = 0 46 - style = "compact" 47 - ''}; 48 - export ATUIN_NOBIND="true" # disable all keybdinings of atuin 49 - eval "$(${pkgs.atuin}/bin/atuin init zsh)" # TODO make this optional? 50 - bindkey '^r' _atuin_search_widget # bind ctrl+r to atuin 51 - # use zsh only session history 52 - fc -p 53 - fi 54 - 55 - #completion magic 56 - autoload -Uz compinit 57 - compinit 58 - zstyle ':completion:*' menu select 59 - 60 - #enable automatic rehashing of $PATH 61 - zstyle ':completion:*' rehash true 62 - 63 - # fancy mv which interactively gets the second argument if not given 64 - function mv() { 65 - if [[ "$#" -ne 1 ]] || [[ ! -e "$1" ]]; then 66 - command mv -v "$@" 67 - return 68 - fi 69 - 70 - newfilename="$1" 71 - vared newfilename 72 - command mv -v -- "$1" "$newfilename" 73 - } 74 - 75 - #emacs bindings 76 - bindkey "[7~" beginning-of-line 77 - bindkey "[8~" end-of-line 78 - bindkey "Oc" emacs-forward-word 79 - bindkey "Od" emacs-backward-word 80 - 81 - # direnv integration 82 - eval "$(${pkgs.direnv}/bin/direnv hook zsh)" 83 - 84 - # This function is called whenever a command is not found. 85 - command_not_found_handler() { 86 - local p='${pkgs.nix-index}/etc/profile.d/command-not-found.sh' 87 - if [ -x "$p" ] && [ -f '/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite' ]; then 88 - # Run the helper program. 89 - "$p" "$@" 90 - 91 - # Retry the command if we just installed it. 92 - if [ $? = 126 ]; then 93 - "$@" 94 - else 95 - return 127 96 - fi 97 - else 98 - # Indicate than there was an error so ZSH falls back to its default handler 99 - echo "$1: command not found" >&2 100 - return 127 101 - fi 102 - } 103 - 104 - download_nixpkgs_cache_index () { 105 - filename="index-$(uname -m | sed 's/^arm64$/aarch64/')-$(uname | tr A-Z a-z)" 106 - mkdir -p ~/.cache/nix-index && cd ~/.cache/nix-index 107 - # -N will only download a new version if there is an update. 108 - wget -q -N https://github.com/nix-community/nix-index-database/releases/latest/download/$filename 109 - ln -f $filename files 110 - } 111 - 112 - # Setup aliases. 113 - alias -- grep='grep --color=auto' 114 - alias -- ip='ip -color=auto' 115 - alias -- l='ls -alh' 116 - alias -- la='ls -la' 117 - alias -- ll='ls -l' 118 - alias -- ls='ls --color' 119 - alias -- ns='nix-shell --command zsh' 120 - alias -- nb='nix build --no-link --print-out-paths -L' 121 - alias -- ne='nix eval --json' 122 - alias -- nloc='nix-locate --top-level --whole-name' 123 - 124 - # Setup prompt. 125 - autoload -U promptinit 126 - promptinit 127 - 128 - p_error='%(?..%F{red}%?%f )' 129 - t_error='%(?..%? )' 130 - 131 - case $UID in 132 - 0) 133 - p_username='%F{red}root%f' 134 - t_username='root' 135 - ;; 136 - 1337) 137 - p_username="" 138 - t_username="" 139 - ;; 140 - *) 141 - p_username='%F{blue}%n%f' 142 - t_username='%n' 143 - ;; 144 - esac 145 - 146 - if test -n "$SSH_CLIENT"; then 147 - p_hostname='@%F{magenta}%M%f ' 148 - t_hostname='@%M ' 149 - else 150 - p_hostname="" 151 - t_hostname="" 152 - fi 153 - 154 - #check if in nix shell 155 - if test -n "$IN_NIX_SHELL"; then 156 - p_nixshell='%F{green}[s]%f ' 157 - t_nixshell='[s] ' 158 - else 159 - p_nixshell="" 160 - t_nixshell="" 161 - fi 162 - 163 - PROMPT="$p_error$p_username$p_hostname$p_nixshell%~ " 164 - TITLE="$t_error$t_username$t_hostname$t_nixshell%~" 165 - case $TERM in 166 - (*xterm* | *rxvt*) 167 - function precmd { 168 - PROMPT_EVALED=$(print -P "$TITLE") 169 - echo -ne "\033]0;$$ $PROMPT_EVALED\007" 170 - } 171 - # This seems broken for some reason 172 - # # This is seen while the shell waits for a command to complete. 173 - # function preexec { 174 - # PROMPT_EVALED=$(print -P "$TITLE") 175 - # echo -ne "\033]0;$$ $PROMPT_EVALED $1\007" 176 - # } 177 - ;; 178 - esac 179 - 180 - 181 - # Disable some features to support TRAMP. 182 - if [ "$TERM" = dumb ]; then 183 - unsetopt zle prompt_cr prompt_subst 184 - unset RPS1 RPROMPT 185 - PS1='$ ' 186 - PROMPT='$ ' 187 - fi 188 - ''; 189 - in 190 - { 191 - packages.zsh = 192 - (pkgs.writeScriptBin "zsh" '' 193 - #!/bin/sh 194 - export ZDOTDIR=${pkgs.writeTextDir "/.zshrc" zshrc} 195 - exec ${pkgs.zsh}/bin/zsh "$@" 196 - '') 197 - // { 198 - zshrc = zshrc; 199 - }; 200 - }; 201 - }
+22
tools/get-spora-hosts/flake-module.nix
··· 1 + { self, ... }: 2 + { 3 + perSystem = 4 + { system, pkgs, ... }: 5 + { 6 + packages.get-spora-hosts = pkgs.writeScriptBin "get-spora-hosts" '' 7 + set -eu 8 + set -o pipefail 9 + set -x 10 + OUTDIR=$1 11 + for host in ${self}/machines/*; do 12 + if test -e "$host"/facts/mycelium_pubkey; then 13 + if ! test -e "$OUTDIR"/"$(basename "$host")".json; then 14 + ${ 15 + self.packages.${pkgs.system}.mycelium 16 + }/bin/mycelium inspect "$(cat "$host"/facts/mycelium_pubkey)" --json > "$OUTDIR/$(basename "$host").json" 17 + fi 18 + fi 19 + done 20 + ''; 21 + }; 22 + }
+102
tools/menu/flake-module.nix
··· 1 + { ... }: 2 + { 3 + perSystem = 4 + { pkgs, ... }: 5 + { 6 + packages.menu = 7 + if pkgs.stdenv.hostPlatform.isDarwin then 8 + (pkgs.writeShellApplication { 9 + name = "menu"; 10 + runtimeInputs = [ 11 + pkgs.choose-gui 12 + pkgs.fzf 13 + ]; 14 + text = '' 15 + set -efu 16 + 17 + # Create temporary files for input and output 18 + TEMP_DIR=$(mktemp -d) 19 + INPUT_FILE="$TEMP_DIR/input" 20 + OUTPUT_FILE="$TEMP_DIR/output" 21 + 22 + # Set up trap to clean up temp dir on exit 23 + trap 'rm -rf "$TEMP_DIR"' EXIT 24 + 25 + # Save stdin to file 26 + cat > "$INPUT_FILE" 27 + 28 + # Try fzf first with terminal UI - explicitly store exit code 29 + # This avoids issues with losing the exit code in a pipe 30 + set +e 31 + fzf "$@" < "$INPUT_FILE" > "$OUTPUT_FILE" 2>/dev/null 32 + FZF_EXIT=$? 33 + set -e 34 + 35 + # Handle fzf results based on exit code 36 + if [ $FZF_EXIT -eq 0 ]; then 37 + # Success - output result and exit 38 + cat "$OUTPUT_FILE" 39 + exit 0 40 + elif [ $FZF_EXIT -eq 130 ]; then 41 + # User pressed Escape - honor the cancellation 42 + exit 130 43 + fi 44 + 45 + # If we get here, fzf failed with error (not cancellation) 46 + 47 + # Fall back to GUI 48 + choose "$@" < "$INPUT_FILE" 49 + ''; 50 + }) 51 + else if pkgs.stdenv.hostPlatform.isLinux then 52 + (pkgs.writeShellApplication { 53 + name = "menu"; 54 + runtimeInputs = [ 55 + pkgs.rofi 56 + pkgs.wofi 57 + pkgs.fzf 58 + ]; 59 + text = '' 60 + set -efu 61 + # Create temporary files for input and output 62 + TEMP_DIR=$(mktemp -d) 63 + INPUT_FILE="$TEMP_DIR/input" 64 + OUTPUT_FILE="$TEMP_DIR/output" 65 + 66 + # Save stdin to file 67 + cat > "$INPUT_FILE" 68 + 69 + # Try fzf first with terminal UI - explicitly store exit code 70 + # This avoids issues with losing the exit code in a pipe 71 + set +e 72 + fzf "$@" < "$INPUT_FILE" > "$OUTPUT_FILE" 2>/dev/null 73 + FZF_EXIT=$? 74 + set -e 75 + 76 + # Handle fzf results based on exit code 77 + if [ $FZF_EXIT -eq 0 ]; then 78 + # Success - output result and exit 79 + cat "$OUTPUT_FILE" 80 + exit 0 81 + elif [ $FZF_EXIT -eq 130 ]; then 82 + # User pressed Escape - honor the cancellation 83 + exit 130 84 + fi 85 + 86 + # If we get here, fzf failed with error (not cancellation) 87 + 88 + # Fall back to GUI based on available display environment 89 + if [ -n "''${WAYLAND_DISPLAY:-}" ]; then 90 + wofi -d "$@" < "$INPUT_FILE" 91 + elif [ -n "''${DISPLAY:-}" ]; then 92 + rofi -dmenu "$@" < "$INPUT_FILE" 93 + else 94 + echo "Error: No suitable display environment available" >&2 95 + exit 1 96 + fi 97 + ''; 98 + }) 99 + else 100 + throw "unsupported system"; 101 + }; 102 + }
+309
tools/nvim/flake-module.nix
··· 1 + { inputs, ... }: 2 + { 3 + perSystem = 4 + { system, pkgs, ... }: 5 + { 6 + packages.nvim = inputs.nixvim.legacyPackages.${system}.makeNixvim { 7 + vimAlias = true; 8 + colorschemes = { 9 + ayu = { 10 + enable = true; 11 + settings.overrides = { 12 + EoLSpace = { 13 + bg = "#883333"; 14 + }; 15 + }; 16 + }; 17 + everforest = { 18 + enable = true; 19 + settings.overrides = { 20 + EoLSpace = { 21 + bg = "#FF2222"; # doesn't work 22 + }; 23 + }; 24 + }; 25 + }; 26 + globals = { 27 + mapleader = " "; 28 + lumen_light_colorscheme = "everforest"; 29 + lumen_dark_colorscheme = "ayu"; 30 + }; 31 + opts = { 32 + mouse = "a"; 33 + number = true; 34 + shiftwidth = 2; 35 + clipboard = "unnamedplus"; 36 + # undo stuff 37 + undofile = true; 38 + undolevels = 10000; 39 + undoreload = 10000; 40 + listchars = "tab:⇥ ,extends:❯,precedes:❮,nbsp:␣,trail:·,eol:↲"; 41 + }; 42 + extraConfigVim = '' 43 + set et 44 + 45 + " show special characters 46 + set list 47 + 48 + " match trailing whitespace 49 + match EoLSpace /\s\+$/ 50 + 51 + " need to use lua to expand $HOME 52 + lua vim.o.undodir = vim.fs.normalize('$HOME/.vim/undodir') 53 + ''; 54 + extraPackages = [ 55 + pkgs.glib # for vim-lumen 56 + ]; 57 + extraPlugins = [ 58 + pkgs.vimPlugins.vim-fetch 59 + (pkgs.vimUtils.buildVimPlugin { 60 + name = "vim-lumen"; 61 + src = pkgs.fetchFromGitHub { 62 + owner = "vimpostor"; 63 + repo = "vim-lumen"; 64 + rev = "ac13c32c3e309f6c6a84ff6cad8dbb135e75f0e4"; 65 + hash = "sha256-rsDUDI9lh4CEX1upMBjeyBOm99GAXWGPQ9vSCN8cmFo="; 66 + }; 67 + }) 68 + ]; 69 + # not ready yet, we are waiting for none-ls to get updated 70 + # extraConfigLua = '' 71 + # local null_ls = require("null-ls") 72 + # null_ls.register(null_ls.builtins.formatting.nix_flake_fmt) 73 + # ''; 74 + keymaps = [ 75 + { 76 + mode = "i"; 77 + key = "<C-p>"; 78 + action = "<Nop>"; 79 + } 80 + { 81 + mode = "i"; 82 + key = "<C-n>"; 83 + action = "<Nop>"; 84 + } 85 + { 86 + mode = "n"; 87 + key = "<C-c>"; 88 + action = ":q<cr>"; 89 + } 90 + { 91 + mode = "n"; 92 + key = "<Space>"; 93 + action = "<Nop>"; 94 + } 95 + { 96 + mode = "n"; 97 + key = "<leader>sd"; 98 + action = ":colorscheme ayu-dark<cr>"; 99 + } 100 + { 101 + mode = "n"; 102 + key = "<leader>sw"; 103 + action = ":colorscheme ayu-light<cr>"; 104 + } 105 + { 106 + mode = [ 107 + "n" 108 + "v" 109 + ]; 110 + key = "<leader>cc"; 111 + action = ":CopilotChatOpen<cr>"; 112 + } 113 + { 114 + mode = [ 115 + "n" 116 + "v" 117 + ]; 118 + key = "<leader>ce"; 119 + action = ":CopilotChatExplain<cr>"; 120 + } 121 + { 122 + mode = [ 123 + "n" 124 + "v" 125 + ]; 126 + key = "<leader>cr"; 127 + action = ":CopilotChatReview<cr>"; 128 + } 129 + { 130 + mode = [ 131 + "n" 132 + "v" 133 + ]; 134 + key = "<leader>cf"; 135 + action = ":CopilotChatFix<cr>"; 136 + } 137 + { 138 + mode = [ 139 + "n" 140 + "v" 141 + ]; 142 + key = "<leader>cd"; 143 + action = ":CopilotChatDocs<cr>"; 144 + } 145 + { 146 + mode = [ 147 + "n" 148 + "x" 149 + ]; 150 + key = "p"; 151 + action = "<Plug>(YankyPutAfter)"; 152 + } 153 + { 154 + mode = [ 155 + "n" 156 + "x" 157 + ]; 158 + key = "P"; 159 + action = "<Plug>(YankyPutBefore)"; 160 + } 161 + { 162 + mode = [ 163 + "c" 164 + "i" 165 + "n" 166 + "x" 167 + ]; 168 + key = "<M-CR>"; 169 + action = ":lua vim.lsp.buf.code_action()<CR>"; 170 + } 171 + { 172 + mode = [ 173 + "n" 174 + ]; 175 + key = "gd"; 176 + action = ":lua vim.lsp.buf.definition()<CR>"; 177 + } 178 + { 179 + mode = [ 180 + "n" 181 + ]; 182 + key = "gD"; 183 + action = ":lua vim.lsp.buf.declaration()<CR>"; 184 + } 185 + ]; 186 + # autoCmd = [ 187 + # { 188 + # event = "BufWritePost"; 189 + # desc = "run treefmt on save"; 190 + # # https://stackoverflow.com/questions/77466697/how-to-automatically-format-on-save 191 + # callback.__raw = '' 192 + # function() 193 + # vim.cmd("silent !treefmt %") 194 + # vim.cmd("edit") 195 + # end 196 + # ''; 197 + # } 198 + # ]; 199 + plugins.none-ls = { 200 + enable = true; 201 + # sources.formatting.treefmt = { 202 + # enable = true; 203 + # package = pkgs.emptyDirectory; 204 + # }; 205 + # package = pkgs.vimPlugins.none-ls-nvim.overrideAttrs (_old: { 206 + # src = pkgs.fetchFromGitHub { 207 + # owner = "lassulus"; 208 + # repo = "none-ls.nvim"; 209 + # rev = "292c2b5eadea0a097b9a01804aea70f5c8125200"; 210 + # sha256 = "sha256-nbzqXsxmYfxngdJH3NXMLmGgygh6reSEnruoc6l8t/s="; 211 + # }; 212 + # }); 213 + sources.formatting.nix_flake_fmt.enable = true; 214 + }; 215 + plugins.web-devicons.enable = true; 216 + plugins.telescope.extensions.undo.enable = true; 217 + plugins.telescope = { 218 + enable = true; 219 + keymaps = { 220 + "<leader>b" = "buffers"; 221 + "<leader>u" = "undo"; 222 + "<leader>ff" = "find_files"; 223 + "<leader>fg" = "live_grep"; 224 + "<leader>fh" = "help_tags"; 225 + "<leader>fp" = "yank_history"; 226 + }; 227 + }; 228 + plugins.lsp-format.enable = true; 229 + plugins.lsp-lines.enable = true; 230 + plugins.lsp = { 231 + enable = true; 232 + servers = { 233 + bashls.enable = true; # bash 234 + nixd = { 235 + enable = true; # nix 236 + extraOptions.offset_encoding = "utf-8"; # workaround https://github.com/nix-community/nixvim/issues/2390#issuecomment-2408101568 237 + }; 238 + ruff.enable = true; # python 239 + pyright.enable = true; # python 240 + jsonls.enable = true; # json 241 + }; 242 + }; 243 + plugins.treesitter.enable = true; 244 + plugins.copilot-cmp.enable = true; 245 + plugins.copilot-lua.settings.panel.enabled = false; 246 + plugins.copilot-lua.settings.suggestion.enabled = false; 247 + plugins.cmp_yanky.enable = true; 248 + plugins.cmp = { 249 + enable = true; 250 + autoEnableSources = true; 251 + settings = { 252 + experimental = { 253 + ghost_text = true; 254 + }; 255 + sources = [ 256 + { name = "nvim_lsp"; } 257 + { name = "emoji"; } 258 + { 259 + name = "buffer"; # text within current buffer 260 + option.get_bufnrs.__raw = "vim.api.nvim_list_bufs"; 261 + keywordLength = 2; 262 + } 263 + { 264 + name = "copilot"; # enable copilot 265 + } 266 + { 267 + name = "path"; # file system paths 268 + keywordLength = 3; 269 + } 270 + { name = "cmp_yanky"; } 271 + ]; 272 + 273 + mapping = { 274 + "<Tab>" = "cmp.mapping.select_next_item()"; 275 + "<S-Tab>" = "cmp.mapping.select_prev_item()"; 276 + "<C-n>" = "cmp.mapping.select_next_item()"; 277 + "<C-p>" = "cmp.mapping.select_prev_item()"; 278 + "<C-e>" = "cmp.mapping.abort()"; 279 + "<C-b>" = "cmp.mapping.scroll_docs(-4)"; 280 + "<C-f>" = "cmp.mapping.scroll_docs(4)"; 281 + "<CR>" = '' 282 + cmp.mapping({ 283 + i = function(fallback) 284 + if cmp.visible() and cmp.get_active_entry() then 285 + cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }) 286 + else 287 + fallback() 288 + end 289 + end, 290 + s = cmp.mapping.confirm({ select = true }), 291 + c = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = true }), 292 + }) 293 + ''; 294 + }; 295 + }; 296 + }; 297 + plugins.bufferline.enable = true; 298 + plugins.which-key.enable = true; 299 + plugins.yanky = { 300 + enable = true; 301 + enableTelescope = true; 302 + }; 303 + plugins.comment.enable = true; 304 + plugins.copilot-chat.enable = true; 305 + plugins.undotree.enable = true; # seems to be needed for undo history in telescope 306 + plugins.gitsigns.enable = true; 307 + }; 308 + }; 309 + }
+26
tools/pass/flake-module.nix
··· 1 + { self, ... }: 2 + { 3 + perSystem = 4 + { pkgs, ... }: 5 + { 6 + packages.pass = pkgs.symlinkJoin { 7 + name = "pass"; 8 + paths = [ 9 + (pkgs.writeShellApplication { 10 + name = "pass"; 11 + runtimeInputs = [ 12 + (pkgs.pass.withExtensions (ext: [ ext.pass-otp ])) 13 + pkgs.gnupg 14 + ]; 15 + text = '' 16 + set -efu 17 + gpg --import ${self.keys.pgp.yubi.key} &>/dev/null 18 + echo '${self.keys.pgp.yubi.id}:6:' | gpg --import-ownertrust &>/dev/null 19 + pass "$@" 20 + ''; 21 + }) 22 + (pkgs.pass.withExtensions (ext: [ ext.pass-otp ])) 23 + ]; 24 + }; 25 + }; 26 + }
+67
tools/passmenu/flake-module.nix
··· 1 + { self, ... }: 2 + { 3 + perSystem = 4 + { pkgs, ... }: 5 + { 6 + packages.passmenu = pkgs.writeShellApplication { 7 + name = "passmenu"; 8 + runtimeInputs = with pkgs; [ 9 + self.packages.${pkgs.system}.menu 10 + self.packages.${pkgs.system}.pass 11 + ] ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ 12 + wtype 13 + xdotool 14 + ]; 15 + text = '' 16 + set -eu 17 + shopt -s nullglob globstar 18 + 19 + typeit=0 20 + if [[ $# -gt 0 && $1 == "--type" ]]; then 21 + typeit=1 22 + shift 23 + fi 24 + 25 + prefix=''${PASSWORD_STORE_DIR-~/.password-store} 26 + password_files=( "$prefix"/**/*.gpg ) 27 + password_files=( "''${password_files[@]#"$prefix"/}" ) 28 + password_files=( "''${password_files[@]%.gpg}" ) 29 + 30 + password=$(printf '%s\n' "''${password_files[@]}" | menu "$@") 31 + 32 + filename=$(basename "$password") 33 + if [[ "$filename" == "otp" ]]; then 34 + if [[ $typeit -eq 1 ]]; then 35 + # Type OTP code 36 + otp_code=$(pass otp "$password" | tr -d '\n') 37 + if [[ "$(uname)" == "Darwin" ]]; then 38 + # On macOS, use osascript to type the code 39 + osascript -e "tell application \"System Events\" to keystroke \"$otp_code\"" 2>/dev/null 40 + elif [[ -n "$WAYLAND_DISPLAY" ]]; then 41 + echo -n "$otp_code" | wtype -d 10 -s 400 - 42 + else 43 + echo -n "$otp_code" | xdotool type --clearmodifiers --file - 44 + fi 45 + else 46 + pass otp --clip "$password" 2>/dev/null 47 + fi 48 + else 49 + if [[ $typeit -eq 1 ]]; then 50 + # Type password 51 + pw=$(pass show "$password" | head -n1 | tr -d '\n') 52 + if [[ "$(uname)" == "Darwin" ]]; then 53 + # On macOS, use osascript to type the password 54 + osascript -e "tell application \"System Events\" to keystroke \"$pw\"" 2>/dev/null 55 + elif [[ -n "$WAYLAND_DISPLAY" ]]; then 56 + echo -n "$pw" | wtype -d 10 -s 400 - 57 + else 58 + echo -n "$pw" | xdotool type --clearmodifiers --file - 59 + fi 60 + else 61 + pass show --clip "$password" 2>/dev/null 62 + fi 63 + fi 64 + ''; 65 + }; 66 + }; 67 + }
+21
tools/wifi-qr/flake-module.nix
··· 1 + 2 + { ... }: 3 + { 4 + perSystem = 5 + { pkgs, ... }: { 6 + packages.wifi-qr = pkgs.writeShellApplication { 7 + name = "wifi-qr"; 8 + runtimeInputs = [ 9 + pkgs.zbar 10 + pkgs.gawk 11 + ]; 12 + text = '' 13 + QR_CODE=$(zbarcam --raw --oneshot) 14 + SSID=$(echo "$QR_CODE" | awk -F 'S:' '{print $2}' | awk -F ';' '{print $1}') 15 + PW=$(echo "$QR_CODE" | awk -F 'P:' '{print $2}' | awk -F ';' '{print $1}') 16 + nmcli dev wifi rescan 17 + nmcli dev wifi connect "$SSID" password "$PW" 18 + ''; 19 + }; 20 + }; 21 + }
+201
tools/zsh/flake-module.nix
··· 1 + { ... }: 2 + { 3 + perSystem = 4 + { pkgs, ... }: 5 + let 6 + zshrc = '' 7 + autoload -U compinit && compinit 8 + 9 + # Setup custom interactive shell init stuff. 10 + # Bind gpg-agent to this TTY if gpg commands are used. 11 + export GPG_TTY=$(tty) 12 + 13 + # show how long a command takes 14 + ZSH_COMMAND_TIME_MIN_SECONDS=3 15 + ZSH_COMMAND_TIME_EXCLUDE=(vim) 16 + ZSH_COMMAND_TIME_MSG="took: %s sec" 17 + source ${ 18 + pkgs.fetchFromGitHub { 19 + owner = "popstas"; 20 + repo = "zsh-command-time"; 21 + rev = "803d26eef526bff1494d1a584e46a6e08d25d918"; 22 + hash = "sha256-ndHVFcz+XmUW0zwFq7pBXygdRKyPLjDZNmTelhd5bv8="; 23 + } 24 + }/command-time.plugin.zsh 25 + 26 + unsetopt nomatch # no matches found urls 27 + setopt autocd extendedglob 28 + bindkey -e 29 + 30 + #C-x C-e open line in editor 31 + autoload -z edit-command-line 32 + zle -N edit-command-line 33 + bindkey "^X^E" edit-command-line 34 + 35 + #fzf inclusion 36 + source ${pkgs.fzf}/share/fzf/completion.zsh 37 + source ${pkgs.fzf}/share/fzf/key-bindings.zsh 38 + 39 + # atuin distributed shell history 40 + if type -p atuin >/dev/null; then 41 + export ATUIN_CONFIG_DIR=${pkgs.writeTextDir "/config.toml" '' 42 + auto_sync = true 43 + update_check = false 44 + sync_address = "http://green.r:8888" 45 + sync_frequency = 0 46 + style = "compact" 47 + ''}; 48 + export ATUIN_NOBIND="true" # disable all keybdinings of atuin 49 + eval "$(${pkgs.atuin}/bin/atuin init zsh)" # TODO make this optional? 50 + bindkey '^r' _atuin_search_widget # bind ctrl+r to atuin 51 + # use zsh only session history 52 + fc -p 53 + fi 54 + 55 + #completion magic 56 + autoload -Uz compinit 57 + compinit 58 + zstyle ':completion:*' menu select 59 + 60 + #enable automatic rehashing of $PATH 61 + zstyle ':completion:*' rehash true 62 + 63 + # fancy mv which interactively gets the second argument if not given 64 + function mv() { 65 + if [[ "$#" -ne 1 ]] || [[ ! -e "$1" ]]; then 66 + command mv -v "$@" 67 + return 68 + fi 69 + 70 + newfilename="$1" 71 + vared newfilename 72 + command mv -v -- "$1" "$newfilename" 73 + } 74 + 75 + #emacs bindings 76 + bindkey "[7~" beginning-of-line 77 + bindkey "[8~" end-of-line 78 + bindkey "Oc" emacs-forward-word 79 + bindkey "Od" emacs-backward-word 80 + 81 + # direnv integration 82 + eval "$(${pkgs.direnv}/bin/direnv hook zsh)" 83 + 84 + # This function is called whenever a command is not found. 85 + command_not_found_handler() { 86 + local p='${pkgs.nix-index}/etc/profile.d/command-not-found.sh' 87 + if [ -x "$p" ] && [ -f '/nix/var/nix/profiles/per-user/root/channels/nixos/programs.sqlite' ]; then 88 + # Run the helper program. 89 + "$p" "$@" 90 + 91 + # Retry the command if we just installed it. 92 + if [ $? = 126 ]; then 93 + "$@" 94 + else 95 + return 127 96 + fi 97 + else 98 + # Indicate than there was an error so ZSH falls back to its default handler 99 + echo "$1: command not found" >&2 100 + return 127 101 + fi 102 + } 103 + 104 + download_nixpkgs_cache_index () { 105 + filename="index-$(uname -m | sed 's/^arm64$/aarch64/')-$(uname | tr A-Z a-z)" 106 + mkdir -p ~/.cache/nix-index && cd ~/.cache/nix-index 107 + # -N will only download a new version if there is an update. 108 + wget -q -N https://github.com/nix-community/nix-index-database/releases/latest/download/$filename 109 + ln -f $filename files 110 + } 111 + 112 + # Setup aliases. 113 + alias -- grep='grep --color=auto' 114 + alias -- ip='ip -color=auto' 115 + alias -- l='ls -alh' 116 + alias -- la='ls -la' 117 + alias -- ll='ls -l' 118 + alias -- ls='ls --color' 119 + alias -- ns='nix-shell --command zsh' 120 + alias -- nb='nix build --no-link --print-out-paths -L' 121 + alias -- ne='nix eval --json' 122 + alias -- nloc='nix-locate --top-level --whole-name' 123 + 124 + # Setup prompt. 125 + autoload -U promptinit 126 + promptinit 127 + 128 + p_error='%(?..%F{red}%?%f )' 129 + t_error='%(?..%? )' 130 + 131 + case $UID in 132 + 0) 133 + p_username='%F{red}root%f' 134 + t_username='root' 135 + ;; 136 + 1337) 137 + p_username="" 138 + t_username="" 139 + ;; 140 + *) 141 + p_username='%F{blue}%n%f' 142 + t_username='%n' 143 + ;; 144 + esac 145 + 146 + if test -n "$SSH_CLIENT"; then 147 + p_hostname='@%F{magenta}%M%f ' 148 + t_hostname='@%M ' 149 + else 150 + p_hostname="" 151 + t_hostname="" 152 + fi 153 + 154 + #check if in nix shell 155 + if test -n "$IN_NIX_SHELL"; then 156 + p_nixshell='%F{green}[s]%f ' 157 + t_nixshell='[s] ' 158 + else 159 + p_nixshell="" 160 + t_nixshell="" 161 + fi 162 + 163 + PROMPT="$p_error$p_username$p_hostname$p_nixshell%~ " 164 + TITLE="$t_error$t_username$t_hostname$t_nixshell%~" 165 + case $TERM in 166 + (*xterm* | *rxvt*) 167 + function precmd { 168 + PROMPT_EVALED=$(print -P "$TITLE") 169 + echo -ne "\033]0;$$ $PROMPT_EVALED\007" 170 + } 171 + # This seems broken for some reason 172 + # # This is seen while the shell waits for a command to complete. 173 + # function preexec { 174 + # PROMPT_EVALED=$(print -P "$TITLE") 175 + # echo -ne "\033]0;$$ $PROMPT_EVALED $1\007" 176 + # } 177 + ;; 178 + esac 179 + 180 + 181 + # Disable some features to support TRAMP. 182 + if [ "$TERM" = dumb ]; then 183 + unsetopt zle prompt_cr prompt_subst 184 + unset RPS1 RPROMPT 185 + PS1='$ ' 186 + PROMPT='$ ' 187 + fi 188 + ''; 189 + in 190 + { 191 + packages.zsh = 192 + (pkgs.writeScriptBin "zsh" '' 193 + #!/bin/sh 194 + export ZDOTDIR=${pkgs.writeTextDir "/.zshrc" zshrc} 195 + exec ${pkgs.zsh}/bin/zsh "$@" 196 + '') 197 + // { 198 + zshrc = zshrc; 199 + }; 200 + }; 201 + }