This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch fix/camel-tui-cosmetic in repository https://gitbox.apache.org/repos/asf/camel.git
commit a9d122f99273e37b4605cc4810f3d35373b02d33 Author: Claus Ibsen <[email protected]> AuthorDate: Fri May 15 19:04:26 2026 +0200 Fix TUI log tab leaving garbage on other tabs due to narrow ANSI stripping The old inline regex only stripped SGR color codes (\e[...m), leaving other control sequences — cursor moves, erase codes, OSC hyperlinks, carriage returns from Windows line endings — in the raw log text. When TamboUI writes these bytes to the terminal they corrupt the terminal's rendering state, which persists across tab switches even though TamboUI clears its own internal buffer before each frame. Add TuiHelper.stripAnsi() with a char-by-char parser that handles: - CSI sequences: \e[ + params/intermediates + any final byte (@-~) - 2-char Fe/Fp escape sequences: \e + char in @-_ - \r (carriage returns from Windows line endings / progress output) Use it in readLogFile() replacing both the old inline regex and the intermediate ANSI_PATTERN constant. --- .../dsl/jbang/core/commands/tui/CamelMonitor.java | 2 +- .../dsl/jbang/core/commands/tui/TuiHelper.java | 37 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) 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 5caed2dfb0e8..82131166e2c4 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 @@ -2018,7 +2018,7 @@ public class CamelMonitor extends CamelCommand { String[] rawLines = content.split("\n", -1); int start = Math.max(0, rawLines.length - MAX_LOG_LINES); for (int i = start; i < rawLines.length; i++) { - String line = rawLines[i].replaceAll("\u001B\\[[;\\d]*m", ""); + String line = TuiHelper.stripAnsi(rawLines[i]); if (!line.isEmpty()) { target.add(line); } diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java index 7384c9bf529d..c8c9471b23b0 100644 --- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java +++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java @@ -132,6 +132,43 @@ final class TuiHelper { return 0; } + /** + * Strip ANSI escape sequences and carriage returns from a log line. Handles CSI sequences (\e[...finalChar where + * finalChar is any char in @-~), 2-char Fe/Fp escape sequences, and \r. + */ + static String stripAnsi(String line) { + if (line == null || line.isEmpty()) { + return line; + } + StringBuilder sb = new StringBuilder(line.length()); + int i = 0; + while (i < line.length()) { + char ch = line.charAt(i); + if (ch == '\u001B' && i + 1 < line.length()) { + char next = line.charAt(i + 1); + if (next == '[') { + // CSI sequence: \e[ + params/intermediates + final byte (any char @-~) + i += 2; + while (i < line.length() && (line.charAt(i) < '@' || line.charAt(i) > '~')) { + i++; + } + i++; // skip the final byte + } else if (next >= '@' && next <= '_') { + // 2-char Fe/Fp escape sequence (e.g. \eM, \e7, \e8) + i += 2; + } else { + i++; // unrecognised, skip just the ESC + } + } else if (ch == '\r') { + i++; // strip carriage returns (Windows line endings, progress output) + } else { + sb.append(ch); + i++; + } + } + return sb.toString(); + } + static String shortTypeName(String type) { if (type == null) { return "null";
