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 5f119fa76bc4a1e4d2142acaee9f33ec633d5991 Author: Paul King <[email protected]> AuthorDate: Wed Jul 23 11:19:34 2025 +1000 GROOVY-8162: Update Groovysh to JLine3 (support /slurp for CSV) --- subprojects/groovy-groovysh/build.gradle | 2 - .../groovy/groovysh/jline/GroovyCommands.groovy | 76 ++++++++++++---------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/subprojects/groovy-groovysh/build.gradle b/subprojects/groovy-groovysh/build.gradle index ece13ebdf7..8fd1ade60a 100644 --- a/subprojects/groovy-groovysh/build.gradle +++ b/subprojects/groovy-groovysh/build.gradle @@ -31,9 +31,7 @@ dependencies { implementation projects.groovyTemplates implementation projects.groovyXml implementation projects.groovyJson - implementation projects.groovyToml implementation projects.groovyNio - implementation projects.groovyYaml testImplementation projects.groovyTest implementation 'net.java.dev.jna:jna:5.17.0' implementation "org.jline:jansi:${versions.jline}" diff --git a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy index bea7f5ac7e..9677f2ba63 100644 --- a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy +++ b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyCommands.groovy @@ -20,10 +20,8 @@ package org.apache.groovy.groovysh.jline import groovy.console.ui.Console import groovy.console.ui.ObjectBrowser -import groovy.toml.TomlSlurper -import groovy.xml.XmlParser -import groovy.yaml.YamlSlurper import org.apache.groovy.groovysh.Main +import org.apache.groovy.groovysh.util.ClassUtils import org.jline.builtins.Completers import org.jline.builtins.Completers.OptDesc import org.jline.builtins.Completers.OptionCompleter @@ -80,32 +78,30 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry { private boolean consoleUi private boolean ivy private Supplier<Path> workDir + private static Map<String, String> slurpers = [ + 'YAML' : 'groovy.yaml.YamlSlurper', + 'XML' : 'groovy.xml.XmlParser', + 'TOML' : 'groovy.toml.TomlSlurper', + ] GroovyCommands(GroovyEngine engine, Supplier<Path> workDir, Printer printer, SyntaxHighlighter highlighter) { this.engine = engine this.printer = printer this.workDir = workDir this.highlighter = highlighter - try { - Class.forName('groovy.console.ui.ObjectBrowser') - consoleUi = true - } catch (Exception e) { - // ignore - } - try { - Class.forName('org.apache.ivy.util.Message') - System.setProperty('groovy.grape.report.downloads', 'false') - ivy = true - } catch (Exception e) { - // ignore - } + consoleUi = ClassUtils.lookFor('groovy.console.ui.ObjectBrowser') if (!consoleUi) { commands.remove('/console') } - if (!ivy) { + + ivy = ClassUtils.lookFor('org.apache.ivy.util.Message') + if (ivy) { + System.setProperty('groovy.grape.report.downloads', 'false') + } else { commands.remove('/grab') } + def available = commands.collectEntries { name, tuple -> [name, new CommandMethods((Function)tuple.v1, tuple.v2)] } @@ -258,7 +254,7 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry { encoding = Charset.forName(arg) } if (option in ['-f', '--format'] && arg) { - format = arg + format = arg.toUpperCase() } optionIndex = optionIdx(args, index) } @@ -281,6 +277,10 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry { format = 'GROOVY' } else if (ext.equalsIgnoreCase('toml')) { format = 'TOML' + } else if (ext.equalsIgnoreCase('properties')) { + format = 'PROPERTIES' + } else if (ext.equalsIgnoreCase('csv')) { + format = 'CSV' } else if (ext.equalsIgnoreCase('txt') || ext.equalsIgnoreCase('text')) { format = 'TEXT' } @@ -290,12 +290,20 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry { } else if (format in engine.deserializationFormats) { byte[] encoded = Files.readAllBytes(path) out = engine.deserialize(new String(encoded, encoding), format) - } else if (format == 'XML') { - out = new XmlParser().parse(path.toFile()) - } else if (format == 'TOML') { - out = new TomlSlurper().parse(path) - } else if (format == 'YAML') { - out = new YamlSlurper().parse(path) + } else if (format in slurpers.keySet()) { + def parser = getParser(format, slurpers[format]) + out = parser.parse(path) + } else if (format == 'CSV') { + def parserName = 'org.apache.commons.csv.CSVFormat' + if (!ClassUtils.lookFor(engine, parserName)) { + throw new IllegalArgumentException("$format format requires $parserName to be available") + } + def parser = engine.execute("${parserName}.DEFAULT.builder().setHeader().setSkipHeaderRecord(true).build()") + out = parser.parse(path.newReader(encoding.displayName())).toList() + } else if (format == 'PROPERTIES') { + out = path.withInputStream{ is -> + new Properties().tap {load(is) } + } } else { out = engine.deserialize(Files.readString(path, encoding), 'NONE') } @@ -304,25 +312,27 @@ class GroovyCommands extends JlineCommandRegistry implements CommandRegistry { out = arg.readLines() } else if (format in engine.deserializationFormats) { out = engine.deserialize(arg, format) - } else if (format == 'XML') { - out = new XmlParser().parseText(arg) - } else if (format == 'TOML') { - out = new TomlSlurper().parseText(arg) - } else if (format == 'YAML') { - out = new YamlSlurper().parseText(arg) + } else if (format in slurpers.keySet()) { + def parser = getParser(format, slurpers[format]) + out = parser.parseText(arg) } else { out = engine.deserialize(arg, 'NONE') } } } catch (Exception ignore) { - println ignore.message - ignore.printStackTrace() - out = engine.deserialize(arg, format) + throw ignore } engine.put("_", out) printer.println(out) } + Object getParser(String format, String parserName) { + if (!ClassUtils.lookFor(parserName)) { + throw new IllegalArgumentException("$format format requires $parserName to be available") + } + engine.execute("new ${parserName}()") + } + static void loadFile(GroovyEngine engine, File file, boolean merge = false) { if (!file) { throw new IllegalArgumentException('File not found: ' + file.path)
