changeset 9806:8e345f2fe4d6

improved support for Contents.m files
author John W. Eaton <jwe@octave.org>
date Wed, 11 Nov 2009 15:11:14 -0500
parents bb70d16cca3b
children 645c478aa89d
files scripts/ChangeLog scripts/help/help.m src/ChangeLog src/help.cc src/load-path.cc src/load-path.h src/utils.cc
diffstat 7 files changed, 208 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Wed Nov 11 13:46:50 2009 -0500
+++ b/scripts/ChangeLog	Wed Nov 11 15:11:14 2009 -0500
@@ -1,3 +1,10 @@
+2009-11-11  John W. Eaton  <jwe@octave.org>
+
+	* help/help.m (help): Return immediately after calling do_contents.
+	(do_contents): Find all matching directories, not just the first.
+	Call get_help_text_from_file to avoid looking in path.
+	Handle printing here.
+
 2009-11-10  John W. Eaton  <jwe@octave.org>
 
 	* Makefile.am, audio/module.mk, deprecated/module.mk,
--- a/scripts/help/help.m	Wed Nov 11 13:46:50 2009 -0500
+++ b/scripts/help/help.m	Wed Nov 11 15:11:14 2009 -0500
@@ -65,10 +65,8 @@
       case "not documented"
         error ("help: `%s' is not documented\n", name);
       case "not found"
-        [text, status] = do_contents (name);
-        if (status != 0)
-          error ("help: `%s' not found\n", name);
-        endif
+        do_contents (name);
+	return;
       otherwise
         error ("help: internal error: unsupported help text format: '%s'\n", format);
     endswitch
@@ -87,30 +85,40 @@
 
 endfunction
 
-function [text, status] = do_contents (name)
-  text = "";
-  status = 1;
+function do_contents (name)
+
+  found = false;
 
-  d = find_dir_in_path (name);
-  if (!isempty (d))
-    p = path ();
-    unwind_protect
-      ## Only include 'd' in the path, and then get the help text of 'Contents'
-      path (d);
-      [text, format] = get_help_text ("Contents");
+  dlist = find_dir_in_path (name, "all");
+
+  for i = 1:numel (dlist)
+    fname = make_absolute_filename (fullfile (dlist{i}, "Contents.m"));
+
+    [text, format] = get_help_text_from_file (fname);
 
-      ## Take action depending on help text format
-      switch (lower (format))
-        case "plain text"
-          status = 0;
-        case "texinfo"
-          [text, status] = __makeinfo__ (text, "plain text");
-        case "html"
-          [text, status] = strip_html_tags (text);
-      endswitch
-    unwind_protect_cleanup
-      ## Restore path
-      path (p);
-    end_unwind_protect
+    ## Take action depending on help text format
+    switch (lower (format))
+      case "plain text"
+	status = 0;
+      case "texinfo"
+	[text, status] = __makeinfo__ (text, "plain text");
+      case "html"
+	[text, status] = strip_html_tags (text);
+    endswitch
+
+    if (! isempty (text))
+      found = true;
+      ## Print text.
+      if (status != 0)
+	warning ("help: Texinfo formatting filter exited abnormally; raw Texinfo source of help text follows...\n");
+      endif
+      printf ("%s:\n\n%s\n", fname, text);
+    endif
+
+  endfor
+
+  if (found)
+    puts (__additional_help_message__ ());
   endif
+
 endfunction
