X-Git-Url: http://nitlanguage.org diff --git a/lib/opts.nit b/lib/opts.nit index 20bf42f..fa5ce15 100644 --- a/lib/opts.nit +++ b/lib/opts.nit @@ -29,26 +29,28 @@ abstract class Option var errors: Array[String] = new Array[String] # Is this option mandatory? - var mandatory: Bool writable = false + var mandatory: Bool = false is writable # Is this option hidden from `usage`? - var hidden: Bool writable = false + var hidden: Bool = false is writable # Has this option been read? - var read: Bool writable = false + var read: Bool = false is writable # Current value of this option - var value: VALUE writable + var value: VALUE is writable # Default value of this option - var default_value: VALUE writable + var default_value: VALUE is writable # Create a new option - init(help: String, default: VALUE, names: nullable Array[String]) - do + init(help: String, default: VALUE, names: nullable Array[String]) is old_style_init do init_opt(help, default, names) end + # Init option `helptext`, `default_value` and `names`. + # + # Also set current `value` to `default`. fun init_opt(help: String, default: VALUE, names: nullable Array[String]) do if names == null then @@ -80,10 +82,11 @@ abstract class Option return text.to_s end + # Pretty print the default value. fun pretty_default: String do var dv = default_value - if dv != null then return " ({dv})" + if dv != null then return " ({dv.to_s})" return "" end @@ -97,7 +100,9 @@ end # Not really an option. Just add a line of text when displaying the usage class OptionText super Option - init(text: String) do super(text, null, null) + + # Init a new OptionText with `text`. + init(text: String) is old_style_init do super(text, null, null) redef fun pretty(off) do return to_s @@ -109,7 +114,8 @@ class OptionBool super Option redef type VALUE: Bool - init(help: String, names: String...) do super(help, false, names) + # Init a new OptionBool with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do super(help, false, names) redef fun read_param(it) do @@ -123,7 +129,8 @@ class OptionCount super Option redef type VALUE: Int - init(help: String, names: String...) do super(help, 0, names) + # Init a new OptionCount with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do super(help, 0, names) redef fun read_param(it) do @@ -135,15 +142,17 @@ end # Option with one parameter (mandatory by default) abstract class OptionParameter super Option + + # Convert `str` to a value of type `VALUE`. protected fun convert(str: String): VALUE is abstract # Is the parameter mandatory? - var parameter_mandatory: Bool writable = true + var parameter_mandatory: Bool = true is writable redef fun read_param(it) do super - if it.is_ok and it.item.chars.first != '-' then + if it.is_ok and (it.item.is_empty or it.item.chars.first != '-') then value = convert(it.item) it.next else @@ -159,7 +168,8 @@ class OptionString super OptionParameter redef type VALUE: nullable String - init(help: String, names: String...) do super(help, null, names) + # Init a new OptionString with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do super(help, null, names) redef fun convert(str) do return str end @@ -170,10 +180,14 @@ end class OptionEnum super OptionParameter redef type VALUE: Int + + # Values in the enumeration. var values: Array[String] - init(values: Array[String], help: String, default: Int, names: String...) - do + # Init a new OptionEnum from `values` with a `help` message and `names`. + # + # `default` is the index of the default value in `values`. + init(values: Array[String], help: String, default: Int, names: String...) is old_style_init do assert values.length > 0 self.values = values.to_a super("{help} <{values.join(", ")}>", default, names) @@ -190,15 +204,12 @@ class OptionEnum return id end + # Get the value name from `values`. fun value_name: String do return values[value] redef fun pretty_default do - if default_value != null then - return " ({values[default_value.as(not null)]})" - else - return "" - end + return " ({values[default_value]})" end end @@ -207,7 +218,10 @@ class OptionInt super OptionParameter redef type VALUE: Int - init(help: String, default: Int, names: String...) do super(help, default, names) + # Init a new OptionInt with a `help` message, a `default` value and `names`. + init(help: String, default: Int, names: String...) is old_style_init do + super(help, default, names) + end redef fun convert(str) do return str.to_i end @@ -217,7 +231,10 @@ class OptionFloat super OptionParameter redef type VALUE: Float - init(help: String, default: Float, names: String...) do super(help, default, names) + # Init a new OptionFloat with a `help` message, a `default` value and `names`. + init(help: String, default: Float, names: String...) is old_style_init do + super(help, default, names) + end redef fun convert(str) do return str.to_f end @@ -228,8 +245,8 @@ class OptionArray super OptionParameter redef type VALUE: Array[String] - init(help: String, names: String...) - do + # Init a new OptionArray with a `help` message and `names`. + init(help: String, names: String...) is old_style_init do values = new Array[String] super(help, values, names) end @@ -245,23 +262,15 @@ end # Context where the options process class OptionContext # Options present in the context - var options: Array[Option] + var options = new Array[Option] # Rest of the options after `parse` is called - var rest: Array[String] + var rest = new Array[String] # Errors found in the context after parsing - var errors: Array[String] + var errors = new Array[String] - private var optmap: Map[String, Option] - - init - do - options = new Array[Option] - optmap = new HashMap[String, Option] - rest = new Array[String] - errors = new Array[String] - end + private var optmap = new HashMap[String, Option] # Add one or more options to the context fun add_option(opts: Option...) do @@ -294,8 +303,15 @@ class OptionContext parse_intern(it) end + # Must all option be given before the first argument? + # + # When set to `false` (the default), options of the command line are + # all parsed until the end of the list of arguments or until "--" is met (in this case "--" is discarded). + # + # When set to `true` options are parsed until the first non-option is met. + var options_before_rest = false is writable + # Parse the command line - # FIXME: avoir crashing on a command line like : `myprog -foo` (more than one letter after a single `-`) protected fun parse_intern(it: Iterator[String]) do var parseargs = true @@ -312,7 +328,7 @@ class OptionContext # We're looking for packed short options if str.chars.last_index_of('-') == 0 and str.length > 2 then var next_called = false - for i in [1..str.length] do + for i in [1..str.length[ do var short_opt = "-" + str.chars[i].to_s if optmap.has_key(short_opt) then var option = optmap[short_opt] @@ -332,6 +348,10 @@ class OptionContext else rest.add(it.item) it.next + if options_before_rest then + rest.add_all(it.to_a) + parseargs = false + end end end end @@ -353,9 +373,10 @@ class OptionContext end end + # Options parsing errors. fun get_errors: Array[String] do - var errors: Array[String] = new Array[String] + var errors = new Array[String] errors.add_all(errors) for o in options do for e in o.errors do