changeset 9916:b3e680ea42ec octave-forge

@inputParser/addSwitch: implemented addSwitch method
author carandraug
date Fri, 30 Mar 2012 00:08:36 +0000
parents 17258f439dc3
children 884f4e76fe41
files main/general/inst/@inputParser/addOptional.m main/general/inst/@inputParser/addParamValue.m main/general/inst/@inputParser/addRequired.m main/general/inst/@inputParser/addSwitch.m main/general/inst/@inputParser/createCopy.m main/general/inst/@inputParser/inputParser.m main/general/inst/@inputParser/parse.m main/general/inst/@inputParser/subsref.m
diffstat 8 files changed, 84 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/main/general/inst/@inputParser/addOptional.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/addOptional.m	Fri Mar 30 00:08:36 2012 +0000
@@ -34,7 +34,7 @@
 ## @emph{Note}: if @command{ParamValue} arguments are also specified, all @command{Optional}
 ## arguments will have to be specified before.
 ##
-## @seealso{inputParser, @@inputParser/addParamValue
+## @seealso{inputParser, @@inputParser/addParamValue, @@inputParser/addSwitch,
 ## @@inputParser/addParamValue, @@inputParser/addRequired, @@inputParser/parse}
 ## @end deftypefn
 
--- a/main/general/inst/@inputParser/addParamValue.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/addParamValue.m	Fri Mar 30 00:08:36 2012 +0000
@@ -29,7 +29,7 @@
 ## for the parameter with name @var{argname}. Alternatively, a function name
 ## can be used.
 ##
-## @seealso{inputParser, @@inputParser/addOptional,
+## @seealso{inputParser, @@inputParser/addOptional, @@inputParser/addSwitch,
 ## @@inputParser/addParamValue, @@inputParser/addRequired, @@inputParser/parse}
 ## @end deftypefn
 
--- a/main/general/inst/@inputParser/addRequired.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/addRequired.m	Fri Mar 30 00:08:36 2012 +0000
@@ -37,7 +37,7 @@
 ## it must be the first (see @command{@@inputParser}).
 ##
 ## @seealso{inputParser, @@inputParser/addOptional, @@inputParser/addParamValue
-## @@inputParser/addParamValue, @@inputParser/parse}
+## @@inputParser/addParamValue, @@inputParser/addSwitch, @@inputParser/parse}
 ## @end deftypefn
 
 function inPar = addRequired (inPar, name, val)
--- a/main/general/inst/@inputParser/addSwitch.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/addSwitch.m	Fri Mar 30 00:08:36 2012 +0000
@@ -1,4 +1,4 @@
-## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+## Copyright (C) 2011-2012 Carnë Draug <carandraug+dev@gmail.com>
 ##
 ## This program is free software; you can redistribute it and/or modify it under
 ## the terms of the GNU General Public License as published by the Free Software
@@ -14,11 +14,35 @@
 ## this program; if not, see <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn {Function File} {@var{parser} =} addSwitch (@var{parser}, @var{argname}, @var{default})
-## @deftypefnx {Function File} {@var{parser} =} @var{parser}.addSwitch (@var{argname}, @var{default})
-## Not implemented yet
+## @deftypefn {Function File} {@var{parser} =} addSwitch (@var{parser}, @var{argname})
+## @deftypefnx {Function File} {@var{parser} =} @var{parser}.addSwitch (@var{argname})
+## Add new switch type of argument to the object @var{parser} of inputParser class.
+##
+## This method belongs to the inputParser class and implements a switch
+## arguments type of API.
+##
+## @var{argname} must be a string with the name of the new argument. Arguments
+## of this type can be specified at the end, after @code{Required} and @code{Optional},
+## and mixed between the @code{ParamValue}. They default to false. If one of the
+## arguments supplied is a string like @var{argname}, then after parsing the value
+## of @var{parse}.Results.@var{argname} will be true.
+##
+## See @command{help @@inputParser} for examples.
+##
+## @seealso{inputParser, @@inputParser/addOptional, @@inputParser/addParamValue
+## @@inputParser/addParamValue, @@inputParser/addRequired, @@inputParser/parse}
 ## @end deftypefn
 
-function inPar = addSwitch (inPar, name, def)
+function inPar = addSwitch (inPar, name)
+
+  ## check @inputParser/subsref for the actual code
+  if (nargin == 2)
+    inPar = subsref (inPar, substruct(
+                                      '.' , 'addParamValue',
+                                      '()', {name}
+                                      ));
+  else
+    print_usage;
+  endif
 
 endfunction
--- a/main/general/inst/@inputParser/createCopy.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/createCopy.m	Fri Mar 30 00:08:36 2012 +0000
@@ -19,7 +19,7 @@
 ## class.
 ##
 ## @seealso{inputParser, @@inputParser/addOptional, @@inputParser/addParamValue
-## @@inputParser/addParamValue, @@inputParser/addRequired,
+## @@inputParser/addParamValue, @@inputParser/addRequired, @@inputParser/addSwitch,
 ## @@inputParser/parse}
 ## @end deftypefn
 
