This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit f9dfaff4ca9862af7e7b84eb04f80741863d17ad
Author: Claus Ibsen <[email protected]>
AuthorDate: Wed Aug 5 22:48:16 2026 +0200

    camel-tui - Fix context detection leaking into nested blocks and offer 
parameters: completion
    
    - Fix findEnclosingEip skipping through structural keys (from:, steps:,
      expression:) and wrongly returning the parent EIP when cursor is nested
      inside a structural block
    - Offer parameters: and steps: completion when cursor is inside a from:/to:
      block that has uri: but no parameters: block yet
    - Filter input, outputs, steps from EIP option completions (structural keys)
    - Add value completion (boolean/enum) for language and data format options
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../dsl/jbang/core/commands/tui/SourceTab.java     |  3 +-
 .../dsl/jbang/core/commands/tui/SourceViewer.java  | 80 ++++++++++++++++++++++
 .../core/commands/tui/YamlCompletionTest.java      |  3 +-
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceTab.java
index bc107776263a..bb3bb9a465b6 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceTab.java
@@ -1086,7 +1086,8 @@ class SourceTab extends AbstractTab {
         return items;
     }
 
-    private static final Set<String> EIP_BOILERPLATE = Set.of("id", "note", 
"description", "disabled");
+    private static final Set<String> EIP_BOILERPLATE = Set.of("id", "note", 
"description", "disabled",
+            "input", "outputs", "steps");
 
     private List<AutocompletePopup.CompletionItem> 
provideEipKeyCompletions(String contextAfterPrefix) {
         CamelCatalog catalog = getCatalog();
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewer.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewer.java
index 93e966bdf096..1b480c4b631c 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewer.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewer.java
@@ -827,6 +827,9 @@ class SourceViewer {
     record YamlDataFormatOptionContext(String dataFormatName) {
     }
 
+    record YamlEndpointBlockContext(String eipName, boolean consumer, 
java.util.Set<String> existingKeys) {
+    }
+
     record YamlExpressionContext(String eipName) {
     }
 
@@ -889,6 +892,7 @@ class SourceViewer {
         }
 
         // walk up to find the parent EIP
+        boolean skippedStructural = false;
         for (int i = fromRow; i >= 0; i--) {
             String line = editState.getLine(i);
             if (line.isBlank()) {
@@ -898,16 +902,74 @@ class SourceViewer {
             if (indent < cursorIndent) {
                 String eipName = extractEipName(line.trim());
                 if (eipName != null && !STRUCTURAL_KEYS.contains(eipName)) {
+                    if (skippedStructural) {
+                        return null;
+                    }
                     String camelName = dashToCamelCase(eipName);
                     return new YamlEipContext(camelName);
                 }
                 // keep walking up if we hit a structural key
+                skippedStructural = true;
                 cursorIndent = indent;
             }
         }
         return null;
     }
 
+    YamlEndpointBlockContext findEndpointBlockContext(int fromRow) {
+        String cursorLine = editState.getLine(fromRow);
+        int cursorIndent = countLeadingSpaces(cursorLine);
+        if (cursorLine.isBlank() && cursorIndent == 0) {
+            int lineCount = editState.lineCount();
+            for (int i = fromRow + 1; i < lineCount; i++) {
+                String next = editState.getLine(i);
+                if (!next.isBlank()) {
+                    cursorIndent = countLeadingSpaces(next);
+                    break;
+                }
+            }
+            if (cursorIndent == 0) {
+                for (int i = fromRow - 1; i >= 0; i--) {
+                    String prev = editState.getLine(i);
+                    if (!prev.isBlank()) {
+                        cursorIndent = countLeadingSpaces(prev);
+                        break;
+                    }
+                }
+            }
+        }
+
+        // walk up to find the parent key
+        for (int i = fromRow; i >= 0; i--) {
+            String line = editState.getLine(i);
+            if (line.isBlank()) {
+                continue;
+            }
+            int indent = countLeadingSpaces(line);
+            if (indent < cursorIndent) {
+                String parentKey = extractEipName(line.trim());
+                if (parentKey != null && (CONSUMER_EIPS.contains(parentKey) || 
PRODUCER_EIPS.contains(parentKey))) {
+                    // check siblings: must have uri: and NOT be inside 
parameters:
+                    java.util.Set<String> siblings = 
collectExistingSiblingKeys(fromRow);
+                    if (siblings.contains("uri") && 
!siblings.contains("parameters")) {
+                        // skip if the cursor line itself has a key with colon 
(not a blank addition)
+                        String ct = cursorLine.trim();
+                        if (ct.startsWith("- ")) {
+                            ct = ct.substring(2).trim();
+                        }
+                        if (ct.indexOf(':') > 0) {
+                            return null;
+                        }
+                        boolean isConsumer = CONSUMER_EIPS.contains(parentKey);
+                        return new YamlEndpointBlockContext(parentKey, 
isConsumer, siblings);
+                    }
+                }
+                break;
+            }
+        }
+        return null;
+    }
+
     YamlExpressionContext findExpressionContext(int fromRow) {
         // cursor is inside an expression: block — find the parent EIP
         String cursorLine = editState.getLine(fromRow);
@@ -1413,6 +1475,24 @@ class SourceViewer {
             return;
         }
 
+        // offer parameters: (and steps: for from:) when inside a from:/to: 
block with uri: but no parameters: yet
+        YamlEndpointBlockContext blockCtx = findEndpointBlockContext(row);
+        if (blockCtx != null && autocompleteProvider != null) {
+            String filter = trimmed;
+            List<AutocompletePopup.CompletionItem> items = new ArrayList<>();
+            items.add(new AutocompletePopup.CompletionItem(
+                    "parameters", "Endpoint configuration options", "object",
+                    null, false, null, "common", true));
+            if (blockCtx.consumer() && 
!blockCtx.existingKeys().contains("steps")) {
+                items.add(new AutocompletePopup.CompletionItem(
+                        "steps", "Processing steps for this route", "array",
+                        null, false, null, "common", true));
+            }
+            autocompletePopup = new AutocompletePopup(items, filter, filter);
+            autocompletePopup.setTitlePrefix(blockCtx.eipName());
+            return;
+        }
+
         YamlEndpointContext ctx = findEnclosingComponent(row);
         if (ctx != null) {
             int colonIdx = trimmed.indexOf(':');
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlCompletionTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlCompletionTest.java
index b7e2105bc4d1..1c3607131703 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlCompletionTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlCompletionTest.java
@@ -1596,7 +1596,8 @@ class YamlCompletionTest {
         return items;
     }
 
-    private static final Set<String> EIP_BOILERPLATE = Set.of("id", "note", 
"description", "disabled");
+    private static final Set<String> EIP_BOILERPLATE = Set.of("id", "note", 
"description", "disabled",
+            "input", "outputs", "steps");
 
     private List<AutocompletePopup.CompletionItem> 
provideEipKeyCompletions(String eipName) {
         return provideEipKeyCompletions(eipName, Set.of());

Reply via email to