[ANN] Ideascript 2.0

A while ago I wrote a scripting engine for Idea based on XML with a syntax and style similar to how Ant works. Most of the complaints at the time stemmed from the fact that we are all Java programmers and thus would like to write the scripts in Java.

To a large extent I agree, but the problem with a pure-java approach is similar to a pure-java approach for generating web pages -- i.e. writing a lot of writer.println() to output html is awkward and ugly. One of the solutions in the servlet world is JSPs. The model with JSPs is to mix plain text (the html) with java code.

This new version of Ideascript now leverages JSPs instead of XML. The scripts you write are actual JSP files that are recognized by Idea thus you have access to the extensive support for JSPs provided by Idea to help you write your scripts.

For many tasks your JSP scripts might only have Java code, in which case you can do whatever you like interacting directly with Idea's Open API and some helper classes provided by Ideascript to make certain Open API tasks more convenient. However, many of your scripts might be template driven. For example, often when you must integrate a new feature into a system it will require creating several classes and supporting classes. You would probably want to stub out each class, likely implementing some interfaces here and there. Ideascript provides some custom JSP tags that you can use for this sort of purpose. For this example, there is a tag called "is:class". The body of the tag can be your templated class. i.e.

<is:class>
public class MyClass {
}
</is:class>

Because this is JSP, it is very easy to parameterize parts of the template like the class name with standard JSP syntax:

<% String className = {obtain class name from user} %>

<is:class>
public class <%= className %> {
}
</is:class>

I'm in the process of writing more documentation, but for now, you can read more about it and some tutorials at http://www.casalus.com/ideascript. You can download it from Idea's plugin manager under "Ideascript". For now, I've only tested it with Pallada 4.5.4. If there is interest I can make it available on other versions.

I'm interested in any feedback like bug reports and enhancement requests. I think the plugin development community in particular might find value in Ideascript since it allows you to test methods and try things out in Idea's Open API by the means of a script you can constantly tweak rather than a plugin you must continually re-deploy.

0
5 comments
Avatar
Stig Kleppe-Jorgensen

This sounds great! I wish I had some more time playing with the Open API...

As we now have the language API, there will hopefully be made plugins for the different script languages out there (like Groovy :-). Then maybe your plugin could use this script language (through BSF, maybe)? I know this would be a rather large change...

Regards,
Stig Kleppe-Jørgensen

0

Would you like that because you prefer to code in "Groovy"? Being a Java IDE I assumed most people would be most comfortable programming in Java.

0

You could say that I choose the language for the task ;)

Script languages like Ruby, Python and their Java counterparts, JRuby, Jython
and now Groovy
makes coding small code snippets faster

To be frank, I've never really used Groovy (or Ruby/Python) as I've not had
an editor that made
it as easy to program as IDEA makes Java. But now that we've got the language
API...

I also guess most people are most comfortable programming in Java, but having
the option would
be great ;)

Regards,
Stig



0

Cool. (But throws lots of exception - Ideascript 2.0.6 in Irida build 3245. See below for first two exceptions.)

A slighty off topic question: In our own app we use velocity to generate code. I often dreamt of using jsp pages instead.
Yet, I have not found any useful information on how to integrate Jasper in a standalone app.
Do you have any tip to get me started?
Oh, I have just noticed that you plugin comes with sources. I'll have a look ;)


On first startup:
Assertion failed: Write access is allowed inside write-action only (see com.intellij.openapi.application.Application.runWriteAction())
java.lang.Throwable
at com.intellij.openapi.diagnostic.Logger.assertTrue(Logger.java:64)
at com.intellij.openapi.application.impl.ApplicationImpl.assertWriteAccessAllowed(ApplicationImpl.java:315)
at com.intellij.openapi.roots.impl.libraries.LibraryTableBase.commit(LibraryTableBase.java:8)
at com.intellij.openapi.roots.impl.libraries.LibraryTableBase$LibraryModel.commit(LibraryTableBase.java:48)
at com.intellij.j2ee.appServerIntegrations.impl.ApplicationServersManagerImpl$ApplicationServersManagerModifiableModelImpl.commit(ApplicationServersManagerImpl.java:5)
at com.casalus.ideascript.IdeaScript.createModuleFile(IdeaScript.java:112)
at com.casalus.ideascript.IdeaScript.initComponent(IdeaScript.java:68)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:251)
at com.intellij.openapi.components.impl.ComponentManagerImpl.access$100(ComponentManagerImpl.java:173)
at com.intellij.openapi.components.impl.ComponentManagerImpl$1.getComponentInstance(ComponentManagerImpl.java:4)
at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:44)
at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:38)
at org.picocontainer.defaults.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:322)
at org.picocontainer.defaults.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:305)
at com.intellij.openapi.extensions.impl.AreaPicoContainerImpl$4.visitContainer(AreaPicoContainerImpl.java:101)
at org.picocontainer.defaults.DefaultPicoContainer.accept(DefaultPicoContainer.java:416)
at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.accept(AbstractDelegatingMutablePicoContainer.java:134)
at com.intellij.openapi.extensions.impl.AreaPicoContainerImpl.getComponentInstance(AreaPicoContainerImpl.java:88)
at com.intellij.openapi.components.impl.ComponentManagerImpl.instantiateComponent(ComponentManagerImpl.java:137)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:126)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:217)
at com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java)
at com.intellij.openapi.application.impl.ApplicationImpl.initComponents(ApplicationImpl.java:374)
at com.intellij.openapi.application.impl.ApplicationImpl.load(ApplicationImpl.java:17)
at com.intellij.idea.IdeaApplication.run(IdeaApplication.java:46)
at com.intellij.idea.Main$4.run(Main.java)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:178)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:454)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)



