[
https://issues.apache.org/jira/browse/GROOVY-12403?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul King closed GROOVY-12403.
------------------------------
> Restore groovysh embedding extension points
> -------------------------------------------
>
> Key: GROOVY-12403
> URL: https://issues.apache.org/jira/browse/GROOVY-12403
> Project: Groovy
> Issue Type: Improvement
> Reporter: Daniel Sun
> Assignee: Daniel Sun
> Priority: Major
> Fix For: 7.0.0-alpha-1, 6.0.0-RC-3
>
>
> h3. Context
> The Gremlin Console (Apache TinkerPop) embeds groovysh. In Groovy 4, a host
> could install an {{ImportCustomizer}} and
> {{ASTTransformationCustomizer(ThreadInterrupt)}} on Groovysh's
> {{CompilerConfiguration}}, and extend the command set. The Groovy 5 rewrite
> onto JLine 3 (GROOVY-8162) removed those seams.
> Reported on the dev list:
> [https://lists.apache.org/thread/c66x4p4mhvmk7dojhddywzsgr4gpngs5]
> h3. What's missing
> # *Compiler configuration.* {{GroovyEngine}} builds the shell as {{new
> GroovyShell(classLoader, sharedData)}} with no configuration.
> {{CompilerConfiguration.DEFAULT}} is immutable, so there is no back door.
> Executing {{import}} statements works, but the engine records them as
> snippets and re-prepends them on every evaluation — expensive when the host
> preloads dozens of star / static-star imports.
> # *Embedding hooks on Main.* The Map overload of {{Main.start}} only takes
> binding variables. Terminal, registries, prompt, banner, result printing, and
> error handling are hardcoded. Hosts copy roughly 230 lines of {{Main}} and
> re-diff them against every Groovy release.
> # *ExtraConsoleCommands visibility.* {{/clear}}, {{/pwd}}, {{/cd}}, the
> POSIX-style commands, and {{/!}} live in a protected nested class. That
> compiles from another package in Groovy, but not from Java or under
> {{@CompileStatic}}.
> # *Class loader access.* The engine class loader field is protected. A getter
> avoids a subclass whose only job is to read it (Grape + {{ServiceLoader}}
> plugin install).
> h3. Direction
> Keep the binding map as bindings only. Do *not* add magic keys — they collide
> with user variables and are awkward from Java.
> * {{GroovyEngine(CompilerConfiguration)}} and a protected {{createShell}}
> override, so customizers apply at compile time instead of as snippets.
> * {{GroovyshOptions}} plus {{Main.start(GroovyshOptions, ...)}} for extra
> {{CommandRegistry}} instances, a prompt supplier, result and error handlers,
> a banner toggle, and an optional {{Terminal}}.
> * {{ExtraConsoleCommands}} as a public top-level class; keep
> {{Main.ExtraConsoleCommands}} as a deprecated subclass for existing Groovy
> callers.
> * {{GroovyEngine.getClassLoader()}}.
> Mark {{GroovyshOptions}} incubating so the shape can still settle after a
> first embedder uses it.
> h3. Example
> {code:groovy}
> def config = new CompilerConfiguration()
> config.addCompilationCustomizers(
> new ImportCustomizer().addStarImports('java.util.concurrent.atomic'),
> new ASTTransformationCustomizer(ThreadInterrupt))
> Main.start(GroovyshOptions.builder()
> .compilerConfiguration(config)
> .prompt { 'gremlin> ' }
> .showBanner(false)
> .build(), args)
> {code}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)