The nested prompter feature allows you to press F4 within a CMD/CMDSTR textarea field to open a new prompter for that nested command. When you submit the nested prompter, it returns the completed command string (unformatted) back to the parent prompter's textarea.
- Open a CL command that has a CMD or CMDSTR parameter (e.g.,
SBMJOB CMD()) - In the prompter, enter a command name in the CMD/CMDSTR textarea (e.g.,
CALL PGM(MYPGM)) - Press F4 while the cursor is in that textarea
- A new prompter opens in a side-by-side panel titled with "(nested)"
- Fill in the parameters for the nested command
- Click Submit
- The completed command string is returned to the parent prompter's textarea (unformatted)
public static async promptNestedCommand(
extensionUri: vscode.Uri,
commandString: string,
parentPanel: ClPromptPanel
): Promise<string | null>- Creates a new webview panel for the nested command
- Extracts the command name from the command string
- Gets the XML definition for that command
- Returns a Promise that resolves when the user submits or cancels
- Panel title includes "(nested)" to distinguish from regular prompter
- Added
isNested?: booleanparameter - Added
nestedResolver?: (value: string | null) => voidparameter - Stores these in private fields
_isNestedand_nestedResolver
New: 'promptNested'
case 'promptNested': {
const result = await ClPromptPanel.promptNestedCommand(
this._extensionUri,
message.commandString,
this
);
this._panel.webview.postMessage({
type: 'nestedResult',
fieldId: message.fieldId,
commandString: result
});
break;
}- Receives request from webview to prompt a nested command
- Opens nested prompter and waits for result
- Sends result back to parent webview
Updated: 'submit'
if (this._isNested && this._nestedResolver) {
this._nestedResolver(cmd);
this._panel.dispose();
break;
}- If this is a nested prompter, resolves the promise with the unformatted command
- Disposes the panel immediately (doesn't try to insert into editor)
Updated: 'cancel'
case 'cancel': {
if (this._isNested && this._nestedResolver) {
this._nestedResolver(null);
}
this._panel.dispose();
break;
}- If nested, resolves promise with null on cancel
Added to both locations where CMD/CMDSTR textareas are created:
if (isCmdType) {
textarea.addEventListener('keydown', (e) => {
if (e.key === 'F4') {
e.preventDefault();
const commandString = textarea.value.trim();
if (commandString) {
vscode?.postMessage({
type: 'promptNested',
fieldId: name,
commandString: commandString
});
}
}
});
}- Detects F4 key press on CMD/CMDSTR textareas
- Sends 'promptNested' message with field ID and command string
else if (message.type === 'nestedResult') {
console.log('[clPrompter] Received nested result for field:',
message.fieldId, 'value:', message.commandString);
if (message.commandString && message.fieldId) {
const field = document.querySelector(`[name="${message.fieldId}"]`);
if (field && (field.tagName === 'TEXTAREA' || field.tagName === 'INPUT')) {
field.value = message.commandString;
field.focus();
state.touchedFields.add(message.fieldId);
}
}
}- Receives the completed command from nested prompter
- Updates the appropriate textarea field
- Focuses the field and marks it as touched
-
User presses F4 in CMD/CMDSTR textarea
Webview → Extension: { type: 'promptNested', fieldId: 'CMD', commandString: 'CALL PGM(MYPGM)' } -
Extension creates nested prompter
- Calls
ClPromptPanel.promptNestedCommand() - Opens new panel with command XML
- Waits for promise to resolve
- Calls
-
User fills in nested prompter and clicks Submit
Nested Webview → Extension: { type: 'submit', values: {...} } -
Extension resolves promise with command string
- Builds unformatted command:
CALL PGM(MYPGM) PARM('VALUE') - Resolves promise (does NOT format or insert into editor)
- Closes nested panel
- Builds unformatted command:
-
Extension sends result back to parent
Extension → Parent Webview: { type: 'nestedResult', fieldId: 'CMD', commandString: 'CALL PGM(MYPGM) PARM(\'VALUE\')' } -
Parent webview updates textarea
- Finds textarea by field ID
- Sets value to returned command string
- Focuses field
- Prompt
SBMJOB - In the CMD parameter textarea, type
CALL PGM(MYPGM) - Press F4
- Nested prompter opens for CALL command
- Fill in PARM, LIB, etc.
- Click Submit
- Parent prompter's CMD field now contains:
CALL PGM(MYLIB/MYPGM) PARM('VALUE1' 'VALUE2')
- Prompt
IF COND(%BIN(&VAR 1 4) *GT 0) THEN() - In the THEN parameter (which is CMDSTR type), type
CHKOBJ OBJ(MYOBJ) - Press F4
- Nested prompter opens for CHKOBJ
- Fill in OBJTYPE, etc.
- Click Submit
- Parent prompter's THEN field contains:
CHKOBJ OBJ(MYLIB/MYOBJ) OBJTYPE(*FILE)
| Aspect | Regular Prompter | Nested Prompter |
|---|---|---|
| Panel Title | CMDNAME Prompt |
CMDNAME Prompt (nested) |
| Submit Action | Formats command, inserts into editor | Returns unformatted command to parent |
| Cancel Action | Just closes panel | Resolves promise with null |
| Input Source | Active editor selection | Command string from parent textarea |
| Output Target | Active editor | Parent prompter textarea |
- No Formatting: Nested prompters return the raw built command without SEU-style formatting
- Promise-based: Uses async/await pattern for clean request/response flow
- Side-by-side: Opens in
vscode.ViewColumn.Besidefor easy comparison - Recursive: Nested prompters can theoretically have their own nested prompters (untested)
- CMD vs CMDSTR: Both parameter types support F4 prompting (IBM uses CMD for system commands, CMDSTR for user commands)