--- a/main/general/inst/@inputParser/inputParser.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/inputParser.m	Fri Mar 30 00:08:36 2012 +0000
@@ -1,4 +1,4 @@
-## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+## Copyright (C) 2011-2012 Carnë Draug <carandraug+dev@gmail.com>
 ##
 ## This program is free software; you can redistribute it and/or modify it under
 ## the terms of the GNU General Public License as published by the Free Software
@@ -24,7 +24,7 @@
 ## @item mandatory (see @command{@@inputParser/addRequired});
 ## @item optional (see @command{@@inputParser/addOptional});
 ## @item named (see @command{@@inputParser/addParamValue});
-## @item switch (not implemented yet).
+## @item switch (see @command{@@inputParser/addSwitch}).
 ## @end enumerate
 ##
 ## After defining the function API with this methods, the supplied arguments can
@@ -53,7 +53,10 @@
 ## @deftypefnx {Class property} parser.KeepUnmatched = @var{boolean}
 ## Set whether an error should be given for non-defined arguments. Defaults to
 ## false. If set to true, the extra arguments can be accessed through
-## @code{Unmatched} after the @code{parse} method.
+## @code{Unmatched} after the @code{parse} method. Note that since @command{Switch}
+## and @command{ParamValue} arguments can be mixed, it is not possible to know
+## the unmatched type. If argument is found unmatched it is assumed to be of the
+## @command{ParamValue} type and it is expected to be followed by a value.
 ##
 ## @deftypefnx {Class property} parser.StructExpand = @var{boolean}
 ## Set whether a structure can be passed to the function instead of parameter
@@ -77,13 +80,16 @@
 ##     ## create two ParamValue type of arguments
 ##     val_type = @@(x) ischar(x) && any(strcmp(x, @{"linear", "quadratic"@});
 ##     p = p.addParamValue ("type", "linear", @@val_type);
-##     val_verb = @@(x) ischar(x) && any(strcmp(x, @{"silent", "verbose", "debug"@});
-##     p = p.addParamValue ("verbosity", "silent", @@val_verb)';
+##     val_verb = @@(x) ischar(x) && any(strcmp(x, @{"low", "medium", "high"@});
+##     p = p.addParamValue ("tolerance", "low", @@val_verb);
+##
+##     ## create a switch type of argument
+##     p = p.addSwitch ("verbose");
 ##
 ##     p = p.parse (pack, path, mat, varargin@{:@});
 ##
 ##     ## the rest of the function can access the input by accessing p.Results
-##     ## for example, to access the value of verbosity, use p.Results.verbosity
+##     ## for example, to access the value of tolerance, use p.Results.tolerance
 ## endfunction
 ##
 ## check ("mech");            # valid, will use defaults for other arguments
@@ -93,6 +99,10 @@
 ##
 ## check ("mech", "~/dev", [0 1 0 0], "type", "linear");  # valid
 ##
+## ## the following is also valid. Note how the Switch type of argument can be
+## ## mixed into or before the ParamValue (but still after Optional)
+## check ("mech", "~/dev", [0 1 0 0], "verbose", "tolerance", "high");
+##
 ## ## the following returns an error since not all optional arguments, `path' and
 ## ## `mat', were given before the named argument `type'.
 ## check ("mech", "~/dev", "type", "linear");
@@ -107,7 +117,8 @@
 ##
 ## @emph{Note 2}: if both @command{Optional} and @command{ParamValue} arguments
 ## are mixed in a function API, the user will have to specify @emph{all}
-## @command{Optional} arguments before the @command{ParamValue} arguments.
+## @command{Optional} arguments before the @command{ParamValue} and
+## @command{Switch}arguments.
 ##
 ## @seealso{@@inputParser/addOptional, @@inputParser/addSwitch,
 ## @@inputParser/addParamValue, @@inputParser/addRequired,
@@ -128,6 +139,7 @@
   inPar.ParamValue    = struct;
   inPar.Optional      = struct;
   inPar.Required      = struct;
+  inPar.Switch        = struct;
 
   ## this will be filled when the methodd parse is used and will be a struct whose
   ## fieldnames are the argnames that return their value
--- a/main/general/inst/@inputParser/parse.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/parse.m	Fri Mar 30 00:08:36 2012 +0000
@@ -23,7 +23,7 @@
 ## accessor. See @command{help inputParser} for a more complete description.
 ##
 ## @seealso{inputParser, @@inputParser/addOptional, @@inputParser/addParamValue
-## @@inputParser/addParamValue, @@inputParser/addRequired}
+## @@inputParser/addParamValue, @@inputParser/addRequired, @@inputParser/addSwitch}
 ## @end deftypefn
 
 function inPar = parse (inPar, varargin)
--- a/main/general/inst/@inputParser/subsref.m	Thu Mar 29 22:55:39 2012 +0000
+++ b/main/general/inst/@inputParser/subsref.m	Fri Mar 30 00:08:36 2012 +0000
@@ -1,4 +1,4 @@
-## Copyright (C) 2011 Carnë Draug <carandraug+dev@gmail.com>
+## Copyright (C) 2011-2012 Carnë Draug <carandraug+dev@gmail.com>
 ##
 ## This program is free software; you can redistribute it and/or modify it under
 ## the terms of the GNU General Public License as published by the Free Software
