Starting groovysh from Gradle


(Thibault Kruse) #1

Hi all,

I would like to start a groovysh session from gradle using the runtime dependencies of my application.

I have one working solution, the gradle file below should work with gradle 1.10 and contains two appoaches.

apply plugin: 'groovy'
  repositories {
    jcenter()
}
  dependencies {
    runtime('org.codehaus.groovy:groovy-all:2.2.2')
    runtime("jline:jline:2.11") {
        exclude(group: 'junit', module: 'junit')
    }
    runtime('commons-cli:commons-cli:1.2')
}
    /*************** 1st way groovysh as a separate application */
  apply plugin: 'application'
mainClassName = "org.codehaus.groovy.tools.shell.Main"
    /*************** 2nd WAY: groovysh as task */
  task shell(dependsOn: 'testClasses', type: JavaExec) {
    doFirst {
      if (project.hasProperty('org.gradle.daemon') && project.getProperty('org.gradle.daemon') == 'true') {
          //throw new IllegalStateException('Do not run shell with gradle daemon, it will eat your arrow keys.')
        }
    }
    group = 'help'
    description 'Runs an interactive shell with all runtime dependencies. "Use with gradle -q shell".'
    main = 'org.codehaus.groovy.tools.shell.Main'
    standardInput = System.in
    // puts all dependencies (compile and test) into classpath
    classpath = sourceSets.test.runtimeClasspath
    // jvmArgs = []
    // standardOutput = System.out
    // workingDir =
    // stops after eval, not useful
    // args = ["load $rootDir/integration-test/src/main/groovy/GroovyshStartup.groovy"]
}

which does the job properly when running:

gradle installApp
build/install/.../bin/<startScript>

However I would prefer to start groovysh from the same jvm if possible. The second approach would be started using

gradle -q shell

Now the problem is, when running without the gradle deamon enabled, The Backspace key and the left and right arrow keys do not have any effect. But the up arrow key works fine.

Funnily, when the daemon is enabled, backspace works, but the arrow keys all do not work.

This on Ubuntu precise with java 7.

I am also aware of the project https://github.com/carlosgsouza/gradle-console, but really the point here is mostly that I want to make groovysh itself better known in the community, so any swing based approach does not help with that goal.


(Thibault Kruse) #2

To make matters even more confusing, the following works. When creating a file like this:

import org.codehaus.groovy.tools.shell.Groovysh
import org.codehaus.groovy.tools.shell.IO
import org.codehaus.groovy.tools.shell.util.NoExitSecurityManager
    class ShellMain {
    public static void main(String[] args) {
      IO io = new IO()
      final Groovysh shell = new Groovysh(io)
      int code
      addShutdownHook {
        if (code == null) {
          println('WARNING: Abnormal JVM shutdown detected')
        }
        if (shell.history) {
          shell.history.flush()
        }
      }
              SecurityManager psm = System.getSecurityManager()
      System.setSecurityManager(new NoExitSecurityManager())
      try {
        code = shell.run([''] as String[])
      } finally {
        System.setSecurityManager(psm)
      }
      System.exit(code)
    }
}

Basically copying the code from org.codehaus.groovy.tools.shell.Main, and creating the Gradle task asin the last post with just the new class as “main”, then the shell works fine when running gradle -q shell.

i can meanwhile work on the groovy side to make subclassing Main easier.


(Thibault Kruse) #3

Obviously this also works then:

import org.codehaus.groovy.tools.shell.Main;
  class ShellMain {
  public static void main(String[] args) {
    Main.main(args);
  }
}

(Thibault Kruse) #4

No, actually that was a fluke. invoking Main.main(args) does not work (e.g. Backspace key no working). So I could narrow down the problem to the call of AnsiConsole.systemInstall() in groovysh Main.groovy.

So a working alternative now looks like this:

import org.codehaus.groovy.tools.shell.Main;
import org.fusesource.jansi.AnsiConsole
  class ShellMain {
  public static void main(String[] args) {
    AnsiConsole.systemUninstall()
    Main.main(args);
  }
}

I can work on a patch for groovysh to make this less painful.