Later:

No message
java.lang.NullPointerException
at com.intellij.openapi.project.impl.ProjectImpl.getName(ProjectImpl.java:225)
at com.casalus.ideascript.IdeaScript.registerProjectComponent(IdeaScript.java:244)
at com.casalus.ideascript.IdeaScriptProjectComponent.(IdeaScriptProjectComponent.java:22) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:274) at org.picocontainer.defaults.InstantiatingComponentAdapter.newInstance(InstantiatingComponentAdapter.java:128) at org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:154) at org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:56) at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:184) at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:44) at com.intellij.openapi.components.impl.ComponentManagerImpl$1.getComponentInstance(ComponentManagerImpl.java:3) at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:44) at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:38) at org.picocontainer.defaults.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:322) at org.picocontainer.defaults.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:305) at com.intellij.openapi.extensions.impl.AreaPicoContainerImpl$4.visitContainer(AreaPicoContainerImpl.java:101) at org.picocontainer.defaults.DefaultPicoContainer.accept(DefaultPicoContainer.java:416) at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.accept(AbstractDelegatingMutablePicoContainer.java:134) at com.intellij.openapi.extensions.impl.AreaPicoContainerImpl.getComponentInstance(AreaPicoContainerImpl.java:88) at com.intellij.openapi.components.impl.ComponentManagerImpl.instantiateComponent(ComponentManagerImpl.java:137) at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:126) at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:217) at com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java) at com.intellij.openapi.project.impl.BaseFileConfigurable.initComponents(BaseFileConfigurable.java:74) at com.intellij.openapi.project.impl.BaseFileConfigurable.init(BaseFileConfigurable.java:164) at com.intellij.openapi.project.impl.ProjectImpl.init(ProjectImpl.java:6) at com.intellij.openapi.project.impl.ProjectManagerImpl.getDefaultProject(ProjectManagerImpl.java:103) at com.intellij.ide.util.projectWizard.ProjectJdkStep.a(ProjectJdkStep.java) at com.intellij.ide.util.projectWizard.ProjectJdkStep.(ProjectJdkStep.java:2) at com.intellij.ide.util.projectWizard.AddModuleWizard.a(AddModuleWizard.java:37) at com.intellij.ide.util.projectWizard.AddModuleWizard.(AddModuleWizard.java:61) at com.intellij.ide.impl.ProjectUtil.createNewProject(ProjectUtil.java:24) at com.intellij.ide.actions.NewProjectAction.actionPerformed(NewProjectAction.java) at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.actionPerformed(ActionMenuItem.java:1) at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1786) at com.intellij.openapi.actionSystem.impl.ActionMenuItem.fireActionPerformed(ActionMenuItem.java:22) at com.intellij.ui.plaf.beg.BegMenuItemUI.a(BegMenuItemUI.java:40) at com.intellij.ui.plaf.beg.BegMenuItemUI.access$300(BegMenuItemUI.java:89) at com.intellij.ui.plaf.beg.BegMenuItemUI$MyMouseInputHandler.mouseReleased(BegMenuItemUI.java:5) at java.awt.Component.processMouseEvent(Component.java:5100) at java.awt.Component.processEvent(Component.java:4897) at java.awt.Container.processEvent(Container.java:1569) at java.awt.Component.dispatchEventImpl(Component.java:3615) at java.awt.Container.dispatchEventImpl(Container.java:1627) at java.awt.Component.dispatchEvent(Component.java:3477) at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483) at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3198) at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128) at java.awt.Container.dispatchEventImpl(Container.java:1613) at java.awt.Window.dispatchEventImpl(Window.java:1606) at java.awt.Component.dispatchEvent(Component.java:3477) at java.awt.EventQueue.dispatchEvent(EventQueue.java:456) at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:18) at com.intellij.ide.IdeEventQueue.a(IdeEventQueue.java:125) at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:141) at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137) at java.awt.EventDispatchThread.run(EventDispatchThread.java:100) java.lang.NullPointerException at com.intellij.openapi.project.impl.ProjectImpl.getName(ProjectImpl.java:225) at com.casalus.ideascript.IdeaScript.registerProjectComponent(IdeaScript.java:244) at com.casalus.ideascript.IdeaScriptProjectComponent.(IdeaScriptProjectComponent.java:22) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:274) at org.picocontainer.defaults.InstantiatingComponentAdapter.newInstance(InstantiatingComponentAdapter.java:128) at org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:154) at org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:56) at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:184) at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:44) at com.intellij.openapi.components.impl.ComponentManagerImpl$1.getComponentInstance(ComponentManagerImpl.java:3) at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:44) at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:38) at org.picocontainer.defaults.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:322) at org.picocontainer.defaults.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:305) at com.intellij.openapi.extensions.impl.AreaPicoContainerImpl$4.visitContainer(AreaPicoContainerImpl.java:101) at org.picocontainer.defaults.DefaultPicoContainer.accept(DefaultPicoContainer.java:416) at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.accept(AbstractDelegatingMutablePicoContainer.java:134) at com.intellij.openapi.extensions.impl.AreaPicoContainerImpl.getComponentInstance(AreaPicoContainerImpl.java:88) at com.intellij.openapi.components.impl.ComponentManagerImpl.instantiateComponent(ComponentManagerImpl.java:137) at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:126) at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponentFromContainer(ComponentManagerImpl.java:236) at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponent(ComponentManagerImpl.java:12) at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponent(ComponentManagerImpl.java:233) at com.intellij.openapi.components.impl.ComponentManagerImpl.getComponents(ComponentManagerImpl.java:98) at com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java:211) at com.intellij.openapi.project.impl.BaseFileConfigurable.initComponents(BaseFileConfigurable.java:74) at com.intellij.openapi.project.impl.BaseFileConfigurable.init(BaseFileConfigurable.java:164) at com.intellij.openapi.project.impl.ProjectImpl.init(ProjectImpl.java:6) at com.intellij.openapi.project.impl.ProjectManagerImpl.getDefaultProject(ProjectManagerImpl.java:103) at com.intellij.ide.util.projectWizard.ProjectJdkStep.a(ProjectJdkStep.java) at com.intellij.ide.util.projectWizard.ProjectJdkStep.(ProjectJdkStep.java:2) at com.intellij.ide.util.projectWizard.AddModuleWizard.a(AddModuleWizard.java:37) at com.intellij.ide.util.projectWizard.AddModuleWizard.]]>(AddModuleWizard.java:61)
at com.intellij.ide.impl.ProjectUtil.createNewProject(ProjectUtil.java:24)
at com.intellij.ide.actions.NewProjectAction.actionPerformed(NewProjectAction.java)
at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.actionPerformed(ActionMenuItem.java:1)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1786)
at com.intellij.openapi.actionSystem.impl.ActionMenuItem.fireActionPerformed(ActionMenuItem.java:22)
at com.intellij.ui.plaf.beg.BegMenuItemUI.a(BegMenuItemUI.java:40)
at com.intellij.ui.plaf.beg.BegMenuItemUI.access$300(BegMenuItemUI.java:89)
at com.intellij.ui.plaf.beg.BegMenuItemUI$MyMouseInputHandler.mouseReleased(BegMenuItemUI.java:5)
at java.awt.Component.processMouseEvent(Component.java:5100)
at java.awt.Component.processEvent(Component.java:4897)
at java.awt.Container.processEvent(Container.java:1569)
at java.awt.Component.dispatchEventImpl(Component.java:3615)
at java.awt.Container.dispatchEventImpl(Container.java:1627)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3198)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128)
at java.awt.Container.dispatchEventImpl(Container.java:1613)
at java.awt.Window.dispatchEventImpl(Window.java:1606)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:18)
at com.intellij.ide.IdeEventQueue.a(IdeEventQueue.java:125)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:141)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)






0

Thanks for taking a look. I hadn't tried it in Irida before, but now it should be working. Please get the latest version and try again.

To run Jasper standalone, look at my class JspInvoker which is the bootstrap class that should show you how to do it. It makes use of the other classes in the invoker package.

You'll also notice I include my own jasper jar. This is because jasper currently requires a URLClassLoader and Idea's plugin classloader doesn't qualify. More than likely you can expect a URLClassLoader in which case you can just use the official jasper jar out of the box.

0

Please sign in to leave a comment.