This is an automated email from the ASF dual-hosted git repository. paulk pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git
commit b9401c31eba5c7c7f18e34ca82dcd4cb51d7aade Author: Paul King <[email protected]> AuthorDate: Sun Aug 10 13:43:58 2025 +1000 GROOVY-8162: Update Groovysh to JLine3 (initial version of /ls, /tail, and /head) --- .../groovy/org/apache/groovy/groovysh/Main.groovy | 101 ++++++++++++++++++++- 1 file changed, 97 insertions(+), 4 deletions(-) diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Main.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Main.groovy index 66ba3dcfa3..12306156e9 100644 --- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Main.groovy +++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/Main.groovy @@ -28,8 +28,11 @@ import org.apache.groovy.groovysh.jline.GroovySystemRegistry import org.apache.groovy.groovysh.util.DocFinder import org.codehaus.groovy.tools.shell.util.MessageSource import org.jline.builtins.ClasspathResourceUtil +import org.jline.builtins.Completers import org.jline.builtins.ConfigurationPath import org.jline.builtins.Options +import org.jline.builtins.PosixCommands +import org.jline.builtins.PosixCommandsRegistry import org.jline.builtins.SyntaxHighlighter import org.jline.console.CommandInput import org.jline.console.CommandMethods @@ -41,6 +44,7 @@ import org.jline.console.impl.JlineCommandRegistry import org.jline.console.impl.SystemHighlighter import org.jline.keymap.KeyMap import org.jline.reader.Binding +import org.jline.reader.Completer import org.jline.reader.EndOfFileException import org.jline.reader.LineReader import org.jline.reader.LineReader.Option @@ -49,6 +53,8 @@ import org.jline.reader.Reference import org.jline.reader.UserInterruptException import org.jline.reader.impl.DefaultParser import org.jline.reader.impl.DefaultParser.Bracket +import org.jline.reader.impl.completer.ArgumentCompleter +import org.jline.reader.impl.completer.NullCompleter import org.jline.terminal.Size import org.jline.terminal.Terminal import org.jline.terminal.Terminal.Signal @@ -79,17 +85,37 @@ class Main { protected static class ExtraConsoleCommands extends JlineCommandRegistry implements CommandRegistry { private LineReader reader private final Supplier<Path> workDir + private final Map<String, Object> variables + private PosixCommandsRegistry posix - ExtraConsoleCommands(Supplier<Path> workDir) { + ExtraConsoleCommands(Supplier<Path> workDir, Map<String, Object> variables) { super() this.workDir = workDir + this.variables = variables registerCommands([ + '/tail' : new CommandMethods((Function) this::tail, this::optFileCompleter), + '/head' : new CommandMethods((Function) this::head, this::optFileCompleter), + '/ls' : new CommandMethods((Function) this::ls, this::optFileCompleter), '/clear': new CommandMethods((Function) this::clear, this::defaultCompleter), '/echo' : new CommandMethods((Function) this::echo, this::defaultCompleter), "/!" : new CommandMethods((Function) this::shell, this::defaultCompleter) ]) } + private void init() { + def terminal = reader.terminal + posix = new PosixCommandsRegistry( + terminal.input(), + new PrintStream(terminal.output()), + new PrintStream(terminal.output()), + workDir.get(), + terminal, + variables::get) + posix.register('/tail', PosixCommands::tail) + posix.register('/head', PosixCommands::head) + posix.register('/ls', PosixCommands::ls) + } + @Override String name() { 'Console Commands' @@ -100,7 +126,73 @@ class Main { } private Terminal terminal() { - return reader.terminal + return reader?.terminal + } + + private List<Completer> optFileCompleter(String command) { + [new ArgumentCompleter(NullCompleter.INSTANCE, new Completers.OptionCompleter(new Completers.FilesCompleter(workDir), this::commandOptions, 1))] + } + + private void tail(CommandInput input) { + def usage = new String[]{ + "/tail - display last lines of files", + "Usage: /tail [-f] [-q] [-c # | -n #] [file ...]", + " -? --help Show help", + " -f --follow Do not stop at end of file", + " -F --FOLLOW Follow and check for file renaming or rotation", + " -n --lines=LINES Number of lines to print", + " -c --bytes=BYTES Number of bytes to print", + } + try { + parseOptions(usage, input.args()) + posix.execute('/tail', input.args()) + } catch (Exception e) { + saveException(e) + } + } + + private void head(CommandInput input) { + def usage = new String[]{ + "/head - display first lines of files", + "Usage: /head [-n lines | -c bytes] [file ...]", + " -? --help Show help", + " -n --lines=LINES Print line counts", + " -c --bytes=BYTES Print byte counts" + } + try { + parseOptions(usage, input.args()) + posix.execute('/head', input.args()) + } catch (Exception e) { + saveException(e) + } + } + + private void ls(CommandInput input) { + def usage = new String[]{ + "/ls - list files", + "Usage: /ls [OPTIONS] [PATTERNS...]", + " -? --help show help", + " -1 list one entry per line", + " -C multi-column output", + " --color=WHEN colorize the output, may be `always', `never' or `auto'", + " -a list entries starting with .", + " -F append file type indicators", + " -m comma separated", + " -l long listing", + " -S sort by size", + " -f output is not sorted", + " -r reverse sort order", + " -t sort by modification time", + " -x sort horizontally", + " -L list referenced file for links", + " -h print sizes in human readable form" + } + try { + parseOptions(usage, input.args()) + posix.execute('/ls', input.args()) + } catch (Exception e) { + saveException(e) + } } private void clear(CommandInput input) { @@ -249,7 +341,7 @@ class Main { CommandRegistry builtins = new GroovyBuiltins(scriptEngine, workDir, configPath, (String fun) -> new ConsoleEngine.WidgetCreator(consoleEngine, fun) ) - def extra = new ExtraConsoleCommands(workDir) + def extra = new ExtraConsoleCommands(workDir, scriptEngine.variables) // Command line highlighter scriptEngine.put(GroovyEngine.NANORC_VALUE, rootURL.toString()) @@ -275,7 +367,7 @@ class Main { if (!OSUtils.IS_WINDOWS) { setSpecificHighlighter("/!", SyntaxHighlighter.build(jnanorc, "SH-REPL")) } - addFileHighlight('/nano', '/less', '/slurp', '/load', '/save') + addFileHighlight('/nano', '/less', '/slurp', '/load', '/save', '/head', '/tail', '/ls') addFileHighlight('/classloader', null, ['-a', '--add']) addExternalHighlighterRefresh(printer::refresh) addExternalHighlighterRefresh(scriptEngine::refresh) @@ -302,6 +394,7 @@ class Main { } [consoleEngine, builtins, extra]*.setLineReader(reader) + extra.init() // widgets and console initialization new TailTipWidgets(reader, systemRegistry::commandDescription, 5, TipType.COMPLETER)
