后期绑定Groovy String?

Joe*_*oeG 7 groovy

我正在将用户交互的文本移动到外部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)

对不起,如果这太详细了 - 我希望它可能会有所帮助.

Lui*_*ñiz 8

你为什么不尝试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)

这允许您通过在委托中添加方法来自然地丰富您的交互,而不是痛苦地向此地图添加元素.