Guest User

Untitled

a guest
Apr 21st, 2018
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.75 KB | None | 0 0
  1. package net.harnly.aaron.options
  2.  
  3. import scala.collection.mutable.{ListBuffer}
  4.  
  5. // Base class for options.
  6. // These are things that get listed when we ask for help,
  7. // and optionally can accept string arguments & perform some kind of action,
  8. // usually mutating a var.
  9. case class OptionDefinition(
  10. canBeInvoked: Boolean,
  11. shortopt: String,
  12. longopt: String,
  13. description: String,
  14. action: String => Unit,
  15. gobbleNextArgument: Boolean
  16. )
  17.  
  18. // ----- Some standard option types ---------
  19. class SeparatorDefinition(
  20. description: String
  21. ) extends OptionDefinition(false,null,null,description, {a: String => {}}, false)
  22.  
  23. class ArgOptionDefinition(
  24. shortopt: String,
  25. longopt: String,
  26. description: String,
  27. action: String => Unit
  28. ) extends OptionDefinition(true,shortopt, longopt, description, action, true)
  29.  
  30. class IntArgOptionDefinition(
  31. shortopt: String,
  32. longopt: String,
  33. description: String,
  34. action: Int => Unit
  35. ) extends OptionDefinition(true,shortopt, longopt, description, {a: String => action(a.toInt)}, true)
  36.  
  37. class DoubleArgOptionDefinition(
  38. shortopt: String,
  39. longopt: String,
  40. description: String,
  41. action: Double => Unit
  42. ) extends OptionDefinition(true,shortopt, longopt, description, {a: String => action(a.toDouble)}, true)
  43.  
  44. class BooleanArgOptionDefinition(
  45. shortopt: String,
  46. longopt: String,
  47. description: String,
  48. action: Boolean => Unit
  49. ) extends OptionDefinition(true,shortopt, longopt, description, { a: String =>
  50. val boolValue = a.toLowerCase match {
  51. case "true" => true
  52. case "false" => false
  53. case "yes" => true
  54. case "no" => false
  55. case "1" => true
  56. case "0" => false
  57. case _ => throw new IllegalArgumentException("Expected a string I can interpret as a boolean")
  58. }
  59. action(boolValue)}, true)
  60.  
  61. class FlagOptionDefinition(
  62. shortopt: String,
  63. longopt: String,
  64. description: String,
  65. action: => Unit
  66. )
  67. extends OptionDefinition(true,shortopt, longopt, description, { a: String => action }, false)
  68.  
  69.  
  70. // OptionParser is instantiated within your object,
  71. // set up by an (ordered) sequence of invocations of #on,
  72. // and then handed the command-line arguments.
  73. case class OptionParser(warnOnUnknownArgument: Boolean){
  74. def this() = this(true)
  75.  
  76. val options = new ListBuffer[OptionDefinition]
  77.  
  78. // -------- Defining options ---------------
  79. def add(option: OptionDefinition){
  80. options += option
  81. }
  82.  
  83. def on(shortopt: String, longopt: String, description: String, action: String => Unit) =
  84. add(new ArgOptionDefinition(shortopt, longopt, description, action))
  85.  
  86. def on(shortopt: String, longopt: String, description: String, action: => Unit) =
  87. add(new FlagOptionDefinition(shortopt, longopt, description, action))
  88.  
  89. def separator(description: String) =
  90. add(new SeparatorDefinition(description))
  91.  
  92. def help(shortopt: String, longopt: String) =
  93. add(new FlagOptionDefinition(shortopt, longopt, "Show this help", { this.showUsage; exit }))
  94.  
  95. // we have to give these typed options separate names, because of &^@$! type erasure
  96. def onInt(shortopt: String, longopt: String, description: String, action: Int => Unit) =
  97. add(new IntArgOptionDefinition(shortopt, longopt, description, action))
  98.  
  99. def onDouble(shortopt: String, longopt: String, description: String, action: Double => Unit) =
  100. add(new DoubleArgOptionDefinition(shortopt, longopt, description, action))
  101.  
  102. def onBoolean(shortopt: String, longopt: String, description: String, action: Boolean => Unit) =
  103. add(new BooleanArgOptionDefinition(shortopt, longopt, description, action))
  104.  
  105. // -------- Getting usage information ---------------
  106. def descriptions: Seq[String] = options.map( opt => opt match {
  107. case x if ! x.canBeInvoked => x.description
  108. case x if x.gobbleNextArgument => x.shortopt + " <value> or " + x.longopt + " <value>: " + x.description
  109. case _ => opt.shortopt + " or " + opt.longopt + ": " + opt.description
  110. })
  111.  
  112. def usage: String = descriptions.mkString("\n")
  113.  
  114. def showUsage = Console.err.println(usage)
  115.  
  116. // -------- Parsing ---------------
  117. def parse(args: Seq[String]){
  118. var i = 0
  119. while (i < args.length) {
  120. val arg = args(i)
  121. val matchingOption = options.find( opt =>
  122. opt.canBeInvoked
  123. && (arg == opt.shortopt || arg == opt.longopt)
  124. )
  125. matchingOption match {
  126. case None => if (warnOnUnknownArgument) System.err.println("WARNING: Unknown argument '" + arg + "'")
  127. case Some(option) =>
  128. val argToPass = if (option.gobbleNextArgument) {
  129. i += 1; args(i)
  130. } else
  131. ""
  132. option.action.apply(argToPass)
  133. }
  134. i += 1
  135. }
  136. }
  137. }
Add Comment
Please, Sign In to add comment