Groovy多行字符串插值空格

塞班·塞萨尔(Serban Cezar)

我正在尝试为Jenkins生成一些通用的Groovy代码,但是我似乎在使用多行字符串和多余的空格时遇到了麻烦。我已经尝试了Googling可以找到的所有内容,但似乎无法正常工作。

我的问题与简单的多行字符串无关。在简单的情况下,我通过使用stripIndent()和stripMargin()方法设法修剪了空白。我的问题是由字符串中的插值方法引起的。

常规信息: Groovy Version: 3.0.2 JVM: 13.0.2 Vendor: Oracle Corporation OS: Mac OS X

String method2(String tier, String jobName) {
    return """
            Map downstreamJobs = [:]
            stage ("${jobName}-${tier}-\${region}_${jobName}") {
                test
            }
        """.stripIndent().stripMargin()
}

static String simpleLog() {
    return """
            script {
               def user = env.BUILD_USER_ID
            }
          """.stripIndent().stripMargin()
}

static String method1() {
    return """\
            import jenkins.model.Jenkins
            currentBuild.displayName = "name"

            ${simpleLog()}
        """.stripIndent().stripMargin()
}

String generateFullDeploymentPipelineCode() {
    return """Text here
            ${method1()}
            ${method2("test1", "test2")}
            """.stripIndent().stripMargin()
}

println(generateFullDeploymentPipelineCode())

这是它打印(或写入磁盘)的内容:

Text here
                      import jenkins.model.Jenkins
          currentBuild.displayName = "name"

script {
   def user = env.BUILD_USER_ID
}



Map downstreamJobs = [:]
stage ("test2-test1-${region}_test2") {
    test
}

为什么在导入线周围有多余的空间?我知道缩进方法应该根据最少的前导空格数修剪所有空白,因此这就是我们使用反斜杠的原因(示例在这里https://stackoverflow.com/a/19882917/7569335)。

这适用于简单的字符串,但是一旦使用插值就可以分解。仅当您插入整个方法时,才使用常规变量。

zett42

通过插值插入字符串时,仅缩进其第一行。插入的字符串的以下各行将以不同的方式缩进,从而弄乱了所有内容。

使用GString.strings[]和的一些鲜为人知的成员.values[],我们可以对齐每个插值的所有行的缩进。

String method2(String tier, String jobName) {
    indented """
        Map downstreamJobs = [:]
        stage ("${jobName}-${tier}-\${region}_${jobName}") {
            test
        }
    """
}

String simpleLog() {
    indented """\
        script {
           def user = env.BUILD_USER_ID
        }
    """
}

String method1() {
    indented """\
        import jenkins.model.Jenkins
        currentBuild.displayName = "name"

        ${simpleLog()}
    """
}

String generateFullDeploymentPipelineCode() {
    indented """\
        Text here
        ${method1()}
        ${method2("test1", "test2")}
    """
}

println generateFullDeploymentPipelineCode()

//---------- Move the following code into its own script ----------

// Function to adjust the indentation of interpolated values so that all lines
// of a value match the indentation of the first line.
// Finally stripIndent() will be called before returning the string.

String indented( GString templ ) {

    // Iterate over the interpolated values of the GString template.
    templ.values.eachWithIndex{ value, i ->

        // Get the string preceding the current value. Always defined, even
        // when the value is at the beginning of the template.
        def beforeValue = templ.strings[ i ]

        // RegEx to match any indent substring before the value.
        // Special case for the first string, which doesn't necessarily contain '\n'. 
        def regexIndent = i == 0
                          ? /(?:^|\n)([ \t]+)$/
                          : /\n([ \t]+)$/

        def matchIndent = ( beforeValue =~ regexIndent )
        if( matchIndent ) {
            def indent = matchIndent[ 0 ][ 1 ]
            def lines = value.readLines()
            def linesNew = [ lines.head() ]  // The 1st line is already indented.
            // Insert the indentation from the 1st line into all subsequent lines.
            linesNew += lines.tail().collect{ indent + it }
            // Finally replace the value with the reformatted lines.
            templ.values[ i ] = linesNew.join('\n')
        }
    }

    return templ.stripIndent()
}

// Fallback in case the input string is not a GString (when it doesn't contain expressions)
String indented( String templ ) {
    return templ.stripIndent()  
}

现场现场演示

输出:

Text here
import jenkins.model.Jenkins
currentBuild.displayName = "name"

script {
   def user = env.BUILD_USER_ID
}

Map downstreamJobs = [:]
stage ("test2-test1-${region}_test2") {
    test
}

结论:

使用该indented功能,GString已经实现了用于从模板生成代码的简洁的Groovy语法

这是相当的学习经验。我首先尝试使用该evaluate功能完全不同,但结果却过于复杂且不够灵活。然后,我随机浏览了mrhaki博客中的一些文章(总是读得不错!),直到发现“ Groovy Goodness:了解有关GString的更多信息”这是实施此解决方案的关键。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章