This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch feature/CAMEL-24372-tui-yaml-editor in repository https://gitbox.apache.org/repos/asf/camel.git
commit ca667a3b4ee5808fd8e0fa11c12286cb6536170c Author: Cursor Agent <[email protected]> AuthorDate: Sat Aug 8 15:36:45 2026 +0000 CAMEL-24372: Address review feedback on find nav and moveBlockDown Use Ctrl+N / Ctrl+Shift+N for find match navigation in edit mode so plain n/N can be typed while a find term is active. Fix moveBlockDown cursor to follow the moved block (same intent as moveBlockUp). Document test-only editText/editState accessors and add footer hints for redo/delete/find nav. Co-authored-by: Omar Atie <[email protected]> --- .../dsl/jbang/core/commands/tui/SearchHighlighter.java | 17 ++++++++++------- .../camel/dsl/jbang/core/commands/tui/SourceViewer.java | 5 +++++ .../dsl/jbang/core/commands/tui/YamlBlockEditor.java | 7 ++++++- .../core/commands/tui/SourceViewerEditorOpsTest.java | 16 ++++++++++++++++ .../jbang/core/commands/tui/YamlBlockEditorTest.java | 13 +++++++++++++ 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SearchHighlighter.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SearchHighlighter.java index c40adefada92..059c2a3350ff 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SearchHighlighter.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SearchHighlighter.java @@ -327,7 +327,10 @@ class SearchHighlighter { } /** - * Find navigation while editing plain text (Ctrl+F opens find, n/N step matches). + * Find navigation while editing plain text (Ctrl+F opens find, Ctrl+N/Ctrl+Shift+N step matches). + * <p> + * Unlike view mode, plain {@code n}/{@code N} are not consumed so users can type freely while a find term is + * active. */ boolean handleEditFindKeyEvent(KeyEvent ke) { if (findInputActive || highlightInputActive) { @@ -337,12 +340,12 @@ class SearchHighlighter { openFindInput(); return true; } - if (findTerm != null && ke.isChar('n') && !ke.hasCtrl() && !ke.hasAlt()) { - navigateToNextMatch(); - return true; - } - if (findTerm != null && ke.isChar('N') && !ke.hasCtrl() && !ke.hasAlt()) { - navigateToPrevMatch(); + if (findTerm != null && ke.hasCtrl() && ke.isCharIgnoreCase('n') && !ke.hasAlt()) { + if (ke.hasShift()) { + navigateToPrevMatch(); + } else { + navigateToNextMatch(); + } return true; } return false; 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 c73b30fdc531..6eb3be625299 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 @@ -273,6 +273,7 @@ class SourceViewer { return dirty; } + /** Package-private for tests that drive the edit buffer directly. */ TextAreaState editState() { return editState; } @@ -553,6 +554,7 @@ class SourceViewer { } } + /** Package-private for tests that assert on edit buffer content. */ String editText() { return editState.text(); } @@ -2335,10 +2337,13 @@ class SourceViewer { TuiHelper.hint(spans, "F5", "save & close"); TuiHelper.hint(spans, "Shift+F5", "save"); TuiHelper.hint(spans, "Ctrl+Z", "undo"); + TuiHelper.hint(spans, "Ctrl+Y", "redo"); TuiHelper.hint(spans, "Alt+↑/↓", "move block"); TuiHelper.hint(spans, "Ctrl+D", "duplicate"); + TuiHelper.hint(spans, "Ctrl+Shift+K", "delete block"); TuiHelper.hint(spans, "Ctrl+/", "comment"); TuiHelper.hint(spans, "Ctrl+F", "find"); + TuiHelper.hint(spans, "Ctrl+N", "next match"); if (autocompleteProvider != null) { TuiHelper.hint(spans, "Tab", "complete"); } diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditor.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditor.java index 6c31c0f69502..8c31ad3cef94 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditor.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditor.java @@ -110,7 +110,12 @@ final class YamlBlockEditor { if (next == null || next.isEmpty()) { return null; } - return swapBlocks(lines, block, next); + EditResult swapped = swapBlocks(lines, block, next); + List<String> answer = swapped.lines(); + int nextHeight = next.endRow() - next.startRow() + 1; + int cursorRow = block.startRow() + nextHeight + (next.startRow() - block.endRow() - 1); + int cursorCol = answer.isEmpty() ? 0 : leadingSpaces(answer.get(cursorRow)); + return new EditResult(answer, cursorRow, cursorCol); } static List<String> toggleComment(List<String> lines, BlockRange block) { diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditorOpsTest.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditorOpsTest.java index 2181378d9174..5acc69c5cfd5 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditorOpsTest.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/SourceViewerEditorOpsTest.java @@ -159,6 +159,19 @@ class SourceViewerEditorOpsTest { assertThat(viewer.isSearchInputActive()).isTrue(); } + @Test + void plainNInsertsWhileFindTermActive() { + viewer.handleKeyEvent(KeyEvent.ofChar('f', CTRL)); + viewer.handleKeyEvent(KeyEvent.ofChar('l', KeyModifiers.NONE)); + viewer.handleKeyEvent(KeyEvent.ofChar('o', KeyModifiers.NONE)); + viewer.handleKeyEvent(KeyEvent.ofChar('g', KeyModifiers.NONE)); + viewer.handleKeyEvent(KeyEvent.ofKey(KeyCode.ENTER, KeyModifiers.NONE)); + + viewer.handleKeyEvent(KeyEvent.ofChar('n', KeyModifiers.NONE)); + + assertThat(viewer.editText()).contains("n"); + } + @Test void footerShowsNewEditorHints() { List<dev.tamboui.text.Span> spans = new ArrayList<>(); @@ -166,10 +179,13 @@ class SourceViewerEditorOpsTest { String footer = spansToString(spans); assertThat(footer).contains("Ctrl+Z"); + assertThat(footer).contains("Ctrl+Y"); assertThat(footer).contains("Alt+↑/↓"); assertThat(footer).contains("Ctrl+D"); + assertThat(footer).contains("Ctrl+Shift+K"); assertThat(footer).contains("Ctrl+/"); assertThat(footer).contains("Ctrl+F"); + assertThat(footer).contains("Ctrl+N"); } private void moveCursorToLineContaining(String needle) { diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditorTest.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditorTest.java index d1449cffe350..f2fa1e947eeb 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditorTest.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/test/java/org/apache/camel/dsl/jbang/core/commands/tui/YamlBlockEditorTest.java @@ -74,6 +74,19 @@ class YamlBlockEditorTest { assertThat(YamlBlockEditor.fromLines(result.lines())).contains("log:info"); } + @Test + void moveBlockDownCursorFollowsMovedBlock() { + List<String> lines = YamlBlockEditor.toLines(SAMPLE); + int firstStep = findLineContaining(lines, "- to: log:info"); + + YamlBlockEditor.EditResult result = YamlBlockEditor.moveBlockDown(lines, firstStep, true); + + assertThat(result).isNotNull(); + assertThat(result.lines().get(result.cursorRow())).contains("log:info"); + assertThat(YamlBlockEditor.fromLines(result.lines()).indexOf("log:warn")) + .isLessThan(YamlBlockEditor.fromLines(result.lines()).indexOf("log:info")); + } + @Test void moveBlockDownSwapsWithNextSibling() { List<String> lines = YamlBlockEditor.toLines(SAMPLE);
