Skip to content

Commit bbd5c6e

Browse files
committed
Update docs for tail tip suggestions, custom parser fallback, unified synopsis
- ghost-text-suggestions.md: Add TailTipSuggestionProvider section with setup, priority ordering, and combining with CommandSuggestionProvider - settings.md: Add tailTipSuggestions option with description and table entry - options.md: Document custom parser + fallback chain behavior (#511), update fallbackValue description to mention custom parser support - documentation-generation.md: Update SYNOPSIS description to mention unified formatting across all doc formats
1 parent 9c6de76 commit bbd5c6e

4 files changed

Lines changed: 147 additions & 3 deletions

File tree

content/docs/aesh/documentation-generation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ Each generated page includes:
8080
| Section | Content |
8181
|---------|---------|
8282
| **NAME** | Command name and description |
83-
| **SYNOPSIS** | Formatted usage with options, arguments, and `[COMMAND]` placeholder for groups |
83+
| **SYNOPSIS** | Formatted usage with short flag clusters, negatable options, exclusive pipes, value placeholders, and `[COMMAND]` placeholder for groups. Consistent across all formats and `--help`. |
8484
| **DESCRIPTION** | Command description from the annotation |
8585
| **OPTIONS** | All visible options with short/long names, value placeholders, defaults, aliases, and negatable display |
8686
| **ARGUMENTS** | Positional parameters with labels |

content/docs/aesh/ghost-text-suggestions.md

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,77 @@ console.setSuggestionProvider(myProvider);
146146

147147
The `suggest` method receives the current input buffer and returns the text to display after the cursor as ghost text. Return `null` when there is no suggestion.
148148

149+
## TailTipSuggestionProvider
150+
151+
`TailTipSuggestionProvider` displays parameter hints after the cursor, showing remaining options and arguments that haven't been provided yet. Unlike `CommandSuggestionProvider` which completes the current word, tail tips show the full synopsis of what comes next.
152+
153+
```
154+
myapp> deploy --force |[-e=<environment>] <app>
155+
^^^^^^^^^^^^^^^^^^^^^^^^^ remaining params (dimmed)
156+
```
157+
158+
As the user fills in parameters, the tail tip updates to show only what's still needed:
159+
160+
```
161+
myapp> deploy --force -e prod |<app>
162+
^^^^^ only argument left (dimmed)
163+
```
164+
165+
### How it works
166+
167+
- Only activates when the buffer ends with a space (the user has finished typing a word)
168+
- Parses the current buffer to determine which options have already been provided
169+
- Builds a synopsis of remaining options and arguments
170+
- Uses the same formatting as `--help` synopsis (short flag clusters, exclusive pipes, value placeholders)
171+
- Caches the last result to avoid re-parsing on unchanged input
172+
173+
### Setup
174+
175+
Tail tips are opt-in via Settings and only apply to interactive `ReadlineConsole` mode (not `AeshRuntimeRunner`):
176+
177+
```java
178+
Settings settings = SettingsBuilder.builder()
179+
.tailTipSuggestions(true) // default: false
180+
.commandRegistry(registry)
181+
.build();
182+
183+
ReadlineConsole console = new ReadlineConsole(settings);
184+
console.start();
185+
```
186+
187+
When enabled, the tail tip provider is automatically added as the lowest-priority provider in the suggestion chain. History suggestions and command auto-suggest take priority when they have a match.
188+
189+
### Priority ordering
190+
191+
When `tailTipSuggestions` is enabled and `setSuggestionProvider()` is also used, the chain is:
192+
193+
1. History suggestions (if history is available)
194+
2. Your suggestion provider (e.g., `CommandSuggestionProvider`)
195+
3. Tail tip suggestions (only when others return null)
196+
197+
This means mid-word typing gets auto-suggest, and after completing a word (trailing space), the tail tip shows remaining parameters.
198+
199+
### Combining with CommandSuggestionProvider
200+
201+
For the best experience, use both providers together:
202+
203+
```java
204+
Settings settings = SettingsBuilder.builder()
205+
.tailTipSuggestions(true)
206+
.commandRegistry(registry)
207+
.build();
208+
209+
ReadlineConsole console = new ReadlineConsole(settings);
210+
console.setSuggestionProvider(
211+
new CommandSuggestionProvider<>(console.getCommandRegistry()));
212+
console.start();
213+
```
214+
215+
This gives:
216+
- History auto-suggest when a history entry matches
217+
- Command/option name completion while typing
218+
- Parameter hints after each completed word
219+
149220
## Ghost Text vs Tab Completion
150221

151222
| Feature | Ghost Text | Tab Completion |
@@ -154,6 +225,6 @@ The `suggest` method receives the current input buffer and returns the text to d
154225
| **Display** | Inline dimmed text | List below prompt |
155226
| **Matches** | Single unambiguous only | Shows all matches |
156227
| **Accept** | Right arrow | Tab / Enter |
157-
| **Scope** | Commands, subcommands, options | Options, arguments, custom values |
228+
| **Scope** | Commands, subcommands, options, tail tips | Options, arguments, custom values |
158229

159230
Both features complement each other. Ghost text gives fast inline suggestions for unambiguous matches, while tab completion helps explore all available options when there are multiple possibilities.

content/docs/aesh/options.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ When `fallbackValue` is set:
220220
3. **Explicit value (`--debug=5005`)** uses the given value, same as any normal option
221221
4. **Not specified** leaves the field as `null` (or the `defaultValue` / `DefaultValueProvider` value if configured)
222222

223-
This eliminates the need for custom `OptionParser` implementations to handle the three-state pattern.
223+
This works with both the built-in `AeshOptionParser` and custom `OptionParser` implementations -- the fallback chain runs automatically after any parser returns without setting a value.
224224

225225
### Compared to `optionalValue`
226226

@@ -1089,6 +1089,64 @@ The `fallbackValue()` method is a `default` method returning `null`. Existing `D
10891089
| Bare flag needs a value from config/env | `DefaultValueProvider.fallbackValue()` |
10901090
| All of the above combined | Both annotation + provider, resolution chain handles priority |
10911091

1092+
### Custom Parsers and the Fallback Chain
1093+
1094+
When using a custom `OptionParser` (via `@Option(parser = MyParser.class)`), the value resolution chain applies automatically. If the custom parser decides not to consume a token and returns without calling `addValue()`, the framework applies the fallback chain (provider `fallbackValue()` -> annotation `fallbackValue` -> annotation `defaultValue`).
1095+
1096+
This separates the **parsing concern** (which tokens to consume) from the **value resolution concern** (what value to use when no tokens were consumed):
1097+
1098+
```java
1099+
public class DebugOptionParser implements OptionParser {
1100+
private static final Pattern PORT = Pattern.compile("\\d+");
1101+
1102+
@Override
1103+
public void parse(ParsedLineIterator iter, ProcessedOption option)
1104+
throws OptionParserException {
1105+
// Consume the option name token
1106+
iter.pollParsedWord();
1107+
1108+
// Peek at next token -- only consume if it matches a port number
1109+
if (iter.hasNextWord()) {
1110+
String next = iter.peekWord();
1111+
if (!next.startsWith("-") && PORT.matcher(next).matches()) {
1112+
option.addValue(next);
1113+
iter.pollParsedWord();
1114+
return;
1115+
}
1116+
}
1117+
// No addValue() call -- framework applies the fallback chain
1118+
}
1119+
}
1120+
1121+
@CommandDefinition(name = "run", description = "Run script")
1122+
public class RunCommand implements Command<CommandInvocation> {
1123+
1124+
@Option(name = "debug", parser = DebugOptionParser.class,
1125+
fallbackValue = "4004")
1126+
String debug;
1127+
1128+
@Argument
1129+
String script;
1130+
}
1131+
```
1132+
1133+
```bash
1134+
$ run --debug=5005 test.java # debug = "5005" (parser consumed)
1135+
$ run --debug 5005 test.java # debug = "5005" (parser consumed)
1136+
$ run --debug test.java # debug = "4004" (parser skipped, fallback applied)
1137+
$ run --debug # debug = "4004" (parser skipped, fallback applied)
1138+
```
1139+
1140+
The custom parser contract:
1141+
1142+
| Parser action | Result |
1143+
|---|---|
1144+
| `option.addValue(x)` | Value is `x` -- no fallback applied |
1145+
| `option.addValue("")` | Value is `""` -- no fallback applied (explicit empty) |
1146+
| No `addValue()` call | Fallback chain runs (provider -> annotation -> default) |
1147+
1148+
This eliminates the need for custom parsers to set sentinel values (like `""`) and handle fallback resolution manually.
1149+
10921150
### Multiple Default Values
10931151

10941152
For options that accept multiple values (lists/arrays), provide multiple defaults:

content/docs/aesh/settings.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,20 @@ SettingsBuilder.builder()
346346

347347
See [Sub-Command Mode](/docs/aesh/sub-command-mode) for complete documentation.
348348

349+
### Ghost Text and Tail Tips
350+
351+
#### tailTipSuggestions(boolean)
352+
353+
Enables tail tip suggestions -- dimmed parameter hints shown after the cursor in interactive mode. When enabled, remaining options and arguments are displayed as ghost text after each completed word. Only applies to `ReadlineConsole` (REPL mode), not `AeshRuntimeRunner`. Default: `false`
354+
355+
```java
356+
SettingsBuilder.builder()
357+
.tailTipSuggestions(true)
358+
.build();
359+
```
360+
361+
See [Ghost Text Suggestions](../ghost-text-suggestions#tailtipsuggestionprovider) for details on how tail tips work and how they interact with other suggestion providers.
362+
349363
### Additional Options
350364

351365
#### readInputrc(boolean)
@@ -466,6 +480,7 @@ public CommandResult execute(CommandInvocation invocation) {
466480
| `setRedirection` | `boolean` | `true` | Enable redirection operators |
467481
| `readInputrc` | `boolean` | `true` | Read .inputrc configuration |
468482
| `echoCtrl` | `boolean` | `true` | Echo control characters |
483+
| `tailTipSuggestions` | `boolean` | `false` | Show parameter hints after cursor |
469484
| `subCommandModeSettings` | `SubCommandModeSettings` | defaults | Sub-command mode configuration |
470485

471486
## Best Practices

0 commit comments

Comments
 (0)