changeset 32039:01868cd10060

inputParser.m: Choose exact Parameter match if it exists under PartialMatching (bug #64050). * inputParser.m (is_argname): If PartialMatching is true and more than one parameter name is found, then attempt an exact match and use it if found. Otherwise, throw an error that input name is ambiguous. Add BIST test for this behavior.
author Rik <rik@octave.org>
date Wed, 19 Apr 2023 17:02:20 -0700
parents 29671873411a
children ba0596c25479
files scripts/miscellaneous/inputParser.m
diffstat 1 files changed, 30 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/miscellaneous/inputParser.m	Wed Apr 19 10:36:29 2023 -0400
+++ b/scripts/miscellaneous/inputParser.m	Wed Apr 19 17:02:20 2023 -0700
@@ -599,22 +599,35 @@
             idx = strncmp (name, fnames, numel (name));
             r = sum (idx);
             if (r > 1)
-              matches = sprintf ("'%s', ", fnames{idx})(1:end-1);
-              matches(end) = '.';
-              this.error (sprintf ("argument '%s' matches more than one %s: %s", name, type, matches));
+              ## Check for exact match and prefer it over a partial match
+              idx2 = strcmp (name, {fnames{idx}});
+              if (any (idx2))
+                idx = (find (idx))(idx2);
+                r = 1;
+              else
+                matches = sprintf ("'%s', ", fnames{idx})(1:end-1);
+                matches(end) = '.';
+                this.error (sprintf ("argument '%s' matches more than one %s: %s", name, type, matches));
+              endif
             endif
             r = logical (r);
-          else
+          else  # not CaseSensitive
             idx = strncmpi (name, fnames, numel (name));
             r = sum (idx);
             if (r > 1)
-              matches = sprintf ("'%s', ", fnames{idx})(1:end-1);
-              matches(end) = '.';
-              this.error (sprintf ("argument '%s' matches more than one %s: %s", name, type, matches));
+              idx2 = strcmpi (name, {fnames{idx}});
+              if (any (idx2))
+                idx = (find (idx))(idx2);
+                r = 1;
+              else
+                matches = sprintf ("'%s', ", fnames{idx})(1:end-1);
+                matches(end) = '.';
+                this.error (sprintf ("argument '%s' matches more than one %s: %s", name, type, matches));
+              endif
             endif
             r = logical (r);
           endif
-        else
+        else  # no PartialMatching
           if (this.CaseSensitive)
             idx = strcmp (name, fnames);
             r = any (idx(:));
@@ -712,6 +725,15 @@
 %! assert ({r.req1, r.op1, r.op2, r.verbose, r.line},
 %!         {"file", "foo", 80,    true,      "circle"});
 
+## Check PartialMatching selects an exact match if it exists
+%!test
+%! p = inputParser ();
+%! p.addParameter ('Mass', []);
+%! p.addParameter ('MassSingular', []);
+%! p.parse ("Mass", pi);
+%! r = p.Results;
+%! assert ({r.Mass, r.MassSingular}, {pi, []});
+
 ## check KeepUnmatched
 %!test
 %! p = create_p ();