在Scala中保留字符串插值的缩进

Sri*_*san 4 scala

我想知道在scala中进行字符串插值时是否有任何保留缩进的方法.基本上,我想知道我是否可以介入我自己的StringContext.宏将解决这个问题,但我想等到他们正式.

这就是我要的:

val x = "line1 \nline2"
val str = s">       ${x}"
Run Code Online (Sandbox Code Playgroud)

str应该评估为

>       line1
        line2
Run Code Online (Sandbox Code Playgroud)

Sri*_*san 8

回答我的问题,并将Daniel Sobral非常有用的答案转换为代码.希望它对具有相同问题的其他人有用.我没有使用隐式类,因为我仍然在2.10之前.

用法:

import Indenter._ 并使用字符串插值 e" $foo "

import Indenter._

object Ex extends App {
  override def main(args: Array[String]) {
    val name = "Foo"
    val fields = "x: Int\ny:String\nz:Double"
    // fields has several lines. All of them will be indented by the same amount.
    print (e"""
        class $name {
           ${fields}
        }
        """)  
  }
}
Run Code Online (Sandbox Code Playgroud)

应该打印

class Foo
   x: Int
   y: String
   z: Double
Run Code Online (Sandbox Code Playgroud)

这是自定义缩进上下文.

class IndentStringContext(sc: StringContext) {
  def e(args: Any*):String = {
    val sb = new StringBuilder()
    for ((s, a) <- sc.parts zip args) {
      sb append s

      val ind = getindent(s)
      if (ind.size > 0) { 
        sb append a.toString().replaceAll("\n", "\n" + ind)
      } else {
        sb append a.toString()
      }
    }
    if (sc.parts.size > args.size)
      sb append sc.parts.last

    sb.toString()
  }

  // get white indent after the last new line, if any
  def getindent(str: String): String = {
    val lastnl = str.lastIndexOf("\n")
    if (lastnl == -1) ""
    else {
      val ind = str.substring(lastnl + 1)
      if (ind.trim.isEmpty) ind  // ind is all whitespace. Use this
      else ""
    }
  }
}

object Indenter {
  // top level implicit defs allowed only in 2.10 and above
  implicit  def toISC(sc: StringContext) = new IndentStringContext(sc)
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ral 5

您可以编写自己的插补器,并且可以使用自己的插值器遮挡标准插值器.现在,我不知道你的例子背后的语义是什么,所以我甚至都不去尝试.

SlideshareSpeakerDeck上查看我在Scala 2.10上的演示文稿,因为它们包含了可以编写/覆盖插补器的所有方式的示例.从幻灯片40开始(现在 - 演示文稿可能会更新,直到2.10终于出来).