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 12e0af7249f CAMEL-21443: Camel JBang shell command (#16182)
12e0af7249f is described below

commit 12e0af7249fe081fcccd74451a008028fe89239c
Author: Guillaume Nodet <gno...@gmail.com>
AuthorDate: Tue Nov 12 16:51:49 2024 +0100

    CAMEL-21443: Camel JBang shell command (#16182)
---
 .../modules/ROOT/pages/camel-jbang.adoc            |   9 ++
 dsl/camel-jbang/camel-jbang-core/pom.xml           |  15 +++
 .../dsl/jbang/core/commands/CamelJBangMain.java    |   4 +
 .../camel/dsl/jbang/core/commands/Shell.java       | 102 +++++++++++++++++++++
 parent/pom.xml                                     |   1 +
 5 files changed, 131 insertions(+)

diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
index 498b68d01cb..741af075c3e 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang.adoc
@@ -110,6 +110,15 @@ To make it permanent, run:
 echo 'source <(camel completion)' >> ~/.bashrc
 ----
 
+== REPL loop
+
+A simple read-eval-print loop is available, you can launch it with:
+
+[source, bash]
+----
+camel shell
+----
+
 == Creating and running Camel routes
 
 You can create a new basic routes with the `init` command.
diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml 
b/dsl/camel-jbang/camel-jbang-core/pom.xml
index c3dfdfe784d..769c54532a2 100644
--- a/dsl/camel-jbang/camel-jbang-core/pom.xml
+++ b/dsl/camel-jbang/camel-jbang-core/pom.xml
@@ -87,6 +87,16 @@
             <artifactId>picocli</artifactId>
             <version>${picocli-version}</version>
         </dependency>
+        <dependency>
+            <groupId>info.picocli</groupId>
+            <artifactId>picocli-shell-jline3</artifactId>
+            <version>${picocli-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jline</groupId>
+            <artifactId>jline</artifactId>
+            <version>${jline-version}</version>
+        </dependency>
         <dependency>
             <groupId>com.github.freva</groupId>
             <artifactId>ascii-table</artifactId>
@@ -136,6 +146,11 @@
             <version>${jansi-version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-xml</artifactId>
+        </dependency>
+
         <!-- test dependencies -->
         <dependency>
             <groupId>org.apache.camel</groupId>
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
index 2dd90261654..9d470e9e0e7 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java
@@ -72,6 +72,7 @@ public class CamelJBangMain implements Callable<Integer> {
         }
 
         commandLine = new CommandLine(main)
+                .addSubcommand("shell", new CommandLine(new Shell(main)))
                 .addSubcommand("init", new CommandLine(new Init(main)))
                 .addSubcommand("run", new CommandLine(new Run(main)))
                 .addSubcommand("debug", new CommandLine(new Debug(main)))
@@ -219,4 +220,7 @@ public class CamelJBangMain implements Callable<Integer> {
         return this;
     }
 
+    public static CommandLine getCommandLine() {
+        return commandLine;
+    }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Shell.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Shell.java
new file mode 100644
index 00000000000..9f54f5ec451
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Shell.java
@@ -0,0 +1,102 @@
+/*
+ * 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 java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.function.Supplier;
+
+import org.jline.builtins.ConfigurationPath;
+import org.jline.console.SystemRegistry;
+import org.jline.console.impl.Builtins;
+import org.jline.console.impl.SystemRegistryImpl;
+import org.jline.keymap.KeyMap;
+import org.jline.reader.Binding;
+import org.jline.reader.EndOfFileException;
+import org.jline.reader.LineReader;
+import org.jline.reader.LineReaderBuilder;
+import org.jline.reader.MaskingCallback;
+import org.jline.reader.Parser;
+import org.jline.reader.Reference;
+import org.jline.reader.UserInterruptException;
+import org.jline.reader.impl.DefaultParser;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.TerminalBuilder;
+import org.jline.widget.TailTipWidgets;
+import picocli.CommandLine;
+import picocli.shell.jline3.PicocliCommands;
+
+@CommandLine.Command(name = "shell",
+                     description = "Interactive Camel JBang shell. Hit 
@|magenta <TAB>|@ to see available commands.",
+                     footer = "Press Ctrl-D to exit.")
+public class Shell extends CamelCommand {
+
+    public Shell(CamelJBangMain main) {
+        super(main);
+    }
+
+    @Override
+    public Integer doCall() throws Exception {
+        Supplier<Path> workDir = () -> 
Paths.get(System.getProperty("user.dir"));
+        // set up JLine built-in commands
+        Builtins builtins = new Builtins(workDir, new 
ConfigurationPath(workDir.get(), workDir.get()), null);
+
+        PicocliCommands.PicocliCommandsFactory factory = new 
PicocliCommands.PicocliCommandsFactory();
+        PicocliCommands picocliCommands = new 
PicocliCommands(CamelJBangMain.getCommandLine());
+
+        Parser parser = new DefaultParser();
+        try (Terminal terminal = TerminalBuilder.builder().build()) {
+            SystemRegistry systemRegistry = new SystemRegistryImpl(parser, 
terminal, workDir, null);
+            systemRegistry.setCommandRegistries(builtins, picocliCommands);
+            systemRegistry.register("help", picocliCommands);
+
+            LineReader reader = LineReaderBuilder.builder()
+                    .terminal(terminal)
+                    .completer(systemRegistry.completer())
+                    .parser(parser)
+                    .variable(LineReader.LIST_MAX, 50)   // max tab completion 
candidates
+                    .build();
+            builtins.setLineReader(reader);
+            factory.setTerminal(terminal);
+            TailTipWidgets widgets
+                    = new TailTipWidgets(reader, 
systemRegistry::commandDescription, 5, TailTipWidgets.TipType.COMPLETER);
+            widgets.enable();
+            KeyMap<Binding> keyMap = reader.getKeyMaps().get("main");
+            keyMap.bind(new Reference("tailtip-toggle"), KeyMap.alt("s"));
+            String prompt = "camel> ";
+            String rightPrompt = null;
+
+            // start the shell and process input until the user quits with 
Ctrl-D
+            String line;
+            while (true) {
+                try {
+                    systemRegistry.cleanUp();
+                    line = reader.readLine(prompt, rightPrompt, 
(MaskingCallback) null, null);
+                    systemRegistry.execute(line);
+                } catch (UserInterruptException e) {
+                    // Ignore
+                } catch (EndOfFileException e) {
+                    break;
+                } catch (Exception e) {
+                    systemRegistry.trace(e);
+                }
+            }
+
+        }
+        return 0;
+    }
+}
diff --git a/parent/pom.xml b/parent/pom.xml
index 84de4b85754..eba36e28e8b 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -285,6 +285,7 @@
         <jgroups-raft-leveldbjni-version>1.8</jgroups-raft-leveldbjni-version>
         <jgroups-raft-mapdb-version>1.0.8</jgroups-raft-mapdb-version>
         <jira-rest-client-api-version>6.0.1</jira-rest-client-api-version>
+        <jline-version>3.27.1</jline-version>
         <libthrift-version>0.21.0</libthrift-version>
         <jodatime2-version>2.13.0</jodatime2-version>
         <jolokia-version>2.1.1</jolokia-version>

Reply via email to