Могут ли команды быть написаны для поддержки многострочных аргументов, то есть с новыми строками в них, как heredocs?
Как можно написать команду sbt, которая поддерживает аргументы с символами новой строки в них какheredocs?
Я хотел бы иметь команду sbt, где пользователь может вставить многострочный блок текста, который затем обрабатывается / преобразуется во что-то еще. Эксперименты пока что показывают, что sbt пытается разобрать команду сразу после появления новой строки.
Пример использованияПримечание: это всего лишь пример использования для объяснения желаемой функциональности SBT. яне ищет другие механизмы для обработкиpom.xml
файлы в SBT; скорее, как реализовать пользовательскую команду с многострочными аргументами.
Предположим, я хотел бы, чтобы пользователь мог вставить фрагмент кода XML из POM-файла Maven в SBT REPL и преобразовать все зависимости в синтаксис SBT. Вот реализация, которая работает, если код XML находится в одной строке:
// NB: Requires SBT >= 0.13.5
package pomhelpers
import sbt._
import Keys._
import sbt.complete.Parser
import sbt.complete.DefaultParsers._
/**
* Plugin to install an SBT command to assist in converting Maven dependency syntax
* to SBT DSL.
*/
object ExtractMvnDependencies extends AutoPlugin {
override def trigger = allRequirements
override lazy val projectSettings = Seq(commands ++= Seq(pomLibs2Sbt))
val Pom2SbtCommand = "pom2sbt"
val Pom2SbtHelp = "<pom-xml-fragment>"
// **How should this be constructed to handle mult-line inputs?**
val MultiLineCommandInputParser: Parser[String] =
OptSpace ~> (StringBasic | StringVerbatim)
lazy val pomLibs2Sbt = Command(
Pom2SbtCommand,
Help((Pom2SbtCommand, Pom2SbtHelp)))(_ => MultiLineCommandInputParser) { (state , xmlFrag) =>
val sbtdeps = pomXml2SbtDsl(xmlFrag)
println(sbtdeps.mkString("\n"))
state
}
/** Convert POM string to SBT form. */
private def pomXml2SbtDsl(xmlFrag: String): Seq[String] = {
import scala.xml._
val deps = XML.loadString(xmlFrag) \\ "dependency"
deps map ((dependency) => {
val coords = Seq("groupId", "artifactId", "version", "scope")
val coordParts = coords.map(coord => (dependency \ coord).text.trim).filter(_.nonEmpty)
coordParts.mkString("\"", "\" % \"", "\"")
})
}
}
С этим установленным плагином можно запустить следующее в SBT REPL:
pom2sbt "<dependency><groupId>org.foo</groupId><artifactId>megalib</artifactId><version>1.1.1</version></dependency>"
или же
pom2sbt """<dependency><groupId>org.foo</groupId><artifactId>megalib</artifactId><version>1.1.1</version></dependency>"""
и получить:
"org.foo" % "megalib" % "1.1.1"
Что является правильным выводом, но переформатирование входной строки для размещения на одной строке сводит на нет большинство преимуществ утилиты.
Желаемая возможность - (в данном случае и в общем случае многострочного аргумента команды) набратьpom2sbt """
вставьте весь многострочный текстовый блок и завершите"""
и иметь SBT задержку синтаксического анализа всей команды до закрытия разделителя heredoc, например:
pom2sbt """<dependency>
<groupId>org.foo</groupId>
<artifactId>megalib</artifactId>
<version>1.1.1</version>
</dependency>"""
Однако даже при использованииStringVerbatim
синтаксический анализатор, как в примере кода, SBT выдает ошибку разбора после первой новой строки:
> pom2sbt """<dependency>
[error] Expected '"""'
[error] pom2sbt """<dependency>
[error] ^
> <groupId>org.foo</groupId>
[error] Expected symbol
[error] < usage:
[error]
[error]
[error] More command help available using 'help <command>' for:
[error] <
...