On 18/feb/08, at 15:28, David Bateman wrote:

c. wrote:
On 18/feb/08, at 13:33, David Bateman wrote:


c. wrote:

Does the attached patch do what you intended?

It fails on the signal package that includes variables in the INDEX
file
like

<quote>
$SPCTOOLS= in spline directory of Dennis Brown's <a
href="ftp://svr-ftp.eng.cam.ac.uk/pub/comp.speech/tools/
spctools">SPCtools</a>
$TFTB= try <a
href="http://www-isis.enst.fr/Applications/tftb/iutsn.univ-
nantes.fr/auger/tftb.html">Time-Frequency
Tool box</a>


signal >> Signal processing
Signals
 diric
 gauspuls
 ...
</quote>

The function categories are incorrectly probed.. You should scan for
"signal >>" and ignore anything beforehand.. Apart from that it
looks good..

D.


David,

Looking at the INDEX for the signal package I also see lines like:

arcov= use <code>ar_covar</code> $SPCTOOLS

I was not aware that such things were possible...
I see this syntax is explained in the comments to main/INDEX while it
is not
on the octave-forge website (wouldn't it be worth adding at least a
reference
to this syntax specification on http://octave.sourceforge.net/
developers.html ?).

To handle such lines with variable substitution and markup tags will
require a bit more
logic than expected, I'll look into it.
Would a patch that implements just skipping those lines be acceptable
for the meantime?
After all this syntax is expected to be used for functions that are
not implemented in the
package, anyway...

c.

P.S. I see the inline octave documentation (doc pkg) also has a section
describing the syntax of the INDEX file but does not mention variable
substitution or markup language.

These variables are typical to give the user a reference to an
alternative means of achieving something in Octave that you can achieve
in Matlab. Therefore its probably better not to use the INDEX files at
all and use the method you previously used of scanning the *.m *.oct and
*.mex files.. Though you'll also need to take care of the dispatch
commands that might be in the PKG_ADD files.

D.


After thinking about this for a while I believe that parsing the INDEX file is still the way to go... The INDEX file is optional, if it is not there it is generated automatically by scanning the package directory,
so there are two cases:

1) The package developer didn't bother to write an INDEX, his package is just a set of functions that he believes do not need to be organized into categories or distinguished one from the other.

in this case the package directory is scanned for a list of functions at the time of install (or rebuild) so to get the list of functions one can parse the INDEX. If the INDEX is missing or corrupted throw an error prompting the user to run 'pkg rebuild'

2) The package developer chose to list only some specific functions in the INDEX file and to organize them into categories. In this case I think the choice of which functions deserve to be listed should be left to the package developer ( non indexed functions may be just for internal use for example), so again parsing the INDEX should be the correct way to get the list of functions.

The attached patch solves the issue with the hiccup on 'pkg describe signal' and implements the behavior described above (which is that intended in the previous version).

What do you think about this?
c.

# HG changeset patch
# User [EMAIL PROTECTED]
# Date 1203424043 0
# Node ID 630ddf983154c1c2d3bb51b1cace09913abf560d
# Parent  bd2bd04e68caf5f52746265c87409a34d037294f
added describe command to pkg

diff -r bd2bd04e68ca -r 630ddf983154 scripts/ChangeLog
--- a/scripts/ChangeLog Mon Feb 18 18:08:29 2008 +0100
+++ b/scripts/ChangeLog Tue Feb 19 12:27:23 2008 +0000
@@ -1,3 +1,10 @@ 2008-02-19  Bill Denney  <[EMAIL PROTECTED]
+2008-02-19 Carlo de Falco <[EMAIL PROTECTED]>
+
+       * pkg/pkg.m: Added the 'describe' ommand to pkg.
+       (pkg:parse_pkg_idx): Parses the INDEX file of a package.
+       (pkg:print_package_description): Formats the description of a
+       package to be output to screen.
+       
 2008-02-19  Bill Denney  <[EMAIL PROTECTED]>
 
        * time/datestr.m: Avoid confusion for datenum vectors that are 6
diff -r bd2bd04e68ca -r 630ddf983154 scripts/pkg/pkg.m
--- a/scripts/pkg/pkg.m Mon Feb 18 18:08:29 2008 +0100
+++ b/scripts/pkg/pkg.m Tue Feb 19 12:27:23 2008 +0000
@@ -101,6 +101,29 @@
 ## @noindent
 ## splits the list of installed packages into those who are installed by
 ## the current user, and those installed by the system administrator.
