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

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


The following commit(s) were added to refs/heads/master by this push:
     new a628cf6918 GROOVY-12002: add MarkdownSlurper support to groovysh
a628cf6918 is described below

commit a628cf6918863e484da57e55e62cf52d9e8e9eeb
Author: Paul King <[email protected]>
AuthorDate: Sat May 9 11:39:17 2026 +1000

    GROOVY-12002: add MarkdownSlurper support to groovysh
---
 subprojects/groovy-groovysh/build.gradle           |  1 +
 .../groovy/groovysh/jline/GroovyCommands.groovy    | 11 ++++-
 .../src/main/resources/nanorc/markdown.nanorc      | 56 ++++++++++++++++++++++
 .../groovy-groovysh/src/spec/doc/groovysh.adoc     |  5 +-
 .../groovy/groovysh/commands/SlurpTest.groovy      | 20 ++++++++
 5 files changed, 91 insertions(+), 2 deletions(-)

diff --git a/subprojects/groovy-groovysh/build.gradle 
b/subprojects/groovy-groovysh/build.gradle
index 9469ea0a60..fa0e7b06fc 100644
--- a/subprojects/groovy-groovysh/build.gradle
+++ b/subprojects/groovy-groovysh/build.gradle
@@ -35,6 +35,7 @@ dependencies {
     implementation projects.groovyNio
     testImplementation projects.groovyTest
     testImplementation projects.groovyCsv         // for /slurp .csv default 
coverage
+    testImplementation projects.groovyMarkdown    // for /slurp .md default 
coverage
     testImplementation projects.groovyTestJunit6  // for @ForkedJvm in CSV 
fallback tests
     implementation "net.java.dev.jna:jna:${versions.jna}"
     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 7030a7685e..2a9e633089 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
@@ -87,6 +87,7 @@ class GroovyCommands extends JlineCommandRegistry implements 
CommandRegistry {
         'YAML'     : 'groovy.yaml.YamlSlurper',
         'XML'      : 'groovy.xml.XmlParser',
         'TOML'     : 'groovy.toml.TomlSlurper',
+        'MARKDOWN' : 'groovy.markdown.MarkdownSlurper',
     ]
 
     /**
@@ -463,6 +464,8 @@ class GroovyCommands extends JlineCommandRegistry 
implements CommandRegistry {
                         format = 'PROPERTIES'
                     } else if (ext.equalsIgnoreCase('csv')) {
                         format = 'CSV'
+                    } else if (ext.equalsIgnoreCase('md') || 
ext.equalsIgnoreCase('markdown')) {
+                        format = 'MARKDOWN'
                     } else if (ext.equalsIgnoreCase('txt') || 
ext.equalsIgnoreCase('text')) {
                         format = 'TEXT'
                     }
@@ -947,7 +950,13 @@ class GroovyCommands extends JlineCommandRegistry 
implements CommandRegistry {
     private List<Completer> slurpCompleter(String command) {
         for (OptDesc o in compileOptDescs(command)) {
             if (o.shortOption()?.equals('-f')) {
-                o.valueCompleter = new StringsCompleter('JSON', 'GROOVY', 
'NONE', 'TEXT', 'YAML', 'TOML', 'XML')
+                // Keep completion in sync with the formats /slurp actually
+                // accepts: parser-style ones come from `slurpers`; the rest
+                // are handled directly in slurpcmd's extension branches.
+                // Deriving from `slurpers.keySet()` prevents new entries
+                // (e.g. MARKDOWN, TOML) from drifting out of the completer.
+                def formats = (['CSV', 'GROOVY', 'JSON', 'NONE', 'PROPERTIES', 
'TEXT'] + slurpers.keySet()).toSet().sort()
+                o.valueCompleter = new StringsCompleter(formats)
                 break
             }
         }
diff --git 
a/subprojects/groovy-groovysh/src/main/resources/nanorc/markdown.nanorc 
b/subprojects/groovy-groovysh/src/main/resources/nanorc/markdown.nanorc
new file mode 100644
index 0000000000..7e87c94333
--- /dev/null
+++ b/subprojects/groovy-groovysh/src/main/resources/nanorc/markdown.nanorc
@@ -0,0 +1,56 @@
+# 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.
+
+syntax "Markdown" "\.(md|markdown)$"
+
+# Blockquotes
+COMMENT:    "^>.*$"
+
+# Lists: -, *, + (unordered); 1. 2. ... (ordered)
+OPERATOR:   "^[[:space:]]*[\*\+\-][[:space:]]"  
"^[[:space:]]*[0-9]+\.[[:space:]]"
+
+# Horizontal rules: --- *** ___ (with optional spaces)
+SECTION:    "^[[:space:]]*([\*\-_][[:space:]]?){3,}[[:space:]]*$"
+
+# Setext-style heading underlines (=== or --- on their own line)
+SECTION:    "^[=\-]+[[:space:]]*$"
+
+# ATX headings: # H1 through ###### H6
+TITLE:      "^#{1,6}[[:space:]].*$"
+
+# Emphasis (italic): *text* or _text_
+VARIABLE:   "(\*[^*]+\*)"  "(_[^_]+_)"
+
+# Strong emphasis (bold): **text** or __text__ (overrides italic on overlap)
+KEYWORD:    "(\*\*[^*]+\*\*)"  "(__[^_]+__)"
+
+# Strike-through: ~~text~~
+WARNING:    "~~[^~]+~~"
+
+# Inline code: `code`
+STRING:     "`[^`]+`"
+
+# Links: [text](url)
+LINK:       "\[[^\]]+\]\([^)]+\)"
+# Images: ![alt](url)
+LINK:       "!\[[^\]]*\]\([^)]+\)"
+# Bare URLs
+LINK:       "\<https?://[^[:space:])>]+"
+
+# GFM tables (lines bracketed by |)
+ATTRIBUTE:  "^[[:space:]]*\|.*\|[[:space:]]*$"
+
+# Fenced code blocks (triple backticks)
+$BLOCK_COMMENT: "```, ```"
diff --git a/subprojects/groovy-groovysh/src/spec/doc/groovysh.adoc 
b/subprojects/groovy-groovysh/src/spec/doc/groovysh.adoc
index e53a5522c4..6b0bb47621 100644
--- a/subprojects/groovy-groovysh/src/spec/doc/groovysh.adoc
+++ b/subprojects/groovy-groovysh/src/spec/doc/groovysh.adoc
@@ -1043,7 +1043,7 @@ image:{reldir_groovysh}/assets/img/repl_show.png[Usage of 
the /show command, wid
 Slurp files to shared variables. Groovy has a bunch of slurpers for
 various formats like XML, JSON, YAML, etc. You can use those in your code
 if you like, but the `/slurp` command can be a convenience shortcut.
-It supports most of the common formats, including JSON, XML, YAML, CSV, TOML 
and property files.
+It supports most of the common formats, including JSON, XML, YAML, CSV, TOML, 
Markdown and property files.
 
 image:{reldir_groovysh}/assets/img/repl_slurp.png[Usage of the /slurp command, 
width=80%]
 
@@ -1070,6 +1070,9 @@ detail which may change in the future, the current 
behavior is as follows:
 | PROPERTIES | Returns a Properties file, which is a Map-like object.
 | CSV | Uses Apache Commons CSV if on the classpath. Assumes a header row 
which is used to
 create a list (the rows) of maps from column name to value.
+| MARKDOWN | Uses MarkdownSlurper from `groovy-markdown` if on the classpath. 
Returns a
+`MarkdownDocument` (an `Iterable<Map<String, Object>>` of structured 
elements). Triggered
+by `.md` and `.markdown` extensions.
 | TEXT | Reads the file as raw lines (or argument as a line).
 | NONE | If you want the raw text rather than parsed content.
 |===
diff --git 
a/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/commands/SlurpTest.groovy
 
b/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/commands/SlurpTest.groovy
index 27f0f89a6a..2d29dbcc1a 100644
--- 
a/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/commands/SlurpTest.groovy
+++ 
b/subprojects/groovy-groovysh/src/test/groovy/org/apache/groovy/groovysh/commands/SlurpTest.groovy
@@ -58,6 +58,26 @@ class SlurpTest extends SystemTestSupport {
         assert value.version == '4.x'
     }
 
+    @Test
+    void slurpMarkdownProducesIterableOfElements() {
+        // Requires groovy.markdown.MarkdownSlurper; supplied via the
+        // testImplementation projects.groovyMarkdown dependency.
+        Path file = Files.writeString(tmp.resolve('notes.md'),
+                "# Title\n\nA paragraph.\n\n- item one\n- item two\n")
+        system.execute("doc = /slurp ${forwardSlashes(file)}")
+        def doc = console.getVariable('doc')
+        assert doc != null
+        // MarkdownDocument is Iterable<Map<String,Object>>; toList lets us
+        // assert without pinning to the exact element-type names (those
+        // belong to groovy-markdown's API and may evolve).
+        def elements = doc.toList()
+        assert elements.size() >= 2
+        def joined = elements.collect { it.values().toString() }.join(' ')
+        assert joined.contains('Title')
+        assert joined.contains('A paragraph.')
+        assert joined.contains('item one')
+    }
+
     @Test
     void slurpCsvProducesListOfMaps() {
         // Requires groovy.csv.CsvSlurper on the classpath; supplied here via

Reply via email to