我正在将用户交互的文本移动到外部groovy配置文件.我没有遇到任何问题"啜饮"这个问题,直到需要处理这样的文本:
text:"Enter the port number used by the program (${defaultPort}): "
Run Code Online (Sandbox Code Playgroud)
有没有办法将此值读入String或GString,然后绑定到活动程序值(如defaultPort)?
在将处理此代码的代码中,"defaultValue"可以设置为多个值.例如,如果使用http,则该值可能为80,但如果使用https,则可能为443.
我意识到SimpleTemplateEngine会起作用,但是有更简单的方法吗?
两个不起作用的解决方案:
1)
text:{ value -> "Enter the port number used by the program ($value)" }
Run Code Online (Sandbox Code Playgroud)
好的,实际上这确实有效!但是,我不能(或者不认为我可以)使用这种方法,因为这是例外情况,绝大多数用途只会读取文本.这种方法要求您将其称为一种方法,它会破坏所有其他用途.
我尝试将其作为Java String(单引号)读取并从中创建一个GString.我甚至不会展示代码 - 这是新的一年,而不是愚人节!我只想说我无法工作!
2)
我也试过这个变种:
def defaultPort = determinePort()
def textVal = myConfig.text // tried single and double quotes in the config file
def newVal = "${writer -> writer << textVal}"
Run Code Online (Sandbox Code Playgroud)
谢谢你的帮助.
根据loteq的回答添加更多细节
如果很清楚,这里有一个更详细的草图,我想做什么:
// questions would be in a file parseable by ConfigSlurper:
someIdentifier {
questions =[1:[text:'Enter http or https ',
anotherField: 'some value',
method2Use: 'getInput'],
2:[text:'Enter the port number used by the program (${defaultPort}): ',
anotherField: 'some value',
method2Use: 'getInput']
]
}
def myConfig = new ConfigSlurper().parse(questionConfigFile.groovy)
def questions = myConfig.someIdentifier?.questions
questions?.each{ number, details ->
// need a way in here to have the answer of the first question
// determine a value of either 80 or 443 (80 = http, 443 = https)
// and use that to substitute into the 'text' of the second question
}
Run Code Online (Sandbox Code Playgroud)
对不起,如果这太详细了 - 我希望它可能会有所帮助.
你为什么不尝试ConfigSlurper方法?
String configScript='''
text1="Enter the port number used by the program (${defaultPort}): "
text2="Normal text"
'''
def sl=new ConfigSlurper()
sl.setBinding(
defaultPort:8080
)
def cfg=sl.parse(configScript)
cfg.each{println it}
Run Code Online (Sandbox Code Playgroud)
结果:
text1=Enter the port number used by the program (8080):
text2=Normal text
Run Code Online (Sandbox Code Playgroud)
更新,基于问题第二部分的更多细节
您可以使用groovy的动态调度功能来很好地处理字符串和闭包.
// questions would be in a file parseable by ConfigSlurper:
someIdentifier {
questions =[1:[text:'Enter http or https ',
anotherField: 'some value',
method2Use: 'getInput'
responseBinding: 'protocol'
],
2:[text:{binding->"Enter the port number used by the program (${binding.defaultPort}): ",
anotherField: 'some value',
method2Use: 'getInput'
responseBinding: 'port'
]
]
}
def myConfig = new ConfigSlurper().parse(questionConfigFile.groovy)
def questions = myConfig.someIdentifier?.questions
def binding=[:]
questions?.each{ number, details ->
this."processResponse$number"(this."${details.method2Use}"(details.text,details,binding))
}
void processResponse1(Map binding) {
def defaultPorts =[
https:443,
http:80
]
binding.defaultPort=defaultPorts[binding.protocol]
}
void processResponse2(Map binding) {
//
}
Map getInput(String prompt, Map interactionDetails, Map binding) {
binding[interactionDetails.responseBinding] = readInput(prompt)
binding
}
Map getInput(Closure<String> prompt, Map interactionDetails, Map binding) {
binding[interactionDetails.responseBinding] = readInput(prompt(binding))
binding
}
Run Code Online (Sandbox Code Playgroud)
UPDATE
一种截然不同的方法,在我看来,更清洁,是定义DSL:
def configScript='''
someIdentifier = {
protocol=getInput("Enter http or https")
port=getInput("Enter the port used for $protocol (${defaultPorts[protocol]}):")
}
'''
Run Code Online (Sandbox Code Playgroud)
您仍然可以使用configSlurper来解析文件,但是您将针对将实现的委托运行闭包someIdentifier:
class Builder {
def defaultPorts =[
https:'443',
http:'80'
]
String protocol
String port
def getInput(String prompt) {
System.console().readLine(prompt)
}
void setPort(String p) {
port = p ?: defaultPorts[protocol]
}
String toString() {
"""
|protocol=$protocol
|port=$port
""".stripMargin()
}
}
Run Code Online (Sandbox Code Playgroud)
然后:
def sl=new ConfigSlurper()
def cfg=sl.parse(configScript)
def id=cfg.someIdentifier.clone()
def builder=new Builder()
id.delegate=builder
id.resolveStrategy=Closure.DELEGATE_ONLY
id()
println builder
Run Code Online (Sandbox Code Playgroud)
这允许您通过在委托中添加方法来自然地丰富您的交互,而不是痛苦地向此地图添加元素.