[英]Gradle: execute Groovy interactive shell with project classpath
我有一个由几个子项目组成的Gradle项目。 我刚刚创建了一个新的,以添加对我想要运行的交互式Groovy shell的支持:
gradle console
要么
gradle console:run
所以我的新console
模块的build.gradle文件如下:
apply plugin: 'groovy'
apply plugin:'application'
mainClassName = 'org.codehaus.groovy.tools.shell.Main'
dependencies {
compile 'org.codehaus.groovy:groovy-all:2.2.2'
compile 'org.fusesource.jansi:jansi:1.11'
compile 'commons-cli:commons-cli:1.2'
compile 'jline:jline:2.11'
compile project(':my-module')
}
task(console, dependsOn: 'classes', type: JavaExec) {
main = 'org.codehaus.groovy.tools.shell.Main'
classpath = sourceSets.main.runtimeClasspath
}
但是,当我运行gradle :console:run
或gradle console
我得到类似的东西:
:console:run
Groovy Shell (2.2.2, JVM: 1.6.0_45)
Type 'help' or '\h' for help.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
groovy:000>
BUILD SUCCESSFUL
Total time: 4.529 secs
giovanni@mylaptop:~/Projects/my-project$
因此,交互式shell似乎已经开始,但它会立即退出。
难道我做错了什么?
编辑 :在build.gradle文件中添加以下内容:
run.standardInput = System.in
现在,从输入流中读取标准输入(由于注释)。
但是,Gradle似乎陷入了困境:
Groovy Shell (2.2.2, JVM: 1.6.0_45)
Type 'help' or '\h' for help.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
groovy:000>
> Building 88% > :console:run
并且没有接受任何输入。 即使这导致了同样的事情:
gradle --no-daemon console:run
2018年更新:
Dylons接受的答案似乎不再起作用了./gradlew console
立即退出:
$ ./gradlew console
配置项目:不推荐使用Task.leftShift(Closure)方法,并计划在Gradle 5.0中删除它。 请改用Task.doLast(Action)。 在build_8qb2gvs00xed46ejq1p63fo92.run(/home/jhe052/eclipse-workspace/QuinCe/build.gradle:118)(使用--stacktrace运行以获取此弃用警告的完整堆栈跟踪。)
在3个3个可操作的任务中建立成功:1个执行,2个最新
用doLast替换leftShift(<<)会删除不推荐使用的消息,但结果相同。 版本信息:
$ ./gradlew --version
Gradle 4.4.1
制作时间:2017-12-20 15:45:23 UTC修订:10ed9dc355dc39f6307cc98fbd8cea314bdd381c
Groovy:2.4.12 Ant:2017年2月2日编译的Apache Ant(TM)版本1.9.9 JVM:1.8.0_151(Oracle Corporation 25.151-b12)操作系统:Linux 4.13.0-32-generic amd64
这适用于JDK 7+(对于JDK 6,请看下图):
configurations {
console
}
dependencies {
// ... compile dependencies, runtime dependencies, etc.
console 'commons-cli:commons-cli:1.2'
console('jline:jline:2.11') {
exclude(group: 'junit', module: 'junit')
}
console 'org.codehaus.groovy:groovy-groovysh:2.2.+'
}
task(console, dependsOn: 'classes') << {
def classpath = sourceSets.main.runtimeClasspath + configurations.console
def command = [
'java',
'-cp', classpath.collect().join(System.getProperty('path.separator')),
'org.codehaus.groovy.tools.shell.Main',
'--color'
]
def proc = new ProcessBuilder(command)
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectInput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
.start()
proc.waitFor()
if (0 != proc.exitValue()) {
throw new RuntimeException("console exited with status: ${proc.exitValue()}")
}
}
为了使这项工作适用于JDK 6,我修改了https://stackoverflow.com/a/4274535/206543的解决方案。 我的解决方案是针对标准Linux终端量身定制的,因此如果您运行的shell使用除了'\\ n'以外的字符序列用于换行或将退格编码为其他127的值,则可能需要对其进行一些修改。 我没有确定如何正确打印颜色,所以它的输出相当单调,但它将完成工作:
configurations {
console
}
dependencies {
// ... compile dependencies, runtime dependencies, etc.
console 'commons-cli:commons-cli:1.2'
console('jline:jline:2.11') {
exclude(group: 'junit', module: 'junit')
}
console 'org.codehaus.groovy:groovy-groovysh:2.2.+'
}
class StreamCopier implements Runnable {
def istream
def ostream
StreamCopier(istream, ostream) {
this.istream = istream
this.ostream = ostream
}
void run() {
int n
def buffer = new byte[4096]
while ((n = istream.read(buffer)) != -1) {
ostream.write(buffer, 0, n)
ostream.flush()
}
}
}
class InputCopier implements Runnable {
def istream
def ostream
def stdout
InputCopier(istream, ostream, stdout) {
this.istream = istream
this.ostream = ostream
this.stdout = stdout
}
void run() {
try {
int n
def buffer = java.nio.ByteBuffer.allocate(4096)
while ((n = istream.read(buffer)) != -1) {
ostream.write(buffer.array(), 0, n)
ostream.flush()
buffer.clear()
if (127 == buffer.get(0)) {
stdout.print("\b \b")
stdout.flush()
}
}
}
catch (final java.nio.channels.AsynchronousCloseException exception) {
// Ctrl+D pressed
}
finally {
ostream.close()
}
}
}
def getChannel(istream) {
def f = java.io.FilterInputStream.class.getDeclaredField("in")
f.setAccessible(true)
while (istream instanceof java.io.FilterInputStream) {
istream = f.get(istream)
}
istream.getChannel()
}
task(console, dependsOn: 'classes') << {
def classpath = sourceSets.main.runtimeClasspath + configurations.console
def command = [
'java',
'-cp', classpath.collect().join(System.getProperty('path.separator')),
'org.codehaus.groovy.tools.shell.Main'
]
def proc = new ProcessBuilder(command).start()
def stdout = new Thread(new StreamCopier(proc.getInputStream(), System.out))
stdout.start()
def stderr = new Thread(new StreamCopier(proc.getErrorStream(), System.err))
stderr.start()
def stdin = new Thread(new InputCopier(
getChannel(System.in),
proc.getOutputStream(),
System.out))
stdin.start()
proc.waitFor()
System.in.close()
stdout.join()
stderr.join()
stdin.join()
if (0 != proc.exitValue()) {
throw new RuntimeException("console exited with status: ${proc.exitValue()}")
}
}
然后,通过以下方式执行:
gradle console
或者,如果你从gradle那里得到很多噪音:
gradle console -q
我创建了一个允许这个的gradle插件( https://github.com/tkruse/gradle-groovysh-plugin )。 遗憾的是,gradle没有为支持REPL的IO提供有用的API /合约,因此该插件不适用于较新版本的Gradle。
但是,在github上的文档中,您可以找到没有插件的手动解决方案 。
该解决方案的大纲是:
package shell;
import org.codehaus.groovy.tools.shell.Main;
import org.fusesource.jansi.AnsiConsole;
class ShellMain {
public static void main(String[] args) {
// workaround for jAnsi problems, (backspace and arrow keys not working)
AnsiConsole.systemUninstall();
Main.main(args);
}
}
然后使用JavaExec任务运行它
apply plugin: 'java'
dependencies {
compile('commons-cli:commons-cli:1.2')
compile('org.codehaus.groovy:groovy-all:2.4.4') { force = true }
// when using groovy < 2.2 above: "jline:jline:1.0"
compile("jline:jline:2.11") {
exclude(group: 'junit', module: 'junit')
}
}
task shell(dependsOn: 'testClasses', type: JavaExec) {
doFirst {
if (getProperty('org.gradle.daemon') == 'true') {
throw new IllegalStateException('Do not run shell with gradle daemon, it will eat your arrow keys.')
}
}
standardInput = System.in
main = 'shell.ShellMain'
classpath = sourceSets.main.runtimeClasspath
jvmArgs = []
}
Gradle目前不能很好地处理ncurses样式的控制台应用程序。 在单独的控制台中运行groovysh
,或者改为运行groovyConsole
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.