view scripts/pkg/private/installed_packages.m @ 19221:b54093acb8fe

ver.m: Overhaul function. Add ability to call "ver PKG_NAME". Add ability to call "pkg list PKG_NAME". * ver.m: Redo docstring. Rename output variable to retval rather than unnecessary use of varargout. Add ability to call "ver PKG_NAME" by passing PKG_NAME to 'pkg list' command. * pkg.m: Redo docstring for 'list' to explain new ability to supply a PKG_NAME. Use numel() rather than length() for clarity. Use isempty() rather than length() == 0 for clarity. * installed_packages.m: Add additional input argument pkgname. Use unique() rather than double for loop to uniquify package list. Add code to report only on package pkgname if given. Use numel() rather than length() for clarity. Replace for loops with cellfun calls to determine max length of string entries. * version.m: Add seealso reference to ver in docstring.
author Rik <rik@octave.org>
date Tue, 30 Sep 2014 08:29:16 -0700
parents d63878346099
children db92e7e28e1f
line wrap: on
line source

## Copyright (C) 2005-2013 Søren Hauberg
## Copyright (C) 2010 VZLU Prague, a.s.
##
## This file is part of Octave.
##
## Octave is free software; you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 3 of the License, or (at
## your option) any later version.
##
## Octave is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with Octave; see the file COPYING.  If not, see
## <http://www.gnu.org/licenses/>.

## -*- texinfo -*-
## @deftypefn {Function File} {[@var{out1}, @var{out2}] =} installed_packages (@var{local_list}, @var{global_list})
## Undocumented internal function.
## @end deftypefn

function [out1, out2] = installed_packages (local_list, global_list, pkgname = {})

  ## Get the list of installed packages.
  try
    local_packages = load (local_list).local_packages;
  catch
    local_packages = {};
  end_try_catch
  try
    global_packages = load (global_list).global_packages;
  catch
    global_packages = {};
  end_try_catch
  installed_pkgs_lst = {local_packages{:}, global_packages{:}};

  ## Eliminate duplicates in the installed package list.
  ## Locally installed packages take precedence.
  installed_names = cellfun (@(x) x.name, installed_pkgs_lst,
                             "uniformoutput", false);
  [~, idx] = unique (installed_names, "first");
  installed_names = installed_names(idx);
  installed_pkgs_lst = installed_pkgs_lst(idx);

  ## Check whether info on a particular package was requested
  if (! isempty (pkgname))
    idx = find (strcmp (pkgname{1}, installed_names));
    if (isempty (idx))
      installed_names = {};
      installed_pkgs_lst = {};
    else
      installed_names = installed_names(idx);
      installed_pkgs_lst = installed_pkgs_lst(idx);
    endif
  endif

  ## Now check if the package is loaded.
  ## FIXME: couldn't dir_in_loadpath() be used here?
  tmppath = strrep (path (), "\\", "/");
  for i = 1:numel (installed_pkgs_lst)
    if (strfind (tmppath, strrep (installed_pkgs_lst{i}.dir, '\', '/')))
      installed_pkgs_lst{i}.loaded = true;
    else
      installed_pkgs_lst{i}.loaded = false;
    endif
  endfor
  for i = 1:numel (local_packages)
    if (strfind (tmppath, strrep (local_packages{i}.dir, '\', '/')))
      local_packages{i}.loaded = true;
    else
      local_packages{i}.loaded = false;
    endif
  endfor
  for i = 1:numel (global_packages)
    if (strfind (tmppath, strrep (global_packages{i}.dir, '\', '/')))
      global_packages{i}.loaded = true;
    else
      global_packages{i}.loaded = false;
    endif
  endfor

  ## Should we return something?
  if (nargout == 2)
    out1 = local_packages;
    out2 = global_packages;
    return;
  elseif (nargout == 1)
    out1 = installed_pkgs_lst;
    return;
  endif

  ## Don't return anything, instead we'll print something.
  num_packages = numel (installed_pkgs_lst);
  if (num_packages == 0)
    if (isempty (pkgname))
      printf ("no packages installed.\n");
    else
      printf ("package %s is not installed.\n", pkgname{1});
    endif
    return;
  endif

  ## Compute the maximal lengths of name, version, and dir.
  h1 = "Package Name";
  h2 = "Version";
  h3 = "Installation directory";
  max_name_length = max ([length(h1), cellfun(@length, installed_names)]);
  version_lengths = cellfun (@(x) length (x.version), installed_pkgs_lst); 
  max_version_length = max ([length(h2), version_lengths]);
  ncols = terminal_size ()(2);
  max_dir_length = ncols - max_name_length - max_version_length - 7;
  if (max_dir_length < 20)
    max_dir_length = Inf;
  endif

  h1 = postpad (h1, max_name_length + 1, " ");
  h2 = postpad (h2, max_version_length, " ");;

  ## Print a header.
  header = sprintf ("%s | %s | %s\n", h1, h2, h3);
  printf (header);
  tmp = sprintf (repmat ("-", 1, length (header) - 1));
  tmp(length(h1)+2) = "+";
  tmp(length(h1)+length(h2)+5) = "+";
  printf ("%s\n", tmp);

  ## Print the packages.
  format = sprintf ("%%%ds %%1s| %%%ds | %%s\n",
                    max_name_length, max_version_length);
  for i = 1:num_packages
    cur_name = installed_pkgs_lst{i}.name;
    cur_version = installed_pkgs_lst{i}.version;
    cur_dir = installed_pkgs_lst{i}.dir;
    if (length (cur_dir) > max_dir_length)
      first_char = length (cur_dir) - max_dir_length + 4;
      first_filesep = strfind (cur_dir(first_char:end), filesep ());
      if (! isempty (first_filesep))
        cur_dir = ["..." cur_dir((first_char + first_filesep(1) - 1):end)];
      else
        cur_dir = ["..." cur_dir(first_char:end)];
      endif
    endif
    if (installed_pkgs_lst{i}.loaded)
      cur_loaded = "*";
    else
      cur_loaded = " ";
    endif
    printf (format, cur_name, cur_loaded, cur_version, cur_dir);
  endfor

endfunction