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 fa6f59a1afdbcfbbba42fa0401450ee565f166e1
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Oct 15 12:55:52 2026 +0200

    chore: camel-jbang - the F-key hints no longer split a field typed in the 
footer
    
    The F-keys every screen has (F2 actions, F10 run) go into a footer after
    the screen's first hint. While a term is typed (a table filter, find or
    highlight in the source viewer) the footer starts with the field instead,
    so they landed between the field and its own Enter and Esc, and inside
    the term when the caret was in its middle.
    
    While a screen takes typed text they now go after the field's keys. The
    Source tab also leaves Tab out of that footer, as it does the other keys
    of the viewer while a term is typed.
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../dsl/jbang/core/commands/tui/CamelMonitor.java  |  4 +--
 .../dsl/jbang/core/commands/tui/FooterHints.java   | 16 +++++++++++
 .../dsl/jbang/core/commands/tui/SourceTab.java     | 19 +++++++------
 .../jbang/core/commands/tui/FooterHintsTest.java   | 30 +++++++++++++++++++++
 .../core/commands/tui/SourceViewerEditTest.java    | 31 ++++++++++++++++++++++
 5 files changed, 88 insertions(+), 12 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
index 13ee96c2dfc0..d3da8b8cdae6 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelMonitor.java
@@ -2531,9 +2531,9 @@ public class CamelMonitor extends CamelCommand {
     private int fKeyStart;
 
     private int insertFKeyHints(List<Span> spans) {
-        int insertPos = Math.min(2, spans.size());
-        List<Span> fKeySpans = new ArrayList<>();
         MonitorTab tab = tabRegistry.activeTab();
+        int insertPos = FooterHints.fKeyPosition(spans, tab != null && 
tab.isTextInputActive());
+        List<Span> fKeySpans = new ArrayList<>();
         // F1 opens the help of every tab, but is seldom pressed: the 
Overview, the first screen, names it
         if (tab == tabRegistry.overviewTab() && tab.getHelpText() != null) {
             hint(fKeySpans, "F1", "help");
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHints.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHints.java
index 2dd5a9ed9b14..5961975063c0 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHints.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHints.java
@@ -30,6 +30,22 @@ final class FooterHints {
     private FooterHints() {
     }
 
+    /**
+     * Where the F-key hints go in a screen's footer: after its first hint, 
its most important one. While text is typed
+     * the footer is the field with its own keys (Enter, Esc): the F-keys go 
after those, as after the first two spans
+     * they would part the field from its keys, or cut it in two when the 
caret is inside it. The field's last key has
+     * no gap after it, so one is added.
+     */
+    static int fKeyPosition(List<Span> spans, boolean typing) {
+        if (!typing) {
+            return Math.min(2, spans.size());
+        }
+        if (!spans.isEmpty() && !spans.get(spans.size() - 
1).content().endsWith("  ")) {
+            spans.add(Span.raw("  "));
+        }
+        return spans.size();
+    }
+
     /**
      * @param  spans       the footer: the screen's hints, with the F-key 
hints inserted at {@code fKeyStart}; the hints
      *                     dropped are removed from it
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 1d0fbcdc8cd3..18c068bc338d 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
@@ -469,17 +469,16 @@ class SourceTab extends AbstractTab {
         }
         if (focusOnViewer && sourceViewer.isVisible()) {
             sourceViewer.renderFooter(spans);
-            if (!sourceViewer.isEditMode()) {
+            // also after a jump, which moves the focus to the viewer; not 
while a term is typed into find or
+            // highlight, as the footer is then that field with its keys
+            if (!sourceViewer.isEditMode() && 
!sourceViewer.isTextInputActive()) {
                 TuiHelper.hint(spans, "Tab", "files");
-                // also after a jump, which moves the focus to the viewer; not 
while g is typed into search
-                if (!sourceViewer.isTextInputActive()) {
-                    if (!routeIndex.isEmpty()) {
-                        TuiHelper.hint(spans, "g", "go to route");
-                    }
-                    TuiHelper.hint(spans, "Ctrl+G", "go to");
-                    if (endpointOnSelectedLine() != null) {
-                        TuiHelper.hint(spans, "u", "usages");
-                    }
+                if (!routeIndex.isEmpty()) {
+                    TuiHelper.hint(spans, "g", "go to route");
+                }
+                TuiHelper.hint(spans, "Ctrl+G", "go to");
+                if (endpointOnSelectedLine() != null) {
+                    TuiHelper.hint(spans, "u", "usages");
                 }
             }
         } else {
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHintsTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHintsTest.java
index e974a8dc180f..c453ffb7f3fe 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHintsTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/FooterHintsTest.java
@@ -127,6 +127,36 @@ class FooterHintsTest {
         assertThat(keys(spans)).containsExactly("Enter", "Esc");
     }
 
+    @Test
+    void theFKeysGoAfterTheFirstHintOfAScreen() {
+        List<Span> spans = new ArrayList<>();
+        hint(spans, "Esc", "back");
+        hint(spans, "/", "find");
+
+        assertThat(FooterHints.fKeyPosition(spans, false)).isEqualTo(2);
+        assertThat(spans).hasSize(4);
+    }
+
+    @Test
+    void whileTextIsTypedTheFKeysGoAfterTheFieldAndItsKeys() {
+        // as a filter draws it with the caret inside the term: "ord|ers", 
where the caret splits the field in three
+        List<Span> spans = new ArrayList<>();
+        spans.add(Span.styled(" /", Theme.label().bold()));
+        spans.add(Span.raw("ord"));
+        spans.add(Span.styled("e", Style.EMPTY.reversed()));
+        spans.add(Span.raw("rs"));
+        spans.add(Span.raw("  "));
+        hint(spans, "Enter", "filter");
+        TuiHelper.hintLast(spans, "Esc", "cancel");
+
+        int position = FooterHints.fKeyPosition(spans, true);
+
+        // after Esc, which has no gap after it as the last key: one is added
+        assertThat(position).isEqualTo(spans.size());
+        assertThat(spans.get(position - 2).content()).isEqualTo(" cancel");
+        assertThat(spans.get(position - 1).content()).isEqualTo("  ");
+    }
+
     private static List<String> keys(List<Span> spans) {
         return spans.stream().filter(s -> 
Theme.hintKey().equals(s.style())).map(s -> s.content().strip()).toList();
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditTest.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditTest.java
index d3f92c2f3a3d..138f00b9f163 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditTest.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditTest.java
@@ -456,6 +456,37 @@ class SourceViewerEditTest {
         assertThat(Files.readString(md, StandardCharsets.UTF_8)).endsWith("!");
     }
 
+    @Test
+    void sourceTabFooterIsTheFieldWhileATermIsTyped() {
+        IntegrationInfo info = new IntegrationInfo();
+        info.pid = "1234";
+        info.name = "test-app";
+        info.directory = tempDir.toString();
+        MonitorContext ctx = new MonitorContext(
+                new AtomicReference<>(List.of(info)), new 
AtomicReference<>(List.of()));
+        ctx.selectedPid = "1234";
+        SourceTab tab = new SourceTab(ctx);
+        tab.onTabSelected();
+
+        // the file opened, the viewer's footer offers Tab back to the files
+        assertThat(tab.handleKeyEvent(KeyEvent.ofKey(KeyCode.ENTER, 
KeyModifiers.NONE))).isTrue();
+        assertThat(footer(tab)).contains(" Tab ");
+
+        // h opens the highlight field: the footer is the field and its keys, 
not the viewer's navigation
+        tab.handleKeyEvent(KeyEvent.ofChar('h', KeyModifiers.NONE));
+        tab.handleKeyEvent(KeyEvent.ofChar('a', KeyModifiers.NONE));
+        assertThat(tab.isTextInputActive()).isTrue();
+        assertThat(footer(tab)).contains(" h:", "a█", " Enter ", " Esc 
").doesNotContain(" Tab ");
+    }
+
+    private static String footer(SourceTab tab) {
+        List<Span> spans = new ArrayList<>();
+        tab.renderFooter(spans);
+        StringBuilder sb = new StringBuilder();
+        spans.forEach(s -> sb.append(s.content()));
+        return sb.toString();
+    }
+
     @Test
     void sourceTabForwardsKeysToViewerWhileEditing() throws Exception {
         IntegrationInfo info = new IntegrationInfo();

Reply via email to