This repository has no description
4.2 kB
130 lines
1{ self, ... }:
2{
3 perSystem =
4 { pkgs, lib, ... }:
5 let
6 # Collect all completable package names
7 packageNames = builtins.attrNames self.packages.${pkgs.system};
8 legacyPackageNames =
9 let
10 lp = self.legacyPackages.${pkgs.system} or { };
11 flatten =
12 prefix: attrs:
13 lib.concatLists (
14 lib.mapAttrsToList (
15 name: value:
16 let
17 path = if prefix == "" then name else "${prefix}.${name}";
18 in
19 if lib.isDerivation value then
20 [ path ]
21 else if builtins.isAttrs value then
22 flatten path value
23 else
24 [ ]
25 ) attrs
26 );
27 in
28 flatten "" lp;
29 allNames = packageNames ++ legacyPackageNames;
30
31 completionPath = lib.makeBinPath [
32 pkgs.nix
33 pkgs.jq
34 pkgs.usage
35 ];
36
37 zshCompletion = pkgs.writeText "_s" ''
38 #compdef s
39
40 _s() {
41 local -x PATH="${completionPath}:$PATH"
42
43 if (( CURRENT == 2 )); then
44 # Complete package name
45 local -a packages
46 packages=(
47 ${lib.concatMapStringsSep "\n " (name: "'${name}'") allNames}
48 )
49 _describe 'package' packages
50 else
51 # Complete args for the selected package using usage spec
52 local pkg="''${words[2]}"
53 [[ -z "$pkg" ]] && return
54
55 # Resolve flake path (same logic as s itself)
56 local flake
57 if [[ -d "$HOME/src/superconfig" ]]; then
58 flake="$HOME/src/superconfig"
59 else
60 flake="${self}"
61 fi
62
63 # Cache directory
64 local cache_dir="''${XDG_CACHE_HOME:-$HOME/.cache}/s-completions"
65
66 # Get cache key from flake narHash (~0.1s)
67 local cache_key
68 cache_key=$(nix flake metadata "$flake" --json 2>/dev/null | jq -r '.locked.narHash // .narHash // (.lastModified | tostring)' 2>/dev/null) || return
69 [[ -z "$cache_key" ]] && return
70 cache_key=''${cache_key//\//_}
71
72 local cached_file="$cache_dir/''${cache_key}/''${pkg}.kdl"
73
74 if [[ ! -f "$cached_file" ]]; then
75 # Cache miss: fetch usage spec via nix eval (~3.6s, first time only)
76 mkdir -p "$cache_dir/$cache_key"
77 local sys
78 sys=$(nix eval --impure --raw --expr 'builtins.currentSystem' 2>/dev/null) || return
79 nix eval "''${flake}#packages.''${sys}.''${pkg}.usage" --raw 2>/dev/null > "$cached_file" || {
80 rm -f "$cached_file"
81 return
82 }
83 # Empty file means no usage spec
84 [[ -s "$cached_file" ]] || { rm -f "$cached_file"; return; }
85 fi
86
87 # Feed to usage complete-word (~4ms), using the ((...)) format that _arguments expects
88 _arguments "*: :(($(usage complete-word --shell zsh -f "$cached_file" -- "''${words[@]:1}")))"
89 fi
90 }
91
92 _s "$@"
93 '';
94 in
95 {
96 packages.s =
97 (pkgs.writeShellApplication {
98 name = "s";
99 runtimeInputs = [ pkgs.nix ];
100 text = ''
101 # Use local checkout if it exists, otherwise fall back to self
102 if [ -d "$HOME/src/superconfig" ]; then
103 flake="$HOME/src/superconfig"
104 else
105 flake="${self}"
106 fi
107
108 if [ $# -eq 0 ]; then
109 echo "Usage: s <package> [args...]" >&2
110 echo "Runs a package from superconfig ($flake)" >&2
111 exit 1
112 fi
113
114 pkg="$1"
115 shift
116
117 exec nix run "$flake#$pkg" -- "$@"
118 '';
119 }).overrideAttrs
120 (old: {
121 buildCommand = old.buildCommand + ''
122 mkdir -p $out/share/zsh/site-functions
123 cp ${zshCompletion} $out/share/zsh/site-functions/_s
124 '';
125 passthru = (old.passthru or { }) // {
126 usage = builtins.readFile ./usage.kdl;
127 };
128 });
129 };
130}