This is an automated email from the ASF dual-hosted git repository.

gnodet 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 36f9299d1322 chore: Reuse shell terminal for TUI subcommands
36f9299d1322 is described below

commit 36f9299d13226de7fe7a61388a37e19860d3dba0
Author: Guillaume Nodet <[email protected]>
AuthorDate: Tue May 26 09:50:27 2026 +0200

    chore: Reuse shell terminal for TUI subcommands
    
    - Introduce TuiBackendHelper to reuse the active JLine terminal from the 
Camel shell
    - Avoids spawning a new terminal when TUI commands run inside the shell
    - Also fixes commands using System.console() to work inside camel shell
---
 .../jbang/core/commands/tui/CamelCatalogTui.java   |  2 +-
 .../dsl/jbang/core/commands/tui/CamelMonitor.java  | 21 +--------
 .../jbang/core/commands/tui/TuiBackendHelper.java  | 55 ++++++++++++++++++++++
 3 files changed, 57 insertions(+), 21 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java
index 7e8aef4c3b3b..40e20580ae6c 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CamelCatalogTui.java
@@ -96,7 +96,7 @@ public class CamelCatalogTui extends CamelCommand {
 
         loadCatalog();
 
-        try (var tui = TuiRunner.create()) {
+        try (var tui = TuiBackendHelper.createTuiRunner()) {
             Signal.handle(new Signal("INT"), sig -> tui.quit());
             tui.run(this::handleEvent, this::render);
         }
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 91d02161000b..bbe0e04ec8b8 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
@@ -317,8 +317,7 @@ public class CamelMonitor extends CamelCommand {
             }
         }
 
-        var tui = TuiRunner.create();
-        try {
+        try (var tui = TuiBackendHelper.createTuiRunner()) {
             this.runner = tui;
             ctx.runner = tui;
             // Intercept Ctrl+C: quit the TUI cleanly instead of letting
@@ -333,24 +332,6 @@ public class CamelMonitor extends CamelCommand {
             }
             deleteMcpJson(mcpJsonFile);
             this.runner = null;
-            // Workaround: on macOS, JLine's terminal close deadlocks in
-            // FileDescriptor.close0() while the reader thread is in native 
read0().
-            // Run close in a daemon thread so the JVM can exit even if it 
hangs.
-            // Remove when fixed upstream: 
https://github.com/tamboui/tamboui/pull/355
-            Thread closeThread = new Thread(() -> {
-                try {
-                    tui.close();
-                } catch (Exception e) {
-                    // best effort
-                }
-            }, "tui-close");
-            closeThread.setDaemon(true);
-            closeThread.start();
-            try {
-                closeThread.join(3000);
-            } catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
-            }
         }
         return 0;
     }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiBackendHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiBackendHelper.java
new file mode 100644
index 000000000000..87c2c641561a
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiBackendHelper.java
@@ -0,0 +1,55 @@
+/*
+ * 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.tui;
+
+import java.lang.reflect.Constructor;
+
+import dev.tamboui.backend.jline3.JLineBackend;
+import dev.tamboui.terminal.Backend;
+import dev.tamboui.tui.TuiConfig;
+import dev.tamboui.tui.TuiRunner;
+import org.apache.camel.dsl.jbang.core.common.EnvironmentHelper;
+import org.jline.terminal.Terminal;
+
+final class TuiBackendHelper {
+
+    private TuiBackendHelper() {
+    }
+
+    static TuiRunner createTuiRunner() throws Exception {
+        Terminal activeTerminal = EnvironmentHelper.getActiveTerminal();
+        if (activeTerminal != null) {
+            Backend backend = createBackendForTerminal(activeTerminal);
+            if (backend != null) {
+                return 
TuiRunner.create(TuiConfig.builder().backend(backend).build());
+            }
+        }
+        return TuiRunner.create();
+    }
+
+    private static Backend createBackendForTerminal(Terminal terminal) {
+        try {
+            Constructor<JLineBackend> ctor = 
JLineBackend.class.getDeclaredConstructor(Terminal.class);
+            return ctor.newInstance(terminal);
+        } catch (NoSuchMethodException e) {
+            // JLineBackend(Terminal) not available in this version, fall back
+            return null;
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}

Reply via email to