openspec-cn 0.23.0

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.
Files changed (235) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +153 -0
  3. package/bin/openspec.js +3 -0
  4. package/dist/cli/index.d.ts +2 -0
  5. package/dist/cli/index.js +480 -0
  6. package/dist/commands/change.d.ts +35 -0
  7. package/dist/commands/change.js +277 -0
  8. package/dist/commands/completion.d.ts +72 -0
  9. package/dist/commands/completion.js +257 -0
  10. package/dist/commands/config.d.ts +8 -0
  11. package/dist/commands/config.js +198 -0
  12. package/dist/commands/feedback.d.ts +9 -0
  13. package/dist/commands/feedback.js +183 -0
  14. package/dist/commands/schema.d.ts +6 -0
  15. package/dist/commands/schema.js +869 -0
  16. package/dist/commands/show.d.ts +14 -0
  17. package/dist/commands/show.js +132 -0
  18. package/dist/commands/spec.d.ts +15 -0
  19. package/dist/commands/spec.js +225 -0
  20. package/dist/commands/validate.d.ts +24 -0
  21. package/dist/commands/validate.js +294 -0
  22. package/dist/commands/workflow/index.d.ts +17 -0
  23. package/dist/commands/workflow/index.js +12 -0
  24. package/dist/commands/workflow/instructions.d.ts +29 -0
  25. package/dist/commands/workflow/instructions.js +381 -0
  26. package/dist/commands/workflow/new-change.d.ts +11 -0
  27. package/dist/commands/workflow/new-change.js +44 -0
  28. package/dist/commands/workflow/schemas.d.ts +10 -0
  29. package/dist/commands/workflow/schemas.js +34 -0
  30. package/dist/commands/workflow/shared.d.ts +52 -0
  31. package/dist/commands/workflow/shared.js +111 -0
  32. package/dist/commands/workflow/status.d.ts +14 -0
  33. package/dist/commands/workflow/status.js +58 -0
  34. package/dist/commands/workflow/templates.d.ts +16 -0
  35. package/dist/commands/workflow/templates.js +68 -0
  36. package/dist/core/archive.d.ts +11 -0
  37. package/dist/core/archive.js +280 -0
  38. package/dist/core/artifact-graph/graph.d.ts +56 -0
  39. package/dist/core/artifact-graph/graph.js +141 -0
  40. package/dist/core/artifact-graph/index.d.ts +7 -0
  41. package/dist/core/artifact-graph/index.js +13 -0
  42. package/dist/core/artifact-graph/instruction-loader.d.ts +143 -0
  43. package/dist/core/artifact-graph/instruction-loader.js +214 -0
  44. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  45. package/dist/core/artifact-graph/resolver.js +257 -0
  46. package/dist/core/artifact-graph/schema.d.ts +13 -0
  47. package/dist/core/artifact-graph/schema.js +108 -0
  48. package/dist/core/artifact-graph/state.d.ts +12 -0
  49. package/dist/core/artifact-graph/state.js +54 -0
  50. package/dist/core/artifact-graph/types.d.ts +45 -0
  51. package/dist/core/artifact-graph/types.js +43 -0
  52. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  53. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  54. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  55. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  56. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  57. package/dist/core/command-generation/adapters/auggie.js +27 -0
  58. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  59. package/dist/core/command-generation/adapters/claude.js +50 -0
  60. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  61. package/dist/core/command-generation/adapters/cline.js +27 -0
  62. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  63. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  64. package/dist/core/command-generation/adapters/codex.d.ts +13 -0
  65. package/dist/core/command-generation/adapters/codex.js +27 -0
  66. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  67. package/dist/core/command-generation/adapters/continue.js +28 -0
  68. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  69. package/dist/core/command-generation/adapters/costrict.js +27 -0
  70. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  71. package/dist/core/command-generation/adapters/crush.js +30 -0
  72. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  73. package/dist/core/command-generation/adapters/cursor.js +44 -0
  74. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  75. package/dist/core/command-generation/adapters/factory.js +27 -0
  76. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  77. package/dist/core/command-generation/adapters/gemini.js +26 -0
  78. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  79. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  80. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/iflow.js +29 -0
  82. package/dist/core/command-generation/adapters/index.d.ts +27 -0
  83. package/dist/core/command-generation/adapters/index.js +27 -0
  84. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  85. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  86. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/opencode.js +26 -0
  88. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  89. package/dist/core/command-generation/adapters/qoder.js +30 -0
  90. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  91. package/dist/core/command-generation/adapters/qwen.js +26 -0
  92. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  93. package/dist/core/command-generation/adapters/roocode.js +27 -0
  94. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  95. package/dist/core/command-generation/adapters/windsurf.js +51 -0
  96. package/dist/core/command-generation/generator.d.ts +21 -0
  97. package/dist/core/command-generation/generator.js +27 -0
  98. package/dist/core/command-generation/index.d.ts +22 -0
  99. package/dist/core/command-generation/index.js +24 -0
  100. package/dist/core/command-generation/registry.d.ts +36 -0
  101. package/dist/core/command-generation/registry.js +88 -0
  102. package/dist/core/command-generation/types.d.ts +55 -0
  103. package/dist/core/command-generation/types.js +8 -0
  104. package/dist/core/completions/command-registry.d.ts +7 -0
  105. package/dist/core/completions/command-registry.js +456 -0
  106. package/dist/core/completions/completion-provider.d.ts +60 -0
  107. package/dist/core/completions/completion-provider.js +102 -0
  108. package/dist/core/completions/factory.d.ts +64 -0
  109. package/dist/core/completions/factory.js +75 -0
  110. package/dist/core/completions/generators/bash-generator.d.ts +32 -0
  111. package/dist/core/completions/generators/bash-generator.js +174 -0
  112. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  113. package/dist/core/completions/generators/fish-generator.js +157 -0
  114. package/dist/core/completions/generators/powershell-generator.d.ts +33 -0
  115. package/dist/core/completions/generators/powershell-generator.js +207 -0
  116. package/dist/core/completions/generators/zsh-generator.d.ts +44 -0
  117. package/dist/core/completions/generators/zsh-generator.js +250 -0
  118. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  119. package/dist/core/completions/installers/bash-installer.js +318 -0
  120. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  121. package/dist/core/completions/installers/fish-installer.js +143 -0
  122. package/dist/core/completions/installers/powershell-installer.d.ts +88 -0
  123. package/dist/core/completions/installers/powershell-installer.js +327 -0
  124. package/dist/core/completions/installers/zsh-installer.d.ts +125 -0
  125. package/dist/core/completions/installers/zsh-installer.js +449 -0
  126. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  127. package/dist/core/completions/templates/bash-templates.js +24 -0
  128. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  129. package/dist/core/completions/templates/fish-templates.js +39 -0
  130. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  131. package/dist/core/completions/templates/powershell-templates.js +25 -0
  132. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  133. package/dist/core/completions/templates/zsh-templates.js +36 -0
  134. package/dist/core/completions/types.d.ts +79 -0
  135. package/dist/core/completions/types.js +2 -0
  136. package/dist/core/config-prompts.d.ts +9 -0
  137. package/dist/core/config-prompts.js +34 -0
  138. package/dist/core/config-schema.d.ts +76 -0
  139. package/dist/core/config-schema.js +200 -0
  140. package/dist/core/config.d.ts +17 -0
  141. package/dist/core/config.js +30 -0
  142. package/dist/core/converters/json-converter.d.ts +6 -0
  143. package/dist/core/converters/json-converter.js +51 -0
  144. package/dist/core/global-config.d.ts +39 -0
  145. package/dist/core/global-config.js +115 -0
  146. package/dist/core/index.d.ts +2 -0
  147. package/dist/core/index.js +3 -0
  148. package/dist/core/init.d.ts +32 -0
  149. package/dist/core/init.js +433 -0
  150. package/dist/core/legacy-cleanup.d.ts +162 -0
  151. package/dist/core/legacy-cleanup.js +501 -0
  152. package/dist/core/list.d.ts +9 -0
  153. package/dist/core/list.js +171 -0
  154. package/dist/core/parsers/change-parser.d.ts +13 -0
  155. package/dist/core/parsers/change-parser.js +193 -0
  156. package/dist/core/parsers/markdown-parser.d.ts +22 -0
  157. package/dist/core/parsers/markdown-parser.js +187 -0
  158. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  159. package/dist/core/parsers/requirement-blocks.js +201 -0
  160. package/dist/core/project-config.d.ts +64 -0
  161. package/dist/core/project-config.js +223 -0
  162. package/dist/core/schemas/base.schema.d.ts +13 -0
  163. package/dist/core/schemas/base.schema.js +13 -0
  164. package/dist/core/schemas/change.schema.d.ts +73 -0
  165. package/dist/core/schemas/change.schema.js +31 -0
  166. package/dist/core/schemas/index.d.ts +4 -0
  167. package/dist/core/schemas/index.js +4 -0
  168. package/dist/core/schemas/spec.schema.d.ts +18 -0
  169. package/dist/core/schemas/spec.schema.js +15 -0
  170. package/dist/core/shared/index.d.ts +8 -0
  171. package/dist/core/shared/index.js +8 -0
  172. package/dist/core/shared/skill-generation.d.ts +41 -0
  173. package/dist/core/shared/skill-generation.js +74 -0
  174. package/dist/core/shared/tool-detection.d.ts +66 -0
  175. package/dist/core/shared/tool-detection.js +140 -0
  176. package/dist/core/specs-apply.d.ts +73 -0
  177. package/dist/core/specs-apply.js +384 -0
  178. package/dist/core/styles/palette.d.ts +7 -0
  179. package/dist/core/styles/palette.js +8 -0
  180. package/dist/core/templates/index.d.ts +8 -0
  181. package/dist/core/templates/index.js +9 -0
  182. package/dist/core/templates/skill-templates.d.ts +112 -0
  183. package/dist/core/templates/skill-templates.js +2893 -0
  184. package/dist/core/update.d.ts +42 -0
  185. package/dist/core/update.js +306 -0
  186. package/dist/core/validation/constants.d.ts +34 -0
  187. package/dist/core/validation/constants.js +40 -0
  188. package/dist/core/validation/types.d.ts +18 -0
  189. package/dist/core/validation/types.js +2 -0
  190. package/dist/core/validation/validator.d.ts +33 -0
  191. package/dist/core/validation/validator.js +409 -0
  192. package/dist/core/view.d.ts +8 -0
  193. package/dist/core/view.js +168 -0
  194. package/dist/index.d.ts +3 -0
  195. package/dist/index.js +3 -0
  196. package/dist/prompts/searchable-multi-select.d.ts +27 -0
  197. package/dist/prompts/searchable-multi-select.js +149 -0
  198. package/dist/telemetry/config.d.ts +32 -0
  199. package/dist/telemetry/config.js +68 -0
  200. package/dist/telemetry/index.d.ts +31 -0
  201. package/dist/telemetry/index.js +145 -0
  202. package/dist/ui/ascii-patterns.d.ts +16 -0
  203. package/dist/ui/ascii-patterns.js +133 -0
  204. package/dist/ui/welcome-screen.d.ts +10 -0
  205. package/dist/ui/welcome-screen.js +146 -0
  206. package/dist/utils/change-metadata.d.ts +51 -0
  207. package/dist/utils/change-metadata.js +147 -0
  208. package/dist/utils/change-utils.d.ts +62 -0
  209. package/dist/utils/change-utils.js +121 -0
  210. package/dist/utils/file-system.d.ts +36 -0
  211. package/dist/utils/file-system.js +281 -0
  212. package/dist/utils/index.d.ts +5 -0
  213. package/dist/utils/index.js +7 -0
  214. package/dist/utils/interactive.d.ts +18 -0
  215. package/dist/utils/interactive.js +21 -0
  216. package/dist/utils/item-discovery.d.ts +4 -0
  217. package/dist/utils/item-discovery.js +72 -0
  218. package/dist/utils/match.d.ts +3 -0
  219. package/dist/utils/match.js +22 -0
  220. package/dist/utils/shell-detection.d.ts +20 -0
  221. package/dist/utils/shell-detection.js +41 -0
  222. package/dist/utils/task-progress.d.ts +8 -0
  223. package/dist/utils/task-progress.js +36 -0
  224. package/package.json +84 -0
  225. package/schemas/spec-driven/schema.yaml +148 -0
  226. package/schemas/spec-driven/templates/design.md +19 -0
  227. package/schemas/spec-driven/templates/proposal.md +23 -0
  228. package/schemas/spec-driven/templates/spec.md +8 -0
  229. package/schemas/spec-driven/templates/tasks.md +9 -0
  230. package/schemas/tdd/schema.yaml +213 -0
  231. package/schemas/tdd/templates/docs.md +15 -0
  232. package/schemas/tdd/templates/implementation.md +11 -0
  233. package/schemas/tdd/templates/spec.md +11 -0
  234. package/schemas/tdd/templates/test.md +11 -0
  235. package/scripts/postinstall.js +147 -0
