@@ -28,29 +28,39 @@ public class ExampleCommand implements Command<CommandInvocation> {
2828
2929``` java
3030public interface CommandInvocation {
31-
31+
3232 // Output methods
3333 void print (String message );
3434 void println (String message );
35-
35+
3636 // Shell access
3737 Shell getShell ();
38-
38+
3939 // Control methods
4040 void stop ();
41-
41+
4242 // Help system
4343 String getHelpInfo ();
4444 String getHelpInfo (String commandName );
45-
45+
4646 // Configuration access
4747 CommandInvocationConfiguration getConfiguration ();
48-
48+
4949 // Operator support
5050 Operator getOperator ();
51-
51+
5252 // Piped input
5353 String getInputLine () throws InterruptedException ;
54+
55+ // Sub-command mode
56+ boolean enterSubCommandMode (Command<?> command );
57+ void exitSubCommandMode ();
58+ boolean isInSubCommandMode ();
59+ CommandContext getCommandContext ();
60+ <T > T getParentValue (String name , Class<T > type );
61+ <T > T getParentValue (String name , Class<T > type , T defaultValue );
62+ <T > T getInheritedValue (String name , Class<T > type );
63+ <T > T getInheritedValue (String name , Class<T > type , T defaultValue );
5464}
5565```
5666
@@ -324,6 +334,238 @@ public class UppercaseCommand implements Command<CommandInvocation> {
324334
325335** Output:** ` HELLO WORLD `
326336
337+ ## Sub-Command Mode Methods
338+
339+ These methods support [ Sub-Command Mode] ( /docs/aesh/sub-command-mode ) , allowing group commands to create interactive contexts where subcommands can access parent values.
340+
341+ ### enterSubCommandMode(Command)
342+
343+ Enters sub-command mode for the current group command. Returns ` true ` if successful, ` false ` if sub-command mode is disabled.
344+
345+ ``` java
346+ @GroupCommandDefinition (name = " project" , groupCommands = {BuildCommand . class, TestCommand . class})
347+ public class ProjectCommand implements Command<CommandInvocation > {
348+
349+ @Option (name = " name" , required = true )
350+ private String projectName;
351+
352+ @Override
353+ public CommandResult execute (CommandInvocation invocation ) {
354+ invocation. println(" Project: " + projectName);
355+
356+ // Enter sub-command mode - prompt changes to "project[myapp]>"
357+ if (invocation. enterSubCommandMode(this )) {
358+ invocation. println(" Available commands: build, test" );
359+ }
360+
361+ return CommandResult . SUCCESS ;
362+ }
363+ }
364+ ```
365+
366+ ### exitSubCommandMode()
367+
368+ Exits the current sub-command mode level. If nested, returns to the parent context. If at the top level, returns to the main prompt.
369+
370+ ``` java
371+ @CommandDefinition (name = " done" , description = " Exit project mode" )
372+ public class DoneCommand implements Command<CommandInvocation > {
373+
374+ @Override
375+ public CommandResult execute (CommandInvocation invocation ) {
376+ invocation. exitSubCommandMode();
377+ return CommandResult . SUCCESS ;
378+ }
379+ }
380+ ```
381+
382+ ### isInSubCommandMode()
383+
384+ Returns ` true ` if currently in sub-command mode.
385+
386+ ``` java
387+ @Override
388+ public CommandResult execute(CommandInvocation invocation) {
389+ if (invocation. isInSubCommandMode()) {
390+ invocation. println(" Currently in sub-command mode" );
391+ } else {
392+ invocation. println(" Running at top level" );
393+ }
394+ return CommandResult . SUCCESS ;
395+ }
396+ ```
397+
398+ ### getParentValue(String name, Class< ; T> ; type)
399+
400+ Retrieves a value from the parent command by field name. Returns ` null ` if not found or not in sub-command mode.
401+
402+ ``` java
403+ @CommandDefinition (name = " build" , description = " Build the project" )
404+ public class BuildCommand implements Command<CommandInvocation > {
405+
406+ @Override
407+ public CommandResult execute (CommandInvocation invocation ) {
408+ // Get parent's projectName field value
409+ String projectName = invocation. getParentValue(" projectName" , String . class);
410+
411+ if (projectName != null ) {
412+ invocation. println(" Building " + projectName);
413+ } else {
414+ invocation. println(" Error: No project name available" );
415+ }
416+
417+ return CommandResult . SUCCESS ;
418+ }
419+ }
420+ ```
421+
422+ ### getParentValue(String name, Class< ; T> ; type, T defaultValue)
423+
424+ Same as above, but returns a default value if the parent value is not found.
425+
426+ ``` java
427+ @Override
428+ public CommandResult execute(CommandInvocation invocation) {
429+ // Get parent value with default
430+ Boolean verbose = invocation. getParentValue(" verbose" , Boolean . class, false );
431+
432+ if (verbose) {
433+ invocation. println(" [VERBOSE] Starting build process..." );
434+ }
435+
436+ return CommandResult . SUCCESS ;
437+ }
438+ ```
439+
440+ ### getInheritedValue(String name, Class< ; T> ; type)
441+
442+ Retrieves a value from inherited options (options marked with ` inherited = true ` on the parent). Returns ` null ` if not found.
443+
444+ ``` java
445+ @Override
446+ public CommandResult execute(CommandInvocation invocation) {
447+ // Get inherited option value
448+ Boolean verbose = invocation. getInheritedValue(" verbose" , Boolean . class);
449+
450+ if (verbose != null && verbose) {
451+ invocation. println(" [VERBOSE] Detailed output enabled" );
452+ }
453+
454+ return CommandResult . SUCCESS ;
455+ }
456+ ```
457+
458+ ### getInheritedValue(String name, Class< ; T> ; type, T defaultValue)
459+
460+ Same as above, but returns a default value if the inherited value is not found.
461+
462+ ``` java
463+ @Override
464+ public CommandResult execute(CommandInvocation invocation) {
465+ // Get inherited value with default
466+ String logLevel = invocation. getInheritedValue(" logLevel" , String . class, " INFO" );
467+ invocation. println(" Log level: " + logLevel);
468+
469+ return CommandResult . SUCCESS ;
470+ }
471+ ```
472+
473+ ### getCommandContext()
474+
475+ Returns the ` CommandContext ` object for advanced context manipulation. Most use cases are covered by the methods above.
476+
477+ ``` java
478+ @Override
479+ public CommandResult execute(CommandInvocation invocation) {
480+ CommandContext context = invocation. getCommandContext();
481+
482+ // Check context depth (nesting level)
483+ int depth = context. depth();
484+ invocation. println(" Context depth: " + depth);
485+
486+ // Get the context path (e.g., "module:project")
487+ String path = context. getContextPath();
488+ invocation. println(" Context path: " + path);
489+
490+ return CommandResult . SUCCESS ;
491+ }
492+ ```
493+
494+ ### Sub-Command Mode Example
495+
496+ Here's a complete example showing how subcommands access parent values:
497+
498+ ``` java
499+ @GroupCommandDefinition (
500+ name = " project" ,
501+ description = " Project management" ,
502+ groupCommands = {BuildCommand . class, StatusCommand . class}
503+ )
504+ public class ProjectCommand implements Command<CommandInvocation > {
505+
506+ @Option (name = " name" , required = true )
507+ private String projectName;
508+
509+ @Option (name = " verbose" , hasValue = false , inherited = true )
510+ private boolean verbose;
511+
512+ public String getProjectName () { return projectName; }
513+ public boolean isVerbose () { return verbose; }
514+
515+ @Override
516+ public CommandResult execute (CommandInvocation invocation ) {
517+ invocation. println(" Project: " + projectName);
518+ invocation. enterSubCommandMode(this );
519+ return CommandResult . SUCCESS ;
520+ }
521+ }
522+
523+ @CommandDefinition (name = " build" , description = " Build the project" )
524+ public class BuildCommand implements Command<CommandInvocation > {
525+
526+ @ParentCommand
527+ private ProjectCommand parent; // Direct injection
528+
529+ @Option (name = " verbose" , hasValue = false )
530+ private boolean verbose; // Auto-populated from parent's inherited option
531+
532+ @Override
533+ public CommandResult execute (CommandInvocation invocation ) {
534+ // Method 1: Use @ParentCommand annotation
535+ String name = parent. getProjectName();
536+
537+ // Method 2: Use getParentValue()
538+ String name2 = invocation. getParentValue(" projectName" , String . class);
539+
540+ // Method 3: Check inherited values
541+ Boolean inheritedVerbose = invocation. getInheritedValue(" verbose" , Boolean . class);
542+
543+ invocation. println(" Building " + name);
544+ if (verbose) {
545+ invocation. println(" [VERBOSE] Compiling sources..." );
546+ }
547+
548+ return CommandResult . SUCCESS ;
549+ }
550+ }
551+ ```
552+
553+ ** Usage:**
554+ ```
555+ [myapp]$ project --name=myapp --verbose
556+ Project: myapp
557+ Entering project mode.
558+
559+ project[myapp]> build
560+ Building myapp
561+ [VERBOSE] Compiling sources...
562+
563+ project[myapp]> exit
564+ [myapp]$
565+ ```
566+
567+ See [ Sub-Command Mode] ( /docs/aesh/sub-command-mode ) for complete documentation.
568+
327569## Complete Example
328570
329571``` java
0 commit comments