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 b95eea2e3389 CAMEL-24759: camel-jbang - upgrade tamboui to 0.5.0 with
window title and syntax highlighting (#26482)
b95eea2e3389 is described below
commit b95eea2e33896b3d1bfea3f0cd52137a52e79d41
Author: Adriano Machado <[email protected]>
AuthorDate: Wed Sep 16 15:18:48 2026 -0400
CAMEL-24759: camel-jbang - upgrade tamboui to 0.5.0 with window title and
syntax highlighting (#26482)
Bump tamboui from 0.4.0 to 0.5.0. The TUI sets the terminal window title
("Camel TUI", or "Camel TUI: <name>" for the selected process) through the new
TuiRunner.setWindowTitle API, and a theme-aware SyntaxTheme is wired into the
13 MarkdownView sites so fenced code blocks in docs, help overlays and the AI
chat panel are syntax coloured (Monokai palette in dark mode, a GitHub-like one
in light mode). The web frontend loads the xterm.js Unicode 11 addon so the
browser uses the same cha [...]
Co-Authored-By: Claude Opus 4.6 <[email protected]>
Co-Authored-By: Claude Opus 5 <[email protected]>
---
.../camel/dsl/jbang/core/commands/tui/AiPanel.java | 3 +-
.../dsl/jbang/core/commands/tui/CamelMonitor.java | 15 ++++++++++
.../dsl/jbang/core/commands/tui/CveAuditTab.java | 1 +
.../core/commands/tui/DiagramDetailSupport.java | 3 ++
.../jbang/core/commands/tui/DocViewerPopup.java | 2 ++
.../dsl/jbang/core/commands/tui/EndpointsTab.java | 3 ++
.../dsl/jbang/core/commands/tui/HelpOverlay.java | 1 +
.../dsl/jbang/core/commands/tui/SourceViewer.java | 1 +
.../camel/dsl/jbang/core/commands/tui/Theme.java | 35 ++++++++++++++++++++++
.../src/main/resources/tui/web/index.html | 4 +++
.../resources/tui/web/vendor/LICENSE-xterm.txt | 11 +++++--
.../tui/web/vendor/xterm-addon-unicode11.js | 2 ++
parent/pom.xml | 2 +-
13 files changed, 78 insertions(+), 5 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
index 9d5b1b6f831b..84696942d1dc 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/AiPanel.java
@@ -2193,7 +2193,8 @@ class AiPanel {
// couple of lines hidden below the visible area.
MarkdownView.Builder viewBuilder = MarkdownView.builder()
.source(source)
- .styles(Theme.chatMarkdownStyles());
+ .styles(Theme.chatMarkdownStyles())
+ .syntaxTheme(Theme.syntaxTheme());
MarkdownView measure = viewBuilder.build();
int totalLines = measure.computeHeight(mdArea.width());
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 90225935f5f6..9454f5319860 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
@@ -202,6 +202,7 @@ public class CamelMonitor extends CamelCommand {
// the AI panel overlays the editor, so it is hidden while an edit is
replayed and shown again afterwards
private boolean replayHidAiPanel;
private TuiRunner runner;
+ private String lastWindowTitle;
// Set by TuiWebServer for browser sessions; local terminal sessions leave
this null
// and let TuiBackendHelper auto-detect the active terminal instead.
Backend webBackend;
@@ -1030,6 +1031,7 @@ public class CamelMonitor extends CamelCommand {
// session registers it.
Signal.handle(new Signal("INT"), sig -> tui.quit());
}
+ updateWindowTitle();
tui.run(
this::handleEvent,
this::render);
@@ -1851,6 +1853,7 @@ public class CamelMonitor extends CamelCommand {
dataService.refresh(runner, this::refreshLogData,
this::refreshConditionalData);
tabRegistry.routesTab().refreshDiagramIfNeeded();
tabRegistry.diagramTab().refreshDiagramIfNeeded();
+ updateWindowTitle();
dataRefreshed = true;
}
// Redraw only when the periodic data refresh fired or an animation is
in flight.
@@ -3064,6 +3067,18 @@ public class CamelMonitor extends CamelCommand {
ctx.selectedPid = phantom.pid;
}
+ private void updateWindowTitle() {
+ if (runner == null) {
+ return;
+ }
+ String name = ctx != null && ctx.selectedPid != null ?
ctx.selectedName() : null;
+ String title = name != null ? "Camel TUI: " + name : "Camel TUI";
+ if (!title.equals(lastWindowTitle)) {
+ lastWindowTitle = title;
+ runner.setWindowTitle(title);
+ }
+ }
+
void setRunnerForTesting(Runnable onQuit) {
aiPanel.setExitCallbackForTestingOrRuntime(onQuit);
}
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
index a7fd1c8ee5f6..fb69a634eb07 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CveAuditTab.java
@@ -337,6 +337,7 @@ class CveAuditTab extends AbstractTableTab {
.scroll(detailScroll)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build(),
area);
}
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramDetailSupport.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramDetailSupport.java
index 3565dd3771f3..cf8cc265aa01 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramDetailSupport.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DiagramDetailSupport.java
@@ -487,6 +487,7 @@ final class DiagramDetailSupport {
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
.title(" EIP Detail ").build())
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build(),
area);
return;
@@ -501,6 +502,7 @@ final class DiagramDetailSupport {
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
.title(" EIP Detail ").build())
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build(),
area);
return;
@@ -551,6 +553,7 @@ final class DiagramDetailSupport {
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
.title(title).build())
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build(),
area);
}
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
index 797c861a9c1e..c3c79bce3a92 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DocViewerPopup.java
@@ -264,6 +264,7 @@ class DocViewerPopup {
int offset = MarkdownView.builder()
.source(prefix)
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build()
.computeHeight(lastContentWidth);
docScroll = offset;
@@ -618,6 +619,7 @@ class DocViewerPopup {
.source(docContent)
.scroll(docScroll)
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build();
frame.renderWidget(view, hChunks.get(0));
int totalHeight = view.computeHeight(lastContentWidth);
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
index 997980952706..a51aa87b522d 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/EndpointsTab.java
@@ -566,6 +566,7 @@ class EndpointsTab extends AbstractTableTab {
.borderStyle(detailBorderStyle)
.title(Title.from(Line.from(Span.styled("
Endpoint Detail ", detailTitleStyle)))).build())
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build(),
area);
return;
@@ -582,6 +583,7 @@ class EndpointsTab extends AbstractTableTab {
.borderStyle(detailBorderStyle)
.title(Title.from(Line.from(Span.styled("
Endpoint Detail ", detailTitleStyle)))).build())
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build(),
area);
return;
@@ -683,6 +685,7 @@ class EndpointsTab extends AbstractTableTab {
.borderStyle(detailBorderStyle)
.title(Title.from(Line.from(Span.styled(title,
detailTitleStyle)))).build())
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build(),
area);
}
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
index ca2aa1a6b4c6..a73b1d81ac14 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HelpOverlay.java
@@ -99,6 +99,7 @@ class HelpOverlay {
.scroll(scroll)
.block(block)
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build();
frame.renderWidget(view, popup);
}
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 38afe57018b6..b489a9666b04 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
@@ -1560,6 +1560,7 @@ class SourceViewer {
.scroll(markdownScroll)
.block(block)
.styles(Theme.markdownStyles())
+ .syntaxTheme(Theme.syntaxTheme())
.build();
frame.renderWidget(view, area);
return;
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
index 5ff339e2c612..6043ff456ad6 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/Theme.java
@@ -31,6 +31,8 @@ import dev.tamboui.css.Styleable;
import dev.tamboui.css.engine.StyleEngine;
import dev.tamboui.style.Color;
import dev.tamboui.style.Style;
+import dev.tamboui.widgets.syntax.SyntaxTheme;
+import dev.tamboui.widgets.syntax.TokenType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -293,6 +295,39 @@ public final class Theme {
.link(Style.EMPTY.fg(accent()).underlined());
}
+ /**
+ * Theme-aware syntax highlighting palette for fenced code blocks in
MarkdownView. Reuses the Monokai (dark) and
+ * GitHub-inspired (light) palettes from {@link SyntaxHighlighter}.
+ */
+ public static SyntaxTheme syntaxTheme() {
+ if (isDark()) {
+ return SyntaxTheme.builder()
+ .token(TokenType.COMMENT,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_COMMENT))
+ .token(TokenType.KEYWORD,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_KEYWORD))
+ .token(TokenType.TYPE,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_TYPE))
+ .token(TokenType.STRING,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_STRING))
+ .token(TokenType.NUMBER,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_CONSTANT))
+ .token(TokenType.CONSTANT,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_CONSTANT))
+ .token(TokenType.FUNCTION,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_FUNCTION))
+ .token(TokenType.ANNOTATION,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_FUNCTION))
+ .token(TokenType.TAG,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_KEYWORD))
+ .token(TokenType.ATTRIBUTE,
Style.EMPTY.fg(SyntaxHighlighter.MONOKAI_FUNCTION))
+ .build();
+ }
+ return SyntaxTheme.builder()
+ .token(TokenType.COMMENT, Style.EMPTY.fg(Color.rgb(106, 115,
125)))
+ .token(TokenType.KEYWORD, Style.EMPTY.fg(Color.rgb(215, 58,
73)))
+ .token(TokenType.TYPE, Style.EMPTY.fg(Color.rgb(0, 92, 197)))
+ .token(TokenType.STRING, Style.EMPTY.fg(Color.rgb(3, 47, 98)))
+ .token(TokenType.NUMBER, Style.EMPTY.fg(Color.rgb(111, 66,
193)))
+ .token(TokenType.CONSTANT, Style.EMPTY.fg(Color.rgb(111, 66,
193)))
+ .token(TokenType.FUNCTION, Style.EMPTY.fg(Color.rgb(0, 92,
197)))
+ .token(TokenType.ANNOTATION, Style.EMPTY.fg(Color.rgb(0, 92,
197)))
+ .token(TokenType.TAG, Style.EMPTY.fg(Color.rgb(215, 58, 73)))
+ .token(TokenType.ATTRIBUTE, Style.EMPTY.fg(Color.rgb(0, 92,
197)))
+ .build();
+ }
+
/** Diagram box-drawing border color. */
public static synchronized Color diagramBorder() {
return color("diagram-border", FALLBACK_DIAGRAM_BORDER);
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/index.html
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/index.html
index 5ffe7b3cfd4f..4362ef184eaf 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/index.html
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/index.html
@@ -143,6 +143,7 @@
<script src="/vendor/xterm.js"></script>
<script src="/vendor/xterm-addon-fit.js"></script>
+ <script src="/vendor/xterm-addon-unicode11.js"></script>
<script>
(function () {
'use strict';
@@ -198,6 +199,9 @@
fitAddon = new FitAddon.FitAddon();
term.loadAddon(fitAddon);
+ var unicode11Addon = new Unicode11Addon.Unicode11Addon();
+ term.loadAddon(unicode11Addon);
+ term.unicode.activeVersion = '11';
term.open(document.getElementById('terminal-container'));
function sendInit() {
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/vendor/LICENSE-xterm.txt
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/vendor/LICENSE-xterm.txt
index 234ea0e7c225..9cad528cd98c 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/vendor/LICENSE-xterm.txt
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/vendor/LICENSE-xterm.txt
@@ -1,6 +1,6 @@
This directory bundles the following third-party components, vendored to
-avoid a runtime dependency on a CDN. Neither is modified from its upstream
-release.
+avoid a runtime dependency on a CDN. None are modified from their upstream
+releases.
xterm.js 5.5.0 (xterm.js, xterm.css)
https://github.com/xtermjs/xterm.js
@@ -14,7 +14,12 @@
https://github.com/xtermjs/xterm.js/tree/master/addons/addon-fit
Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
-Both are released under the MIT License:
+xterm-addon-unicode11 0.9.0 (xterm-addon-unicode11.js)
+https://github.com/xtermjs/xterm.js/tree/master/addons/addon-unicode11
+
+Copyright (c) 2019, The xterm.js authors (https://github.com/xtermjs/xterm.js)
+
+All are released under the MIT License:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/vendor/xterm-addon-unicode11.js
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/vendor/xterm-addon-unicode11.js
new file mode 100644
index 000000000000..941130afb3ad
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/resources/tui/web/vendor/xterm-addon-unicode11.js
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof
module?module.exports=t():"function"==typeof
define&&define.amd?define([],t):"object"==typeof
exports?exports.Unicode11Addon=t():e.Unicode11Addon=t()}(globalThis,(()=>(()=>{"use
strict";var
e={384:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.UnicodeV11=void
0;const
r=s(765),n=[[768,879],[1155,1161],[1425,1469],[1471,1471],[1473,1474],[1476,1477],[1479,1479],[1536,1541],[1552,1562],[1564,1564],[1611,1631],[1648,1648
[...]
+//# sourceMappingURL=addon-unicode11.js.map
\ No newline at end of file
diff --git a/parent/pom.xml b/parent/pom.xml
index 72b5b21b60fc..0f6c5f179025 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -522,7 +522,7 @@
<swagger-ui-version>5.32.14</swagger-ui-version>
<stringtemplate-version>4.3.4</stringtemplate-version>
<tahu-version>1.0.21</tahu-version>
- <tamboui-version>0.4.0</tamboui-version>
+ <tamboui-version>0.5.0</tamboui-version>
<testcontainers-version>2.0.5</testcontainers-version>
<thymeleaf-version>3.1.5.RELEASE</thymeleaf-version>
<tika-version>4.0.0</tika-version>