changeset 29106:c661350ee8df

__pltopt__.m: Overhaul function and add support for long color names (bug #59534). * __pltopt__.m: Don't call __default_plot_options__() unnecessarily. Add FIXME note about removing input validation for an internal function. Add BIST test for new long form color. * __pltopt__.m (decode_linespec): Rename function from "__pltopt1__" for clarity. Declare persistent variable "default_options" which calls __default_plot_options__() just once per Octave session. Simplify checking for Marker style by using "any (topt == "LIST_OF_CHARS")" rather than "topt == "+" || topt == "o" || ...". For each potential color spec, also look for long form such as "black", "blue", etc. using strncmp.
author Rik <rik@octave.org>
date Thu, 26 Nov 2020 18:25:42 -0800
parents 3d9a05cb0894
children f8afcf772ba0
files scripts/plot/util/__pltopt__.m
diffstat 1 files changed, 103 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/plot/util/__pltopt__.m	Thu Nov 26 19:25:01 2020 +0100
+++ b/scripts/plot/util/__pltopt__.m	Thu Nov 26 18:25:42 2020 -0800
@@ -93,30 +93,35 @@
 
 function [options, valid] = __pltopt__ (caller, opt, err_on_invalid = true)
 
-  options = __default_plot_options__ ();
-  valid = true;
-
   if (ischar (opt))
     opt = cellstr (opt);
   elseif (! iscellstr (opt))
+    ## FIXME: This is an internal function.  Can't we rely on valid input?
     error ("__pltopt__: argument must be a character string or cell array of character strings");
   endif
 
   nel = numel (opt);
 
-  for i = nel:-1:1
-    [options(i), valid] = __pltopt1__ (caller, opt{i}, err_on_invalid);
-    if (! err_on_invalid && ! valid)
-      return;
-    endif
-  endfor
+  if (nel) 
+    for i = nel:-1:1
+      [options(i), valid] = decode_linespec (caller, opt{i}, err_on_invalid);
+      if (! err_on_invalid && ! valid)
+        return;
+      endif
+    endfor
+  else
+    options = __default_plot_options__ ();
+    valid = true;
+  endif
 
 endfunction
 
 ## Really decode plot option strings.
-function [options, valid] = __pltopt1__ (caller, opt, err_on_invalid)
+function [options, valid] = decode_linespec (caller, opt, err_on_invalid)
 
-  options = __default_plot_options__ ();
+  persistent default_options = __default_plot_options__ ();
+
+  options = default_options;
   valid = true;
 
   have_linestyle = false;
@@ -141,79 +146,103 @@
   endif
 
   while (! isempty (opt))
+    topt = opt(1);
+    n = 1;
+
+    ## LineStyles
     if (strncmp (opt, "--", 2) || strncmp (opt, "-.", 2))
       options.linestyle = opt(1:2);
       have_linestyle = true;
       n = 2;
-    else
-      topt = opt(1);
-      n = 1;
-      if (topt == "-" || topt == ":")
-        have_linestyle = true;
-        options.linestyle = topt;
-      elseif (topt == "+" || topt == "o" || topt == "*"
-              || topt == "." || topt == "x" || topt == "s"
-              || topt == "d" || topt == "^" || topt == "v"
-              || topt == ">" || topt == "<" || topt == "p"
-              || topt == "h")
-        have_marker = true;
-        ## Check for long form marker styles
-        if (any (topt == "sdhp"))
-          if (strncmp (opt, "square", 6))
-            n = 6;
-          elseif (strncmp (opt, "diamond", 7))
-            n = 7;
-          elseif (strncmp (opt, "hexagram", 8))
-            n = 8;
-          elseif (strncmp (opt, "pentagram", 9))
-            n = 9;
-          endif
+    elseif (topt == "-" || topt == ":")
+      have_linestyle = true;
+      options.linestyle = topt;
+    ## Markers
+    elseif (any (topt == "+o*.xsd^v><ph"))
+      have_marker = true;
+      ## Check for long form marker styles
+      if (any (topt == "sdhp"))
+        if (strncmp (opt, "square", 6))
+          n = 6;
+        elseif (strncmp (opt, "diamond", 7))
+          n = 7;
+        elseif (strncmp (opt, "hexagram", 8))
+          n = 8;
+        elseif (strncmp (opt, "pentagram", 9))
+          n = 9;
         endif
-        options.marker = topt;
-      ## Color specs
-      elseif (topt == "k")
+      endif
+      options.marker = topt;
+    ## Color specs
+    elseif (topt == "k")
+      options.color = [0, 0, 0];
+    elseif (topt == "r")
+      if (strncmp (opt, "red", 3))
+        n = 3;
+      endif
+      options.color = [1, 0, 0];
+    elseif (topt == "g")
+      if (strncmp (opt, "green", 5))
+        n = 5;
+      endif
+      options.color = [0, 1, 0];
+    elseif (topt == "b")
+      if (strncmp (opt, "black", 5))
         options.color = [0, 0, 0];
-      elseif (topt == "r")
-        options.color = [1, 0, 0];
-      elseif (topt == "g")
-        options.color = [0, 1, 0];
-      elseif (topt == "b")
+        n = 5;
+      elseif (strncmp (opt, "blue", 4))
+        options.color = [0, 0, 1];
+        n = 4;
+      else
         options.color = [0, 0, 1];
-      elseif (topt == "y")
-        options.color = [1, 1, 0];
-      elseif (topt == "m")
-        options.color = [1, 0, 1];
-      elseif (topt == "c")
-        options.color = [0, 1, 1];
-      elseif (topt == "w")
-        options.color = [1, 1, 1];
-      elseif (isspace (topt))
-        ## Do nothing.
-      elseif (topt == ";")
-        t = index (opt(2:end), ";");
-        if (t)
-          options.key = opt(2:t);
-          n = t+1;
-        else
-          if (err_on_invalid)
-            error ("%s: unfinished key label", caller);
-          else
-            valid = false;
-            options = __default_plot_options__ ();
-            return;
-          endif
-        endif
+      endif
+    elseif (topt == "y")
+      if (strncmp (opt, "yellow", 6))
+        n = 6;
+      endif
+      options.color = [1, 1, 0];
+    elseif (topt == "m")
+      if (strncmp (opt, "magenta", 7))
+        n = 7;
+      endif
+      options.color = [1, 0, 1];
+    elseif (topt == "c")
+      if (strncmp (opt, "cyan", 4))
+        n = 4;
+      endif
+      options.color = [0, 1, 1];
+    elseif (topt == "w")
+      if (strncmp (opt, "white", 5))
+        n = 5;
+      endif
+      options.color = [1, 1, 1];
+    elseif (isspace (topt))
+      ## Do nothing.
+    elseif (topt == ";")
+      t = index (opt(2:end), ";");
+      if (t)
+        options.key = opt(2:t);
+        n = t+1;
       else
         if (err_on_invalid)
-          error ("%s: unrecognized format character: '%s'", caller, topt);
+          error ("%s: unfinished key label", caller);
         else
           valid = false;
-          options = __default_plot_options__ ();
+          options = default_options;
           return;
         endif
       endif
+    else
+      if (err_on_invalid)
+        error ("%s: unrecognized format character: '%s'", caller, topt);
+      else
+        valid = false;
+        options = default_options;
+        return;
+      endif
     endif
-    opt(1:n) = [];
+
+    opt(1:n) = [];  # Delete decoded portion
   endwhile
 
   if (! have_linestyle && have_marker)
@@ -240,6 +269,11 @@
 %! assert (opts.linestyle, ":");
 %! assert (opts.marker, "x");
 %!test
+%! opts = __pltopt__ ("abc", "-.blackx");
+%! assert (opts.color, [0 0 0]);
+%! assert (opts.linestyle, "-.");
+%! assert (opts.marker, "x");
+%!test
 %! opts = __pltopt__ ("abc", "gsquare");
 %! assert (opts.color, [0 1 0]);
 %! assert (opts.linestyle, "none");