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

paulk pushed a commit to branch GROOVY_5_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit b456c608a789790974e554c451692a6a6e28b233
Author: Paul King <[email protected]>
AuthorDate: Thu Oct 23 12:10:46 2025 +1000

    GROOVY-11791: Support unquoted URLs in groovysh
---
 .../groovy/org/apache/groovy/groovysh/Main.groovy  |  3 ++-
 .../groovy/groovysh/jline/GroovyCommands.groovy    | 25 +++++++++++++---------
 .../apache/groovy/groovysh/jline/GroovyEngine.java |  3 ++-
 .../src/main/resources/nanorc/groovy.nanorc        |  5 +++--
 4 files changed, 22 insertions(+), 14 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 cca9464657..1aa8308cc2 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
@@ -471,8 +471,9 @@ class Main {
                     line = line.readLines().collect{ s ->
                         // remove Groovy continuation character for repl not 
Groovy's sake
                         s.endsWith(' \\') ? s[0..-3] : s
-                    }.join('\n')
+                    }.join('\n').replaceAll($/(/[a-z]+\s+)(https?://\S+)/$, 
'$1"$2"') // quote URLs after commands
                     if (line.startsWith(':')) {
+                        // some simple legacy support for ':' commands
                         def maybeCmd = line.split()[0].replaceFirst(':', '/')
                         if (systemRegistry.hasCommand(maybeCmd) || 
systemRegistry.isCommandAlias(maybeCmd)) {
                             line = line.replaceFirst(':', '/')
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 75929369e0..d5e6693c70 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
@@ -376,7 +376,9 @@ class GroovyCommands extends JlineCommandRegistry 
implements CommandRegistry {
             try {
                 path = workDir.get().resolve(arg)
             } catch(Exception ignore) { }
+            Reader source = null
             if (path && Files.exists(path)) {
+                source = Files.newBufferedReader(path, encoding)
                 if (!format) {
                     def ext = path.extension
                     if (ext.equalsIgnoreCase('json')) {
@@ -397,23 +399,26 @@ class GroovyCommands extends JlineCommandRegistry 
implements CommandRegistry {
                         format = 'TEXT'
                     }
                 }
+            }
+            if (!source && (arg.startsWith('http://') || 
arg.startsWith('https://'))) {
+                URL url = new URL(arg)
+                source = new InputStreamReader(url.openStream(), encoding)
+            }
+            if (source) {
                 if (format == 'TEXT') {
-                    out = Files.readAllLines(path, encoding)
+                    out = source.readLines()
                 } else if (format in engine.deserializationFormats) {
-                    byte[] encoded = Files.readAllBytes(path)
-                    out = engine.deserialize(new String(encoded, encoding), 
format)
+                    out = engine.deserialize(source.text, format)
                 } else if (format in slurpers.keySet()) {
                     def parser = getParser(format, slurpers[format])
-                    out = parser.parse(path)
+                    out = parser.parse(source)
                 } else if (format == 'CSV') {
                     def parser = getCsvParser(format)
-                    out = 
parser.parse(path.newReader(encoding.displayName())).toList()*.toMap()
+                    out = parser.parse(source).toList()*.toMap()
                 } else if (format == 'PROPERTIES') {
-                    out = path.withInputStream{ is ->
-                        new Properties().tap {load(is) }
-                    }
+                    out = new Properties().tap {load(source) }
                 } else {
-                    out = engine.deserialize(Files.readString(path, encoding), 
'NONE')
+                    out = engine.deserialize(source.text, 'AUTO')
                 }
             } else {
                 if (format == 'TEXT') {
@@ -427,7 +432,7 @@ class GroovyCommands extends JlineCommandRegistry 
implements CommandRegistry {
                     def parser = getCsvParser(format)
                     out = parser.parse(new StringReader(arg)).toList()*.toMap()
                 } else {
-                    out = engine.deserialize(arg, 'NONE')
+                    out = engine.deserialize(arg, 'AUTO')
                 }
             }
         } catch (Exception ignore) {
diff --git 
a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyEngine.java
 
b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyEngine.java
index 3117c22744..aecfa63e9d 100644
--- 
a/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyEngine.java
+++ 
b/subprojects/groovy-groovysh/src/main/groovy/org/apache/groovy/groovysh/jline/GroovyEngine.java
@@ -90,7 +90,8 @@ public class GroovyEngine implements ScriptEngine {
     public enum Format {
         JSON,
         GROOVY,
-        NONE
+        NONE,
+        AUTO
     }
 
     public static final String CANONICAL_NAMES = "canonicalNames";
diff --git 
a/subprojects/groovy-groovysh/src/main/resources/nanorc/groovy.nanorc 
b/subprojects/groovy-groovysh/src/main/resources/nanorc/groovy.nanorc
index c4d570877e..557f54cb3f 100644
--- a/subprojects/groovy-groovysh/src/main/resources/nanorc/groovy.nanorc
+++ b/subprojects/groovy-groovysh/src/main/resources/nanorc/groovy.nanorc
@@ -19,7 +19,8 @@ TYPE:        
"\<(boolean|byte|char|def|double|float|int|it|long|new|short|this|t
 KEYWORD:     
"\<(case|catch|default|do|else|finally|for|if|return|switch|throw|try|while)\>"
 KEYWORD:     
"\<(abstract|class|extends|final|implements|import|instanceof|interface|native|non-sealed|package)\>"
 KEYWORD:     
"\<(permits|private|protected|public|record|sealed|static|strictfp|super|synchronized|throws|trait|volatile)\>"
-PACKAGE:     "(([a-z0-9]{2,}[.]{1}){2,10}([a-z0-9]{2,}){0,1})"
+PATH:        "\<https?://\S*\>"
+PACKAGE:     "(?<!://\w{0,99})(([a-z0-9]{2,}[.]{1}){2,10}([a-z0-9]{2,}){0,1})"
 
 CLASS:       "\<[A-Z]{0,2}([A-Z]{1}[a-z0-9]+){1,}\>"
 # Annotation
@@ -37,7 +38,7 @@ OPERATOR:    "[-+/*=<>?:!~%&|]"
 ~NUMBER:     "\b-?(([1-9][0-9_]*)|0)\.[0-9_e]+[dfg]?\b" 
"\b-?([1-9][0-9_]*)?[0-9][ilg]?\b" "\b0[0-7_]*[ilg]?\b" 
"\b0x([1-9a-f][0-9a-f_]*)?[0-9a-f][lg]?\b" "\b0b([01][01_]*)?[01]\b"
 #STRING:      "['][^']*[^\\][']" "[']{3}.*[^\\][']{3}"
 $BALANCED_DELIMITERS:  """", ''', ', ""
-$LINE_COMMENT:         "//"
+$LINE_COMMENT:         "(?<!:)//"
 $BLOCK_COMMENT:        "/*, */"
 REGEXP:      "~/[^/]*/"
 

Reply via email to