@@ -49,6 +49,12 @@ define abstract class <parse-node> (<object>)
4949 init-keyword: repeat-marker:;
5050end class ;
5151
52+ define open generic node-help-symbol (node :: <parse-node>)
53+ => (help-symbol :: <string> );
54+
55+ define open generic node-help-text (node :: <parse-node>)
56+ => (help-text :: <string> );
57+
5258/* Generate completions for the given node
5359 *
5460 * May or may not be provided a partial token.
@@ -69,6 +75,16 @@ define open generic node-accept ( node :: <parse-node>, parser :: <command-parse
6975 => ();
7076
7177
78+ define method node-help-symbol (node :: <parse-node>)
79+ => (help-symbol :: <string> );
80+ "<...>" ;
81+ end method ;
82+
83+ define method node-help-text (node :: <parse-node>)
84+ => (help-symbol :: <string> );
85+ "No help." ;
86+ end method ;
87+
7288/* Is the node acceptable as next node in given parser state?
7389 *
7490 * This prevents non-repeatable parameters from being added again.
@@ -148,6 +164,16 @@ define method print-object(object :: <symbol-node>, stream :: <stream>) => ();
148164 format(stream, "%s" , node-symbol(object));
149165end method ;
150166
167+ define method node-help-symbol (node :: <symbol-node>)
168+ => (help-symbol :: <string> );
169+ as (<string> , node-symbol(node));
170+ end method ;
171+
172+ define method node-help-text (node :: <symbol-node>)
173+ => (help-symbol :: <string> );
174+ "" ;
175+ end method ;
176+
151177define method node-match (node :: <symbol-node>, parser :: <command-parser>, token :: <command-token>)
152178 => (matched? :: <boolean> );
153179 starts-with?(as (<string> , node-symbol(node)),
@@ -186,13 +212,25 @@ define method print-object(object :: <command-node>, stream :: <stream>) => ();
186212 format(stream, "%s - %s" , node-symbol(object), command-help(object));
187213end method ;
188214
215+ define method node-help-text (node :: <command-node>)
216+ => (help-text :: <string> );
217+ command-help(node) | "Command" ;
218+ end method ;
219+
189220define method node-accept (node :: <command-node>, parser :: <command-parser>, token :: <command-token>)
190221 => ();
191222 if (command-handler(node))
192223 parser-push-command(parser, node);
193224 end
194225end method ;
195226
227+ define method node-complete (node :: <command-node>, parser :: <command-parser>, token :: false-or (<command-token>))
228+ => (completion :: <command-completion>);
229+ make-completion(node, token,
230+ exhaustive?: #t ,
231+ complete-options: list (as (<string> , node-symbol(node))));
232+ end method ;
233+
196234define method command-add-parameter (node :: <command-node>, parameter :: <parameter-node>)
197235 => ();
198236 command-parameters(node) := add! (command-parameters(node), parameter);
@@ -224,6 +262,32 @@ define method node-successors (node :: <wrapper-node>)
224262 concatenate (node-successors(wrapper-root(node)), next-method ());
225263end method ;
226264
265+
266+ /* A symbol that comes before a parameter
267+ */
268+ define class <parameter-symbol-node> (<symbol-node>)
269+ constant slot symbol-parameter :: <parameter-node>,
270+ init-keyword: parameter:;
271+ end class ;
272+
273+ define method node-help-symbol (node :: <parameter-symbol-node>)
274+ => (help-symbol :: <string> );
275+ let parameter = symbol-parameter(node);
276+ concatenate (as (<string> , node-symbol(node)),
277+ " <" , as (<string> , parameter-name(parameter)),
278+ if (node-repeatable?(parameter))
279+ ">..."
280+ else
281+ ">"
282+ end );
283+ end method ;
284+
285+ define method node-help-text (node :: <parameter-symbol-node>)
286+ => (help-text :: <string> );
287+ node-help-text(symbol-parameter(node));
288+ end method ;
289+
290+
227291/* Syntactical kinds of parameters
228292 */
229293define constant <parameter-kind> = one-of (# "simple" , # "named" , # "flag" );
@@ -245,6 +309,21 @@ define open abstract class <parameter-node> (<parse-node>)
245309 init-keyword: value-type:;
246310end class ;
247311
312+ define method node-help-symbol (node :: <parameter-node>)
313+ => (help-symbol :: <string> );
314+ concatenate ("<" , as (<string> , parameter-name(node)),
315+ if (node-repeatable?(node))
316+ ">..."
317+ else
318+ ">"
319+ end )
320+ end method ;
321+
322+ define method node-help-text (node :: <parameter-node>)
323+ => (help-symbol :: <string> );
324+ parameter-help(node) | "Parameter" ;
325+ end method ;
326+
248327/* Parameters can be converted to values
249328 *
250329 * By default they convert to simple strings.
@@ -299,9 +378,19 @@ end class;
299378
300379/* Flag parameters
301380 */
302- define class <flag-node> (<parameter-node>, <symbol-node>)
381+ define class <flag-node> (<parameter-node>, <parameter- symbol-node>)
303382end class ;
304383
384+ define method node-help-symbol (node :: <flag-node>)
385+ => (help-symbol :: <string> );
386+ as (<string> , parameter-name(node));
387+ end method ;
388+
389+ define method node-help-text (node :: <flag-node>)
390+ => (help-symbol :: <string> );
391+ parameter-help(node) | "Flag" ;
392+ end method ;
393+
305394define method parameter-convert (parser :: <command-parser>, node :: <flag-node>, token :: <command-token>)
306395 => (value :: <boolean> );
307396 #t ;
@@ -338,6 +427,15 @@ define class <oneof-node> (<parameter-node>)
338427 required-init-keyword: alternatives:;
339428end class ;
340429
430+ define method node-help-text (node :: <oneof-node>)
431+ => (help-symbol :: <string> );
432+ let alternatives = oneof-alternatives(node);
433+ unless (oneof-case-sensitive?(node))
434+ alternatives := map (as-lowercase , alternatives);
435+ end ;
436+ parameter-help(node) | concatenate ("One of: " , join(alternatives, ", " ));
437+ end method ;
438+
341439define method node-match (node :: <oneof-node>, parser :: <command-parser>, token :: <command-token>)
342440 => (matched? :: <boolean> );
343441 let string = token-string(token);
0 commit comments