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 c16c723916d4 CAMEL-26929: camel-jbang - no ANSI color codes in the 
piped output of cmd send, trace, browse and the other action commands (#29924)
c16c723916d4 is described below

commit c16c723916d458ef43f50226945339da1fe153ca
Author: Claus Ibsen <[email protected]>
AuthorDate: Sat Nov 14 19:26:00 2026 +0100

    CAMEL-26929: camel-jbang - no ANSI color codes in the piped output of cmd 
send, trace, browse and the other action commands (#29924)
    
    --logging-color defaults to true for camel cmd send, trace, cmd browse, get 
history,
    cmd receive, get span and cmd stub, which print the colors through the 
printer: in a
    file or a pipe the output had the ANSI codes, which an agent or a script 
reads as noise.
    
    CamelCommand.colorOutput follows --logging-color when it is given, and 
otherwise prints
    in colors only to a terminal; a command that prints to another printer (the 
TUI, the
    MCP server) keeps the option.
    
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../dsl/jbang/core/commands/CamelCommand.java      | 16 ++++++
 .../core/commands/action/CamelBrowseAction.java    |  2 +
 .../core/commands/action/CamelHistoryAction.java   |  2 +
 .../core/commands/action/CamelReceiveAction.java   |  2 +
 .../core/commands/action/CamelSendAction.java      |  2 +
 .../core/commands/action/CamelSpanAction.java      |  2 +
 .../core/commands/action/CamelStubAction.java      |  2 +
 .../core/commands/action/CamelTraceAction.java     |  2 +
 .../dsl/jbang/core/commands/ColorOutputTest.java   | 58 ++++++++++++++++++++++
 9 files changed, 88 insertions(+)

diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
index 608d4ad24496..b504f74fcd17 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
@@ -355,6 +355,22 @@ public abstract class CamelCommand implements 
Command<CommandInvocation>, Comman
         return printsToConsole() && AnsiConsole.out().getMode() == 
AnsiMode.Strip;
     }
 
+    /**
+     * Whether the command prints in colors: as --logging-color says when it 
is given, else only when it prints to a
+     * terminal, as the default of the option is colors. In a file or a pipe, 
which an AI agent or a script reads, the
+     * ANSI codes of the colors are noise (CAMEL-26929). A command that prints 
to another printer than the console keeps
+     * its option.
+     *
+     * @param  loggingColor the --logging-color option
+     * @return              whether to print in colors
+     */
+    protected boolean colorOutput(boolean loggingColor) {
+        if (!loggingColor || isOptionGiven("--logging-color")) {
+            return loggingColor;
+        }
+        return !printsToConsole() || EnvironmentHelper.hasTerminal();
+    }
+
     private boolean printsToConsole() {
         return printer() instanceof Printer.SystemOutPrinter && 
!EnvironmentHelper.isEmbedded();
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
index 5a6485d8e027..14d656a95501 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelBrowseAction.java
@@ -135,6 +135,8 @@ public class CamelBrowseAction extends ActionBaseCommand {
 
     @Override
     public Integer doCall() throws Exception {
+        // no ANSI codes of colors in a file or a pipe, unless --logging-color 
is given
+        loggingColor = colorOutput(loggingColor);
         CamelProcess process = findOne(name);
         this.pid = process.pid();
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java
index 61ff5bb87e0a..b865d644b289 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelHistoryAction.java
@@ -159,6 +159,8 @@ public class CamelHistoryAction extends ActionWatchCommand {
 
     @Override
     public Integer doCall() throws Exception {
+        // no ANSI codes of colors in a file or a pipe, unless --logging-color 
is given
+        loggingColor = colorOutput(loggingColor);
         if (it) {
             // cannot run in watch mode for interactive
             watch = false;
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java
index 80e5d91fcf2b..d493a0b89cfd 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelReceiveAction.java
@@ -246,6 +246,8 @@ public class CamelReceiveAction extends ActionBaseCommand {
 
     @Override
     public Integer doCall() throws Exception {
+        // no ANSI codes of colors in a file or a pipe, unless --logging-color 
is given
+        loggingColor = colorOutput(loggingColor);
         boolean autoDump = false;
         if (endpoint != null) {
             // if using --endpoint then action should be start and auto-dump
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
index 87b43b832621..031bc12acdbf 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSendAction.java
@@ -183,6 +183,8 @@ public class CamelSendAction extends ActionBaseCommand {
 
     @Override
     public Integer doCall() throws Exception {
+        // no ANSI codes of colors in a file or a pipe, unless --logging-color 
is given
+        loggingColor = colorOutput(loggingColor);
         if (headers != null) {
             for (String h : headers) {
                 if (!h.contains("=")) {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSpanAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSpanAction.java
index 94a9e65dd903..d7b71d961fee 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSpanAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelSpanAction.java
@@ -118,6 +118,8 @@ public class CamelSpanAction extends ActionBaseCommand {
 
     @Override
     public Integer doCall() throws Exception {
+        // no ANSI codes of colors in a file or a pipe, unless --logging-color 
is given
+        loggingColor = colorOutput(loggingColor);
         CamelProcess process = findOne(name);
         this.pid = process.pid();
 
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java
index 1367ee49688b..93925621659d 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelStubAction.java
@@ -122,6 +122,8 @@ public class CamelStubAction extends ActionWatchCommand {
 
     @Override
     protected Integer doWatchCall() throws Exception {
+        // no ANSI codes of colors in a file or a pipe, unless --logging-color 
is given
+        loggingColor = colorOutput(loggingColor);
         // setup table helper
         tableHelper = new MessageTableHelper();
         tableHelper.setPretty(pretty);
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
index 62848187ca09..712bab723f8d 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelTraceAction.java
@@ -218,6 +218,8 @@ public class CamelTraceAction extends ActionBaseCommand {
 
     @Override
     public Integer doCall() throws Exception {
+        // no ANSI codes of colors in a file or a pipe, unless --logging-color 
is given
+        loggingColor = colorOutput(loggingColor);
         if ("dump".equals(action)) {
             return doDumpCall();
         } else if ("status".equals(action)) {
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ColorOutputTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ColorOutputTest.java
new file mode 100644
index 000000000000..2099bf88409d
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/ColorOutputTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.dsl.jbang.core.commands;
+
+import org.apache.camel.dsl.jbang.core.commands.action.CamelSendAction;
+import org.apache.camel.dsl.jbang.core.common.CommandLineTestHelper;
+import org.apache.camel.dsl.jbang.run.common.StringPrinter;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The colors of camel cmd send --reply, camel trace and camel cmd browse: 
ANSI codes in a file or a pipe, which an AI
+ * agent or a script reads, were noise (CAMEL-26929).
+ */
+class ColorOutputTest {
+
+    @Test
+    void noColorsWhenTheOutputIsNoTerminal() {
+        // the forked JVM of the test has no terminal, and the command prints 
to the console
+        CamelSendAction command = new CamelSendAction(new CamelJBangMain());
+        CommandLineTestHelper.parse(command, "--endpoint=direct:foo");
+
+        assertThat(command.colorOutput(true)).isFalse();
+        assertThat(command.colorOutput(false)).isFalse();
+    }
+
+    @Test
+    void colorsWhenTheOptionIsGiven() {
+        CamelSendAction command = new CamelSendAction(new CamelJBangMain());
+        CommandLineTestHelper.parse(command, "--endpoint=direct:foo", 
"--logging-color");
+
+        assertThat(command.colorOutput(true)).isTrue();
+    }
+
+    @Test
+    void anotherPrinterKeepsTheOption() {
+        // such as the TUI or the MCP server, which take the output of the 
command
+        CamelSendAction command = new CamelSendAction(new 
CamelJBangMain().withPrinter(new StringPrinter()));
+        CommandLineTestHelper.parse(command, "--endpoint=direct:foo");
+
+        assertThat(command.colorOutput(true)).isTrue();
+    }
+}

Reply via email to