ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
powershell.c
Go to the documentation of this file.
1
7#include <string.h>
8#include <stdio.h>
9#include <ascii-chat/options/completions/powershell.h>
10#include <ascii-chat/options/registry.h>
11#include <ascii-chat/common.h>
12
17static void ps_escape_help(FILE *output, const char *text) {
18 if (!text) {
19 return;
20 }
21
22 for (const char *p = text; *p; p++) {
23 if (*p == '\'') {
24 // Escape single quotes by doubling them
25 fprintf(output, "''");
26 } else if (*p == '\n' || *p == '\t') {
27 // Convert newlines and tabs to spaces
28 fprintf(output, " ");
29 } else {
30 fputc(*p, output);
31 }
32 }
33}
34
35static void ps_write_option(FILE *output, const option_descriptor_t *opt) {
36 if (!opt) {
37 return;
38 }
39
40 // Get completion metadata for this option
41 const option_metadata_t *meta = options_registry_get_metadata(opt->long_name);
42
43 // Build values array if metadata exists
44 if (meta) {
45 if (meta->input_type == OPTION_INPUT_ENUM && meta->enum_values && meta->enum_values[0] != NULL) {
46 // Enum values
47 if (opt->short_name != '\0') {
48 fprintf(output, " @{ Name = '-%c'; Description = '", opt->short_name);
49 ps_escape_help(output, opt->help_text);
50 fprintf(output, "'; Values = @(");
51 for (size_t i = 0; meta->enum_values[i] != NULL; i++) {
52 if (i > 0)
53 fprintf(output, ", ");
54 fprintf(output, "'%s'", meta->enum_values[i]);
55 }
56 fprintf(output, ") }\n");
57 }
58 fprintf(output, " @{ Name = '--%s'; Description = '", opt->long_name);
59 ps_escape_help(output, opt->help_text);
60 fprintf(output, "'; Values = @(");
61 for (size_t i = 0; meta->enum_values[i] != NULL; i++) {
62 if (i > 0)
63 fprintf(output, ", ");
64 fprintf(output, "'%s'", meta->enum_values[i]);
65 }
66 fprintf(output, ") }\n");
67 return;
68 } else if (meta->examples && meta->examples[0] != NULL) {
69 // Example values (practical values, higher priority than calculated ranges)
70 if (opt->short_name != '\0') {
71 fprintf(output, " @{ Name = '-%c'; Description = '", opt->short_name);
72 ps_escape_help(output, opt->help_text);
73 fprintf(output, "'; Values = @(");
74 for (size_t i = 0; meta->examples[i] != NULL; i++) {
75 if (i > 0)
76 fprintf(output, ", ");
77 fprintf(output, "'%s'", meta->examples[i]);
78 }
79 fprintf(output, ") }\n");
80 }
81 fprintf(output, " @{ Name = '--%s'; Description = '", opt->long_name);
82 ps_escape_help(output, opt->help_text);
83 fprintf(output, "'; Values = @(");
84 for (size_t i = 0; meta->examples[i] != NULL; i++) {
85 if (i > 0)
86 fprintf(output, ", ");
87 fprintf(output, "'%s'", meta->examples[i]);
88 }
89 fprintf(output, ") }\n");
90 return;
91 } else if (meta->input_type == OPTION_INPUT_NUMERIC) {
92 // Numeric range - suggest min, middle, max values
93 if (opt->short_name != '\0') {
94 fprintf(output, " @{ Name = '-%c'; Description = '", opt->short_name);
95 ps_escape_help(output, opt->help_text);
96 fprintf(output, " (numeric %d-%d)'; Values = @(", meta->numeric_range.min, meta->numeric_range.max);
97 fprintf(output, "'%d'", meta->numeric_range.min);
98 if (meta->numeric_range.max > meta->numeric_range.min) {
99 int middle = (meta->numeric_range.min + meta->numeric_range.max) / 2;
100 fprintf(output, ", '%d'", middle);
101 fprintf(output, ", '%d'", meta->numeric_range.max);
102 }
103 fprintf(output, ") }\n");
104 }
105 fprintf(output, " @{ Name = '--%s'; Description = '", opt->long_name);
106 ps_escape_help(output, opt->help_text);
107 fprintf(output, " (numeric %d-%d)'; Values = @(", meta->numeric_range.min, meta->numeric_range.max);
108 fprintf(output, "'%d'", meta->numeric_range.min);
109 if (meta->numeric_range.max > meta->numeric_range.min) {
110 int middle = (meta->numeric_range.min + meta->numeric_range.max) / 2;
111 fprintf(output, ", '%d'", middle);
112 fprintf(output, ", '%d'", meta->numeric_range.max);
113 }
114 fprintf(output, ") }\n");
115 return;
116 }
117 }
118
119 // Basic option without values
120 if (opt->short_name != '\0') {
121 fprintf(output, " @{ Name = '-%c'; Description = '", opt->short_name);
122 ps_escape_help(output, opt->help_text);
123 fprintf(output, "' }\n");
124 }
125 fprintf(output, " @{ Name = '--%s'; Description = '", opt->long_name);
126 ps_escape_help(output, opt->help_text);
127 fprintf(output, "' }\n");
128}
129
130asciichat_error_t completions_generate_powershell(FILE *output) {
131 if (!output) {
132 return SET_ERRNO(ERROR_INVALID_PARAM, "Output stream cannot be NULL");
133 }
134
135 fprintf(output, "# PowerShell completion script for ascii-chat\n"
136 "# Generated from options registry - DO NOT EDIT MANUALLY\n"
137 "# Usage: ascii-chat --completions powershell | Out-String | Invoke-Expression\n"
138 "\n"
139 "$script:AsciiChatCompleter = {\n"
140 " param($wordToComplete, $commandAst, $cursorPosition)\n"
141 "\n"
142 " $words = @($commandAst.CommandElements | ForEach-Object { $_.Value })\n"
143 " $mode = $null\n"
144 "\n"
145 " foreach ($word in $words) {\n"
146 " if ($word -in @('server', 'client', 'mirror')) {\n"
147 " $mode = $word\n"
148 " break\n"
149 " }\n"
150 " }\n"
151 "\n"
152 " $binaryOptions = @(\n");
153
154 /* Binary options - use unified display API matching help system */
155 size_t binary_count = 0;
156 const option_descriptor_t *binary_opts = options_registry_get_for_display(MODE_DISCOVERY, true, &binary_count);
157
158 if (binary_opts) {
159 for (size_t i = 0; i < binary_count; i++) {
160 ps_write_option(output, &binary_opts[i]);
161 }
162 SAFE_FREE(binary_opts);
163 }
164
165 fprintf(output, " )\n\n $serverOptions = @(\n");
166
167 /* Server options - use unified display API matching help system */
168 size_t server_count = 0;
169 const option_descriptor_t *server_opts = options_registry_get_for_display(MODE_SERVER, false, &server_count);
170
171 if (server_opts) {
172 for (size_t i = 0; i < server_count; i++) {
173 ps_write_option(output, &server_opts[i]);
174 }
175 SAFE_FREE(server_opts);
176 }
177
178 fprintf(output, " )\n\n $clientOptions = @(\n");
179
180 /* Client options - use unified display API matching help system */
181 size_t client_count = 0;
182 const option_descriptor_t *client_opts = options_registry_get_for_display(MODE_CLIENT, false, &client_count);
183
184 if (client_opts) {
185 for (size_t i = 0; i < client_count; i++) {
186 ps_write_option(output, &client_opts[i]);
187 }
188 SAFE_FREE(client_opts);
189 }
190
191 fprintf(output, " )\n\n $mirrorOptions = @(\n");
192
193 /* Mirror options - use unified display API matching help system */
194 size_t mirror_count = 0;
195 const option_descriptor_t *mirror_opts = options_registry_get_for_display(MODE_MIRROR, false, &mirror_count);
196
197 if (mirror_opts) {
198 for (size_t i = 0; i < mirror_count; i++) {
199 ps_write_option(output, &mirror_opts[i]);
200 }
201 SAFE_FREE(mirror_opts);
202 }
203
204 fprintf(output, " )\n\n $discoverySvcOptions = @(\n");
205
206 /* Discovery-service options */
207 size_t discovery_svc_count = 0;
208 const option_descriptor_t *discovery_svc_opts =
209 options_registry_get_for_display(MODE_DISCOVERY_SERVICE, false, &discovery_svc_count);
210
211 if (discovery_svc_opts) {
212 for (size_t i = 0; i < discovery_svc_count; i++) {
213 ps_write_option(output, &discovery_svc_opts[i]);
214 }
215 SAFE_FREE(discovery_svc_opts);
216 }
217
218 fprintf(output,
219 " )\n"
220 "\n"
221 " $options = $binaryOptions\n"
222 " \n"
223 " if ($mode -eq 'server') {\n"
224 " $options += $serverOptions\n"
225 " } elseif ($mode -eq 'client') {\n"
226 " $options += $clientOptions\n"
227 " } elseif ($mode -eq 'mirror') {\n"
228 " $options += $mirrorOptions\n"
229 " } elseif ($mode -eq 'discovery-service') {\n"
230 " $options += $discoverySvcOptions\n"
231 " }\n"
232 "\n"
233 " if (-not $mode -and -not $wordToComplete.StartsWith('-')) {\n"
234 " @('server', 'client', 'mirror', 'discovery-service') | Where-Object { $_ -like \"$wordToComplete*\" } | "
235 "ForEach-Object {\n"
236 " [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', \"Mode: $_\")\n"
237 " }\n"
238 " } else {\n"
239 " $options | Where-Object { $_.Name -like \"$wordToComplete*\" } | ForEach-Object {\n"
240 " if ($_.Values) {\n"
241 " $_.Values | ForEach-Object {\n"
242 " [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_.Description)\n"
243 " }\n"
244 " } else {\n"
245 " [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', "
246 "$_.Description)\n"
247 " }\n"
248 " }\n"
249 " }\n"
250 "}\n"
251 "\n"
252 "Register-ArgumentCompleter -CommandName ascii-chat -ScriptBlock $script:AsciiChatCompleter\n");
253
254 return ASCIICHAT_OK;
255}
asciichat_error_t completions_generate_powershell(FILE *output)
Definition powershell.c:130
const option_descriptor_t * options_registry_get_for_display(asciichat_mode_t mode, bool for_binary_help, size_t *num_options)
Definition public_api.c:323
const option_metadata_t * options_registry_get_metadata(const char *long_name)
Definition public_api.c:369