--- a/src/ChangeLog	Wed Nov 11 13:46:50 2009 -0500
+++ b/src/ChangeLog	Wed Nov 11 15:11:14 2009 -0500
@@ -1,3 +1,16 @@
+2009-11-11  John W. Eaton  <jwe@octave.org>
+
+	* help.cc (do_get_help_text_from_file, Fget_help_text_from_file):
+	New functions.
+	(do_get_help_text): Pass NAME by const reference.
+	* utils.cc (find_dir_in_path): New optional argument "all".
+	* load-path.cc (load_path::do_find_matching_dirs): New function.
+	(load_path::do_find_dir): Perform match on absolute directory
+	names, but return name as it appears in dir_info_list.  Adjust
+	dname_len after stripping directory separator.
+	* load-path.h (load_path::do_find_matching_dirs): Provide decl.
+	(load_path::find_matching_dirs): New function.
+
 2009-11-11  Shai Ayal  <shaiay@users.sourceforge.net>
 
 	* DLD-FUNCTIONS/fltk_backend.cc (Fl_Gl_Window::draw):
--- a/src/help.cc	Wed Nov 11 13:46:50 2009 -0500
+++ b/src/help.cc	Wed Nov 11 15:11:14 2009 -0500
@@ -705,7 +705,7 @@
 }
 
 static void