+## @item describe
+## Show a short description of the named installed packages, with the option
+## '-verbose' also list functions provided by the package, e.g.:
+## @example
+##  pkg describe -verbose all
+## @end example
+## @noindent
+## will describe all installed packages and the functions they provide.
+## If one output is requested a cell of structure containing the
+## description and list of functions of each package is returned as
+## output rather than printed on screen:
+## @example
+##  desc = pkg ("describe", "secs1d", "image")
+## @end example
+## @noindent
+## If any of the requested packages is not installed, pkg returns an
+## error, unless a second output is requested:
+## @example
+##  [ desc, flag] = pkg ("describe", "secs1d", "image")
+## @end example
+## @noindent
+## @var{flag} will take one of the values "Not installed", "Loaded" or
+## "Not loaded" for each of the named packages.
 ## @item prefix
 ## Set the installation prefix directory. For example,
 ## @example
@@ -198,6 +221,8 @@ function [local_packages, global_package
     archprefix = tilde_expand (archprefix);
   endif
 
+  available_actions = {"list", "install", "uninstall", "load", "unload", 
"prefix", ...
+                      "local_list", "global_list", "rebuild", 
"build","describe"};
   ## Handle input
   if (length (varargin) == 0 || ! iscellstr (varargin))
     print_usage ();
@@ -227,8 +252,7 @@ function [local_packages, global_package
        if (! user_prefix)
          prefix = fullfile (OCTAVE_HOME (), "share", "octave", "packages");
        endif
-      case {"list", "install", "uninstall", "load", "unload", "prefix", ...
-           "local_list", "global_list", "rebuild", "build"}
+      case available_actions
        if (strcmp (action, "none"))
          action = varargin{i};
        else
@@ -365,6 +389,28 @@ function [local_packages, global_package
       endif
       build (files, deps, auto, verbose);
 
+    case "describe"
+      if (length (files) == 0)
+       error ("you must specify at least one package or 'all' when calling 
'pkg describe'");
+      endif
+      ## XXX FIXME: the name of the output variables is inconsistent
+      ##            with their content
+      switch (nargout)
+         case 0
+           describe (files, verbose, local_list, global_list);
+         case 1
+           pkg_desc_list = describe (files, verbose, local_list, ...
+                                global_list);
+           local_packages = pkg_desc_list;
+         case 2
+           [pkg_desc_list, flag] = describe (files, verbose, local_list, ...
+                                        global_list);
+           local_packages  = pkg_desc_list;
+           global_packages = flag;
+         otherwise
+           error ("you can request at most two outputs when calling 'pkg 
describe'");
+       endswitch
+               
     otherwise
       error ("you must specify a valid action for 'pkg'. See 'help pkg' for 
details");
   endswitch
@@ -900,9 +946,139 @@ function uninstall (pkgnames, handle_dep
 
 endfunction
 
+function [pkg_desc_list, flag] = describe (pkgnames, verbose, 
+                                          local_list, global_list)
+
+  ## Get the list of installed packages
+  installed_pkgs_lst = installed_packages(local_list, global_list);
+  num_packages       = length (installed_pkgs_lst);
+  
+
+  describe_all       = false;
+  if (any (strcmp ('all', pkgnames)))
+    describe_all         = true;
+    flag{1:num_packages} = "Not Loaded";
+    num_pkgnames         = num_packages;
+  else
+    num_pkgnames         = length (pkgnames);
+    flag{1:num_pkgnames} = "Not installed";
+  end
+
+  for i = 1:num_packages
+    curr_name= installed_pkgs_lst{i}.name;
+    if (describe_all)
+      name_pos = i;
+    else
+      name_pos = find(strcmp (curr_name, pkgnames));
+    end
+    if (!isempty(name_pos))
+      if (installed_pkgs_lst{i}.loaded)
+       flag{name_pos} = "Loaded";
+      else
+       flag{name_pos} = "Not loaded";
+      endif
+
+      pkg_desc_list{name_pos}.name = ...
+         installed_pkgs_lst{i}.name;
+      pkg_desc_list{name_pos}.description = ...
+         installed_pkgs_lst{i}.description;
+      pkg_desc_list{name_pos}.provides = ...
+         parse_pkg_idx(installed_pkgs_lst{i}.dir);
+
+    endif
+  endfor
+
+  non_inst = find(strcmp(flag,"Not installed"));
+  if (!isempty(non_inst) && (nargout<2))
+    non_inst_str = sprintf(" %s ",pkgnames{non_inst});
+    error("some packages are not installed: %s",non_inst_str);
+  endif
+
+  if (nargout == 0)
+    for i=1:num_pkgnames
+      print_package_description (pkg_desc_list{i}.name, 
+                                pkg_desc_list{i}.provides,  
+                                pkg_desc_list{i}.description,
+                                flag{i}, verbose);
+    endfor
+  endif
+
+endfunction
+
 ##########################################################
 ##        A U X I L I A R Y    F U N C T I O N S        ##
 ##########################################################
+
+## This function reads an INDEX file
+function [pkg_idx_struct] = parse_pkg_idx(packdir)
+
+  fINDEX = fullfile (packdir, "packinfo", "INDEX");
+
+  if (!exist(fINDEX, "file")  )
+    error("could not find any INDEX file in directory %s, \
+\ntry 'pkg rebuild all' to generate missing INDEX files", packdir);
+  endif    
+
+    
+  [fid, msg] = fopen(fINDEX,"r");
+  if (fid == -1)
+    error("the INDEX file %s could not be read: %s", 
+         fINDEX, msg);
+  endif
+  
+  cat_num = 1;
+  pkg_idx_struct{1}.category = "Uncategorized";
+  pkg_idx_struct{1}.functions = {};
+
+  line = fgetl(fid);
+  while (isempty(strfind(line,">>")))
+    line = fgetl(fid);
+  endwhile
+  while (line != -1)
+    if (!isempty(strfind(line,">>")))
+      ## Skip package name and description as they are in
+      ## DESCRIPTION already
+    elseif ((line(1) == "#") || any(line=="=") || !any(isspace(line)))
+      ## Comments,  blank lines or comments about unimplemented 
+      ## functions: do nothing
+      ## XXX: probably comments and pointers to external functions
+      ## could be treated better when printing to screen?
+    elseif (!isspace(line(1)))
+      ## Category
+      pkg_idx_struct{++cat_num}.category = deblank(line);
+      pkg_idx_struct{cat_num}.functions  = {};
+    else
+      ## Function names
+      while (any(!isspace(line)))
+       [fun_name, line] = strtok(line);
+       pkg_idx_struct{cat_num}.functions{end+1}  = deblank(fun_name);
+      endwhile
+    endif
+    line = fgetl(fid);
+  endwhile
+  fclose (fid);
+endfunction
+
+function print_package_description (pkg_name, pkg_idx_struct, 
+                                   pkg_desc, status, verbose)
+
+  printf("---\nPackage name:\n\t%s\n", pkg_name);
+  printf("Short description:\n\t%s\n", pkg_desc);
+  printf("Status:\n\t%s\n", status);
+  if (verbose)
+    printf("---\nProvides:\n");    
+    for i=1:length(pkg_idx_struct)
+      if (!isempty(pkg_idx_struct{i}.functions))
+       printf("%s\n", pkg_idx_struct{i}.category);
+       for j=1:length(pkg_idx_struct{i}.functions)
+         printf("\t%s\n", pkg_idx_struct{i}.functions{j});
+       endfor
+      endif
+    endfor
+  endif
+
+endfunction
+
 
 function pth = absolute_pathname (pth)
   [status, msg, msgid] = fileattrib(pth);
@@ -1580,7 +1756,7 @@ endfunction
 
 ## Creates an INDEX file for a package that doesn't provide one.
 ##   'desc'  describes the package.
-##   'dir'   is the 'inst' direcotyr in temporary directory.
+##   'dir'   is the 'inst' direcotry in temporary directory.
 ##   'INDEX' is the name (including path) of resulting INDEX file.
 function write_INDEX (desc, dir, INDEX, global_install)
   ## Get names of functions in dir
@@ -2104,3 +2280,5 @@ function dep = is_architecture_dependent
     endif
   endfor
 endfunction
+
+


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Octave-dev mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/octave-dev

Reply via email to