diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml b/dsl/camel-jbang/camel-jbang-core/pom.xml index 31dccd48d50da..f236054ebe756 100644 --- a/dsl/camel-jbang/camel-jbang-core/pom.xml +++ b/dsl/camel-jbang/camel-jbang-core/pom.xml @@ -89,13 +89,13 @@ ${picocli-version} - info.picocli - picocli-shell-jline3 - ${picocli-version} + org.jline + jline + ${jline-version} org.jline - jline + jline-picocli ${jline-version} 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 index 4eb84de7e2b58..c550f328fbce4 100644 --- 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 @@ -16,35 +16,17 @@ */ package org.apache.camel.dsl.jbang.core.commands; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.function.Supplier; import org.apache.camel.util.HomeHelper; -import org.jline.builtins.ClasspathResourceUtil; -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.builtins.InteractiveCommandGroup; +import org.jline.builtins.PosixCommandGroup; +import org.jline.picocli.PicocliCommandRegistry; 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.DefaultHighlighter; -import org.jline.reader.impl.DefaultParser; -import org.jline.terminal.Terminal; -import org.jline.terminal.TerminalBuilder; -import org.jline.utils.AttributedStringBuilder; -import org.jline.utils.AttributedStyle; -import org.jline.utils.InfoCmp; -import org.jline.widget.TailTipWidgets; +import org.jline.shell.impl.DefaultAliasManager; import picocli.CommandLine; -import picocli.shell.jline3.PicocliCommands; @CommandLine.Command(name = "shell", description = "Interactive Camel JBang shell.", @@ -57,86 +39,39 @@ public Shell(CamelJBangMain main) { @Override public Integer doCall() throws Exception { - Supplier workDir = () -> Paths.get(System.getProperty("user.dir")); - // set up JLine built-in commands - Path appConfig = ClasspathResourceUtil.getResourcePath("/nano/jnanorc", getClass()).getParent(); - Builtins builtins = new Builtins(workDir, new ConfigurationPath(appConfig, workDir.get()), null) { - @Override - public String name() { - return "built-in"; - } - }; + PicocliCommandRegistry registry = new PicocliCommandRegistry(CamelJBangMain.getCommandLine()); - PicocliCommands.PicocliCommandsFactory factory = new PicocliCommands.PicocliCommandsFactory(); - PicocliCommands commands = new PicocliCommands(CamelJBangMain.getCommandLine()); - commands.name("Camel"); + String homeDir = HomeHelper.resolveHomeDir(); + Path history = Paths.get(homeDir, ".camel-jbang-history"); - try (Terminal terminal = TerminalBuilder.builder().build()) { - Parser parser = new DefaultParser(); - SystemRegistry systemRegistry = new SystemRegistryImpl(parser, terminal, workDir, null); - systemRegistry.setCommandRegistries(builtins, commands); - systemRegistry.register("help", commands); + // Alias persistence: aliases are stored in ~/.camel-jbang-aliases + Path aliasFile = Paths.get(homeDir, ".camel-jbang-aliases"); + DefaultAliasManager aliasManager = new DefaultAliasManager(aliasFile); - String history = Paths.get(HomeHelper.resolveHomeDir(), ".camel-jbang-history").toString(); - LineReader reader = LineReaderBuilder.builder() - .terminal(terminal) - .completer(systemRegistry.completer()) - .parser(parser) - .highlighter(new ReplHighlighter()) - .variable(LineReader.LIST_MAX, 50) // max tab completion candidates - .variable(LineReader.HISTORY_FILE, history) - .variable(LineReader.OTHERS_GROUP_NAME, "Others") - .variable(LineReader.COMPLETION_STYLE_GROUP, "fg:blue,bold") - .variable("HELP_COLORS", "ti=1;34:co=38:ar=3:op=33:de=90") - .option(LineReader.Option.GROUP_PERSIST, true) - .build(); - builtins.setLineReader(reader); - factory.setTerminal(terminal); - TailTipWidgets widgets - = new TailTipWidgets(reader, systemRegistry::commandDescription, 5, TailTipWidgets.TipType.COMPLETER); - widgets.enable(); - KeyMap keyMap = reader.getKeyMaps().get("main"); - keyMap.bind(new Reference("tailtip-toggle"), KeyMap.alt("s")); - String prompt = "camel> "; - String rightPrompt = null; + // Init script: if ~/.camel-jbang-init exists, it will be executed on shell startup + Path initScript = Paths.get(homeDir, ".camel-jbang-init"); - // start the shell and process input until the user quits with Ctrl-C or Ctrl-D - String line; - boolean run = true; - TerminalBuilder.setTerminalOverride(terminal); - while (run) { - try { - systemRegistry.cleanUp(); - line = reader.readLine(prompt, rightPrompt, (MaskingCallback) null, null); - systemRegistry.execute(line); - } catch (UserInterruptException e) { - // ctrl + c is pressed so exit - run = false; - } catch (EndOfFileException e) { - // ctrl + d is pressed so exit - run = false; - } catch (Exception e) { - systemRegistry.trace(e); - } - } - } finally { - TerminalBuilder.setTerminalOverride(null); + org.jline.shell.ShellBuilder builder = org.jline.shell.Shell.builder() + .prompt("camel> ") + .groups(registry, new PosixCommandGroup(), new InteractiveCommandGroup()) + .historyFile(history) + .historyCommands(true) + .helpCommands(true) + .variableCommands(true) + .commandHighlighter(true) + .aliasManager(aliasManager) + // scriptCommands(true) requires a scriptRunner to be set; + // omitting for now until a DefaultScriptRunner is available + .variable(LineReader.LIST_MAX, 50) + .option(LineReader.Option.GROUP_PERSIST, true); + + if (Files.exists(initScript)) { + builder.initScript(initScript.toFile()); } - return 0; - } - private static class ReplHighlighter extends DefaultHighlighter { - @Override - protected void commandStyle(LineReader reader, AttributedStringBuilder sb, boolean enable) { - if (enable) { - if (reader.getTerminal().getNumericCapability(InfoCmp.Capability.max_colors) >= 256) { - sb.style(AttributedStyle.DEFAULT.bold().foreground(69)); - } else { - sb.style(AttributedStyle.DEFAULT.foreground(AttributedStyle.CYAN)); - } - } else { - sb.style(AttributedStyle.DEFAULT.boldOff().foregroundOff()); - } + try (org.jline.shell.Shell shell = builder.build()) { + shell.run(); } + return 0; } }