-do_get_help_text (const std::string name, std::string& text,
+do_get_help_text (const std::string& name, std::string& text,
 		  std::string& format)
 {
   bool symbol_found = false;
@@ -774,6 +774,80 @@
   return retval;
 }
 
+static void
+do_get_help_text_from_file (const std::string& fname, std::string& text,
+			    std::string& format)
+{
+  bool symbol_found = false;
+
+  std::string f;
+
+  raw_help_from_file (fname, text, f, symbol_found);
+
+  format = "Not found";
+  if (symbol_found)
+    {
+      size_t idx = -1;
+      if (text.empty ())
+        {
+          format = "Not documented";
+        }
+      else if (looks_like_texinfo (text, idx))
+        {
+          format = "texinfo";
+          text.erase (0, idx);
+        }
+      else if (looks_like_html (text))
+        {
+          format = "html";
+        }
+      else
+        {
+          format = "plain text";
+        }
+    }
+}
+
+DEFUN (get_help_text_from_file, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn {Loadable Function} {[@var{text}, @var{format}] =} get_help_text_from_file (@var{fname})\n\
+Returns the help text from the given file.\n\
+\n\
+This function returns the raw help text @var{text} and an indication of\n\
+its format for the function @var{name}.  The format indication @var{format}\n\
+is a string that can be either @t{\"texinfo\"}, @t{\"html\"}, or\n\
+@t{\"plain text\"}.\n\
+\n\
+To convert the help text to other formats, use the @code{makeinfo} function.\n\
+\n\
+@seealso{makeinfo}\n\
+@end deftypefn")
+{
+  octave_value_list retval;
+
+  if (args.length () == 1)
+    {
+      const std::string fname = args(0).string_value ();
+
+      if (! error_state)
+	{
+	  std::string text;
+	  std::string format;
+
+	  do_get_help_text_from_file (fname, text, format);
+  
+	  retval(1) = format;
+	  retval(0) = text;
+	}
+      else
+	error ("get_help_text_from_file: invalid input");
+    }
+  else
+    print_usage ();
+
+  return retval;
+}
+
 // Return a cell array of strings containing the names of all
 // operators.
 
--- a/src/load-path.cc	Wed Nov 11 13:46:50 2009 -0500
+++ b/src/load-path.cc	Wed Nov 11 15:11:14 2009 -0500
@@ -1167,12 +1167,16 @@
 	   p != dir_info_list.end ();
 	   p++)
 	{
-	  std::string dname = p->dir_name;
+	  std::string dname
+	    = octave_env::make_absolute (p->dir_name, octave_env::getcwd ());
 
 	  size_t dname_len = dname.length ();
 
 	  if (dname.substr (dname_len - 1) == file_ops::dir_sep_str ())
-	    dname = dname.substr (0, dname_len - 1);
+	    {
+	      dname = dname.substr (0, dname_len - 1);
+	      dname_len--;
+	    }
 
 	  size_t dir_len = dir.length ();
 
@@ -1191,6 +1195,54 @@
   return retval;
 }
 
+string_vector
+load_path::do_find_matching_dirs (const std::string& dir) const
+{
+  std::list<std::string> retlist;
+
+  if (dir.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos
+      && (octave_env::absolute_pathname (dir)
+	  || octave_env::rooted_relative_pathname (dir)))
+    {
+      file_stat fs (dir);
+
+      if (fs.exists () && fs.is_dir ())
+	retlist.push_back (dir);
+    }
+  else
+    {
+      for (const_dir_info_list_iterator p = dir_info_list.begin ();
+	   p != dir_info_list.end ();
+	   p++)
+	{
+	  std::string dname
+	    = octave_env::make_absolute (p->dir_name, octave_env::getcwd ());
+
+	  size_t dname_len = dname.length ();
+
+	  if (dname.substr (dname_len - 1) == file_ops::dir_sep_str ())
+	    {
+	      dname = dname.substr (0, dname_len - 1);
+	      dname_len--;
+	    }
+
+	  size_t dir_len = dir.length ();
+
+	  if (dname_len >= dir_len
+	      && file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
+	      && dir.compare (dname.substr (dname_len - dir_len)) == 0)
+	    {
+	      file_stat fs (p->dir_name);
+
+	      if (fs.exists () && fs.is_dir ())
+		retlist.push_back (p->dir_name);
+	    }
+	}
+    }
+
+  return retlist;
+}
+
 std::string
 load_path::do_find_first_of (const string_vector& flist) const
 {
--- a/src/load-path.h	Wed Nov 11 13:46:50 2009 -0500
+++ b/src/load-path.h	Wed Nov 11 15:11:14 2009 -0500
@@ -169,6 +169,12 @@
       ? instance->do_find_dir (dir) : std::string ();
   }
 
+  static string_vector find_matching_dirs (const std::string& dir)
+  {
+    return instance_ok ()
+      ? instance->do_find_matching_dirs (dir) : string_vector ();
+  }
+
   static std::string find_first_of (const string_vector& files)
   {
     return instance_ok () ?
@@ -479,6 +485,8 @@
 
   std::string do_find_dir (const std::string& dir) const;
 
+  string_vector do_find_matching_dirs (const std::string& dir) const;
+
   std::string do_find_first_of (const string_vector& files) const;
 
   string_vector do_find_all_first_of (const string_vector& files) const;
--- a/src/utils.cc	Wed Nov 11 13:46:50 2009 -0500
+++ b/src/utils.cc	Wed Nov 11 15:11:14 2009 -0500
@@ -802,22 +802,34 @@
 
 DEFUN (find_dir_in_path, args, ,
   "-*- texinfo -*-\n\
-@deftypefn {Built-in Function} {} find_dir_in_path (@var{dir})\n\
+@deftypefn {Built-in Function} {} find_dir_in_path (@var{dir}, \"all\")\n\
 Return the full name of the path element matching @var{dir}.  The\n\
 match is performed at the end of each path element.  For example, if\n\
 @var{dir} is @code{\"foo/bar\"}, it matches the path element\n\
 @code{\"/some/dir/foo/bar\"}, but not @code{\"/some/dir/foo/bar/baz\"}\n\
 or @code{\"/some/dir/allfoo/bar\"}.\n\
+\n\
+The second argument is optional.  If it is supplied, return a cell array\n\
+containing all the directory names that match.\n\
 @end deftypefn")
 {
   octave_value retval = std::string ();
 
-  if (args.length () == 1)
+  int nargin = args.length ();
+
+  std::string dir;
+
+  if (nargin == 1 || nargin == 2)
     {
-      std::string dir = args(0).string_value ();
+      dir = args(0).string_value ();
 
       if (! error_state)
-	retval = load_path::find_dir (dir);
+	{
+	  if (nargin == 1)
+	    retval = load_path::find_dir (dir);
+	  else if (nargin == 2)
+	    retval = Cell (load_path::find_matching_dirs (dir));
+	}
       else
 	error ("find_dir_in_path: expecting argument to be a directory name");
     }