On 2026/09/14 21:32:51 Paul King wrote:
> Hi Ken,
> 
> There were some slight tweaks to Daniel's original PR just to remove a
> couple of API parameters to deprecated classes. AI did a
> TinkerPop/Gremlin migration spike and thinks what is there is suitable
> for you. 6.0.0-RC-3 is out for voting, so the details for the
> distribution and temporary Maven repo URL are in that email if you
> want to try further.
> 
> Cheers, Paul.
> 
> On Tue, Sep 15, 2026 at 7:25 AM Ken Hu <[email protected]> wrote:
> >
> > Thanks for getting to this so quickly. I appreciate it very much. I had an 
> > agent take a quick look at the merged changes and it should cover 
> > everything we need. I'll do a quick test against the RC version when that's 
> > available on Maven Central, but based on static analysis it should be good. 
> > Thanks again.
> >
> > On Sat, Sep 12, 2026 at 7:01 PM Daniel Sun <[email protected]> wrote:
> >>
> >> Hi Ken,
> >>
> >> Thanks for the careful write-up. That matches what disappeared in
> >> the JLine 3 groovysh rewrite, and the four asks look reasonable
> >> to me.
> >>
> >> I'd rather not hang embedding hooks off the binding Map that
> >> Main.start already takes. Those keys would collide with user
> >> variables and are awkward from Java. A small GroovyshOptions type
> >> (incubating) plus Main.start(GroovyshOptions, String[]) keeps
> >> bindings as bindings.
> >>
> >> The rest maps fairly directly onto what you suggested:
> >>
> >>  1. GroovyEngine(CompilerConfiguration), and a protected
> >>     createShell(...) for subclasses. ImportCustomizer and
> >>     ThreadInterrupt then apply at compile time instead of being
> >>     re-prepended as snippets on every evaluation.
> >>
> >>  2. GroovyshOptions for extra CommandRegistry instances, a prompt
> >>     supplier, result/error handlers, a banner toggle, and an
> >>     optional Terminal.
> >>
> >>  3. ExtraConsoleCommands as a public top-level class. The nested
> >>     Main.ExtraConsoleCommands can remain as a deprecated subclass
> >>     so existing Groovy callers still compile.
> >>
> >>  4. GroovyEngine.getClassLoader().
> >>
> >> This is new public API, so I'm inclined to land it on the current 
> >> development
> >> line rather than a 5.1.x backport. Marking GroovyshOptions
> >> incubating leaves room to adjust once Gremlin Console is actually
> >> on it.
> >>
> >> I've started a candidate along these lines and will share a PR[1].
> >> Please do say if that would be enough for TinkerPop, or if I'm
> >> still missing a seam you need.
> >>
> >> [1] https://github.com/apache/groovy/pull/2927
> >>
> >> Cheers,
> >> Daniel Sun
> >>
> >>
> >> On 2026/09/11 21:17:57 Ken Hu wrote:
> >> > Hi all,
> >> >
> >> > I'm working on upgrading Apache TinkerPop from Groovy 4.0.32 to 5.1.2.
> >> > TinkerPop ships the Gremlin Console, the primary REPL for the Gremlin
> >> > language, and it is built by embedding groovysh. The Groovy 5 rewrite 
> >> > onto
> >> > JLine 3 removed the extension points we depended on. I'd like to discuss
> >> > what a supported embedding path could look like and whether the Groovy
> >> > community would accept this change for Groovy 5 or defer to Groovy 6.
> >> >
> >> > The Gremlin Console preloads the Gremlin DSL so users can type
> >> > "g.V().out()" directly. That is 63 imports: 40 package star imports and 
> >> > 23
> >> > "import static X.*". In Groovy 4 we installed them as an ImportCustomizer
> >> > on Groovysh's CompilerConfiguration, and we added an
> >> > ASTTransformationCustomizer(ThreadInterrupt) so ctrl+C can interrupt a
> >> > long-running query.
> >> >
> >> > In 5.1.2, GroovyEngine creates its shell as
> >> >
> >> >     new GroovyShell(classLoader, sharedData)
> >> >
> >> > at GroovyEngine.java:171, with no configuration parameter, and the shell
> >> > field is private final. CompilerConfiguration.DEFAULT is immutable in 5, 
> >> > so
> >> > there is no indirect route either.
> >> >
> >> > The only supported alternative is executing import statements, which
> >> > GroovyEngine records as snippets and textually re-prepends to every
> >> > evaluation but as we've talked about previously on this list, this can
> >> > lead to a substantial performance loss.
> >> >
> >> > ------------------------------
> >> >
> >> > Main.start(Map<String,?>, String...) accepts only binding variables, and
> >> > the body hardcodes the terminal, parser, engine, registries, prompt, 
> >> > banner
> >> > and REPL loop. We need to register our own commands, render results our 
> >> > own
> >> > way (Gremlin auto-iterates result sets with a user-configurable cap), and
> >> > control the prompt and error rendering. Today that means copying roughly
> >> > 230 lines of Main into TinkerPop and re-diffing it against every Groovy
> >> > release.
> >> >
> >> > Since start already takes a Map, the smallest version of this could be a
> >> > few recognized keys: extra CommandRegistry instances, a prompt supplier, 
> >> > a
> >> > result handler, an error handler, a banner toggle.
> >> >
> >> > ------------------------------
> >> >
> >> > Main.ExtraConsoleCommands provides /clear /pwd /cd /ls /cat /grep /head
> >> > /tail /wc /sort /date /echo and /!. It is protected static nested in 
> >> > Main.
> >> > It currently compiles from another package only because Groovy does not
> >> > enforce protected access at compile time, which would not hold from Java 
> >> > or
> >> > under CompileStatic. Anyone embedding the REPL has to copy it.
> >> >
> >> > ------------------------------
> >> >
> >> > Our :install command uses Grape plus ServiceLoader against the shell's
> >> > classloader so freshly downloaded plugins load without a restart. The
> >> > classLoader field is protected, so subclassing works today. A getter 
> >> > would
> >> > just avoid requiring a subclass in order to read one field.
> >> >
> >> > To recap, I have several asks:
> >> > Ask 1: add GroovyEngine(CompilerConfiguration), or a protected 
> >> > GroovyShell
> >> > createShell(ClassLoader, Binding) seam that a subclass can override.
> >> > Ask 2: embedding hooks on Main
> >> > Ask 3: make Main.ExtraConsoleCommands a public top-level class
> >> > Ask 4: a public accessor for the engine's classloader (minor)
> >> >
> >> > Please let me know if I'm going about this the wrong way and there are
> >> > actually already extension points that I should be using instead.
> >> >
> >> > Thanks,
> >> > Ken
> >> >


> Are there any plans to backport and support Groovy 5.x?

The Grace framework uses groovysh and has made a lot of custom extensions. 
https://github.com/graceframework/grace-framework/blob/2024.2.x/grace-console/src/main/groovy/grails/ui/shell/GrailsShell.groovy

Reply via email to