@@ -38,7 +38,7 @@
     inPar = parse_args (inPar, idx);
   case 'Unmatched'
   case 'UsingDefaults'
-  case {'addOptional', 'addParamValue', 'addRequired'}
+  case {'addOptional', 'addParamValue', 'addRequired', 'addSwitch'}
     inPar = check_methods (inPar, idx);
   otherwise
     error ("invalid index for reference of class %s", class (inPar) );
@@ -109,39 +109,47 @@
     inPar.Results.(name) = value;
   endfor
 
-  ## only ParamValue can be after Optional so their number must be even
-  if ( rem (numel (args), 2) )
-    error("%sodd number of Parameter/Values arguments", inPar.FunctionName);
-  endif
-
   ## loop a maximum #times of the number of ParamValue, taking pairs of keys and
   ## values out 'args'. We no longer expect an order so we need the index in
   ## 'copy' to remove it from there. Once ran out of 'args', move their name
   ## into usingDefaults, place their default values into 'Results', and break
-  for i = 1 : numel (fieldnames (inPar.ParamValue))
+  for i = 1 : (numel (fieldnames (inPar.ParamValue)) + numel (fieldnames (inPar.Switch)))
     if ( !numel (args) )
       ## loops the number of times left in 'copy' since these are the last type
       for n = 1 : numel (inPar.copy)
         [name, inPar.copy]   = pop (inPar.copy);
         inPar.UsingDefaults  = push (inPar.UsingDefaults, name);
-        inPar.Results.(name) = inPar.ParamValue.(name).default;
+        if (isfield (inPar.ParamValue, name))
+          inPar.Results.(name) = inPar.ParamValue.(name).default;
+        else
+          inPar.Results.(name) = inPar.Switch.(name).default;
+        endif
       endfor
       break
     endif
-    [key, args]   = pop (args);
-    [value, args] = pop (args);
+    [key, args] = pop (args);
     if ( !ischar (key) )
-      error("%sParameter names must be strings", inPar.FunctionName);
+      error("%sParameter/Switch names must be strings", inPar.FunctionName);
     endif
     if (inPar.CaseSensitive)
       index = find( strcmp(inPar.copy, key));
     else
       index = find( strcmpi(inPar.copy, key));
     endif
+    ## we can't use isfield here to support case insensitive
+    if (any (strcmpi (fieldnames (inPar.Switch), key)))
+      value  = true;
+      method = "Switch";
+    else
+      ## then it must be a ParamValue, pop its value
+      [value, args] = pop (args);
+      method = "ParamValue";
+    endif
+
     ## index == 0 means no match so either return error or move them into 'Unmatched'
     if ( index != 0 )
       [name, inPar.copy] = pop (inPar.copy, index);
-      if ( !feval (inPar.ParamValue.(name).validator, value) )
+      if ( !feval (inPar.(method).(name).validator, value))
         error("%sinvalid value for parameter '%s'", inPar.FunctionName, key);
       endif
       ## we use the name popped from 'copy' instead of the key from 'args' in case
@@ -188,7 +196,7 @@
   ## a validator is optional but that complicates handling all the parsing with
   ## few functions and conditions. If not specified @() true will always return
   ## true. Simply using true is not enough because if the argument is zero it
-  ## return false and it it's too large, takes up memory
+  ## return false and if it's too large, takes up memory
   switch method
   case {'addOptional', 'addParamValue'}
     if     ( numel (args) == 1 )
@@ -208,6 +216,9 @@
       print_usage(func);
     endif
     def = false;
+  case {'addSwitch'}
+    val = def_val;
+    def = false;
   otherwise
     error ("invalid index for reference of class %s", class (inPar) );
   endswitch
@@ -238,13 +249,14 @@
   endif
 
   ## because the order arguments are specified are the order they are expected,
-  ## can't have ParamValue before Optional, and Optional before Required
+  ## can't have ParamValue/Switch before Optional, and Optional before Required
   n_optional  = numel (fieldnames (inPar.Optional));
   n_params    = numel (fieldnames (inPar.ParamValue));
-  if     ( strcmp (method, 'Required') && ( n_optional || n_params ) )
-    error ("Can't specify 'Required' arguments after Optional or ParamValue");
-  elseif ( strcmp (method, 'Optional') && n_params )
-    error ("Can't specify 'Required' arguments after Optional or ParamValue");
+  n_switch    = numel (fieldnames (inPar.Switch));
+  if     ( strcmp (method, 'Required') && ( n_optional || n_params || n_switch) )
+    error ("Can't specify 'Required' arguments after Optional, ParamValue or Switch");
+  elseif ( strcmp (method, 'Optional') && ( n_params || n_switch) )
+    error ("Can't specify 'Optional' arguments after ParamValue or Switch");
   endif
 
   ## even if CaseSensitive is turned on, we still shouldn't have two args with