changeset 20135:4c6d70a35192

lookfor.m: Overhaul function and fix bug #44924. * lookfor.m: Rewrite docstring. Match variable names in function prototype to docstring. Use more meaningful variable names throughout function. Don't continue to process a function if get_first_help_sentence returns an error (bug #44924). Iterate directly over cell list rather than using a for loop with a range to index into cell list.
author Rik <rik@octave.org>
date Sun, 26 Apr 2015 21:14:53 -0700
parents 57b6e06ed811
children 46fb763e5f3a
files scripts/help/lookfor.m
diffstat 1 files changed, 71 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/help/lookfor.m	Sun Apr 26 22:36:44 2015 -0400
+++ b/scripts/help/lookfor.m	Sun Apr 26 21:14:53 2015 -0700
@@ -19,50 +19,52 @@
 ## -*- texinfo -*-
 ## @deftypefn  {Command} {} lookfor @var{str}
 ## @deftypefnx {Command} {} lookfor -all @var{str}
-## @deftypefnx {Function File} {[@var{func}, @var{helpstring}] =} lookfor (@var{str})
-## @deftypefnx {Function File} {[@var{func}, @var{helpstring}] =} lookfor ("-all", @var{str})
-## Search for the string @var{str} in all functions found in the current
-## function search path.  By default, @code{lookfor} searches for @var{str}
-## in the first sentence of the help string of each function found.  The entire
-## help text of each function can be searched if the @qcode{"-all"} argument is
-## supplied.  All searches are case insensitive.
+## @deftypefnx {Function File} {[@var{fcn}, @var{help1str}] =} lookfor (@var{str})
+## @deftypefnx {Function File} {[@var{fcn}, @var{help1str}] =} lookfor ("-all", @var{str})
+## Search for the string @var{str} in all functions using the current function
+## search path.
+##
+## By default, @code{lookfor} looks for @var{str} in the first sentence of the
+## help string for each function found.  The entire help text of each function
+## can be searched by using the @qcode{"-all"} argument.  All searches are case
+## insensitive.
 ##
-## Called with no output arguments, @code{lookfor} prints the list of
-## matching functions to the terminal.  Otherwise, the output arguments
-## @var{func} and @var{helpstring} define the matching functions and the
-## first sentence of each of their help strings.
+## When called with no output arguments, @code{lookfor} prints the list of
+## matching functions to the terminal.  Otherwise, the output argument
+## @var{fcns} contains the function names and @var{help1str} contains the first
+## sentence from the help string of each function.
 ##
-## The ability of @code{lookfor} to correctly identify the first
-## sentence of the help text is dependent on the format of the
-## function's help.  All Octave core functions are correctly
-## formatted, but the same can not be guaranteed for external packages and
-## user-supplied functions.  Therefore, the use of the @qcode{"-all"}
-## argument may be necessary to find related functions that are not a part of
-## Octave.
+## Programming Note: The ability of @code{lookfor} to correctly identify the
+## first sentence of the help text is dependent on the format of the function's
+## help.  All Octave core functions are correctly formatted, but the same can
+## not be guaranteed for external packages and user-supplied functions.
+## Therefore, the use of the @qcode{"-all"} argument may be necessary to find
+## related functions that are not a part of Octave.
 ## @seealso{help, doc, which}
 ## @end deftypefn
 
-function [out_fun, out_help_text] = lookfor (str, arg2)
+function [fcn, help1str] = lookfor (str, arg2)
 
   if (strcmpi (str, "-all"))
-    ## The difference between using '-all' and not, is which part of the caches
-    ## we search.  The cache is organized such that the first column contains
-    ## the function name, the second column contains the full help text, and
-    ## the third column contains the first sentence of the help text.
+    ## The difference between using '-all' and not is which part of the caches
+    ## we search.  The cache is organized such that row
+    ## 1) contains the function name
+    ## 2) contains the full help text
+    ## 3) contains the first sentence of the help text.
     str = arg2;
-    search_type = 2; # when using caches, search the second column
+    search_type = 2;  # search the second row (full help text)
   else
-    search_type = 3; # when using caches, search the third column
+    search_type = 3;  # search the third column (first help sentence)
   endif
-  str = lower (str);   # Compare is case insensitive
+  str = lower (str);  # Compare is case insensitive
 
   ## Search functions, operators, and keywords that come with Octave
   cache_file = doc_cache_file ();
   if (exist (cache_file, "file"))
-    [fun, help_text] = search_cache (str, cache_file, search_type);
+    [fcnlist, help_text] = search_cache (str, cache_file, search_type);
     had_core_cache = true;
   else
-    fun = help_text = {};
+    fcnlist = help_text = {};
     had_core_cache = false;
   endif
 
@@ -72,37 +74,38 @@
   ## ditto for path.
   new_path = ostrsplit (path (), pathsep ());
 
