Remembering imports between script invocations

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Remembering imports between script invocations

David Ekholm
We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?

Regards
/David, jAlbum founder and client lead developer.
Reply | Threaded
Open this post in threaded view
|

RE: Remembering imports between script invocations

eric.milles

You can add all the imports you want to your compiler configuration and they will be consistently available for all scripts.

 

From: David Ekholm [mailto:[hidden email]]
Sent: Thursday, February 08, 2018 2:12 PM
To: [hidden email]
Subject: Remembering imports between script invocations

 

We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?

 

Regards

/David, jAlbum founder and client lead developer.

Reply | Threaded
Open this post in threaded view
|

Re: Remembering imports between script invocations

David Ekholm
How do I do that via the javax.script API?

Even if this is possible via the javax.script API, chances are that a user wishes to ad-hoc add another import, but as they are forgotten between script invocations, it makes it hard to use Groovy to interactively create, say a Swing or JavaFX UI one line at a time. With BeanShell, the user can add the needed imports, execute that "script" and then continue to refer to the imported classes in the following script invocations. Making Groovy remember imports would make it behave in as nice fashion as the new JShell tool in Java 9. JShell unfortunately cannot run embedded via the javax.script API :-(

Regards
/David

On 8 Feb 2018, at 21:34, [hidden email] wrote:

You can add all the imports you want to your compiler configuration and they will be consistently available for all scripts.
 
From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:12 PM
To: [hidden email]
Subject: Remembering imports between script invocations 
 
We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?
 
Regards
/David, jAlbum founder and client lead developer.

Reply | Threaded
Open this post in threaded view
|

RE: Remembering imports between script invocations

eric.milles

Sounds more like the Groovy Shell or Groovy Console.  Not too sure myself how the javax.script stuff is tied in.

 

From: David Ekholm [mailto:[hidden email]]
Sent: Thursday, February 08, 2018 2:47 PM
To: [hidden email]
Subject: Re: Remembering imports between script invocations

 

How do I do that via the javax.script API?

 

Even if this is possible via the javax.script API, chances are that a user wishes to ad-hoc add another import, but as they are forgotten between script invocations, it makes it hard to use Groovy to interactively create, say a Swing or JavaFX UI one line at a time. With BeanShell, the user can add the needed imports, execute that "script" and then continue to refer to the imported classes in the following script invocations. Making Groovy remember imports would make it behave in as nice fashion as the new JShell tool in Java 9. JShell unfortunately cannot run embedded via the javax.script API :-(

 

Regards

/David

 

On 8 Feb 2018, at 21:34, [hidden email] wrote:

 

You can add all the imports you want to your compiler configuration and they will be consistently available for all scripts.

 

From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:12 PM
To: [hidden email]
Subject: Remembering imports between script invocations 

 

We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?

 

Regards

/David, jAlbum founder and client lead developer.

 

Reply | Threaded
Open this post in threaded view
|

Re: Remembering imports between script invocations

David Ekholm
Who can I contact?

Regards
/David

On 8 Feb 2018, at 23:25, <[hidden email]> <[hidden email]> wrote:

Sounds more like the Groovy Shell or Groovy Console.  Not too sure myself how the javax.script stuff is tied in.
 
From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:47 PM
To: [hidden email]
Subject: Re: Remembering imports between script invocations
 
How do I do that via the javax.script API?
 
Even if this is possible via the javax.script API, chances are that a user wishes to ad-hoc add another import, but as they are forgotten between script invocations, it makes it hard to use Groovy to interactively create, say a Swing or JavaFX UI one line at a time. With BeanShell, the user can add the needed imports, execute that "script" and then continue to refer to the imported classes in the following script invocations. Making Groovy remember imports would make it behave in as nice fashion as the new JShell tool in Java 9. JShell unfortunately cannot run embedded via the javax.script API :-(
 
Regards
/David
 
On 8 Feb 2018, at 21:34, [hidden email] wrote:
 
You can add all the imports you want to your compiler configuration and they will be consistently available for all scripts.
 
From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:12 PM
To: [hidden email]
Subject: Remembering imports between script invocations 
 
We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?
 
Regards
/David, jAlbum founder and client lead developer.

Reply | Threaded
Open this post in threaded view
|

Re: Remembering imports between script invocations

Jorge Aguilera Gonzalez
I'm not sure if it's what you want but you can use "evaluate" to include one script into another (see http://gangmax.me/blog/2015/10/15/include-a-groovy-script-in-another/) althought I think is a little dirty

To generate UI maybe you can evaluate MarkupTemplateEngine (http://groovy-lang.org/templating.html#_the_markuptemplateengine

Regards


El 9 feb. 2018 17:06, "David Ekholm" <[hidden email]> escribió:
Who can I contact?

Regards
/David

On 8 Feb 2018, at 23:25, <[hidden email]> <[hidden email]> wrote:

Sounds more like the Groovy Shell or Groovy Console.  Not too sure myself how the javax.script stuff is tied in.
 
From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:47 PM
To: [hidden email]
Subject: Re: Remembering imports between script invocations
 
How do I do that via the javax.script API?
 
Even if this is possible via the javax.script API, chances are that a user wishes to ad-hoc add another import, but as they are forgotten between script invocations, it makes it hard to use Groovy to interactively create, say a Swing or JavaFX UI one line at a time. With BeanShell, the user can add the needed imports, execute that "script" and then continue to refer to the imported classes in the following script invocations. Making Groovy remember imports would make it behave in as nice fashion as the new JShell tool in Java 9. JShell unfortunately cannot run embedded via the javax.script API :-(
 
Regards
/David
 
On 8 Feb 2018, at 21:34, [hidden email] wrote:
 
You can add all the imports you want to your compiler configuration and they will be consistently available for all scripts.
 
From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:12 PM
To: [hidden email]
Subject: Remembering imports between script invocations 
 
We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?
 
Regards
/David, jAlbum founder and client lead developer.


Reply | Threaded
Open this post in threaded view
|

Re: Remembering imports between script invocations

Keith Suderman
In reply to this post by David Ekholm
Import statements are really just shortcuts to tell the compiler how to resolve class names so there is nothing to "remember" between invocations, that is, nothing gets added to the Binding.

I am not familiar with the javax.script API, but I suspect that you will have to provide your own ScriptEngine implementation as you will need to modify the CompilerConfiguration object the GroovyShell is using to compile the Groovy code.  For example:

        CompilerConfiguration configuration = new CompilerConfiguration()
        GroovyShell compiler = new GroovyShell(configuration)
        println compiler.evaluate('json=\'{"foo":"bar"}\'')
        println compiler.evaluate("groovy.json.JsonOutput.prettyPrint(json)")

        /* Fails: MissingPropertyException */
        /* println compiler.evaluate("JsonOutput.prettyPrint(json)") */

        ImportCustomizer imports = new ImportCustomizer()
        imports.addStarImports("groovy.json")
        configuration.addCompilationCustomizers(imports)
// Works, the compiler can now resolve groovy.json.JsonOutput
        println compiler.evaluate("JsonOutput.prettyPrint(json)")

The difficult part will be "hooking" into the compiler to know when an import statement is used so you can update your CompilerConfiguration object.  I am sure the really clever programmers here could come up with some sort of AST transform that would do this.  However, depending on what you are allowed to do one option would be to tell your users that you have a "Groovy DSL" and then implement an "include" method that users would use to "import" Java packages.

        println eval('json=\'{"foo":"bar"}\'')
        println eval('include "groovy.json"')
        println eval('JsonOutput.prettyPrint(json)')


    Object eval(String code) {
        Script script = compiler.parse(code)
        ExpandoMetaClass metaClass = new ExpandoMetaClass(script.class, false)
        metaClass.include = { String name ->
            ImportCustomizer includes = new ImportCustomizer()
            includes.addStarImports(name)
            configuration.addCompilationCustomizers(includes)
            "Imported $name"
        }
        metaClass.initialize()
        script.metaClass = metaClass
        script.run()
    }

Hopefully that gives you some ideas.

Cheers,
Keith

On Feb 8, 2018, at 3:47 PM, David Ekholm <[hidden email]> wrote:

How do I do that via the javax.script API?

Even if this is possible via the javax.script API, chances are that a user wishes to ad-hoc add another import, but as they are forgotten between script invocations, it makes it hard to use Groovy to interactively create, say a Swing or JavaFX UI one line at a time. With BeanShell, the user can add the needed imports, execute that "script" and then continue to refer to the imported classes in the following script invocations. Making Groovy remember imports would make it behave in as nice fashion as the new JShell tool in Java 9. JShell unfortunately cannot run embedded via the javax.script API :-(

Regards
/David

On 8 Feb 2018, at 21:34, [hidden email] wrote:

You can add all the imports you want to your compiler configuration and they will be consistently available for all scripts.
 
From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:12 PM
To: [hidden email]
Subject: Remembering imports between script invocations 
 
We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?
 
Regards
/David, jAlbum founder and client lead developer.


----------------------
Keith Suderman
Research Associate
Department of Computer Science
Vassar College, Poughkeepsie NY




Reply | Threaded
Open this post in threaded view
|

Re: Remembering imports between script invocations

David Ekholm
Thanks for your suggestions Keith, but this approch doesn't feel very straight forward. What I really like to, is to be able to forward these "sticky imports between script invocations" as a feature suggestion. This makes Groovy even more suitable as a language for quick embedded mock-ups. Who in the dev team can comment on this?

Regards
/David

On 10 Feb 2018, at 21:25, Keith Suderman <[hidden email]> wrote:

Import statements are really just shortcuts to tell the compiler how to resolve class names so there is nothing to "remember" between invocations, that is, nothing gets added to the Binding.

I am not familiar with the javax.script API, but I suspect that you will have to provide your own ScriptEngine implementation as you will need to modify the CompilerConfiguration object the GroovyShell is using to compile the Groovy code.  For example:

        CompilerConfiguration configuration = new CompilerConfiguration()
        GroovyShell compiler = new GroovyShell(configuration)
        println compiler.evaluate('json=\'{"foo":"bar"}\'')
        println compiler.evaluate("groovy.json.JsonOutput.prettyPrint(json)")

        /* Fails: MissingPropertyException */
        /* println compiler.evaluate("JsonOutput.prettyPrint(json)") */

        ImportCustomizer imports = new ImportCustomizer()
        imports.addStarImports("groovy.json")
        configuration.addCompilationCustomizers(imports)
// Works, the compiler can now resolve groovy.json.JsonOutput
        println compiler.evaluate("JsonOutput.prettyPrint(json)")

The difficult part will be "hooking" into the compiler to know when an import statement is used so you can update your CompilerConfiguration object.  I am sure the really clever programmers here could come up with some sort of AST transform that would do this.  However, depending on what you are allowed to do one option would be to tell your users that you have a "Groovy DSL" and then implement an "include" method that users would use to "import" Java packages.

        println eval('json=\'{"foo":"bar"}\'')
        println eval('include "groovy.json"')
        println eval('JsonOutput.prettyPrint(json)')

    Object eval(String code) {
        Script script = compiler.parse(code)
        ExpandoMetaClass metaClass = new ExpandoMetaClass(script.class, false)
        metaClass.include = { String name ->
            ImportCustomizer includes = new ImportCustomizer()
            includes.addStarImports(name)
            configuration.addCompilationCustomizers(includes)
            "Imported $name"
        }
        metaClass.initialize()
        script.metaClass = metaClass
        script.run()
    }

Hopefully that gives you some ideas.

Cheers,
Keith

On Feb 8, 2018, at 3:47 PM, David Ekholm <[hidden email]> wrote:

How do I do that via the javax.script API?

Even if this is possible via the javax.script API, chances are that a user wishes to ad-hoc add another import, but as they are forgotten between script invocations, it makes it hard to use Groovy to interactively create, say a Swing or JavaFX UI one line at a time. With BeanShell, the user can add the needed imports, execute that "script" and then continue to refer to the imported classes in the following script invocations. Making Groovy remember imports would make it behave in as nice fashion as the new JShell tool in Java 9. JShell unfortunately cannot run embedded via the javax.script API :-(

Regards
/David

On 8 Feb 2018, at 21:34, [hidden email] wrote:

You can add all the imports you want to your compiler configuration and they will be consistently available for all scripts.
 
From: David Ekholm [[hidden email]] 
Sent: Thursday, February 08, 2018 2:12 PM
To: [hidden email]
Subject: Remembering imports between script invocations 
 
We're considering supporting Groovy as an additional scripting language to our web gallery software jAlbum (http://jalbum.net), but one aspect bugs me: It doesn't seem like import statements are remembered between script invocations. This makes it far harder to use Groovy to prototype UIs within jAlbum's scripting console than for instance BeanShell (using the javax.script API). We currently support the slow BeanShell scripting language and JavaScript. BeanShell behaves well in this regard, remembering earlier imported packages between script invocations. Can this be added to Groovy or is there some API flag we can set?
 
Regards
/David, jAlbum founder and client lead developer.


----------------------
Keith Suderman
Research Associate
Department of Computer Science
Vassar College, Poughkeepsie NY