@@ -0,0 +1,207 @@
1
+ import { POWERSHELL_DYNAMIC_HELPERS } from '../templates/powershell-templates.js';
2
+ /**
3
+ * Generates PowerShell completion scripts for the OpenSpec CLI.
4
+ * Uses Register-ArgumentCompleter for command completion.
5
+ */
6
+ export class PowerShellGenerator {
7
+ shell = 'powershell';
8
+ stripTrailingCommaFromLastLine(lines) {
9
+ if (lines.length === 0)
10
+ return;
11
+ lines[lines.length - 1] = lines[lines.length - 1].replace(/,\s*$/, '');
12
+ }
13
+ /**
14
+ * Generate a PowerShell completion script
15
+ *
16
+ * @param commands - Command definitions to generate completions for
17
+ * @returns PowerShell completion script as a string
18
+ */
19
+ generate(commands) {
20
+ // Build top-level commands using push() for loop clarity
21
+ const commandLines = [];
22
+ for (const cmd of commands) {
23
+ commandLines.push(` @{Name="${cmd.name}"; Description="${this.escapeDescription(cmd.description)}"},`);
24
+ }
25
+ this.stripTrailingCommaFromLastLine(commandLines);
26
+ const topLevelCommands = commandLines.join('\n');
27
+ // Build command cases using push() for loop clarity
28
+ const commandCaseLines = [];
29
+ for (const cmd of commands) {
30
+ commandCaseLines.push(` "${cmd.name}" {`);
31
+ commandCaseLines.push(...this.generateCommandCase(cmd, ' '));
32
+ commandCaseLines.push(' }');
33
+ }
34
+ const commandCases = commandCaseLines.join('\n');
35
+ // Dynamic completion helpers from template
36
+ const helpers = POWERSHELL_DYNAMIC_HELPERS;
37
+ // Assemble final script with template literal
38
+ return `# PowerShell completion script for OpenSpec CLI
39
+ # Auto-generated - do not edit manually
40
+
41
+ ${helpers}
42
+ $openspecCompleter = {
43
+ param($wordToComplete, $commandAst, $cursorPosition)
44
+
45
+ $tokens = $commandAst.ToString() -split "\\s+"
46
+ $commandCount = ($tokens | Measure-Object).Count
47
+
48
+ # Top-level commands
49
+ if ($commandCount -eq 1 -or ($commandCount -eq 2 -and $wordToComplete)) {
50
+ $commands = @(
51
+ ${topLevelCommands}
52
+ )
53
+ $commands | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object {
54
+ [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, "ParameterValue", $_.Description)
55
+ }
56
+ return
57
+ }
58
+
59
+ $command = $tokens[1]
60
+
61
+ switch ($command) {
62
+ ${commandCases}
63
+ }
64
+ }
65
+
66
+ Register-ArgumentCompleter -CommandName openspec -ScriptBlock $openspecCompleter
67
+ `;
68
+ }
69
+ /**
70
+ * Generate completion case for a command
71
+ */
72
+ generateCommandCase(cmd, indent) {
73
+ const lines = [];
74
+ if (cmd.subcommands && cmd.subcommands.length > 0) {
75
+ // First, check if user is typing a flag for the parent command
76
+ if (cmd.flags.length > 0) {
77
+ lines.push(`${indent}if ($wordToComplete -like "-*") {`);
78
+ lines.push(`${indent} $flags = @(`);
79
+ for (const flag of cmd.flags) {
80
+ const longFlag = `--${flag.name}`;
81
+ const shortFlag = flag.short ? `-${flag.short}` : undefined;
82
+ if (shortFlag) {
83
+ lines.push(`${indent} @{Name="${longFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
84
+ lines.push(`${indent} @{Name="${shortFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
85
+ }
86
+ else {
87
+ lines.push(`${indent} @{Name="${longFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
88
+ }
89
+ }
90
+ this.stripTrailingCommaFromLastLine(lines);
91
+ lines.push(`${indent} )`);
92
+ lines.push(`${indent} $flags | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object {`);
93
+ lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, "ParameterName", $_.Description)`);
94
+ lines.push(`${indent} }`);
95
+ lines.push(`${indent} return`);
96
+ lines.push(`${indent}}`);
97
+ lines.push('');
98
+ }
99
+ // Handle subcommands
100
+ lines.push(`${indent}if ($commandCount -eq 2 -or ($commandCount -eq 3 -and $wordToComplete)) {`);
101
+ lines.push(`${indent} $subcommands = @(`);
102
+ for (const subcmd of cmd.subcommands) {
103
+ lines.push(`${indent} @{Name="${subcmd.name}"; Description="${this.escapeDescription(subcmd.description)}"},`);
104
+ }
105
+ this.stripTrailingCommaFromLastLine(lines);
106
+ lines.push(`${indent} )`);
107
+ lines.push(`${indent} $subcommands | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object {`);
108
+ lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, "ParameterValue", $_.Description)`);
109
+ lines.push(`${indent} }`);
110
+ lines.push(`${indent} return`);
111
+ lines.push(`${indent}}`);
112
+ lines.push('');
113
+ lines.push(`${indent}$subcommand = if ($commandCount -gt 2) { $tokens[2] } else { "" }`);
114
+ lines.push(`${indent}switch ($subcommand) {`);
115
+ for (const subcmd of cmd.subcommands) {
116
+ lines.push(`${indent} "${subcmd.name}" {`);
117
+ lines.push(...this.generateArgumentCompletion(subcmd, indent + ' '));
118
+ lines.push(`${indent} }`);
119
+ }
120
+ lines.push(`${indent}}`);
121
+ }
122
+ else {
123
+ // No subcommands
124
+ lines.push(...this.generateArgumentCompletion(cmd, indent));
125
+ }
126
+ return lines;
127
+ }
128
+ /**
129
+ * Generate argument completion (flags and positional)
130
+ */
131
+ generateArgumentCompletion(cmd, indent) {
132
+ const lines = [];
133
+ // Flag completion
134
+ if (cmd.flags.length > 0) {
135
+ lines.push(`${indent}if ($wordToComplete -like "-*") {`);
136
+ lines.push(`${indent} $flags = @(`);
137
+ for (const flag of cmd.flags) {
138
+ const longFlag = `--${flag.name}`;
139
+ const shortFlag = flag.short ? `-${flag.short}` : undefined;
140
+ if (shortFlag) {
141
+ lines.push(`${indent} @{Name="${longFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
142
+ lines.push(`${indent} @{Name="${shortFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
143
+ }
144
+ else {
145
+ lines.push(`${indent} @{Name="${longFlag}"; Description="${this.escapeDescription(flag.description)}"},`);
146
+ }
147
+ }
148
+ this.stripTrailingCommaFromLastLine(lines);
149
+ lines.push(`${indent} )`);
150
+ lines.push(`${indent} $flags | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object {`);
151
+ lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, "ParameterName", $_.Description)`);
152
+ lines.push(`${indent} }`);
153
+ lines.push(`${indent} return`);
154
+ lines.push(`${indent}}`);
155
+ lines.push('');
156
+ }
157
+ // Positional completion
158
+ if (cmd.acceptsPositional) {
159
+ lines.push(...this.generatePositionalCompletion(cmd.positionalType, indent));
160
+ }
161
+ return lines;
162
+ }
163
+ /**
164
+ * Generate positional argument completion
165
+ */
166
+ generatePositionalCompletion(positionalType, indent) {
167
+ const lines = [];
168
+ switch (positionalType) {
169
+ case 'change-id':
170
+ lines.push(`${indent}Get-OpenSpecChanges | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {`);
171
+ lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", "Change: $_")`);
172
+ lines.push(`${indent}}`);
173
+ break;
174
+ case 'spec-id':
175
+ lines.push(`${indent}Get-OpenSpecSpecs | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {`);
176
+ lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", "Spec: $_")`);
177
+ lines.push(`${indent}}`);
178
+ break;
179
+ case 'change-or-spec-id':
180
+ lines.push(`${indent}$items = @(Get-OpenSpecChanges) + @(Get-OpenSpecSpecs)`);
181
+ lines.push(`${indent}$items | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {`);
182
+ lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", $_)`);
183
+ lines.push(`${indent}}`);
184
+ break;
185
+ case 'shell':
186
+ lines.push(`${indent}$shells = @("zsh", "bash", "fish", "powershell")`);
187
+ lines.push(`${indent}$shells | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {`);
188
+ lines.push(`${indent} [System.Management.Automation.CompletionResult]::new($_, $_, "ParameterValue", "Shell: $_")`);
189
+ lines.push(`${indent}}`);
190
+ break;
191
+ case 'path':
192
+ // PowerShell handles file path completion automatically
193
+ break;
194
+ }
195
+ return lines;
196
+ }
197
+ /**
198
+ * Escape description text for PowerShell
199
+ */
200
+ escapeDescription(description) {
201
+ return description
202
+ .replace(/`/g, '``') // Backticks (escape sequences)
203
+ .replace(/\$/g, '`$') // Dollar signs (prevents $())
204
+ .replace(/"/g, '""'); // Double quotes
205
+ }
206
+ }
207
+ //# sourceMappingURL=powershell-generator.js.map
@@ -0,0 +1,44 @@
1
+ import { CompletionGenerator, CommandDefinition } from '../types.js';
2
+ /**
3
+ * Generates Zsh completion scripts for the OpenSpec CLI.
4
+ * Follows Zsh completion system conventions using the _openspec function.
5
+ */
6
+ export declare class ZshGenerator implements CompletionGenerator {
7
+ readonly shell: "zsh";
8
+ /**
9
+ * Generate a Zsh completion script
10
+ *
11
+ * @param commands - Command definitions to generate completions for
12
+ * @returns Zsh completion script as a string
13
+ */
14
+ generate(commands: CommandDefinition[]): string;
15
+ /**
16
+ * Generate completion function for a specific command
17
+ */
18
+ private generateCommandFunction;
19
+ /**
20
+ * Generate completion function for a subcommand
21
+ */
22
+ private generateSubcommandFunction;
23
+ /**
24
+ * Generate flag specification for _arguments
25
+ */
26
+ private generateFlagSpec;
27
+ /**
28
+ * Generate positional argument specification
29
+ */
30
+ private generatePositionalSpec;
31
+ /**
32
+ * Escape special characters in descriptions
33
+ */
34
+ private escapeDescription;
35
+ /**
36
+ * Escape special characters in values
37
+ */
38
+ private escapeValue;
39
+ /**
40
+ * Sanitize command names for use in function names
41
+ */
42
+ private sanitizeFunctionName;
43
+ }
44
+ //# sourceMappingURL=zsh-generator.d.ts.map
@@ -0,0 +1,250 @@
1
+ import { ZSH_DYNAMIC_HELPERS } from '../templates/zsh-templates.js';
2
+ /**
3
+ * Generates Zsh completion scripts for the OpenSpec CLI.
4
+ * Follows Zsh completion system conventions using the _openspec function.
5
+ */
6
+ export class ZshGenerator {
7
+ shell = 'zsh';
8
+ /**
9
+ * Generate a Zsh completion script
10
+ *
11
+ * @param commands - Command definitions to generate completions for
12
+ * @returns Zsh completion script as a string
13
+ */
14
+ generate(commands) {
15
+ // Build command list using push() for loop clarity
16
+ const commandLines = [];
17
+ for (const cmd of commands) {
18
+ const escapedDesc = this.escapeDescription(cmd.description);
19
+ commandLines.push(` '${cmd.name}:${escapedDesc}'`);
20
+ }
21
+ const commandList = commandLines.join('\n');
22
+ // Build command cases using push() for loop clarity
23
+ const commandCaseLines = [];
24
+ for (const cmd of commands) {
25
+ commandCaseLines.push(` ${cmd.name})`);
26
+ commandCaseLines.push(` _openspec_${this.sanitizeFunctionName(cmd.name)}`);
27
+ commandCaseLines.push(' ;;');
28
+ }
29
+ const commandCases = commandCaseLines.join('\n');
30
+ // Build command functions using push() for loop clarity
31
+ const commandFunctionLines = [];
32
+ for (const cmd of commands) {
33
+ commandFunctionLines.push(...this.generateCommandFunction(cmd));
34
+ commandFunctionLines.push('');
35
+ }
36
+ const commandFunctions = commandFunctionLines.join('\n');
37
+ // Dynamic completion helpers from template
38
+ const helpers = ZSH_DYNAMIC_HELPERS;
39
+ // Assemble final script with template literal
40
+ return `#compdef openspec
41
+
42
+ # Zsh completion script for OpenSpec CLI
43
+ # Auto-generated - do not edit manually
44
+
45
+ _openspec() {
46
+ local context state line
47
+ typeset -A opt_args
48
+
49
+ local -a commands
50
+ commands=(
51
+ ${commandList}
52
+ )
53
+
54
+ _arguments -C \\
55
+ "1: :->command" \\
56
+ "*::arg:->args"
57
+
58
+ case $state in
59
+ command)
60
+ _describe "openspec command" commands
61
+ ;;
62
+ args)
63
+ case $words[1] in
64
+ ${commandCases}
65
+ esac
66
+ ;;
67
+ esac
68
+ }
69
+
70
+ ${commandFunctions}
71
+ ${helpers}
72
+ compdef _openspec openspec
73
+ `;
74
+ }
75
+ /**
76
+ * Generate completion function for a specific command
77
+ */
78
+ generateCommandFunction(cmd) {
79
+ const funcName = `_openspec_${this.sanitizeFunctionName(cmd.name)}`;
80
+ const lines = [];
81
+ lines.push(`${funcName}() {`);
82
+ // If command has subcommands, handle them
83
+ if (cmd.subcommands && cmd.subcommands.length > 0) {
84
+ lines.push(' local context state line');
85
+ lines.push(' typeset -A opt_args');
86
+ lines.push('');
87
+ lines.push(' local -a subcommands');
88
+ lines.push(' subcommands=(');
89
+ for (const subcmd of cmd.subcommands) {
90
+ const escapedDesc = this.escapeDescription(subcmd.description);
91
+ lines.push(` '${subcmd.name}:${escapedDesc}'`);
92
+ }
93
+ lines.push(' )');
94
+ lines.push('');
95
+ lines.push(' _arguments -C \\');
96
+ // Add command flags
97
+ for (const flag of cmd.flags) {
98
+ lines.push(' ' + this.generateFlagSpec(flag) + ' \\');
99
+ }
100
+ lines.push(' "1: :->subcommand" \\');
101
+ lines.push(' "*::arg:->args"');
102
+ lines.push('');
103
+ lines.push(' case $state in');
104
+ lines.push(' subcommand)');
105
+ lines.push(' _describe "subcommand" subcommands');
106
+ lines.push(' ;;');
107
+ lines.push(' args)');
108
+ lines.push(' case $words[1] in');
109
+ for (const subcmd of cmd.subcommands) {
110
+ lines.push(` ${subcmd.name})`);
111
+ lines.push(` _openspec_${this.sanitizeFunctionName(cmd.name)}_${this.sanitizeFunctionName(subcmd.name)}`);
112
+ lines.push(' ;;');
113
+ }
114
+ lines.push(' esac');
115
+ lines.push(' ;;');
116
+ lines.push(' esac');
117
+ }
118
+ else {
119
+ // Command without subcommands
120
+ lines.push(' _arguments \\');
121
+ // Add flags
122
+ for (const flag of cmd.flags) {
123
+ lines.push(' ' + this.generateFlagSpec(flag) + ' \\');
124
+ }
125
+ // Add positional argument completion
126
+ if (cmd.acceptsPositional) {
127
+ const positionalSpec = this.generatePositionalSpec(cmd.positionalType);
128
+ lines.push(' ' + positionalSpec);
129
+ }
130
+ else {
131
+ // Remove trailing backslash from last flag
132
+ if (lines[lines.length - 1].endsWith(' \\')) {
133
+ lines[lines.length - 1] = lines[lines.length - 1].slice(0, -2);
134
+ }
135
+ }
136
+ }
137
+ lines.push('}');
138
+ // Generate subcommand functions if they exist
139
+ if (cmd.subcommands) {
140
+ for (const subcmd of cmd.subcommands) {
141
+ lines.push('');
142
+ lines.push(...this.generateSubcommandFunction(cmd.name, subcmd));
143
+ }
144
+ }
145
+ return lines;
146
+ }
147
+ /**
148
+ * Generate completion function for a subcommand
149
+ */
150
+ generateSubcommandFunction(parentName, subcmd) {
151
+ const funcName = `_openspec_${this.sanitizeFunctionName(parentName)}_${this.sanitizeFunctionName(subcmd.name)}`;
152
+ const lines = [];
153
+ lines.push(`${funcName}() {`);
154
+ lines.push(' _arguments \\');
155
+ // Add flags
156
+ for (const flag of subcmd.flags) {
157
+ lines.push(' ' + this.generateFlagSpec(flag) + ' \\');
158
+ }
159
+ // Add positional argument completion
160
+ if (subcmd.acceptsPositional) {
161
+ const positionalSpec = this.generatePositionalSpec(subcmd.positionalType);
162
+ lines.push(' ' + positionalSpec);
163
+ }
164
+ else {
165
+ // Remove trailing backslash from last flag
166
+ if (lines[lines.length - 1].endsWith(' \\')) {
167
+ lines[lines.length - 1] = lines[lines.length - 1].slice(0, -2);
168
+ }
169
+ }
170
+ lines.push('}');
171
+ return lines;
172
+ }
173
+ /**
174
+ * Generate flag specification for _arguments
175
+ */
176
+ generateFlagSpec(flag) {
177
+ const parts = [];
178
+ // Handle mutually exclusive short and long forms
179
+ if (flag.short) {
180
+ parts.push(`'(-${flag.short} --${flag.name})'{-${flag.short},--${flag.name}}'`);
181
+ }
182
+ else {
183
+ parts.push(`'--${flag.name}`);
184
+ }
185
+ // Add description
186
+ const escapedDesc = this.escapeDescription(flag.description);
187
+ parts.push(`[${escapedDesc}]`);
188
+ // Add value completion if flag takes a value
189
+ if (flag.takesValue) {
190
+ if (flag.values && flag.values.length > 0) {
191
+ // Provide specific value completions
192
+ const valueList = flag.values.map(v => this.escapeValue(v)).join(' ');
193
+ parts.push(`:value:(${valueList})`);
194
+ }
195
+ else {
196
+ // Generic value placeholder
197
+ parts.push(':value:');
198
+ }
199
+ }
200
+ // Close the quote (needed for both short and long forms)
201
+ parts.push("'");
202
+ return parts.join('');
203
+ }
204
+ /**
205
+ * Generate positional argument specification
206
+ */
207
+ generatePositionalSpec(positionalType) {
208
+ switch (positionalType) {
209
+ case 'change-id':
210
+ return "'*: :_openspec_complete_changes'";
211
+ case 'spec-id':
212
+ return "'*: :_openspec_complete_specs'";
213
+ case 'change-or-spec-id':
214
+ return "'*: :_openspec_complete_items'";
215
+ case 'path':
216
+ return "'*:path:_files'";
217
+ case 'shell':
218
+ return "'*:shell:(zsh bash fish powershell)'";
219
+ default:
220
+ return "'*: :_default'";
221
+ }
222
+ }
223
+ /**
224
+ * Escape special characters in descriptions
225
+ */
226
+ escapeDescription(desc) {
227
+ return desc
228
+ .replace(/\\/g, '\\\\')
229
+ .replace(/'/g, "\\'")
230
+ .replace(/\[/g, '\\[')
231
+ .replace(/]/g, '\\]')
232
+ .replace(/:/g, '\\:');
233
+ }
234
+ /**
235
+ * Escape special characters in values
236
+ */
237
+ escapeValue(value) {
238
+ return value
239
+ .replace(/\\/g, '\\\\')
240
+ .replace(/'/g, "\\'")
241
+ .replace(/ /g, '\\ ');
242
+ }
243
+ /**
244
+ * Sanitize command names for use in function names
245
+ */
246
+ sanitizeFunctionName(name) {
247
+ return name.replace(/-/g, '_');
248
+ }
249
+ }
250
+ //# sourceMappingURL=zsh-generator.js.map
@@ -0,0 +1,87 @@
1
+ import { InstallationResult } from '../factory.js';
2
+ /**
3
+ * Installer for Bash completion scripts.
4
+ * Supports bash-completion package and standalone installations.
5
+ */
6
+ export declare class BashInstaller {
7
+ private readonly homeDir;
8
+ /**
9
+ * Markers for .bashrc configuration management
10
+ */
11
+ private readonly BASHRC_MARKERS;
12
+ constructor(homeDir?: string);
13
+ /**
14
+ * Check if bash-completion is installed
15
+ *
16
+ * @returns true if bash-completion directories exist
17
+ */
18
+ isBashCompletionInstalled(): Promise<boolean>;
19
+ /**
20
+ * Get the appropriate installation path for the completion script
21
+ *
22
+ * @returns Installation path
23
+ */
24
+ getInstallationPath(): Promise<string>;
25
+ /**
26
+ * Backup an existing completion file if it exists
27
+ *
28
+ * @param targetPath - Path to the file to backup
29
+ * @returns Path to the backup file, or undefined if no backup was needed
30
+ */
31
+ backupExistingFile(targetPath: string): Promise<string | undefined>;
32
+ /**
33
+ * Get the path to .bashrc file
34
+ *
35
+ * @returns Path to .bashrc
36
+ */
37
+ private getBashrcPath;
38
+ /**
39
+ * Generate .bashrc configuration content
40
+ *
41
+ * @param completionsDir - Directory containing completion scripts
42
+ * @returns Configuration content
43
+ */
44
+ private generateBashrcConfig;
45
+ /**
46
+ * Configure .bashrc to enable completions
47
+ *
48
+ * @param completionsDir - Directory containing completion scripts
49
+ * @returns true if configured successfully, false otherwise
50
+ */
51
+ configureBashrc(completionsDir: string): Promise<boolean>;
52
+ /**
53
+ * Remove .bashrc configuration
54
+ * Used during uninstallation
55
+ *
56
+ * @returns true if removed successfully, false otherwise
57
+ */
58
+ removeBashrcConfig(): Promise<boolean>;
59
+ /**
60
+ * Install the completion script
61
+ *
62
+ * @param completionScript - The completion script content to install
63
+ * @returns Installation result with status and instructions
64
+ */
65
+ install(completionScript: string): Promise<InstallationResult>;
66
+ /**
67
+ * Generate user instructions for enabling completions
68
+ *
69
+ * @param installedPath - Path where the script was installed
70
+ * @returns Array of instruction strings
71
+ */
72
+ private generateInstructions;
73
+ /**
74
+ * Uninstall the completion script
75
+ *
76
+ * @param options - Optional uninstall options
77
+ * @param options.yes - Skip confirmation prompt (handled by command layer)
78
+ * @returns Uninstallation result
79
+ */
80
+ uninstall(options?: {
81
+ yes?: boolean;
82
+ }): Promise<{
83
+ success: boolean;
84
+ message: string;
85
+ }>;
86
+ }
87
+ //# sourceMappingURL=bash-installer.d.ts.map