-  ## scratch out directories already covered by orig_path.
+  ## remove  directories already covered by orig_path.
   if (had_core_cache)
     new_path = setdiff (new_path, orig_path);
   endif
 
   for n = 1:numel (new_path)
-    elt = new_path{n};
-    cache_file = fullfile (elt, "doc-cache");
+    fcndir = new_path{n};
+    cache_file = fullfile (fcndir, "doc-cache");
     if (exist (cache_file, "file"))
       ## We have a cache in the directory, then read it and search it!
-      [funs, hts] = search_cache (str, cache_file, search_type);
-      fun(end+1:end+length (funs)) = funs;
-      help_text(end+1:end+length (hts)) = hts;
+      [fcns, htext] = search_cache (str, cache_file, search_type);
+      fcnlist(end+1:end+length (fcns)) = fcns;
+      help_text(end+1:end+length (htext)) = htext;
+
     else
-    ## We don't have a cache. Search files
-      funs_in_f = __list_functions__ (elt);
-      for m = 1:length (funs_in_f)
-        fn = funs_in_f{m};
+      ## We don't have a cache.  Search files.
+      for fcn_in_fcndir = (__list_functions__ (fcndir)).'
+        fn = fcn_in_fcndir{1};
 
-        ## Skip files that start with __
-        if (length (fn) > 2 && strcmp (fn(1:2), "__"))
+        ## Skip files that start with "__"
+        if (strncmp (fn, "__", 2))
           continue;
         endif
 
+        status = 0;
+
         ## Extract first sentence
         try
           warn_state = warning ();
           unwind_protect
             warning ("off");
             first_sentence = get_first_help_sentence (fn, 1024);
-            status = 0;
           unwind_protect_cleanup
             warning (warn_state);
           end_unwind_protect
@@ -110,39 +113,39 @@
           status = 1;
         end_try_catch
 
-        if (search_type == 2) # search entire help text
+        if (status)
+          ## Error getting first help sentence
+        elseif (search_type == 3)
+          ## only search the first sentence of the help text
+          text = first_sentence;
+        elseif (search_type == 2)
+          ## search entire help text
           try
             warn_state = warning ();
             unwind_protect
               warning ("off");
               [text, fmt] = get_help_text (fn);
-              status = 0;
+              switch (lower (fmt))
+                case "plain text"
+                  status = 0;
+                case "texinfo"
+                  [text, status] = __makeinfo__ (text, "plain text");
+                case "html"
+                  [text, status] = strip_html_tags (text);
+                otherwise
+                  status = 1;
+              endswitch
             unwind_protect_cleanup
               warning (warn_state);
             end_unwind_protect
           catch
             status = 1;
           end_try_catch
-
-          ## Take action depending on help text fmt
-          switch (lower (fmt))
-            case "plain text"
-              status = 0;
-            case "texinfo"
-              [text, status] = __makeinfo__ (text, "plain text");
-            case "html"
-              [text, status] = strip_html_tags (text);
-            otherwise
-              status = 1;
-          endswitch
-
-        elseif (status == 0) # only search the first sentence of the help text
-          text = first_sentence;
         endif
 
-        ## Search the help text, if we can
-        if (status == 0 && ! isempty (strfind (lower (text), str)))
-          fun(end+1) = fn;
+        ## Search the help text
+        if (status == 0 && strfind (lower (text), str))
+          fcnlist(end+1) = fn;
           help_text(end+1) = first_sentence;
         endif
       endfor
@@ -155,8 +158,8 @@
     term_width = (terminal_size ())(2);
     desc_width = term_width - indent - 2;
     indent_space = blanks (indent);
-    for k = 1:length (fun)
-      f = fun{k};
+    for k = 1:length (fcnlist)
+      f = fcnlist{k};
       f(end+1:indent-1) = " ";
       puts ([f " "]);
       lf = length (f);
@@ -168,25 +171,24 @@
         printf ("%s%s\n", indent_space, strtrim (desc (start:stop)));
       endfor
     endfor
-
   else
     ## Return the results instead of displaying them
-    out_fun = fun;
-    out_help_text = help_text;
+    fcn = fcnlist;
+    help1str = help_text;
   endif
 
 endfunction
 
-function [funs, help_texts] = search_cache (str, cache_file, search_type)
+function [fcns, help_texts] = search_cache (str, cache_file, search_type)
   load (cache_file);
   if (! isempty (cache))
     t1 = strfind (lower (cache (1, :)), str);
     t2 = strfind (lower (cache (search_type, :)), str);
     cache_idx = find (! (cellfun ("isempty", t1) & cellfun ("isempty", t2)));
-    funs = cache(1, cache_idx);
+    fcns = cache(1, cache_idx);
     help_texts = cache(3, cache_idx);
   else
-    funs = help_texts = {};
+    fcns = help_texts = {};
   endif
 endfunction