aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/definitions.scala
blob: cb05532ba01378afe8eff83bd9eeb236492dc421 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package commando

import scala.{Option => Maybe}

sealed trait Definition

case class Option(long: String,
                  short: Maybe[Char] = None,
                  parameter: Maybe[Parameter] = None)
    extends Definition {
  def argumentAllowed: Boolean = parameter.isDefined
  def argumentRequired: Boolean = parameter.map(_.required).getOrElse(false)
  override def toString = {
    val shortString = short.map(c => s"-$c|").getOrElse("")
    val argString = parameter match {
      case None                            => ""
      case Some(Parameter(argName, false)) => s"[=<$argName>]"
      case Some(Parameter(argName, true))  => s"=<$argName>"
    }
    s"[$shortString--$long$argString]"
  }
}

case class Parameter(
    name: String,
    required: Boolean = true
) extends Definition {
  override def toString = if (required) s"<$name>" else s"[<$name>]"
}

case class Command(
    name: String,
    options: Set[Option] = Set.empty,
    parameters: Seq[Parameter] = Seq.empty,
    commands: Set[Command] = Set.empty
) extends Definition {
  override def toString = name

  def subusage(level: Int): String = {
    val optionStrings = options.map { opt =>
      opt.toString
    }
    val parameterStrings = parameters map { param =>
      param.toString
    }
    val commandStrings = Seq(commands.map(cmd => cmd.name).mkString("|"))

    val headline =
      (Seq(name) ++ optionStrings ++ parameterStrings ++ commandStrings)
        .mkString(" ")
    val sublines = commands
      .map(_.subusage(level + 1))
      .map(line => "    " * (level + 1) + line)
    headline + sublines.mkString("\n", "", "")
  }

  def usage: String = "Usage: " + subusage(0)

  def completion: String = commando.completion.Bash.completion(this)

}
object Command {

  def apply(name: String, defs: Definition*): Command = {
    Command(
      name,
      options = defs.collect { case opt: Option         => opt }.toSet,
      parameters = defs.collect { case param: Parameter => param }.toSeq,
      commands = defs.collect { case cmd: Command       => cmd }.toSet
    )
  }

}