quilltap 4.9.0-dev.62 → 4.9.0-dev.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavioural guard for the shell-completion templates.
|
|
3
|
+
*
|
|
4
|
+
* The static coverage test next door proves every subcommand is *mentioned*.
|
|
5
|
+
* This one proves the completions still fire once flags are on the line — the
|
|
6
|
+
* failure the templates actually shipped with: `quilltap docs --instance
|
|
7
|
+
* Friday <TAB>` offered nothing, because the verb was looked up by counting
|
|
8
|
+
* words rather than by parsing them.
|
|
9
|
+
*
|
|
10
|
+
* Bash is driven for real (source the script, set COMP_WORDS/COMP_CWORD, read
|
|
11
|
+
* COMPREPLY back). Zsh's completion system can only be driven from inside a
|
|
12
|
+
* completion widget, so its template is checked structurally instead.
|
|
13
|
+
*
|
|
14
|
+
* @jest-environment node
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
'use strict';
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const os = require('os');
|
|
21
|
+
const path = require('path');
|
|
22
|
+
const { execFileSync } = require('child_process');
|
|
23
|
+
|
|
24
|
+
const COMPLETION_DIR = path.join(__dirname, '..', 'completion');
|
|
25
|
+
|
|
26
|
+
/** A `quilltap` on PATH that answers the completion lookups deterministically. */
|
|
27
|
+
function makeStubBin() {
|
|
28
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'quilltap-completion-'));
|
|
29
|
+
const stub = path.join(dir, 'quilltap');
|
|
30
|
+
fs.writeFileSync(
|
|
31
|
+
stub,
|
|
32
|
+
[
|
|
33
|
+
'#!/bin/sh',
|
|
34
|
+
'case "$*" in',
|
|
35
|
+
' *"instances list --names-only"*) printf "StubInstance\\n" ;;',
|
|
36
|
+
' *"docs list --names-only"*) printf "Stub Store\\nOther Store\\n" ;;',
|
|
37
|
+
'esac',
|
|
38
|
+
'exit 0',
|
|
39
|
+
'',
|
|
40
|
+
].join('\n'),
|
|
41
|
+
{ mode: 0o755 }
|
|
42
|
+
);
|
|
43
|
+
return dir;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const STUB_BIN = makeStubBin();
|
|
47
|
+
afterAll(() => fs.rmSync(STUB_BIN, { recursive: true, force: true }));
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Complete `line` with the bash template and return the candidate list.
|
|
51
|
+
* A trailing space means "start a new word", exactly as at a real prompt.
|
|
52
|
+
*/
|
|
53
|
+
function bashComplete(line) {
|
|
54
|
+
const script = `
|
|
55
|
+
source ${JSON.stringify(path.join(COMPLETION_DIR, 'bash.template'))}
|
|
56
|
+
COMP_LINE=${JSON.stringify(line)}
|
|
57
|
+
COMP_POINT=\${#COMP_LINE}
|
|
58
|
+
eval "COMP_WORDS=(\$COMP_LINE)"
|
|
59
|
+
[[ "\$COMP_LINE" =~ [[:space:]]$ ]] && COMP_WORDS+=("")
|
|
60
|
+
COMP_CWORD=\$(( \${#COMP_WORDS[@]} - 1 ))
|
|
61
|
+
_quilltap_complete
|
|
62
|
+
printf '%s\\n' "\${COMPREPLY[@]}"
|
|
63
|
+
`;
|
|
64
|
+
return execFileSync('bash', ['-c', script], {
|
|
65
|
+
encoding: 'utf8',
|
|
66
|
+
env: { ...process.env, PATH: `${STUB_BIN}:${process.env.PATH}` },
|
|
67
|
+
})
|
|
68
|
+
.split('\n')
|
|
69
|
+
.filter(Boolean);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
describe('bash completion survives flags on the line', () => {
|
|
73
|
+
it('offers docs verbs with no flags', () => {
|
|
74
|
+
expect(bashComplete('quilltap docs ')).toContain('list');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it.each([
|
|
78
|
+
['an instance flag', 'quilltap docs --instance Friday '],
|
|
79
|
+
['a short instance flag', 'quilltap docs -i Friday '],
|
|
80
|
+
['a subcommand flag that takes a value', 'quilltap docs --limit 5 '],
|
|
81
|
+
['a valueless flag', 'quilltap docs --json '],
|
|
82
|
+
['flags on both sides', 'quilltap --instance Friday docs --json '],
|
|
83
|
+
])('still offers docs verbs after %s', (_label, line) => {
|
|
84
|
+
expect(bashComplete(line)).toContain('list');
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('still offers db verbs after a flag', () => {
|
|
88
|
+
expect(bashComplete('quilltap db --limit 5 ')).toContain('characters');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('still offers db characters verbs after a flag', () => {
|
|
92
|
+
expect(bashComplete('quilltap db characters --instance Friday ')).toContain('status');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('treats -i as --ignore-case under memories, not --instance', () => {
|
|
96
|
+
const got = bashComplete('quilltap memories -i ');
|
|
97
|
+
expect(got).toContain('ls');
|
|
98
|
+
expect(got).not.toContain('StubInstance');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('bash completion looks up names against the addressed instance', () => {
|
|
103
|
+
it('completes --mount from the document stores', () => {
|
|
104
|
+
expect(bashComplete('quilltap docs --mount ')).toContain('Stub\\ Store');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('completes a store positional for verbs that take one', () => {
|
|
108
|
+
expect(bashComplete('quilltap docs ls ')).toContain('Stub\\ Store');
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it('completes the destination store of a move', () => {
|
|
112
|
+
expect(bashComplete('quilltap docs move Src a.md ')).toContain('Stub\\ Store');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('does not offer stores where the verb takes none', () => {
|
|
116
|
+
expect(bashComplete('quilltap docs find ')).not.toContain('Stub\\ Store');
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('zsh completion parses positions instead of counting words', () => {
|
|
121
|
+
const tpl = fs.readFileSync(path.join(COMPLETION_DIR, 'zsh.template'), 'utf8');
|
|
122
|
+
|
|
123
|
+
it('has no hard-coded word-index tests', () => {
|
|
124
|
+
// `(( CURRENT == 2 ))` is the bug: it only holds when the verb sits
|
|
125
|
+
// immediately after the subcommand, so any preceding flag hides it.
|
|
126
|
+
expect(tpl).not.toMatch(/\(\(\s*CURRENT\s*==/);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('stops the top-level _arguments swallowing flags typed after the subcommand', () => {
|
|
130
|
+
// Without the (-) prefixes the rest-argument array comes back empty and
|
|
131
|
+
// _quilltap_subcommand has nothing to dispatch on.
|
|
132
|
+
expect(tpl).toContain("'(-): :->subcommand'");
|
|
133
|
+
expect(tpl).toContain("'(-)*::arg:->args'");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('hands every subcommand verb to _arguments as a positional', () => {
|
|
137
|
+
const dispatchers = tpl.match(/'\(?-?\)?1: :->\w+'/g) || [];
|
|
138
|
+
expect(dispatchers.length).toBeGreaterThanOrEqual(6);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it('is syntactically valid', () => {
|
|
142
|
+
const file = path.join(STUB_BIN, '_quilltap');
|
|
143
|
+
fs.writeFileSync(file, tpl);
|
|
144
|
+
expect(() => execFileSync('zsh', ['-n', file], { stdio: 'pipe' })).not.toThrow();
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -3,6 +3,52 @@
|
|
|
3
3
|
# Bash completion for quilltap
|
|
4
4
|
# Source this file or place it in /etc/bash_completion.d/ or ~/.bash_completion.d/
|
|
5
5
|
|
|
6
|
+
# Fill COMPREPLY from newline-separated candidates on stdin. Store and
|
|
7
|
+
# instance names routinely contain spaces ("Project Files: The Estate"), which
|
|
8
|
+
# `compgen -W` would chop into separate candidates.
|
|
9
|
+
_quilltap_lines_compreply() {
|
|
10
|
+
local cur="$1" line
|
|
11
|
+
local oldifs="$IFS"
|
|
12
|
+
COMPREPLY=()
|
|
13
|
+
IFS=$'\n'
|
|
14
|
+
while read -r line; do
|
|
15
|
+
[[ -n "$line" ]] || continue
|
|
16
|
+
[[ "$line" == "$cur"* ]] && COMPREPLY+=("$(printf '%q' "$line")")
|
|
17
|
+
done
|
|
18
|
+
IFS="$oldifs"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# Which docs positionals name a document store, and which name a local path.
|
|
22
|
+
# move/copy/link take <srcMount> <srcPath> <dstMount> <dstPath>, so a store is
|
|
23
|
+
# wanted at both 2 and 4; every other store-taking verb takes it first.
|
|
24
|
+
_quilltap_docs_positional() {
|
|
25
|
+
local verb="$1" argpos="$2" cur="$3"
|
|
26
|
+
local store_verbs=" show files ls dir tree read export scan reindex embed write delete mkdir rmdir mvdir move copy link "
|
|
27
|
+
|
|
28
|
+
if [[ "$argpos" == "2" ]] && [[ "$store_verbs" == *" $verb "* ]]; then
|
|
29
|
+
_quilltap_lines_compreply "$cur" \
|
|
30
|
+
<<< "$(command quilltap docs list --names-only "${ctx_flags[@]}" 2>/dev/null)"
|
|
31
|
+
return
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
case "$verb" in
|
|
35
|
+
move|copy|link)
|
|
36
|
+
if [[ "$argpos" == "4" ]]; then
|
|
37
|
+
_quilltap_lines_compreply "$cur" \
|
|
38
|
+
<<< "$(command quilltap docs list --names-only "${ctx_flags[@]}" 2>/dev/null)"
|
|
39
|
+
fi
|
|
40
|
+
;;
|
|
41
|
+
export)
|
|
42
|
+
# `docs export <mount> <outputDir>` — the second one is a local directory.
|
|
43
|
+
[[ "$argpos" == "3" ]] && COMPREPLY=($(compgen -d -- "$cur"))
|
|
44
|
+
;;
|
|
45
|
+
write)
|
|
46
|
+
# `docs write <mount> <path> [file]` — the optional source is local.
|
|
47
|
+
[[ "$argpos" == "4" ]] && COMPREPLY=($(compgen -f -- "$cur"))
|
|
48
|
+
;;
|
|
49
|
+
esac
|
|
50
|
+
}
|
|
51
|
+
|
|
6
52
|
_quilltap_complete() {
|
|
7
53
|
local cur prev words cword
|
|
8
54
|
COMPREPLY=()
|
|
@@ -17,23 +63,62 @@ _quilltap_complete() {
|
|
|
17
63
|
# Top-level subcommands
|
|
18
64
|
local top_cmds="db docs themes instances memories memory-diff recall-replay logs migrations maintenance file-verify completion"
|
|
19
65
|
|
|
66
|
+
# Flags that swallow the word after them. A flat list will not do: -o is the
|
|
67
|
+
# valueless global --open but themes' valued --output, and `memories`
|
|
68
|
+
# reserves -i for --ignore-case rather than --instance. Counting those wrong
|
|
69
|
+
# makes a flag's value look like the subcommand's verb, which is how
|
|
70
|
+
# `quilltap docs --limit 5 <TAB>` used to lose the verb list.
|
|
71
|
+
local vf_global=" -d --data-dir -i --instance -p --port --passphrase "
|
|
72
|
+
local vf_db=" --limit --grep --character --project --about --source --chat --message --field --tail --last --from --type --out --id --count "
|
|
73
|
+
local vf_docs=" --mount --folder --type --ext --limit --max --context --top --threshold --sort --depth --max-nodes "
|
|
74
|
+
local vf_themes=" -o --output -k --key -n --name "
|
|
75
|
+
local vf_memories=" -d --data-dir --instance --passphrase --port --character --about --source --chat --project --since --until --min-importance --min-reinforced --sort --limit --in --max --context --depth --max-nodes --top --threshold "
|
|
76
|
+
local vf_logs=" --stream --tail --grep "
|
|
77
|
+
local vf_memory_diff=" --concurrency --out "
|
|
78
|
+
local vf_recall_replay=" --turn --char --limit --port "
|
|
79
|
+
local vf_file_verify=" --stall-ms "
|
|
80
|
+
|
|
20
81
|
# Get the subcommand (first non-option word after quilltap)
|
|
21
82
|
local subcommand=""
|
|
22
83
|
local subverb=""
|
|
84
|
+
local -a ctx_flags=()
|
|
85
|
+
local positional_count=0
|
|
23
86
|
local i=1
|
|
24
87
|
while [[ $i -lt $cword ]]; do
|
|
25
88
|
local word="${words[$i]}"
|
|
89
|
+
|
|
90
|
+
# Which flags take a value depends on the subcommand seen so far; before
|
|
91
|
+
# one is seen, only the global flags are in play.
|
|
92
|
+
local valued="$vf_global"
|
|
93
|
+
case "$subcommand" in
|
|
94
|
+
db) valued="$vf_global$vf_db" ;;
|
|
95
|
+
docs) valued="$vf_global$vf_docs" ;;
|
|
96
|
+
themes) valued="$vf_global$vf_themes" ;;
|
|
97
|
+
memories) valued="$vf_memories" ;;
|
|
98
|
+
logs) valued="$vf_global$vf_logs" ;;
|
|
99
|
+
memory-diff) valued="$vf_global$vf_memory_diff" ;;
|
|
100
|
+
recall-replay) valued="$vf_global$vf_recall_replay" ;;
|
|
101
|
+
file-verify) valued="$vf_global$vf_file_verify" ;;
|
|
102
|
+
esac
|
|
103
|
+
|
|
104
|
+
if [[ "$valued" == *" $word "* ]]; then
|
|
105
|
+
# Remember how the user is addressing an instance so the live lookups
|
|
106
|
+
# below query that database rather than the default one.
|
|
107
|
+
case "$word" in
|
|
108
|
+
-d|--data-dir|-i|--instance|--passphrase)
|
|
109
|
+
if (( i + 1 < cword )); then
|
|
110
|
+
ctx_flags+=("$word" "${words[$((i + 1))]}")
|
|
111
|
+
fi
|
|
112
|
+
;;
|
|
113
|
+
esac
|
|
114
|
+
# Takes a value, skip the next word
|
|
115
|
+
((i += 2))
|
|
116
|
+
continue
|
|
117
|
+
fi
|
|
118
|
+
|
|
26
119
|
case "$word" in
|
|
27
|
-
-d|--data-dir|-i|--instance|-p|--port|--passphrase)
|
|
28
|
-
# These take a value, skip the next word
|
|
29
|
-
((i += 2))
|
|
30
|
-
;;
|
|
31
|
-
-o|--open|-v|--version|-h|--help|--update)
|
|
32
|
-
# Flags without values
|
|
33
|
-
((i += 1))
|
|
34
|
-
;;
|
|
35
120
|
-*)
|
|
36
|
-
#
|
|
121
|
+
# Valueless (or unknown) flag
|
|
37
122
|
((i += 1))
|
|
38
123
|
;;
|
|
39
124
|
*)
|
|
@@ -42,6 +127,10 @@ _quilltap_complete() {
|
|
|
42
127
|
elif [[ -z "$subverb" ]]; then
|
|
43
128
|
subverb="$word"
|
|
44
129
|
fi
|
|
130
|
+
# Counts the subcommand itself, so the word under the cursor sits at
|
|
131
|
+
# positional_count within the subcommand: 1 is its verb, 2 the verb's
|
|
132
|
+
# first argument, and so on.
|
|
133
|
+
((positional_count += 1))
|
|
45
134
|
((i += 1))
|
|
46
135
|
;;
|
|
47
136
|
esac
|
|
@@ -56,9 +145,9 @@ _quilltap_complete() {
|
|
|
56
145
|
if [[ "$prev" == "-p" ]] || [[ "$prev" == "--port" ]] || [[ "$prev" == "--passphrase" ]]; then
|
|
57
146
|
return
|
|
58
147
|
fi
|
|
59
|
-
if [[ "$prev" == "
|
|
60
|
-
|
|
61
|
-
|
|
148
|
+
if [[ "$prev" == "--instance" ]] || { [[ "$prev" == "-i" ]] && [[ "$subcommand" != "memories" ]]; }; then
|
|
149
|
+
_quilltap_lines_compreply "$cur" \
|
|
150
|
+
<<< "$(command quilltap instances list --names-only 2>/dev/null)"
|
|
62
151
|
return
|
|
63
152
|
fi
|
|
64
153
|
|
|
@@ -75,8 +164,8 @@ _quilltap_complete() {
|
|
|
75
164
|
# Shared flag-value completions for any subcommand
|
|
76
165
|
case "$prev" in
|
|
77
166
|
--mount)
|
|
78
|
-
|
|
79
|
-
|
|
167
|
+
_quilltap_lines_compreply "$cur" \
|
|
168
|
+
<<< "$(command quilltap docs list --names-only "${ctx_flags[@]}" 2>/dev/null)"
|
|
80
169
|
return
|
|
81
170
|
;;
|
|
82
171
|
--character|--about)
|
|
@@ -137,16 +226,14 @@ _quilltap_complete() {
|
|
|
137
226
|
docs)
|
|
138
227
|
local docs_verbs="list show files ls dir tree read export scan write delete mkdir move copy link rmdir mvdir status docker-mounts find grep reindex embed"
|
|
139
228
|
local docs_flags="--mount --instance --data-dir --passphrase --port --json --help \
|
|
140
|
-
--force --rendered --links --folder --type --ext --limit --max --context --top --threshold \
|
|
229
|
+
--uri --base64 --force --rendered --links --folder --type --ext --limit --max --context --top --threshold \
|
|
141
230
|
--ignore-case -l --wait -R --recursive --sort -r --reverse --depth --max-nodes --long --semantic"
|
|
142
|
-
if [[
|
|
143
|
-
if [[ "$cur" == -* ]]; then
|
|
144
|
-
COMPREPLY=($(compgen -W "$docs_flags" -- "$cur"))
|
|
145
|
-
else
|
|
146
|
-
COMPREPLY=($(compgen -W "$docs_verbs" -- "$cur"))
|
|
147
|
-
fi
|
|
148
|
-
else
|
|
231
|
+
if [[ "$cur" == -* ]]; then
|
|
149
232
|
COMPREPLY=($(compgen -W "$docs_flags" -- "$cur"))
|
|
233
|
+
elif [[ -z "$subverb" ]]; then
|
|
234
|
+
COMPREPLY=($(compgen -W "$docs_verbs" -- "$cur"))
|
|
235
|
+
else
|
|
236
|
+
_quilltap_docs_positional "$subverb" "$positional_count" "$cur"
|
|
150
237
|
fi
|
|
151
238
|
;;
|
|
152
239
|
themes)
|
|
@@ -8,6 +8,10 @@ function __quilltap_instance_names
|
|
|
8
8
|
command quilltap instances list --names-only 2>/dev/null
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
function __quilltap_mount_names
|
|
12
|
+
command quilltap docs list --names-only 2>/dev/null
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
function __quilltap_no_subcommand
|
|
12
16
|
set -l cmd (commandline -opc)
|
|
13
17
|
if test (count $cmd) -lt 2
|
|
@@ -157,7 +161,7 @@ complete -c quilltap -n '__quilltap_using_subcommand docs' -f -a 'rmdir' -d 'Rem
|
|
|
157
161
|
complete -c quilltap -n '__quilltap_using_subcommand docs' -f -a 'mvdir' -d 'Rename or move a folder'
|
|
158
162
|
|
|
159
163
|
# docs flags
|
|
160
|
-
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'mount' -d 'Mount name or id' -x
|
|
164
|
+
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'mount' -d 'Mount name or id' -x -a '(__quilltap_mount_names)'
|
|
161
165
|
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'port' -s 'p' -d 'Server port' -x
|
|
162
166
|
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'folder' -d 'Folder filter' -x
|
|
163
167
|
complete -c quilltap -n '__quilltap_using_subcommand docs' -l 'force' -d 'Force operation'
|
|
@@ -2,12 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
# Zsh completion for quilltap
|
|
4
4
|
|
|
5
|
+
# Position is worked out by _arguments, never by counting words. A hard-coded
|
|
6
|
+
# `CURRENT == 2` test means the verb only completes when it sits immediately
|
|
7
|
+
# after the subcommand, so `quilltap docs --instance Friday <TAB>` offers
|
|
8
|
+
# nothing at all. Every function below hands its option list *and* its
|
|
9
|
+
# positional specs to one `_arguments -C` call and branches on $state, so flags
|
|
10
|
+
# may appear anywhere the CLI itself accepts them.
|
|
11
|
+
|
|
5
12
|
local ret=1
|
|
6
13
|
|
|
7
14
|
_quilltap() {
|
|
8
15
|
local -a subcommands
|
|
9
16
|
local -a global_options
|
|
10
17
|
|
|
18
|
+
# The whole command line, kept before _arguments rebases `words` for the
|
|
19
|
+
# subcommand dispatch. The lookup helpers read it so that an --instance
|
|
20
|
+
# typed anywhere picks which database they query.
|
|
21
|
+
local -a _quilltap_line
|
|
22
|
+
local -i _quilltap_cword
|
|
23
|
+
_quilltap_line=("${words[@]}")
|
|
24
|
+
_quilltap_cword=$CURRENT
|
|
25
|
+
|
|
11
26
|
global_options=(
|
|
12
27
|
'(-d --data-dir)'{-d,--data-dir}'[Data directory]:directory:_directories'
|
|
13
28
|
'(-i --instance)'{-i,--instance}'[Use a registered instance]:instance:_quilltap_instance_names'
|
|
@@ -34,10 +49,14 @@ _quilltap() {
|
|
|
34
49
|
'completion:Generate shell completion scripts'
|
|
35
50
|
)
|
|
36
51
|
|
|
52
|
+
# (-) on both positionals stops the top-level _arguments from swallowing a
|
|
53
|
+
# flag typed *after* the subcommand: without it `quilltap docs --instance
|
|
54
|
+
# Friday <TAB>` parses --instance as a global option, leaving the rest-arg
|
|
55
|
+
# array empty and the subcommand dispatch with nothing to dispatch on.
|
|
37
56
|
_arguments -C \
|
|
38
|
-
'1: :->subcommand' \
|
|
39
57
|
"${global_options[@]}" \
|
|
40
|
-
'
|
|
58
|
+
'(-): :->subcommand' \
|
|
59
|
+
'(-)*::arg:->args'
|
|
41
60
|
|
|
42
61
|
case "$state" in
|
|
43
62
|
subcommand)
|
|
@@ -74,7 +93,7 @@ _quilltap_subcommand() {
|
|
|
74
93
|
_quilltap_memory_diff
|
|
75
94
|
;;
|
|
76
95
|
recall-replay)
|
|
77
|
-
|
|
96
|
+
_quilltap_recall_replay
|
|
78
97
|
;;
|
|
79
98
|
logs)
|
|
80
99
|
_quilltap_logs
|
|
@@ -86,7 +105,7 @@ _quilltap_subcommand() {
|
|
|
86
105
|
_quilltap_maintenance
|
|
87
106
|
;;
|
|
88
107
|
file-verify)
|
|
89
|
-
|
|
108
|
+
_quilltap_file_verify
|
|
90
109
|
;;
|
|
91
110
|
completion)
|
|
92
111
|
_quilltap_completion
|
|
@@ -95,7 +114,10 @@ _quilltap_subcommand() {
|
|
|
95
114
|
}
|
|
96
115
|
|
|
97
116
|
_quilltap_db() {
|
|
117
|
+
local curcontext="$curcontext" state line
|
|
118
|
+
typeset -A opt_args
|
|
98
119
|
local -a subverbs db_opts
|
|
120
|
+
|
|
99
121
|
subverbs=(
|
|
100
122
|
'schema:Show database schema'
|
|
101
123
|
'find:Find entities by name'
|
|
@@ -147,46 +169,74 @@ _quilltap_db() {
|
|
|
147
169
|
'(-h --help)'{-h,--help}'[Show help]'
|
|
148
170
|
)
|
|
149
171
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
172
|
+
# (-) again: a flag typed after the verb belongs to the verb's own
|
|
173
|
+
# _arguments call below, not to this one.
|
|
174
|
+
_arguments -C $db_opts \
|
|
175
|
+
'(-): :->verb' \
|
|
176
|
+
'(-)*::arg:->rest'
|
|
154
177
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
'--id[Single character by name or id]:character:'
|
|
173
|
-
'--write[Perform the archive/rehydrate write]'
|
|
174
|
-
'(-p --port)'{-p,--port}'[Server port]:port:'
|
|
175
|
-
'--out[Output .qtap path]:path:_files'
|
|
176
|
-
'(-h --help)'{-h,--help}'[Show help]'
|
|
177
|
-
)
|
|
178
|
-
if (( CURRENT == 3 )); then
|
|
179
|
-
_describe 'characters subcommand' char_verbs
|
|
180
|
-
fi
|
|
181
|
-
_arguments $char_opts
|
|
182
|
-
return
|
|
183
|
-
fi
|
|
178
|
+
case "$state" in
|
|
179
|
+
verb)
|
|
180
|
+
_describe -t commands 'db subcommand' subverbs
|
|
181
|
+
;;
|
|
182
|
+
rest)
|
|
183
|
+
case "$line[1]" in
|
|
184
|
+
characters)
|
|
185
|
+
_quilltap_db_characters
|
|
186
|
+
;;
|
|
187
|
+
*)
|
|
188
|
+
# Nothing to complete positionally, but the flags still apply.
|
|
189
|
+
_arguments $db_opts
|
|
190
|
+
;;
|
|
191
|
+
esac
|
|
192
|
+
;;
|
|
193
|
+
esac
|
|
194
|
+
}
|
|
184
195
|
|
|
185
|
-
|
|
196
|
+
_quilltap_db_characters() {
|
|
197
|
+
local curcontext="$curcontext" state line
|
|
198
|
+
typeset -A opt_args
|
|
199
|
+
local -a char_verbs char_opts
|
|
200
|
+
|
|
201
|
+
char_verbs=(
|
|
202
|
+
'status:Per-character vault status report'
|
|
203
|
+
'archives:List archived characters and ARCHIVE bundles'
|
|
204
|
+
'archive:Archive a character (runs through the server)'
|
|
205
|
+
'rehydrate:Wake an archived character (runs through the server)'
|
|
206
|
+
'export:Write a plaintext .qtap for a character'
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
char_opts=(
|
|
210
|
+
'(-i --instance)'{-i,--instance}'[Registered instance name]:instance:_quilltap_instance_names'
|
|
211
|
+
'(-d --data-dir)'{-d,--data-dir}'[Data directory]:directory:_directories'
|
|
212
|
+
'--passphrase[Database passphrase]:passphrase:'
|
|
213
|
+
'--json[JSON output]'
|
|
214
|
+
'--limit[Result limit]:limit:'
|
|
215
|
+
'--diverged[Only characters whose DB and vault differ]'
|
|
216
|
+
'--blocked[Only characters with vault issues]'
|
|
217
|
+
'--id[Single character by name or id]:character:'
|
|
218
|
+
'--write[Perform the archive/rehydrate write]'
|
|
219
|
+
'(-p --port)'{-p,--port}'[Server port]:port:'
|
|
220
|
+
'--out[Output .qtap path]:path:_files'
|
|
221
|
+
'(-h --help)'{-h,--help}'[Show help]'
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
_arguments -C $char_opts \
|
|
225
|
+
'1: :->cverb' \
|
|
226
|
+
'*: :'
|
|
227
|
+
|
|
228
|
+
case "$state" in
|
|
229
|
+
cverb)
|
|
230
|
+
_describe -t commands 'characters subcommand' char_verbs
|
|
231
|
+
;;
|
|
232
|
+
esac
|
|
186
233
|
}
|
|
187
234
|
|
|
188
235
|
_quilltap_docs() {
|
|
236
|
+
local curcontext="$curcontext" state line
|
|
237
|
+
typeset -A opt_args
|
|
189
238
|
local -a subverbs docs_opts
|
|
239
|
+
|
|
190
240
|
subverbs=(
|
|
191
241
|
'list:List all mount points'
|
|
192
242
|
'show:Details for one mount point'
|
|
@@ -219,10 +269,12 @@ _quilltap_docs() {
|
|
|
219
269
|
'--passphrase[Database passphrase]:passphrase:'
|
|
220
270
|
'(-p --port)'{-p,--port}'[Server port]:port:'
|
|
221
271
|
'--json[JSON output]'
|
|
222
|
-
'--
|
|
272
|
+
'--uri[Show canonical qtap:// URIs as the locator]'
|
|
273
|
+
'--mount[Mount name or id]:mount:_quilltap_mount_names'
|
|
223
274
|
'--folder[Folder filter]:folder:'
|
|
224
275
|
'--force[Force operation]'
|
|
225
276
|
'--rendered[Render rich content]'
|
|
277
|
+
'--base64[Base64 transfer for binary files]'
|
|
226
278
|
'--links[Include link details]'
|
|
227
279
|
'--type[Filter by type]:type:(file folder)'
|
|
228
280
|
'--ext[Extension filter]:ext:'
|
|
@@ -244,14 +296,61 @@ _quilltap_docs() {
|
|
|
244
296
|
'(-h --help)'{-h,--help}'[Show help]'
|
|
245
297
|
)
|
|
246
298
|
|
|
247
|
-
|
|
248
|
-
|
|
299
|
+
_arguments -C $docs_opts \
|
|
300
|
+
'1: :->verb' \
|
|
301
|
+
'2: :->pos2' \
|
|
302
|
+
'3: :->pos3' \
|
|
303
|
+
'4: :->pos4' \
|
|
304
|
+
'*: :'
|
|
305
|
+
|
|
306
|
+
case "$state" in
|
|
307
|
+
verb)
|
|
308
|
+
_describe -t commands 'docs subcommand' subverbs
|
|
309
|
+
;;
|
|
310
|
+
pos2|pos3|pos4)
|
|
311
|
+
_quilltap_docs_positional ${state#pos}
|
|
312
|
+
;;
|
|
313
|
+
esac
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
# Which docs positionals name a document store, and which name a local path.
|
|
317
|
+
# `move`/`copy`/`link` take <srcMount> <srcPath> <dstMount> <dstPath>, so a
|
|
318
|
+
# store is wanted at both 2 and 4; everything else that takes a store takes it
|
|
319
|
+
# first. `$line` comes from the caller's _arguments -C.
|
|
320
|
+
_quilltap_docs_positional() {
|
|
321
|
+
local -i n=$1
|
|
322
|
+
local verb="$line[1]"
|
|
323
|
+
local -a store_verbs
|
|
324
|
+
store_verbs=(
|
|
325
|
+
show files ls dir tree read export scan reindex embed
|
|
326
|
+
write delete mkdir rmdir mvdir move copy link
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
if (( n == 2 )) && (( ${store_verbs[(I)$verb]} )); then
|
|
330
|
+
_quilltap_mount_names
|
|
331
|
+
return
|
|
249
332
|
fi
|
|
250
|
-
|
|
333
|
+
|
|
334
|
+
case "$verb" in
|
|
335
|
+
move|copy|link)
|
|
336
|
+
(( n == 4 )) && _quilltap_mount_names
|
|
337
|
+
;;
|
|
338
|
+
export)
|
|
339
|
+
# `docs export <mount> <outputDir>` — the second one is a local directory.
|
|
340
|
+
(( n == 3 )) && _directories
|
|
341
|
+
;;
|
|
342
|
+
write)
|
|
343
|
+
# `docs write <mount> <path> [file]` — the optional source is local.
|
|
344
|
+
(( n == 4 )) && _files
|
|
345
|
+
;;
|
|
346
|
+
esac
|
|
251
347
|
}
|
|
252
348
|
|
|
253
349
|
_quilltap_themes() {
|
|
254
|
-
local
|
|
350
|
+
local curcontext="$curcontext" state line
|
|
351
|
+
typeset -A opt_args
|
|
352
|
+
local -a subverbs themes_opts
|
|
353
|
+
|
|
255
354
|
subverbs=(
|
|
256
355
|
'list:List available themes'
|
|
257
356
|
'install:Install a theme'
|
|
@@ -271,37 +370,70 @@ _quilltap_themes() {
|
|
|
271
370
|
'(-h --help)'{-h,--help}'[Show help]'
|
|
272
371
|
)
|
|
273
372
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
373
|
+
# (-) again: a flag typed after the verb belongs to the verb's own
|
|
374
|
+
# _arguments call below, not to this one.
|
|
375
|
+
_arguments -C $themes_opts \
|
|
376
|
+
'(-): :->verb' \
|
|
377
|
+
'(-)*::arg:->rest'
|
|
278
378
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
'
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
379
|
+
case "$state" in
|
|
380
|
+
verb)
|
|
381
|
+
_describe -t commands 'themes subcommand' subverbs
|
|
382
|
+
;;
|
|
383
|
+
rest)
|
|
384
|
+
case "$line[1]" in
|
|
385
|
+
registry)
|
|
386
|
+
_quilltap_themes_registry
|
|
387
|
+
;;
|
|
388
|
+
*)
|
|
389
|
+
_arguments $themes_opts
|
|
390
|
+
;;
|
|
391
|
+
esac
|
|
392
|
+
;;
|
|
393
|
+
esac
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
_quilltap_themes_registry() {
|
|
397
|
+
local curcontext="$curcontext" state line
|
|
398
|
+
typeset -A opt_args
|
|
399
|
+
local -a registry_verbs registry_opts
|
|
400
|
+
|
|
401
|
+
registry_verbs=(
|
|
402
|
+
'list:List registries'
|
|
403
|
+
'add:Add a registry'
|
|
404
|
+
'remove:Remove a registry'
|
|
405
|
+
'refresh:Refresh registries'
|
|
406
|
+
'keygen:Generate Ed25519 key'
|
|
407
|
+
'sign:Sign a registry or bundle'
|
|
408
|
+
)
|
|
299
409
|
|
|
300
|
-
|
|
410
|
+
# themesCommand() parses -d/-i/-o/-h anywhere in the argv, including after
|
|
411
|
+
# `registry`, so they belong in this list too.
|
|
412
|
+
registry_opts=(
|
|
413
|
+
'(-k --key)'{-k,--key}'[Signing key path]:path:_files'
|
|
414
|
+
'(-n --name)'{-n,--name}'[Registry name]:name:'
|
|
415
|
+
'(-o --output)'{-o,--output}'[Output path]:path:_files'
|
|
416
|
+
'(-i --instance)'{-i,--instance}'[Registered instance name]:instance:_quilltap_instance_names'
|
|
417
|
+
'(-d --data-dir)'{-d,--data-dir}'[Data directory]:directory:_directories'
|
|
418
|
+
'(-h --help)'{-h,--help}'[Show help]'
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
_arguments -C $registry_opts \
|
|
422
|
+
'1: :->rverb' \
|
|
423
|
+
'*: :'
|
|
424
|
+
|
|
425
|
+
case "$state" in
|
|
426
|
+
rverb)
|
|
427
|
+
_describe -t commands 'registry subcommand' registry_verbs
|
|
428
|
+
;;
|
|
429
|
+
esac
|
|
301
430
|
}
|
|
302
431
|
|
|
303
432
|
_quilltap_instances() {
|
|
433
|
+
local curcontext="$curcontext" state line
|
|
434
|
+
typeset -A opt_args
|
|
304
435
|
local -a subverbs inst_opts
|
|
436
|
+
|
|
305
437
|
subverbs=(
|
|
306
438
|
'list:List registered instances'
|
|
307
439
|
'ls:List registered instances'
|
|
@@ -326,25 +458,30 @@ _quilltap_instances() {
|
|
|
326
458
|
'(-h --help)'{-h,--help}'[Show help]'
|
|
327
459
|
)
|
|
328
460
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
461
|
+
_arguments -C $inst_opts \
|
|
462
|
+
'1: :->verb' \
|
|
463
|
+
'2: :->name' \
|
|
464
|
+
'*: :'
|
|
333
465
|
|
|
334
|
-
case "$
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
466
|
+
case "$state" in
|
|
467
|
+
verb)
|
|
468
|
+
_describe -t commands 'instances subcommand' subverbs
|
|
469
|
+
;;
|
|
470
|
+
name)
|
|
471
|
+
case "$line[1]" in
|
|
472
|
+
show|remove|rm|delete|set-passphrase|passphrase|default|rename)
|
|
473
|
+
_quilltap_instance_names
|
|
474
|
+
;;
|
|
475
|
+
esac
|
|
340
476
|
;;
|
|
341
477
|
esac
|
|
342
|
-
|
|
343
|
-
_arguments $inst_opts
|
|
344
478
|
}
|
|
345
479
|
|
|
346
480
|
_quilltap_memories() {
|
|
481
|
+
local curcontext="$curcontext" state line
|
|
482
|
+
typeset -A opt_args
|
|
347
483
|
local -a subverbs mem_opts
|
|
484
|
+
|
|
348
485
|
subverbs=(
|
|
349
486
|
'ls:List memories'
|
|
350
487
|
'find:Substring search'
|
|
@@ -356,10 +493,10 @@ _quilltap_memories() {
|
|
|
356
493
|
)
|
|
357
494
|
|
|
358
495
|
mem_opts=(
|
|
359
|
-
'
|
|
496
|
+
'--instance[Registered instance name]:instance:_quilltap_instance_names'
|
|
360
497
|
'(-d --data-dir)'{-d,--data-dir}'[Data directory]:directory:_directories'
|
|
361
498
|
'--passphrase[Database passphrase]:passphrase:'
|
|
362
|
-
'
|
|
499
|
+
'--port[Server port]:port:'
|
|
363
500
|
'--json[JSON output]'
|
|
364
501
|
'--character[Character name or id]:character:'
|
|
365
502
|
'--about[Subject of memory]:character:'
|
|
@@ -379,7 +516,7 @@ _quilltap_memories() {
|
|
|
379
516
|
'--in[Restrict find-in field]:field:'
|
|
380
517
|
'--no-related[Hide related neighbors]'
|
|
381
518
|
'--list[List-only output]'
|
|
382
|
-
'(-i --ignore-case)'{-i,--ignore-case}'[Case-insensitive]'
|
|
519
|
+
'(-i --ignore-case)'{-i,--ignore-case}'[Case-insensitive (memories reserves -i for this, not --instance)]'
|
|
383
520
|
'(-l --paths-only)'{-l,--paths-only}'[Paths only]'
|
|
384
521
|
'--max[Maximum results]:n:'
|
|
385
522
|
'--context[Context lines]:n:'
|
|
@@ -391,10 +528,15 @@ _quilltap_memories() {
|
|
|
391
528
|
'(-h --help)'{-h,--help}'[Show help]'
|
|
392
529
|
)
|
|
393
530
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
531
|
+
_arguments -C $mem_opts \
|
|
532
|
+
'1: :->verb' \
|
|
533
|
+
'*: :'
|
|
534
|
+
|
|
535
|
+
case "$state" in
|
|
536
|
+
verb)
|
|
537
|
+
_describe -t commands 'memories subcommand' subverbs
|
|
538
|
+
;;
|
|
539
|
+
esac
|
|
398
540
|
}
|
|
399
541
|
|
|
400
542
|
_quilltap_memory_diff() {
|
|
@@ -405,7 +547,22 @@ _quilltap_memory_diff() {
|
|
|
405
547
|
'--passphrase[Database passphrase]:passphrase:' \
|
|
406
548
|
'(-p --port)'{-p,--port}'[Server port]:port:' \
|
|
407
549
|
'--concurrency[Concurrency limit]:n:' \
|
|
408
|
-
'--out[Output file]:path:_files'
|
|
550
|
+
'--out[Output file]:path:_files' \
|
|
551
|
+
'*: :'
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
_quilltap_recall_replay() {
|
|
555
|
+
_arguments \
|
|
556
|
+
'(-h --help)'{-h,--help}'[Show help]' \
|
|
557
|
+
'(-i --instance)'{-i,--instance}'[Use instance]:instance:_quilltap_instance_names' \
|
|
558
|
+
'(-d --data-dir)'{-d,--data-dir}'[Data directory]:directory:_directories' \
|
|
559
|
+
'--passphrase[Database passphrase]:passphrase:' \
|
|
560
|
+
'--turn[interchange to replay]:turn:' \
|
|
561
|
+
'--char[character id]:char:' \
|
|
562
|
+
'--limit[rows per path]:limit:' \
|
|
563
|
+
'--port[server port]:port:' \
|
|
564
|
+
'--json[raw JSON output]' \
|
|
565
|
+
'*: :'
|
|
409
566
|
}
|
|
410
567
|
|
|
411
568
|
_quilltap_logs() {
|
|
@@ -417,11 +574,27 @@ _quilltap_logs() {
|
|
|
417
574
|
'--stream[Which log stream]:stream:(combined error stdout stderr startup)' \
|
|
418
575
|
'--tail[Last N lines (0=full)]:n:' \
|
|
419
576
|
'(-f --follow)'{-f,--follow}'[Stream new lines]' \
|
|
420
|
-
'--grep[Regex filter]:pattern:'
|
|
577
|
+
'--grep[Regex filter]:pattern:' \
|
|
578
|
+
'*: :'
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
_quilltap_file_verify() {
|
|
582
|
+
_arguments \
|
|
583
|
+
'(-h --help)'{-h,--help}'[Show help]' \
|
|
584
|
+
'(-i --instance)'{-i,--instance}'[Use instance]:instance:_quilltap_instance_names' \
|
|
585
|
+
'(-d --data-dir)'{-d,--data-dir}'[Data directory]:directory:_directories' \
|
|
586
|
+
'--passphrase[Database passphrase]:passphrase:' \
|
|
587
|
+
'--all[read every top-level file, not just dataless ones]' \
|
|
588
|
+
'--stall-ms[per-chunk stall threshold in ms]:ms:' \
|
|
589
|
+
'--json[machine-readable output]' \
|
|
590
|
+
'*: :'
|
|
421
591
|
}
|
|
422
592
|
|
|
423
593
|
_quilltap_migrations() {
|
|
594
|
+
local curcontext="$curcontext" state line
|
|
595
|
+
typeset -A opt_args
|
|
424
596
|
local -a subverbs mig_opts
|
|
597
|
+
|
|
425
598
|
subverbs=(
|
|
426
599
|
'status:Migration status'
|
|
427
600
|
'pending:List pending migrations'
|
|
@@ -437,14 +610,22 @@ _quilltap_migrations() {
|
|
|
437
610
|
'(-h --help)'{-h,--help}'[Show help]'
|
|
438
611
|
)
|
|
439
612
|
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
613
|
+
_arguments -C $mig_opts \
|
|
614
|
+
'1: :->verb' \
|
|
615
|
+
'*: :'
|
|
616
|
+
|
|
617
|
+
case "$state" in
|
|
618
|
+
verb)
|
|
619
|
+
_describe -t commands 'migrations subcommand' subverbs
|
|
620
|
+
;;
|
|
621
|
+
esac
|
|
444
622
|
}
|
|
445
623
|
|
|
446
624
|
_quilltap_maintenance() {
|
|
625
|
+
local curcontext="$curcontext" state line
|
|
626
|
+
typeset -A opt_args
|
|
447
627
|
local -a subverbs maint_opts
|
|
628
|
+
|
|
448
629
|
subverbs=(
|
|
449
630
|
'status:Show dry-run retention counts'
|
|
450
631
|
'run:Run retention/cleanup sweeps (lock-gated)'
|
|
@@ -458,20 +639,71 @@ _quilltap_maintenance() {
|
|
|
458
639
|
'(-h --help)'{-h,--help}'[Show help]'
|
|
459
640
|
)
|
|
460
641
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
642
|
+
_arguments -C $maint_opts \
|
|
643
|
+
'1: :->verb' \
|
|
644
|
+
'*: :'
|
|
645
|
+
|
|
646
|
+
case "$state" in
|
|
647
|
+
verb)
|
|
648
|
+
_describe -t commands 'maintenance subcommand' subverbs
|
|
649
|
+
;;
|
|
650
|
+
esac
|
|
465
651
|
}
|
|
466
652
|
|
|
467
653
|
_quilltap_completion() {
|
|
468
|
-
|
|
654
|
+
local curcontext="$curcontext" state line
|
|
655
|
+
typeset -A opt_args
|
|
656
|
+
|
|
657
|
+
_arguments -C \
|
|
658
|
+
'(-h --help)'{-h,--help}'[Show help]' \
|
|
659
|
+
'1: :(bash zsh fish)' \
|
|
660
|
+
'*: :'
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
# ---------------------------------------------------------------------------
|
|
664
|
+
# Lookup helpers
|
|
665
|
+
#
|
|
666
|
+
# These shell out to quilltap itself, so they have to be told which instance
|
|
667
|
+
# the user is addressing — otherwise `--instance Friday` completes mount names
|
|
668
|
+
# from the default instance. _quilltap_ctx_flags rebuilds the addressing flags
|
|
669
|
+
# from the command line being typed and the helpers pass them straight through.
|
|
670
|
+
# ---------------------------------------------------------------------------
|
|
671
|
+
|
|
672
|
+
_quilltap_ctx_flags() {
|
|
673
|
+
ctx_flags=()
|
|
674
|
+
local -i i=2
|
|
675
|
+
while (( i <= $#_quilltap_line )); do
|
|
676
|
+
case "$_quilltap_line[i]" in
|
|
677
|
+
-i|--instance|-d|--data-dir|--passphrase)
|
|
678
|
+
# The word under the cursor is a half-typed value, not an answer.
|
|
679
|
+
if (( i + 1 <= $#_quilltap_line && i + 1 != _quilltap_cword )) \
|
|
680
|
+
&& [[ -n "$_quilltap_line[i+1]" ]]; then
|
|
681
|
+
ctx_flags+=("$_quilltap_line[i]" "${(Q)_quilltap_line[i+1]}")
|
|
682
|
+
fi
|
|
683
|
+
(( i += 2 ))
|
|
684
|
+
;;
|
|
685
|
+
*)
|
|
686
|
+
(( i += 1 ))
|
|
687
|
+
;;
|
|
688
|
+
esac
|
|
689
|
+
done
|
|
469
690
|
}
|
|
470
691
|
|
|
471
692
|
_quilltap_instance_names() {
|
|
472
|
-
local instances
|
|
693
|
+
local -a instances expl
|
|
473
694
|
instances=(${(f)"$(command quilltap instances list --names-only 2>/dev/null)"})
|
|
474
|
-
|
|
695
|
+
(( $#instances )) || return 1
|
|
696
|
+
# compadd -a, not _values: instance and store names may contain spaces and
|
|
697
|
+
# colons, which _values would chop into value:description pairs.
|
|
698
|
+
_wanted instances expl 'instance' compadd -a instances
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
_quilltap_mount_names() {
|
|
702
|
+
local -a ctx_flags mounts expl
|
|
703
|
+
_quilltap_ctx_flags
|
|
704
|
+
mounts=(${(f)"$(command quilltap docs list --names-only $ctx_flags 2>/dev/null)"})
|
|
705
|
+
(( $#mounts )) || return 1
|
|
706
|
+
_wanted mounts expl 'document store' compadd -a mounts
|
|
475
707
|
}
|
|
476
708
|
|
|
477
709
|
_quilltap "$@"
|