gabriel / muse public
_muse
432 lines 16.5 KB
9a9dba59 Fix oh-my-zsh tab completion: drop argcomplete, fix _muse helpers Gabriel Cardona <gabriel@tellurstori.com> 17h ago
1 #compdef muse
2 # Zsh completion for the Muse CLI.
3 #
4 # Installation (pick one):
5 # 1. Symlink into a directory already on $fpath:
6 # ln -sf /path/to/muse/completions/_muse ~/.zsh/completions/_muse
7 # 2. Oh-My-Zsh users — copy or symlink into the custom completions dir:
8 # ln -sf /path/to/muse/completions/_muse \
9 # ~/.oh-my-zsh/completions/_muse
10 # 3. Add the completions directory directly to $fpath in ~/.zshrc:
11 # fpath=(/path/to/muse/completions $fpath)
12 # autoload -Uz compinit && compinit
13 #
14 # After installing, reload completions:
15 # exec zsh OR autoload -Uz compinit && compinit -u
16
17 # ---------------------------------------------------------------------------
18 # Helpers — read repo state directly from the filesystem; no subprocess.
19 # ---------------------------------------------------------------------------
20
21 # Walk up from $PWD and return the .muse directory path, or "" if not found.
22 _muse_dot_muse() {
23 local dir="$PWD"
24 while [[ "$dir" != "/" ]]; do
25 if [[ -f "$dir/.muse/repo.json" ]]; then
26 print -r -- "$dir/.muse"
27 return 0
28 fi
29 dir="${dir:h}"
30 done
31 return 1
32 }
33
34 # Emit branch names by listing .muse/refs/heads/ — zero subprocesses.
35 _muse_branches() {
36 local dot_muse
37 dot_muse="$(_muse_dot_muse)" || return
38 local heads_dir="$dot_muse/refs/heads"
39 [[ -d "$heads_dir" ]] || return
40 local -a branches
41 # ${heads_dir}/**/*(N:t) recurses and strips directory prefix.
42 branches=(${(f)"$(find "$heads_dir" -type f 2>/dev/null | sed "s|$heads_dir/||")"})
43 (( ${#branches} )) && _describe 'branches' branches
44 }
45
46 # Emit remote names from .muse/config.toml — zero subprocesses.
47 _muse_remotes() {
48 local dot_muse
49 dot_muse="$(_muse_dot_muse)" || { _values 'remote' 'origin' 'local'; return; }
50 local cfg="$dot_muse/config.toml"
51 local -a remotes
52 if [[ -f "$cfg" ]]; then
53 # Extract remote names from [remotes.<name>] section headers.
54 remotes=(${(f)"$(grep -E '^\[remotes\.' "$cfg" 2>/dev/null \
55 | sed -E 's/\[remotes\.([^]]+)\]/\1/')"})
56 fi
57 if (( ${#remotes} )); then
58 _describe 'remotes' remotes
59 else
60 _values 'remote' 'origin' 'local'
61 fi
62 }
63
64 # ---------------------------------------------------------------------------
65 # Command lists (kept in sync with muse/cli/app.py)
66 # ---------------------------------------------------------------------------
67
68 local -a _muse_top_cmds=(
69 'plumbing:Tier 1 machine-readable plumbing commands'
70 'init:Initialise a new Muse repository'
71 'status:Show working-tree drift against HEAD'
72 'log:Display commit history'
73 'commit:Record the current state as a new version'
74 'diff:Compare working tree against HEAD or two commits'
75 'show:Inspect a commit'
76 'branch:List, create, or delete branches'
77 'checkout:Switch branches or restore from a commit'
78 'merge:Three-way merge a branch into HEAD'
79 'reset:Move HEAD to a prior commit'
80 'revert:Undo a prior commit'
81 'cherry-pick:Apply a specific commit on top of HEAD'
82 'stash:Shelve uncommitted changes'
83 'tag:Attach and query semantic tags'
84 'push:Upload commits and objects to a remote'
85 'pull:Fetch from a remote and merge'
86 'fetch:Download commits from a remote'
87 'clone:Create a local copy of a remote repository'
88 'remote:Manage remote connections'
89 'auth:Identity management'
90 'hub:MuseHub fabric connection'
91 'config:Local repository configuration'
92 'domains:Domain plugin dashboard'
93 'attributes:Display .museattributes rules'
94 'annotate:Attach CRDT annotations to a commit'
95 'blame:Show per-line commit provenance'
96 'reflog:History of HEAD and branch-ref movements'
97 'rerere:Reuse recorded conflict resolutions'
98 'gc:Remove unreachable objects'
99 'archive:Export a historical snapshot'
100 'bisect:Binary search commit history'
101 'worktree:Manage multiple branch checkouts'
102 'workspace:Compose multiple Muse repositories'
103 'rebase:Replay commits onto a new base'
104 'clean:Remove untracked files'
105 'describe:Label a commit by its nearest tag'
106 'shortlog:Summarise history by author or agent'
107 'verify:Check repository integrity'
108 'snapshot:Explicit snapshot management'
109 'bundle:Pack commits into a portable bundle'
110 'content-grep:Search tracked file content'
111 'whoami:Show current identity'
112 'check:Run domain invariant checks'
113 'cat:Print a single tracked symbol'
114 'midi:MIDI domain semantic commands'
115 'code:Code domain semantic commands'
116 'coord:Multi-agent coordination commands'
117 )
118
119 local -a _muse_plumbing_cmds=(
120 'hash-object:SHA-256 a file and optionally store it'
121 'cat-object:Emit raw bytes of a stored object'
122 'rev-parse:Resolve branch or HEAD to a commit ID'
123 'ls-files:List tracked files and object IDs'
124 'read-commit:Emit full commit JSON'
125 'read-snapshot:Emit full snapshot JSON'
126 'commit-tree:Create a commit from an explicit snapshot ID'
127 'update-ref:Move a branch HEAD to a specific commit'
128 'commit-graph:Emit the commit DAG as JSON'
129 'pack-objects:Build a PackBundle to stdout'
130 'unpack-objects:Read a PackBundle from stdin'
131 'ls-remote:List remote branch heads'
132 'merge-base:Find the lowest common ancestor of two commits'
133 'snapshot-diff:Diff two snapshot manifests'
134 'domain-info:Inspect the active domain plugin'
135 'show-ref:List all refs and their commit IDs'
136 'check-ignore:Test paths against .museignore rules'
137 'check-attr:Query merge-strategy attributes for paths'
138 'verify-object:Re-hash stored objects to detect corruption'
139 'symbolic-ref:Read or write HEAD symbolic reference'
140 'for-each-ref:Iterate all refs with rich commit metadata'
141 'name-rev:Map commit IDs to descriptive names'
142 'check-ref-format:Validate branch or ref names'
143 'verify-pack:Verify the integrity of a PackBundle'
144 )
145
146 local -a _muse_midi_cmds=(
147 'notes:List notes in a MIDI track'
148 'note-log:Show note-level history'
149 'note-blame:Show per-note commit provenance'
150 'harmony:Analyse harmonic content'
151 'piano-roll:Render a piano-roll view'
152 'note-hotspots:Find most-changed note regions'
153 'velocity-profile:Plot velocity distribution'
154 'transpose:Shift pitches by semitones'
155 'mix:Merge MIDI tracks'
156 'query:Query note events'
157 'check:Run MIDI domain checks'
158 'rhythm:Analyse rhythmic patterns'
159 'scale:Detect active scales'
160 'contour:Analyse melodic contour'
161 'density:Compute note density over time'
162 'tension:Compute harmonic tension'
163 'cadence:Detect cadence points'
164 'motif:Find recurring motifs'
165 'voice-leading:Analyse voice-leading quality'
166 'instrumentation:List instrumentation per track'
167 'tempo:Display tempo map'
168 'compare:Compare two MIDI commits'
169 'quantize:Snap notes to a rhythmic grid'
170 'humanize:Add expressive timing variation'
171 'invert:Invert intervals around an axis'
172 'retrograde:Reverse note sequence'
173 'arpeggiate:Spread chords into arpeggios'
174 'normalize:Normalise velocity levels'
175 'shard:Split a MIDI file into shards'
176 'agent-map:Show which agents modified which notes'
177 'find-phrase:Search for a melodic phrase'
178 )
179
180 local -a _muse_code_cmds=(
181 'cat:Print a symbol'\''s source'
182 'symbols:List symbols in the snapshot'
183 'symbol-log:Show per-symbol commit history'
184 'detect-refactor:Detect renames and extractions'
185 'grep:Search symbol names and bodies'
186 'blame:Show per-symbol commit provenance'
187 'hotspots:Find most-changed symbols'
188 'stable:Find stable (rarely changed) symbols'
189 'coupling:Show frequently co-changed symbol pairs'
190 'compare:Compare two code commits'
191 'languages:List languages in the snapshot'
192 'patch:Apply a delta patch to symbols'
193 'query:Query the symbol graph'
194 'query-history:Query across commit history'
195 'deps:Show dependency graph'
196 'find-symbol:Search for a symbol by name'
197 'impact:Estimate change impact'
198 'dead:Find unreachable symbols'
199 'coverage:Show test coverage mapping'
200 'lineage:Trace a symbol'\''s ancestry'
201 'api-surface:Enumerate public API symbols'
202 'codemap:Render the module dependency map'
203 'clones:Detect duplicate code'
204 'checkout-symbol:Restore a symbol to a prior version'
205 'semantic-cherry-pick:Apply a symbol-level change'
206 'index:Rebuild the symbol index'
207 'breakage:Detect breaking changes'
208 'invariants:Run symbol invariant checks'
209 'add:Stage files for commit'
210 'reset:Unstage files'
211 'code-check:Run code-domain checks'
212 'code-query:Run a structured code query'
213 )
214
215 local -a _muse_coord_cmds=(
216 'reserve:Reserve a symbol for exclusive editing'
217 'intent:Declare editing intent'
218 'forecast:Forecast merge conflicts'
219 'plan-merge:Plan a coordinated merge'
220 'shard:Partition work across agents'
221 'reconcile:Reconcile diverged agent branches'
222 )
223
224 # ---------------------------------------------------------------------------
225 # Main dispatcher
226 # ---------------------------------------------------------------------------
227
228 _muse() {
229 local curcontext="$curcontext" state line
230 typeset -A opt_args
231
232 _arguments -C \
233 '(-h --help)'{-h,--help}'[Show help]' \
234 '(-V --version)'{-V,--version}'[Show version]' \
235 '1: :->command' \
236 '*:: :->args' \
237 && return 0
238
239 case $state in
240 command)
241 _describe 'muse commands' _muse_top_cmds
242 ;;
243
244 args)
245 case $words[1] in
246
247 # --- sub-namespaces -----------------------------------------
248 plumbing)
249 _arguments '1: :->sub' '*:: :->plumbing_args'
250 case $state in
251 sub) _describe 'plumbing commands' _muse_plumbing_cmds ;;
252 esac
253 ;;
254
255 midi)
256 _arguments '1: :->sub'
257 case $state in
258 sub) _describe 'midi commands' _muse_midi_cmds ;;
259 esac
260 ;;
261
262 code)
263 _arguments '1: :->sub' '*:: :->code_args'
264 case $state in
265 sub) _describe 'code commands' _muse_code_cmds ;;
266 code_args)
267 case $words[1] in
268 add|reset) _files ;;
269 esac
270 ;;
271 esac
272 ;;
273
274 coord)
275 _arguments '1: :->sub'
276 case $state in
277 sub) _describe 'coord commands' _muse_coord_cmds ;;
278 esac
279 ;;
280
281 # --- branch-aware commands -----------------------------------
282 checkout)
283 _arguments \
284 '(-b --branch)'{-b,--branch}'[Create new branch]:branch:_muse_branches' \
285 '(-f --force)'{-f,--force}'[Force checkout]' \
286 '1: :_muse_branches'
287 ;;
288
289 merge)
290 _arguments \
291 '--no-commit[Do not auto-commit after merge]' \
292 '--squash[Squash into a single commit]' \
293 '--strategy[Merge strategy]:strategy:(ours theirs union)' \
294 '1: :_muse_branches'
295 ;;
296
297 branch)
298 _arguments \
299 '(-d --delete)'{-d,--delete}'[Delete a branch]:branch:_muse_branches' \
300 '(-D --force-delete)'{-D,--force-delete}'[Force-delete a branch]:branch:_muse_branches' \
301 '(-m --move)'{-m,--move}'[Rename a branch]:branch:_muse_branches' \
302 '1:: :_muse_branches'
303 ;;
304
305 cherry-pick)
306 _arguments \
307 '(-n --no-commit)'{-n,--no-commit}'[Stage without committing]' \
308 '1: :_muse_branches'
309 ;;
310
311 rebase)
312 _arguments \
313 '--onto[New base branch]:branch:_muse_branches' \
314 '1: :_muse_branches'
315 ;;
316
317 # --- remote-aware commands -----------------------------------
318 push)
319 _arguments \
320 '(-b --branch)'{-b,--branch}'[Branch to push]:branch:_muse_branches' \
321 '(-u --set-upstream)'{-u,--set-upstream}'[Set upstream tracking]' \
322 '--force[Force push even if remote diverged]' \
323 '1:: :_muse_remotes' \
324 '2:: :_muse_branches'
325 ;;
326
327 pull)
328 _arguments \
329 '(-b --branch)'{-b,--branch}'[Branch to pull into]:branch:_muse_branches' \
330 '--rebase[Rebase instead of merge]' \
331 '--no-commit[Do not auto-commit after merge]' \
332 '1:: :_muse_remotes' \
333 '2:: :_muse_branches'
334 ;;
335
336 fetch)
337 _arguments \
338 '(-b --branch)'{-b,--branch}'[Specific branch to fetch]:branch:_muse_branches' \
339 '--all[Fetch from all configured remotes]' \
340 '1:: :_muse_remotes'
341 ;;
342
343 clone)
344 _arguments \
345 '(-b --branch)'{-b,--branch}'[Branch to check out after clone]:branch' \
346 '--name[Override repo directory name]:name' \
347 '1: :_urls'
348 ;;
349
350 # --- simple flag commands ------------------------------------
351 commit)
352 _arguments \
353 '(-m --message)'{-m,--message}'[Commit message]:message' \
354 '--allow-empty[Allow a commit with no changes]' \
355 '--sign[Sign the commit]' \
356 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
357 ;;
358
359 status)
360 _arguments \
361 '(-s --short)'{-s,--short}'[Condensed output]' \
362 '--porcelain[Machine-readable output]' \
363 '(-b --branch)'{-b,--branch}'[Show branch only]' \
364 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
365 ;;
366
367 log)
368 _arguments \
369 '(-n --max-count)'{-n,--max-count}'[Limit number of commits]:count' \
370 '--oneline[Compact one-line output]' \
371 '--graph[Show commit graph]' \
372 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
373 ;;
374
375 diff)
376 _arguments \
377 '--stat[Show diffstat summary]' \
378 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)' \
379 '1:: :_muse_branches' \
380 '2:: :_muse_branches'
381 ;;
382
383 show)
384 _arguments \
385 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)' \
386 '1:: :_muse_branches'
387 ;;
388
389 reset)
390 _arguments \
391 '--hard[Discard working tree changes]' \
392 '--soft[Keep working tree changes staged]' \
393 '1:: :_muse_branches'
394 ;;
395
396 tag)
397 _arguments \
398 '(-d --delete)'{-d,--delete}'[Delete a tag]' \
399 '(-l --list)'{-l,--list}'[List tags]' \
400 '(-f --format)'{-f,--format}'[Output format]:fmt:(text json)'
401 ;;
402
403 stash)
404 _arguments \
405 '1:: :(push pop list drop show apply)'
406 ;;
407
408 remote)
409 _arguments \
410 '1:: :(add remove list rename set-url show)'
411 ;;
412
413 auth)
414 _arguments \
415 '1:: :(login logout whoami)'
416 ;;
417
418 hub)
419 _arguments \
420 '1:: :(connect disconnect status ping)'
421 ;;
422
423 config)
424 _arguments \
425 '1:: :(show get set edit)'
426 ;;
427 esac
428 ;;
429 esac
430 }
431
432 _muse "$@"