grace/dots

dotfiles/nix configs

git clone https://git.gae.moe/grace/dots

Grace Yodertpb enabled8e8bfe4

main
15.6 KiB594 linesraw
1{
2  config,
3  lib,
4  pkgs,
5  ...
6}:
7
8let
9  tpbSrc = builtins.fetchGit {
10    url = "https://git.gae.moe/grace/tpb.git";
11    ref = "refs/heads/main";
12  };
13in
14{
15  home.packages = with pkgs; [
16    pfetch-rs
17    sesh
18    ripgrep
19    dust
20    tree
21    btop
22    curl
23    fd
24    uutils-coreutils
25    wget
26    jq
27    yq
28    yj
29    most
30    asciinema
31    bash
32    openssh
33    openssl
34
35    (
36      (import "${tpbSrc}/default.nix" {
37        inherit pkgs;
38      }).overrideAttrs
39      (_: {
40        unpackPhase = ''
41          mkdir source
42          tar --no-same-owner --no-same-permissions --no-overwrite-dir --mode=0755 \
43            -C "$src" -cf - . \
44            | tar --no-same-owner --no-same-permissions --no-overwrite-dir --mode=0755 \
45              -C source -xf -
46          chmod -R u+w source
47          sourceRoot=source
48        '';
49      })
50    )
51  ];
52
53  xdg.configFile."fish/themes/rose_pine.theme".source = ../fish/rose_pine.theme;
54
55  programs.fish = {
56    enable = true;
57
58    shellAliases = {
59      setupidf = "source /opt/esp/esp-idf/export.fish";
60      pysource = "source .venv/bin/activate.fish";
61      tcl = "clear && clear";
62      tclear = "clear && clear";
63    };
64
65    functions = {
66      nixos-target = {
67        description = "Build and deploy a local NixOS configuration to a remote host";
68        body = ''
69          set -lx NIX_HOST $argv[1]
70          ${pkgs.nixos-rebuild}/bin/nixos-rebuild switch \
71            --file ./system.nix \
72            --build-host builder@dijkstra.i.gae.moe \
73            --target-host "grace@$NIX_HOST.i.gae.moe" \
74            --elevate sudo
75        '';
76      };
77
78      ask = {
79        description = "Ask for input and respond with input";
80        body = ''
81          read -s -P "Enter Input: " response
82          echo $response
83        '';
84      };
85
86      loadenv = ''
87        argparse h/help print printb U/unload -- $argv
88        or return 1
89
90        if set -q _flag_help
91            echo "Usage: loadenv [OPTIONS] [FILE]"
92            echo ""
93            echo "Export keys and values from a dotenv file."
94            echo ""
95            echo "Options:"
96            echo "  --help, -h      Show this help message"
97            echo "  --print         Print env keys (export preview)"
98            echo "  --printb        Print keys with surrounding brackets"
99            echo "  --unload, -U    Unexport all keys defined in the dotenv file"
100            echo ""
101            echo "Arguments:"
102            echo "  FILE            Path to dotenv file (default: .env)"
103            return 0
104        end
105
106        if test (count $argv) -gt 1
107            echo "Too many arguments. Only one argument is allowed. Use --help for more information."
108            return 1
109        end
110
111        set -l dotenv_file ".env"
112        if test (count $argv) -eq 1
113            set dotenv_file $argv[1]
114        end
115
116        if not test -f $dotenv_file
117            echo "Error: File '$dotenv_file' not found in the current directory."
118            return 1
119        end
120
121        set -l mode load
122        if set -q _flag_print
123            set mode print
124        else if set -q _flag_printb
125            set mode printb
126        else if set -q _flag_unload
127            set mode unload
128        end
129
130        set lineNumber 0
131
132        for line in (cat $dotenv_file)
133            set lineNumber (math $lineNumber + 1)
134
135            if string match -qr '^\s*$|^\s*#' $line
136                continue
137            end
138
139            if not string match -qr '^[A-Za-z_][A-Za-z0-9_]*=' $line
140                echo "Error: invalid declaration (line $lineNumber): $line"
141                return 1
142            end
143
144            set -l key (string split -m 1 '=' $line)[1]
145            set -l after_equals_sign (string split -m 1 '=' $line)[2]
146
147            set -l value
148            set -l double_quoted_value_regex '^"(.*)"\s*(?:#.*)*$'
149            set -l single_quoted_value_regex '^\'(.*)\'\s*(?:#.*)*$'
150            set -l plain_value_regex '^([^\'"\s]*)\s*(?:#.*)*$'
151            if string match -qgr $double_quoted_value_regex $after_equals_sign
152                set value (string match -gr $double_quoted_value_regex $after_equals_sign)
153            else if string match -qgr $single_quoted_value_regex $after_equals_sign
154                set value (string match -gr $single_quoted_value_regex $after_equals_sign)
155            else if string match -qgr $plain_value_regex $after_equals_sign
156                set value (string match -gr $plain_value_regex $after_equals_sign)
157            else
158                echo "Error: invalid value (line $lineNumber): $line"
159                return 1
160            end
161
162            switch $mode
163                case print
164                    echo "$key=$value"
165                case printb
166                    echo "[$key=$value]"
167                case load
168                    set -gx $key $value
169                case unload
170                    set -e $key
171            end
172        end
173      '';
174
175      # Broken :/
176      nix = {
177        wraps = "nix";
178        body = ''
179          if test (count $argv) -gt 0; and test "$argv[1]" = shell
180              set -lx STARSHIP_NIX_SHELL shell
181          end
182
183          command nix $argv
184        '';
185      };
186
187      sshsignkey = ''
188        argparse \
189          't/tag=+' \
190          'h/host=' \
191          'u/user=' \
192          'I/identity=' \
193          'V/validity=' \
194          -- $argv
195        or return 2
196
197        if test (count $argv) -ne 1
198          echo "usage: sshsignkey [-t TAG ...] [-h HOST] [-u USER] [-I ID] [-V VALIDITY] 'PUBLIC KEY'" >&2
199          return 2
200        end
201
202        set -l ca_pub ~/.ssh/ssh-ca.pub
203        set -l principals
204
205        for tag in $_flag_tag
206          set -a principals "t:$tag"
207        end
208
209        if set -q _flag_host
210          set -a principals "h:$_flag_host"
211        end
212
213        if set -q _flag_user
214          set -a principals "u:$_flag_user"
215        end
216
217        if test (count $principals) -eq 0
218          echo "sshsignkey: at least one principal is required" >&2
219          return 2
220        end
221
222        if set -q _flag_identity
223          set -l identity "$_flag_identity"
224        else if set -q _flag_user; and set -q _flag_host
225          set -l identity "$_flag_user@$_flag_host"
226        else if set -q _flag_user
227          set -l identity "$_flag_user"
228        else if set -q _flag_host
229          set -l identity "$_flag_host"
230        else
231          set -l identity "ssh-cert"
232        end
233
234        if not test -f "$ca_pub"
235          echo "sshsignkey: CA public key not found: $ca_pub" >&2
236          return 1
237        end
238
239        set -l pivroot (dirname (dirname "${pkgs.yubico-piv-tool}/bin/yubico-piv-tool"))
240
241        set -l ykcs11 (
242          ${pkgs.findutils}/bin/find "$pivroot" \
243            -name 'libykcs11.dylib' \
244            -o -name 'libykcs11.so' \
245            | ${pkgs.coreutils}/bin/head -n1
246        )
247
248        if test -z "$ykcs11"
249          echo "sshsignkey: could not find libykcs11" >&2
250          return 1
251        end
252
253        set -l tmpdir (${pkgs.coreutils}/bin/mktemp -d)
254        or return 1
255
256        set -l pubfile "$tmpdir/key.pub"
257        printf '%s\n' "$argv[1]" > "$pubfile"
258
259        set -l ssh_args \
260          -s "$ca_pub" \
261          -D "$ykcs11" \
262          -I "$identity" \
263          -n (string join ',' $principals)
264
265        if set -q _flag_validity
266          set -a ssh_args -V "$_flag_validity"
267        end
268
269        set -lx SSH_ASKPASS_REQUIRE force
270        set -lx SSH_ASKPASS ${pkgs.writeShellScript "yubikey-verify-none" ''
271          printf '%s\n' VERIFY_NONE
272        ''}
273
274        echo "Touch your YubiKey to sign the SSH certificate..." >&2
275
276        ${pkgs.openssh}/bin/ssh-keygen $ssh_args "$pubfile" >/dev/null
277        set -l rc $status
278
279        if test $rc -ne 0
280          ${pkgs.coreutils}/bin/rm -rf "$tmpdir"
281          return $rc
282        end
283
284        ${pkgs.coreutils}/bin/cat "$tmpdir/key-cert.pub"
285
286        ${pkgs.coreutils}/bin/rm -rf "$tmpdir"
287      '';
288    };
289
290    interactiveShellInit = ''
291      set -g fish_greeting ""
292      fish_vi_key_bindings
293      fish_config theme choose rose_pine
294      pfetch
295    '';
296  };
297
298  programs.fzf = {
299    enable = true;
300    enableFishIntegration = true;
301  };
302
303  programs.zoxide = {
304    enable = true;
305    enableFishIntegration = true;
306  };
307
308  programs.starship = {
309    enable = true;
310    enableFishIntegration = true;
311    extraPackages = [
312      pkgs.jj-starship
313    ];
314
315    settings = {
316      format = lib.concatStrings [
317        "$hostname"
318        "$username"
319        "$directory"
320        "$git_branch"
321        "$git_status"
322        "\${custom.jj}"
323        "\${custom.git_status}"
324        "$fill"
325        "\${env_var.NIX_SHELL}"
326        "$c"
327        "$elixir"
328        "$elm"
329        "$golang"
330        "$haskell"
331        "$java"
332        "$julia"
333        "$nodejs"
334        "$nim"
335        "$rust"
336        "$scala"
337        "$conda"
338        "$python"
339        "$time"
340        "\n"
341        "[❯](fg:iris) "
342      ];
343
344      palette = "rose-pine";
345
346      palettes = {
347        rose-pine = {
348          overlay = "#26233a";
349          love = "#eb6f92";
350          gold = "#f6c177";
351          rose = "#ebbcba";
352          pine = "#31748f";
353          foam = "#9ccfd8";
354          iris = "#c4a7e7";
355        };
356      };
357
358      directory = {
359        format = "[](fg:overlay)[ $path ]($style)[](fg:overlay) ";
360        style = "bg:overlay fg:pine";
361        truncation_length = 3;
362        truncation_symbol = "…/";
363
364        substitutions = {
365          Documents = "󰈙";
366          Downloads = " ";
367          Music = " ";
368          Pictures = " ";
369        };
370      };
371
372      fill = {
373        style = "fg:overlay";
374        symbol = " ";
375      };
376
377      git_branch = {
378        disabled = true;
379        format = "[](fg:overlay)[ $symbol $branch ]($style)[](fg:overlay) ";
380        style = "bg:overlay fg:foam";
381        symbol = "";
382      };
383
384      git_status = {
385        disabled = true;
386        style = "bg:overlay fg:love";
387        format = "[](fg:overlay)([$all_status$ahead_behind]($style))[](fg:overlay) ";
388
389        up_to_date = "[ ✓ ](bg:overlay fg:iris)";
390
391        untracked = ''[?\($count\)](bg:overlay fg:gold)'';
392
393        stashed = ''[\$](bg:overlay fg:iris)'';
394
395        modified = ''[!\($count\)](bg:overlay fg:gold)'';
396
397        renamed = ''[»\($count\)](bg:overlay fg:iris)'';
398
399        deleted = ''[✘\($count\)](style)'';
400
401        staged = ''[++\($count\)](bg:overlay fg:gold)'';
402
403        ahead = ''[⇡\(''${count}\)](bg:overlay fg:foam)'';
404
405        diverged = ''⇕[\[](bg:overlay fg:iris)[⇡\(''${ahead_count}\)](bg:overlay fg:foam)[⇣\(''${behind_count}\)](bg:overlay fg:rose)[\]](bg:overlay fg:iris)'';
406
407        behind = ''[⇣\(''${count}\)](bg:overlay fg:rose)'';
408      };
409
410      custom = {
411        jj = {
412          command = ''
413            jj-starship --git-symbol "" --no-git-status | sed "s/\x1b\[0m//g"
414          '';
415
416          when = "jj-starship detect";
417
418          shell = [
419            "sh"
420          ];
421
422          format = "[](fg:overlay)[[ $output ](bg:overlay)]($style)[](fg:overlay) ";
423
424          style = "bg:overlay fg:rose";
425
426          unsafe_no_escape = true;
427        };
428
429        git_status = {
430          command = ''
431            git status --porcelain | awk '
432              /^[MARC ][MD]/ || /^[MARC][MARC ]/ { modified++ }
433              /^\?\?/ { untracked++ }
434              /^[D ]D/ || /^D/ { deleted++ }
435              END {
436                if (modified + untracked + deleted == 0) {
437                  printf "\033[38;2;196;167;231m✓"
438                } else {
439                  if (modified)  printf "\033[38;2;246;193;119m%d ", modified
440                  if (untracked) printf "\033[38;2;246;193;119m%d ", untracked
441                  if (deleted)   printf "\033[38;2;235;111;146m󰆴%d ", deleted
442                }
443              }
444            '
445
446            unpushed=$(git rev-list @{u}..HEAD 2>/dev/null | wc -l | tr -d ' ')
447
448            if [ -n "$unpushed" ] && [ "$unpushed" -gt 0 ]; then
449              printf "\033[38;2;137;220;235m⇡%d " "$unpushed"
450            fi
451          '';
452
453          when = "git rev-parse --is-inside-work-tree 2>/dev/null && ! jj root 2>/dev/null";
454
455          shell = [
456            "sh"
457          ];
458
459          format = "[](fg:overlay)[[ $output ](bg:overlay)]($style)[](fg:overlay) ";
460
461          style = "bg:overlay fg:love";
462
463          unsafe_no_escape = true;
464        };
465      };
466
467      time = {
468        disabled = false;
469        format = " [](fg:overlay)[ $time 󰴈 ]($style)[](fg:overlay)";
470        style = "bg:overlay fg:rose";
471        time_format = "%I:%M%P";
472        use_12hr = true;
473      };
474
475      hostname = {
476        disabled = false;
477        ssh_only = false;
478        trim_at = "";
479        format = "[](fg:overlay)[ 󰠧 $hostname$ssh_symbol ]($style)[](fg:overlay) ";
480        style = "bg:overlay fg:rose";
481        ssh_symbol = " ";
482      };
483
484      username = {
485        disabled = false;
486        format = "[](fg:overlay)[ 󰧱 $user ]($style)[](fg:overlay) ";
487        show_always = true;
488        style_root = "bg:overlay fg:iris";
489        style_user = "bg:overlay fg:iris";
490      };
491
492      env_var.NIX_SHELL = {
493        variable = "STARSHIP_NIX_SHELL";
494        symbol = " ";
495        format = "[](fg:overlay)[ $symbol$env_value ]($style)[](fg:overlay) ";
496        style = "bg:overlay fg:foam";
497      };
498
499      # Languages
500
501      c = {
502        style = "bg:overlay fg:pine";
503        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
504        disabled = false;
505        symbol = " ";
506      };
507
508      elixir = {
509        style = "bg:overlay fg:pine";
510        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
511        disabled = false;
512        symbol = " ";
513      };
514
515      elm = {
516        style = "bg:overlay fg:pine";
517        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
518        disabled = false;
519        symbol = " ";
520      };
521
522      golang = {
523        style = "bg:overlay fg:pine";
524        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
525        disabled = false;
526        symbol = " ";
527      };
528
529      haskell = {
530        style = "bg:overlay fg:pine";
531        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
532        disabled = false;
533        symbol = " ";
534      };
535
536      java = {
537        style = "bg:overlay fg:pine";
538        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
539        disabled = false;
540        symbol = " ";
541      };
542
543      julia = {
544        style = "bg:overlay fg:pine";
545        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
546        disabled = false;
547        symbol = " ";
548      };
549
550      nodejs = {
551        style = "bg:overlay fg:pine";
552        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
553        disabled = false;
554        symbol = "󰎙 ";
555      };
556
557      nim = {
558        style = "bg:overlay fg:pine";
559        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
560        disabled = false;
561        symbol = "󰆥 ";
562      };
563
564      rust = {
565        style = "bg:overlay fg:pine";
566        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
567        disabled = false;
568        symbol = " ";
569      };
570
571      scala = {
572        style = "bg:overlay fg:pine";
573        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
574        disabled = false;
575        symbol = " ";
576      };
577
578      python = {
579        style = "bg:overlay fg:pine";
580        format = " [](fg:overlay)[ $symbol$version ]($style)[](fg:overlay)";
581        disabled = false;
582        symbol = " ";
583      };
584
585      conda = {
586        style = "bg:overlay fg:pine";
587        format = " [](fg:overlay)[ $symbol$environment ]($style)[](fg:overlay)";
588        disabled = false;
589        symbol = "🅒 ";
590      };
591    };
592  };
593
594}