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


The following commit(s) were added to refs/heads/main by this push:
     new e487300810aa chore: camel-tui - plain mode for source editor to easily 
copy/paste
e487300810aa is described below

commit e487300810aa3fbaee49bd7561238ba75e50a280
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Aug 6 17:20:40 2026 +0200

    chore: camel-tui - plain mode for source editor to easily copy/paste
    
    chore: camel-tui - update F1 help with plain mode and word wrap keys
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../dsl/jbang/core/commands/tui/RoutesTab.java     |  2 +
 .../dsl/jbang/core/commands/tui/SourceTab.java     |  8 +++
 .../dsl/jbang/core/commands/tui/SourceViewer.java  | 60 +++++++++++++++++++---
 3 files changed, 63 insertions(+), 7 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
index ec2fca008d8a..8ca40eaf89be 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RoutesTab.java
@@ -2602,6 +2602,8 @@ class RoutesTab extends AbstractTab {
                 - `←→` — horizontal scroll
                 - `PgUp/PgDn` — page jump
                 - `Home/End` — go to top/bottom
+                - `w` — toggle word wrap
+                - `p` — toggle plain mode (hides line numbers and borders for 
easy copy/paste)
                 - `Enter` — select the closest diagram node at cursor line
                 - `Esc/c` — close source view
                 """;
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 a67e4ce45234..0df23241f51b 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
@@ -276,6 +276,13 @@ class SourceTab extends AbstractTab {
             return;
         }
 
+        if (sourceViewer.isPlainMode() && sourceViewer.isVisible()) {
+            leftArea = null;
+            rightArea = area;
+            renderSourcePanel(frame, area);
+            return;
+        }
+
         if (leftPanelWidth < 0) {
             leftPanelWidth = Math.max(25, Math.min(35, area.width() * 25 / 
100));
         }
@@ -349,6 +356,7 @@ class SourceTab extends AbstractTab {
                 - **h** — highlight text
                 - **n/N** — next/previous match
                 - **w** — toggle word wrap
+                - **p** — toggle plain mode (hides line numbers, borders, and 
file panel for easy copy/paste)
                 - **Esc/c** — close source viewer
 
                 ## Edit Mode (Tab Completion)
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 d97978584b0c..3ad8bf3d02c1 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
@@ -132,6 +132,7 @@ class SourceViewer {
     private Style titleStyle;
     private Style borderStyle;
     private boolean focused = true;
+    private boolean plainMode;
 
     /** Local file path when content was loaded via {@link #loadFile(Path)} 
and is writable. */
     private Path editableFile;
@@ -266,6 +267,10 @@ class SourceViewer {
         return editableFile != null;
     }
 
+    boolean isPlainMode() {
+        return plainMode;
+    }
+
     /**
      * True when the viewer is consuming typed input (search box or plain-text 
edit mode). Used by the monitor to avoid
      * treating digit/letter keys as global shortcuts.
@@ -416,6 +421,10 @@ class SourceViewer {
             scrollX = 0;
             return true;
         }
+        if (ke.isChar('p')) {
+            plainMode = !plainMode;
+            return true;
+        }
         if (ke.isKey(KeyCode.UP) && ke.hasCtrl()) {
             scrollY = Math.max(0, scrollY - 1);
         } else if (ke.isKey(KeyCode.DOWN) && ke.hasCtrl()) {
@@ -1751,8 +1760,16 @@ class SourceViewer {
         }
 
         Block.Builder blockBuilder = Block.builder()
-                .borderType(BorderType.ROUNDED).borders(Borders.ALL)
-                .title(buildTitle());
+                .borderType(BorderType.ROUNDED);
+        if (plainMode) {
+            int lineNum = selectedLine + 1;
+            Title posTitle = Title.from(
+                    Line.from(Span.styled(" line:" + lineNum + " ", 
Style.EMPTY.dim()))).right();
+            blockBuilder.borders(java.util.EnumSet.of(Borders.TOP, 
Borders.BOTTOM))
+                    .titleBottom(posTitle);
+        } else {
+            blockBuilder.borders(Borders.ALL).title(buildTitle());
+        }
         if (borderStyle != null) {
             blockBuilder.borderStyle(borderStyle);
         }
@@ -1872,6 +1889,14 @@ class SourceViewer {
         Overflow overflow = wordWrap ? Overflow.WRAP_WORD : Overflow.CLIP;
         
frame.renderWidget(Paragraph.builder().text(Text.from(visible)).overflow(overflow).build(),
 hChunks.get(0));
 
+        if (plainMode && selectedLine >= scrollY && selectedLine < scrollY + 
visibleLines) {
+            int relRow = selectedLine - scrollY;
+            int screenY = inner.top() + relRow;
+            Rect lineRect = new Rect(inner.left(), screenY, inner.width(), 1);
+            Style selBg = focused ? Theme.selectionBg() : 
Theme.selectionBg().dim();
+            frame.buffer().setStyle(lineRect, selBg);
+        }
+
         int totalDocLines = quickDocEnabled ? 
quickDocEntries.values().stream().mapToInt(List::size).sum() : 0;
         int totalContentLines = lines.size() + totalDocLines;
         if (totalContentLines > visibleLines) {
@@ -1899,9 +1924,15 @@ class SourceViewer {
         Title posTitle = Title.from(
                 Line.from(Span.styled(" row:" + row + " col:" + col + " ", 
Style.EMPTY.dim()))).right();
         Block.Builder blockBuilder = Block.builder()
-                .borderType(BorderType.ROUNDED).borders(Borders.ALL)
-                .title(Title.from(Line.from(titleSpans)))
-                .titleBottom(posTitle);
+                .borderType(BorderType.ROUNDED);
+        if (plainMode) {
+            blockBuilder.borders(java.util.EnumSet.of(Borders.TOP, 
Borders.BOTTOM))
+                    .titleBottom(posTitle);
+        } else {
+            blockBuilder.borders(Borders.ALL)
+                    .title(Title.from(Line.from(titleSpans)))
+                    .titleBottom(posTitle);
+        }
         if (borderStyle != null) {
             blockBuilder.borderStyle(borderStyle);
         }
@@ -1913,7 +1944,7 @@ class SourceViewer {
 
         TextArea textArea = TextArea.builder()
                 .cursorStyle(Style.EMPTY.reversed())
-                .showLineNumbers(true)
+                .showLineNumbers(!plainMode)
                 .lineNumberStyle(Style.EMPTY.dim())
                 .build();
         textArea.renderWithCursor(inner, frame.buffer(), editState, frame);
@@ -2089,6 +2120,7 @@ class SourceViewer {
         }
         search.renderSearchHints(spans);
         TuiHelper.hint(spans, "w", "wrap" + (wordWrap ? " [on]" : " [off]"));
+        TuiHelper.hint(spans, "p", "plain" + (plainMode ? " [on]" : " [off]"));
         if (onLineSelected != null) {
             TuiHelper.hint(spans, "Enter", "select node");
         }
@@ -2552,7 +2584,21 @@ class SourceViewer {
 
         List<Span> spans = new ArrayList<>();
         Style selBg = focused ? Theme.selectionBg() : 
Theme.selectionBg().dim();
-        if (isSelected) {
+        if (plainMode) {
+            // strip line-number prefix (spaces, digits, 2 separator spaces) 
but keep code indentation
+            int pos = 0;
+            while (pos < raw.length() && raw.charAt(pos) == ' ') {
+                pos++;
+            }
+            while (pos < raw.length() && Character.isDigit(raw.charAt(pos))) {
+                pos++;
+            }
+            if (pos + 1 < raw.length() && raw.charAt(pos) == ' ' && 
raw.charAt(pos + 1) == ' ') {
+                pos += 2;
+            }
+            String plainCode = raw.substring(pos);
+            spans.addAll(SyntaxHighlighter.highlightLine(plainCode, 
language).spans());
+        } else if (isSelected) {
             spans.add(Span.styled(">> ", focused ? Theme.label().bold() : 
Theme.label().dim()));
             if (!prefix.isEmpty()) {
                 spans.add(Span.styled(prefix, (focused ? Theme.label().bold() 
: Theme.label().dim()).patch(selBg)));

Reply via email to