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 8c1132353b98 CAMEL-23831: Show platform emoji and remove docs shortcut
in camel-tui overview CAMEL-23831: Rename Setup AI to Setup MCP in footer hint
in camel-tui CAMEL-23831: Fix Browse Files showing wrong directory for exported
Quarkus apps in camel-tui CAMEL-23831: Add trailing padding to last table
column in all camel-tui tabs CAMEL-23831: Remove docs hint from footer and
detect readme files for exported apps in camel-tui CAMEL-23831: Make info panel
height-aware to always sh [...]
8c1132353b98 is described below
commit 8c1132353b988b9fbaf9814909fefdb12c6734b5
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Jul 3 10:26:42 2026 +0200
CAMEL-23831: Show platform emoji and remove docs shortcut in camel-tui
overview
CAMEL-23831: Rename Setup AI to Setup MCP in footer hint in camel-tui
CAMEL-23831: Fix Browse Files showing wrong directory for exported Quarkus
apps in camel-tui
CAMEL-23831: Add trailing padding to last table column in all camel-tui tabs
CAMEL-23831: Remove docs hint from footer and detect readme files for
exported apps in camel-tui
CAMEL-23831: Make info panel height-aware to always show load section in
camel-tui
CAMEL-23831: Add Quarkus log file support and colorize plain log lines in
camel-tui
CAMEL-23831: Add runtime and profile emojis to overview info panel and run
dialog in camel-tui
Co-Authored-By: Claude <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../apache/camel/dsl/jbang/core/commands/Run.java | 19 +++++++
.../jbang/core/commands/action/CamelLogAction.java | 20 +++++--
.../dsl/jbang/core/commands/tui/BrowseTab.java | 2 +-
.../dsl/jbang/core/commands/tui/CamelMonitor.java | 13 +++--
.../dsl/jbang/core/commands/tui/FilesBrowser.java | 11 ++++
.../jbang/core/commands/tui/HeapHistogramTab.java | 2 +-
.../dsl/jbang/core/commands/tui/HistoryTab.java | 2 +-
.../camel/dsl/jbang/core/commands/tui/HttpTab.java | 2 +-
.../dsl/jbang/core/commands/tui/InflightTab.java | 2 +-
.../camel/dsl/jbang/core/commands/tui/LogTab.java | 54 ++++++++++++++++++-
.../dsl/jbang/core/commands/tui/MemoryLeakTab.java | 4 +-
.../dsl/jbang/core/commands/tui/OverviewTab.java | 62 ++++++++++++++++------
.../dsl/jbang/core/commands/tui/RoutesTab.java | 8 +--
.../jbang/core/commands/tui/RunOptionsForm.java | 9 ++--
.../dsl/jbang/core/commands/tui/SpansTab.java | 2 +-
.../dsl/jbang/core/commands/tui/SqlQueryTab.java | 3 +-
.../dsl/jbang/core/commands/tui/SqlTraceTab.java | 2 +-
.../dsl/jbang/core/commands/tui/ThreadsTab.java | 2 +-
18 files changed, 174 insertions(+), 45 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index f6c852b81348..b3336b687eb9 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -1291,6 +1291,7 @@ public class Run extends CamelCommand {
}
AtomicReference<Process> processRef = new AtomicReference<>();
+ AtomicReference<String> appNameRef = new AtomicReference<>();
// create temp run dir
Path runDirPath = Paths.get(RUN_PLATFORM_DIR,
Long.toString(System.currentTimeMillis()));
@@ -1317,6 +1318,11 @@ public class Run extends CamelCommand {
}
removeDir(runDirPath);
+ // cleanup log file
+ String appName = appNameRef.get();
+ if (appName != null) {
+
Files.deleteIfExists(CommandLineHelper.getCamelDir().resolve(appName + ".log"));
+ }
} catch (Exception e) {
// Ignore
}
@@ -1373,6 +1379,19 @@ public class Run extends CamelCommand {
return exit;
}
+ appNameRef.set(eq.name);
+
+ // prepare quarkus for logging to file
+ Path appProps = Paths.get(eq.exportDir,
"src/main/resources/application.properties");
+ if (Files.exists(appProps)) {
+ String content = Files.readString(appProps);
+ content += "\n# logging to file\n"
+ + "quarkus.log.file.enabled=true\n"
+ + "quarkus.log.file.path=${user.home}/.camel/" +
eq.name + ".log\n"
+ + "quarkus.log.file.format=%d{yyyy-MM-dd HH:mm:ss.SSS}
%5p %i --- [%15.15t] %-40.40c{3.} : %s%e%n\n";
+ Files.writeString(appProps, content);
+ }
+
// run quarkus via maven
String mvnw = "/mvnw";
if (FileUtil.isWindows()) {
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
index e1be84e7f314..07953aaf14f1 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
@@ -262,7 +262,7 @@ public class CamelLogAction extends ActionBaseCommand {
for (Row row : rows.values()) {
if (row.reader == null) {
- Path file = logFile(row.pid);
+ Path file = logFile(row.pid, row.name);
if (Files.exists(file)) {
row.reader = new
LineNumberReader(Files.newBufferedReader(file));
if (tail == 0) {
@@ -444,14 +444,24 @@ public class CamelLogAction extends ActionBaseCommand {
}
private static Path logFile(String pid) {
- String name = pid + ".log";
+ return logFile(pid, null);
+ }
+
+ private static Path logFile(String pid, String appName) {
Path parent = CommandLineHelper.getCamelDir();
- return parent.resolve(name);
+ Path pidLog = parent.resolve(pid + ".log");
+ if (!Files.exists(pidLog) && appName != null) {
+ Path nameLog = parent.resolve(appName + ".log");
+ if (Files.exists(nameLog)) {
+ return nameLog;
+ }
+ }
+ return pidLog;
}
private void tailStartupLogFiles(Map<Long, Row> rows) throws Exception {
for (Row row : rows.values()) {
- Path log = logFile(row.pid);
+ Path log = logFile(row.pid, row.name);
if (Files.exists(log)) {
row.fifo = new ArrayDeque<>();
row.reader = new
LineNumberReader(Files.newBufferedReader(log));
@@ -473,7 +483,7 @@ public class CamelLogAction extends ActionBaseCommand {
private void tailLogFiles(Map<Long, Row> rows, int tail, Date limit)
throws Exception {
for (Row row : rows.values()) {
- Path log = logFile(row.pid);
+ Path log = logFile(row.pid, row.name);
if (Files.exists(log)) {
row.reader = new
LineNumberReader(Files.newBufferedReader(log));
String line;
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/BrowseTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/BrowseTab.java
index 91f26da31b2b..aa1780fd4f47 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/BrowseTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/BrowseTab.java
@@ -315,7 +315,7 @@ class BrowseTab extends AbstractTab {
Constraint.fill(),
Constraint.length(8),
Constraint.length(10),
- Constraint.length(10))
+ Constraint.length(11))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
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 9cf2a2b38a14..fa6ec335c4ea 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
@@ -1703,7 +1703,7 @@ public class CamelMonitor extends CamelCommand {
rightSpans.add(Span.styled(mcpLabel, labelStyle));
rightSpans.add(Span.styled(suffix, suffixStyle));
if (client == null) {
- rightSpans.add(Span.styled(" F2 → Setup AI", Theme.muted()));
+ rightSpans.add(Span.styled(" F2 → Setup MCP", Theme.muted()));
}
}
@@ -1789,9 +1789,6 @@ public class CamelMonitor extends CamelCommand {
if (ctx.selectedPid != null && !isInfraSelected()) {
IntegrationInfo selInfo = findSelectedIntegration();
if (selInfo != null) {
- if (selInfo.readmeFiles != null &&
!selInfo.readmeFiles.isEmpty()) {
- hint(spans, "d", "docs");
- }
if (selInfo.directory != null && !selInfo.directory.isEmpty())
{
hint(spans, "f", "files");
}
@@ -1825,6 +1822,14 @@ public class CamelMonitor extends CamelCommand {
if (selected != null) {
logPid = selected.pid;
logFileName = selected.pid + ".log";
+ // fallback to name-based log file (e.g. Quarkus apps use app
name)
+ if
(!Files.exists(CommandLineHelper.getCamelDir().resolve(logFileName))
+ && selected.name != null) {
+ Path nameLog =
CommandLineHelper.getCamelDir().resolve(selected.name + ".log");
+ if (Files.exists(nameLog)) {
+ logFileName = selected.name + ".log";
+ }
+ }
}
}
if (logPid != null) {
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FilesBrowser.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FilesBrowser.java
index 8df721a40fc8..26f1e5309ab9 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FilesBrowser.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/FilesBrowser.java
@@ -294,6 +294,17 @@ class FilesBrowser {
}
}
}
+ // For exported apps (Quarkus, Spring Boot), MAVEN_PROJECTBASEDIR
points to the
+ // actual project directory inside .camel-jbang-run, which may differ
from info.directory
+ for (ConfigurationTab.ConfigProperty cp : info.configProperties) {
+ if (("MAVEN_PROJECTBASEDIR".equals(cp.key) ||
"maven.projectbasedir".equals(cp.key))
+ && cp.value != null &&
cp.value.contains(".camel-jbang-run")) {
+ Path dir = Path.of(cp.value);
+ if (Files.isDirectory(dir)) {
+ return dir;
+ }
+ }
+ }
if (info.directory != null && !info.directory.isEmpty()) {
return Path.of(info.directory);
}
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HeapHistogramTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HeapHistogramTab.java
index 72644ef64b4f..5a2004fd154b 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HeapHistogramTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HeapHistogramTab.java
@@ -164,7 +164,7 @@ class HeapHistogramTab extends AbstractTableTab {
Constraint.length(6),
Constraint.fill(),
Constraint.length(14),
- Constraint.length(14))
+ Constraint.length(15))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HistoryTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HistoryTab.java
index 16ad6de044d5..f9c960c90344 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HistoryTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HistoryTab.java
@@ -1955,7 +1955,7 @@ class HistoryTab extends AbstractTab {
Constraint.length(25),
Constraint.fill(),
Constraint.length(4),
- Constraint.length(10))
+ Constraint.length(11))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(block)
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HttpTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HttpTab.java
index 0039896dea6d..00528093544a 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HttpTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/HttpTab.java
@@ -1307,7 +1307,7 @@ class HttpTab extends AbstractTableTab {
Constraint.length(30),
Constraint.length(30),
Constraint.length(15),
- Constraint.length(8))
+ Constraint.length(9))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
index c4a36a794f8f..27f5656de1d7 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/InflightTab.java
@@ -116,7 +116,7 @@ class InflightTab extends AbstractTableTab {
Constraint.length(40),
Constraint.fill(),
Constraint.length(14),
- Constraint.length(22))
+ Constraint.length(23))
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
.build();
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/LogTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/LogTab.java
index 08c3e5902624..f4338d3c326f 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/LogTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/LogTab.java
@@ -336,11 +336,16 @@ class LogTab extends AbstractTab {
List<Line> built = new ArrayList<>(entries.size());
int maxW = 0;
for (int i = 0; i < entries.size(); i++) {
- String raw = entries.get(i).raw != null ? entries.get(i).raw :
"";
+ LogEntry entry = entries.get(i);
+ String raw = entry.raw != null ? entry.raw : "";
if (!wordWrap) {
maxW = Math.max(maxW,
CharWidth.of(TuiHelper.stripAnsi(raw)));
}
- built.add(TuiHelper.ansiToLine(raw, hSkip));
+ if (raw.indexOf('\u001B') >= 0) {
+ built.add(TuiHelper.ansiToLine(raw, hSkip));
+ } else {
+ built.add(colorizePlainLog(raw, entry));
+ }
}
cachedLogMaxWidth = maxW;
cachedLogLines = built;
@@ -614,6 +619,51 @@ class LogTab extends AbstractTab {
}
}
+ private static final Style DIM = Style.EMPTY.dim();
+ private static final Style CYAN = Style.EMPTY.fg(Color.CYAN);
+ private static final Style MAGENTA = Style.EMPTY.fg(Color.MAGENTA);
+
+ private static final Pattern PID_PATTERN = Pattern.compile(
+ "^(\\d{4}-\\d{2}-\\d{2})[T ](\\d{2}:\\d{2}:\\d{2}\\.\\d+)\\S*\\s+"
+ +
"(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)\\s+"
+ +
"(\\d+)\\s+---\\s+"
+ +
"\\[([^]]*)]\\s+"
+ +
"(\\S+)\\s*:\\s*(.*)$");
+
+ private static Line colorizePlainLog(String raw, LogEntry entry) {
+ String plain = TuiHelper.stripAnsi(raw);
+ Matcher m = PID_PATTERN.matcher(plain);
+ if (!m.matches()) {
+ return Line.from(Span.raw(plain));
+ }
+ String date = m.group(1) + " " + m.group(2);
+ String level = m.group(3);
+ String pid = m.group(4);
+ String thread = "[" + m.group(5) + "]";
+ String logger = m.group(6);
+ String message = m.group(7);
+ Style levelStyle = switch (level) {
+ case "ERROR", "FATAL" -> Style.EMPTY.fg(Color.RED);
+ case "WARN" -> Style.EMPTY.fg(Color.YELLOW);
+ case "INFO" -> Style.EMPTY.fg(Color.GREEN);
+ case "DEBUG" -> Style.EMPTY.fg(Color.CYAN);
+ case "TRACE" -> Style.EMPTY.dim();
+ default -> Style.EMPTY;
+ };
+ return Line.from(
+ Span.styled(date, DIM),
+ Span.raw(" "),
+ Span.styled(String.format("%5s", level), levelStyle),
+ Span.raw(" "),
+ Span.styled(pid, MAGENTA),
+ Span.styled(" --- ", DIM),
+ Span.styled(thread, DIM),
+ Span.raw(" "),
+ Span.styled(logger, CYAN),
+ Span.styled(" :", DIM),
+ Span.raw(" " + message));
+ }
+
static LogEntry parseLogLine(String line) {
LogEntry entry = new LogEntry();
entry.raw = line;
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MemoryLeakTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MemoryLeakTab.java
index c8a246a5e485..8cd5fa016cf4 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MemoryLeakTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/MemoryLeakTab.java
@@ -436,7 +436,7 @@ class MemoryLeakTab extends AbstractTab {
Constraint.fill(),
Constraint.length(8),
Constraint.length(12),
- Constraint.length(12))
+ Constraint.length(13))
.highlightStyle(Style.EMPTY.fg(Color.WHITE).bold().onBlue())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
@@ -591,7 +591,7 @@ class MemoryLeakTab extends AbstractTab {
Constraint.length(10),
Constraint.length(10),
Constraint.length(9),
- Constraint.length(12))
+ Constraint.length(13))
.highlightStyle(Style.EMPTY.fg(Color.WHITE).bold().onBlue())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/OverviewTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/OverviewTab.java
index 66b4ed035447..e6d8691d09d1 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/OverviewTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/OverviewTab.java
@@ -93,7 +93,7 @@ class OverviewTab extends AbstractTab {
private Rect lastTableArea;
int dividerIndex = -1;
int chartMode = CHART_SINGLE;
- private int bottomPanelHeight = 14;
+ private int bottomPanelHeight = 16;
private final DragSplit vSplit = new DragSplit();
private String sort = "name";
@@ -155,13 +155,6 @@ class OverviewTab extends AbstractTab {
actions.restartSelectedProcess();
return true;
}
- if (ke.isChar('d') && ctx.selectedPid != null &&
!ctx.isInfraSelected()) {
- IntegrationInfo selInfo = ctx.findSelectedIntegration();
- if (selInfo != null && selInfo.readmeFiles != null &&
!selInfo.readmeFiles.isEmpty()) {
- actions.openDoc(selInfo);
- return true;
- }
- }
if (ke.isChar('f') && ctx.selectedPid != null &&
!ctx.isInfraSelected()) {
actions.openFilesPopup();
return true;
@@ -323,7 +316,15 @@ class OverviewTab extends AbstractTab {
String sinceLastDisplay = formatSinceLast(info);
boolean hasDoc = info.readmeFiles != null &&
!info.readmeFiles.isEmpty();
- String nameText = "🐪 " + (info.name != null ? info.name : "");
+ if (!hasDoc) {
+ hasDoc = hasReadmeInSourceDir(info);
+ }
+ String platformIcon = switch (info.platform != null ?
info.platform : "") {
+ case "Spring Boot" -> "🍃";
+ case "Quarkus" -> "🚀";
+ default -> "🐪";
+ };
+ String nameText = platformIcon + " " + (info.name != null ?
info.name : "");
List<Span> nameSpans = new ArrayList<>();
nameSpans.add(Span.styled(nameText,
Style.EMPTY.fg(Color.CYAN)));
if (info.devMode) {
@@ -431,7 +432,7 @@ class OverviewTab extends AbstractTab {
Constraint.length(8),
Constraint.length(6),
Constraint.length(8),
- Constraint.length(12))
+ Constraint.length(13))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title("
Overview ").build())
@@ -445,7 +446,7 @@ class OverviewTab extends AbstractTab {
Rect chartTotalArea = chunks.get(chunks.size() - 1);
List<Rect> chartHSplit = Layout.horizontal()
- .constraints(Constraint.fill(), Constraint.length(30))
+ .constraints(Constraint.fill(), Constraint.length(34))
.split(chartTotalArea);
Rect chartArea = chartHSplit.get(0);
Rect infoArea = chartHSplit.get(1);
@@ -603,11 +604,19 @@ class OverviewTab extends AbstractTab {
Rect inner = infoBlock.inner(area);
List<Line> lines = new ArrayList<>();
Style dim = Style.EMPTY.dim();
+ int jvmDetailStart = -1;
+ int jvmDetailCount = 0;
if (sel != null) {
if (sel.platform != null) {
+ String platEmoji = switch (sel.platform) {
+ case "Spring Boot" -> "🍃 ";
+ case "Quarkus" -> "🚀 ";
+ case "JBang", "Camel" -> "🐪 ";
+ default -> "";
+ };
String plat = sel.platformVersion != null
- ? sel.platform + " v" + sel.platformVersion
- : sel.platform;
+ ? platEmoji + sel.platform + " v" + sel.platformVersion
+ : platEmoji + sel.platform;
lines.add(Line.from(
Span.styled("Runtime: ", dim),
Span.raw(TuiHelper.truncate(plat, inner.width() -
9))));
@@ -621,7 +630,8 @@ class OverviewTab extends AbstractTab {
List<Span> profileSpans = new ArrayList<>();
if (sel.profile != null) {
profileSpans.add(Span.styled("Profile: ", dim));
- profileSpans.add(Span.raw(sel.profile));
+ String profileEmoji = "dev".equals(sel.profile) ? "🛠️ " :
"prod".equals(sel.profile) ? "🔒 " : "";
+ profileSpans.add(Span.raw(profileEmoji + sel.profile));
}
if (sel.reloaded > 0) {
if (!profileSpans.isEmpty()) {
@@ -639,14 +649,20 @@ class OverviewTab extends AbstractTab {
Span.raw(TuiHelper.truncate(sel.javaVersion,
inner.width() - 6))));
}
if (sel.javaVendor != null) {
+ jvmDetailStart = lines.size();
lines.add(Line.from(
Span.styled(" ", dim),
Span.raw(TuiHelper.truncate(sel.javaVendor,
inner.width() - 6))));
+ jvmDetailCount++;
}
if (sel.javaVmName != null) {
+ if (jvmDetailStart < 0) {
+ jvmDetailStart = lines.size();
+ }
lines.add(Line.from(
Span.styled(" ", dim),
Span.raw(TuiHelper.truncate(sel.javaVmName,
inner.width() - 6))));
+ jvmDetailCount++;
}
lines.add(Line.from(
Span.styled("Uptime: ", dim),
@@ -684,8 +700,12 @@ class OverviewTab extends AbstractTab {
Span.raw(sel.inflightLoad01 + " / " +
sel.inflightLoad05 + " / " + sel.inflightLoad15)));
}
}
+ // if content exceeds panel height, drop JVM vendor/VM name to
make room for load
+ if (lines.size() > inner.height() && jvmDetailStart >= 0) {
+ lines.subList(jvmDetailStart, jvmDetailStart +
jvmDetailCount).clear();
+ }
} else {
- lines.add(Line.from(Span.raw("-")));
+ lines.add(Line.from(Span.raw("")));
}
frame.renderWidget(Paragraph.builder().text(Text.from(lines)).build(),
inner);
}
@@ -862,6 +882,18 @@ class OverviewTab extends AbstractTab {
return sortStyle(column, sort);
}
+ private static boolean hasReadmeInSourceDir(IntegrationInfo info) {
+ java.nio.file.Path srcDir = FilesBrowser.resolveSourceDirectory(info);
+ if (srcDir != null) {
+ try (java.util.stream.Stream<java.nio.file.Path> files =
java.nio.file.Files.list(srcDir)) {
+ return files.anyMatch(p ->
p.getFileName().toString().toLowerCase(java.util.Locale.ROOT).startsWith("readme"));
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ return false;
+ }
+
@Override
public String description() {
return "Running integrations with PID, uptime, and exchange
statistics";
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 bb031f6eec95..3b52b4753e76 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
@@ -611,7 +611,7 @@ class RoutesTab extends AbstractTab {
Constraint.length(6),
Constraint.length(8),
Constraint.length(8),
- Constraint.length(12))
+ Constraint.length(13))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
@@ -671,7 +671,7 @@ class RoutesTab extends AbstractTab {
Constraint.length(6),
Constraint.length(8),
Constraint.length(14),
- Constraint.length(12))
+ Constraint.length(13))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
@@ -1149,7 +1149,7 @@ class RoutesTab extends AbstractTab {
Constraint.length(6),
Constraint.length(8),
Constraint.length(6),
- Constraint.length(8))
+ Constraint.length(9))
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
.title(" Top Processors [" + route.routeId + "]
sort:" + routeTopSort + " ").build())
.build();
@@ -1211,7 +1211,7 @@ class RoutesTab extends AbstractTab {
Constraint.length(6),
Constraint.length(8),
Constraint.length(14),
- Constraint.length(12))
+ Constraint.length(13))
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
.title(" Processors [" + route.routeId + "]
").build())
.build();
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RunOptionsForm.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RunOptionsForm.java
index 27bbfdf87646..967947065946 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RunOptionsForm.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/RunOptionsForm.java
@@ -62,9 +62,10 @@ class RunOptionsForm {
private static final String[] MAX_MODES = { "Max seconds:", "Max
messages:", "Max idle secs:" };
private static final String[] MAX_FLAGS = { "--max-seconds=",
"--max-messages=", "--max-idle-seconds=" };
- private static final String[] RUNTIME_LABELS = { "Camel Main", "Spring
Boot", "Quarkus" };
+ private static final String[] RUNTIME_LABELS = { "🐪 Camel Main", "🍃 Spring
Boot", "🚀 Quarkus" };
private static final String[] RUNTIME_VALUES = { "camel-main",
"spring-boot", "quarkus" };
- private static final String[] PROFILE_LABELS = { "dev", "prod" };
+ private static final String[] PROFILE_LABELS = { "🛠️ dev", "🔒 prod" };
+ private static final String[] PROFILE_VALUES = { "dev", "prod" };
// Text fields
private TextInputState nameInput;
@@ -198,7 +199,7 @@ class RunOptionsForm {
if (runtimeMode > 0) {
args.add("--runtime=" + RUNTIME_VALUES[runtimeMode]);
}
- args.add("--profile=" + PROFILE_LABELS[profileMode]);
+ args.add("--profile=" + PROFILE_VALUES[profileMode]);
String port = portInput.text().trim();
if (!port.isEmpty()) {
args.add("--port=" + port);
@@ -442,7 +443,7 @@ class RunOptionsForm {
// ---- Rendering ----
private void renderOptionsPage(Frame frame, Rect area) {
- int popupW = Math.min(56, area.width() - 4);
+ int popupW = Math.min(64, area.width() - 4);
int popupH = 15;
int x = area.left() + Math.max(0, (area.width() - popupW) / 2);
int y = area.top() + Math.max(0, (area.height() - popupH) / 4);
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SpansTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SpansTab.java
index 3e2cb3021f7e..943452f11957 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SpansTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SpansTab.java
@@ -412,7 +412,7 @@ class SpansTab extends AbstractTab {
Constraint.fill(),
Constraint.length(8),
Constraint.length(12),
- Constraint.length(7))
+ Constraint.length(8))
.highlightStyle(Theme.selectionBg())
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())
.build();
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlQueryTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlQueryTab.java
index 40775ad7ea69..428edaf08a77 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlQueryTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlQueryTab.java
@@ -504,7 +504,8 @@ class SqlQueryTab extends AbstractTab {
Constraint[] colConstraints = new Constraint[widths.length];
for (int i = 0; i < widths.length; i++) {
- colConstraints[i] = Constraint.length(widths[i]);
+ // Add 1 extra char to the last column for trailing padding before
the border
+ colConstraints[i] = Constraint.length(widths[i] + (i ==
widths.length - 1 ? 1 : 0));
}
Table table = Table.builder()
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlTraceTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlTraceTab.java
index ddf7f3e97115..0787cfb02df5 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlTraceTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/SqlTraceTab.java
@@ -284,7 +284,7 @@ class SqlTraceTab extends AbstractTableTab {
Constraint.length(20),
Constraint.length(10),
Constraint.length(8),
- Constraint.length(8))
+ Constraint.length(9))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL)
diff --git
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ThreadsTab.java
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ThreadsTab.java
index ed9712c99392..c79e36215ac4 100644
---
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ThreadsTab.java
+++
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/ThreadsTab.java
@@ -246,7 +246,7 @@ class ThreadsTab extends AbstractTableTab {
Constraint.fill(),
Constraint.length(16),
Constraint.length(14),
- Constraint.length(14))
+ Constraint.length(15))
.highlightStyle(Theme.selectionBg())
.highlightSpacing(Table.HighlightSpacing.ALWAYS)
.block(Block.builder().borderType(BorderType.ROUNDED).borders(Borders.ALL).title(title).build())