Skip to content

Commit dba15d7

Browse files
committed
added dynamic default value provider docs
1 parent d47bca0 commit dba15d7

3 files changed

Lines changed: 110 additions & 5 deletions

File tree

content/docs/aesh/annotation-processor.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,4 @@ public class DeployCommand extends BaseCommand {
192192
- **Java 8+** -- The processor targets source version 8
193193
- **No code changes required** -- Drop in the dependency and the processor runs automatically
194194
- **Fully backward compatible** -- Removing the dependency reverts to the reflection path with no behavior change
195-
- **Works with all Aesh features** -- Custom validators, completers, converters, activators, renderers, result handlers, and option parsers are all supported
195+
- **Works with all Aesh features** -- Custom validators, completers, converters, activators, renderers, result handlers, option parsers, default value providers, optional-value options, negatable options, stop-at-positional, and inherited options are all supported

content/docs/aesh/command-definition.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The `@CommandDefinition` annotation is used to define a command class.
2525
| `validator` | `Class<? extends CommandValidator>` | `NullCommandValidator.class` | Validator to run before execution |
2626
| `resultHandler` | `Class<? extends ResultHandler>` | `NullResultHandler.class` | Handler to run after execution |
2727
| `activator` | `Class<? extends CommandActivator>` | `NullCommandActivator.class` | Activator to check if command is available |
28+
| `defaultValueProvider` | `Class<? extends DefaultValueProvider>` | `NullDefaultValueProvider.class` | Dynamic default value resolver |
2829
| `stopAtFirstPositional` | `boolean` | `false` | Stop option parsing after the first positional argument |
2930
| `helpUrl` | `String` | `""` | URL to documentation (shown in `--help` output) |
3031

@@ -68,6 +69,71 @@ Return one of the following:
6869
- `CommandResult.FAILURE` - Command failed
6970
- `CommandResult.RETURN` - Return from current subcommand
7071

72+
## Dynamic Default Value Provider
73+
74+
The `defaultValueProvider` attribute specifies a class that resolves option defaults at runtime. This is useful when defaults come from configuration files, environment variables, or other external sources not known at compile time.
75+
76+
### Implementing a Provider
77+
78+
Create a class that implements `DefaultValueProvider`:
79+
80+
```java
81+
public class ConfigDefaultProvider implements DefaultValueProvider {
82+
83+
@Override
84+
public String defaultValue(ProcessedOption option) {
85+
// Use option.name() and option.parent().name() to build a config key
86+
String key = option.parent().name() + "." + option.name();
87+
return Configuration.get(key); // returns null if not configured
88+
}
89+
}
90+
```
91+
92+
### Registering the Provider
93+
94+
```java
95+
@CommandDefinition(
96+
name = "init",
97+
description = "Initialize a project",
98+
defaultValueProvider = ConfigDefaultProvider.class
99+
)
100+
public class InitCommand implements Command<CommandInvocation> {
101+
102+
@Option(defaultValue = "hello")
103+
private String template;
104+
105+
@Option
106+
private String editor;
107+
108+
@Override
109+
public CommandResult execute(CommandInvocation invocation) {
110+
invocation.println("Template: " + template);
111+
invocation.println("Editor: " + editor);
112+
return CommandResult.SUCCESS;
113+
}
114+
}
115+
```
116+
117+
### Value Precedence
118+
119+
When determining option values, the precedence is (highest to lowest):
120+
121+
1. **User-provided value** -- Explicitly set on the command line
122+
2. **Dynamic default** -- Returned by the `DefaultValueProvider` (if non-null)
123+
3. **Static default** -- The `defaultValue` from the annotation
124+
4. **null** -- If nothing else is set
125+
126+
If the provider returns `null` for an option, aesh falls back to the static `defaultValue`. This lets you use annotation defaults as fallbacks:
127+
128+
```java
129+
// Provider returns "from-config" for template -> uses "from-config"
130+
// Provider returns null for editor -> falls back to static default "vi"
131+
@Option(defaultValue = "vi")
132+
private String editor;
133+
```
134+
135+
See [Options - Dynamic Default Values](/docs/aesh/options#dynamic-default-values) for more details.
136+
71137
## Stop at First Positional
72138

73139
When `stopAtFirstPositional = true`, option parsing stops as soon as the first positional argument is consumed. All remaining tokens are treated as positional arguments, even if they look like options.

content/docs/aesh/options.md

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,15 +471,54 @@ $ connect -h dev-db.local -p 5434
471471
Connecting to john@dev-db.local:5434/myapp
472472
```
473473

474+
### Dynamic Default Values
475+
476+
For defaults that must be resolved at runtime (e.g., from configuration files, databases, or user profiles), use a `DefaultValueProvider`. The provider is registered on the command, not on individual options:
477+
478+
```java
479+
public class AppConfigProvider implements DefaultValueProvider {
480+
481+
@Override
482+
public String defaultValue(ProcessedOption option) {
483+
// Build a hierarchical key from command + option name
484+
String key = option.parent().name() + "." + option.name();
485+
return AppConfig.instance().get(key); // null if not configured
486+
}
487+
}
488+
489+
@CommandDefinition(
490+
name = "run",
491+
description = "Run application",
492+
defaultValueProvider = AppConfigProvider.class
493+
)
494+
public class RunCommand implements Command<CommandInvocation> {
495+
496+
@Option(description = "Debug port", defaultValue = "4004")
497+
private String debug;
498+
499+
@Option(description = "JFR settings")
500+
private String jfr;
501+
502+
@Override
503+
public CommandResult execute(CommandInvocation invocation) {
504+
// debug = config value if set, else "4004", unless user provided a value
505+
return CommandResult.SUCCESS;
506+
}
507+
}
508+
```
509+
510+
If the provider returns `null` for an option, the static `defaultValue` from the annotation is used as a fallback. See [Command Definition - Dynamic Default Value Provider](/docs/aesh/command-definition#dynamic-default-value-provider) for more details.
511+
474512
### Priority Order
475513

476514
When determining option values, Æsh uses this priority (highest to lowest):
477515

478516
1. **Command-line argument** - Explicitly provided by user
479-
2. **Environment variable / System property** - If referenced in `defaultValue`
480-
3. **Fallback value** - Value after `:` in the `defaultValue` expression
481-
4. **Field initializer** - Java field initialization value
482-
5. **null** - If nothing else is set
517+
2. **Dynamic default** - From `DefaultValueProvider` (if non-null)
518+
3. **Static default / Environment variable / System property** - From `defaultValue` annotation
519+
4. **Fallback value** - Value after `:` in the `defaultValue` expression
520+
5. **Field initializer** - Java field initialization value
521+
6. **null** - If nothing else is set
483522

484523
### Multiple Default Values
485524

0 commit comments

Comments
 (0)