diff --git a/lib/spack/docs/conf.py b/lib/spack/docs/conf.py index de136dc047..237a062c14 100644 --- a/lib/spack/docs/conf.py +++ b/lib/spack/docs/conf.py @@ -69,7 +69,7 @@ # with open('package_list.rst', 'w') as plist_file: subprocess.Popen( - [spack_root + '/bin/spack', 'package-list'], stdout=plist_file) + [spack_root + '/bin/spack', 'list', '--format=rst'], stdout=plist_file) # # Find all the `cmd-spack-*` references and add them to a command index diff --git a/lib/spack/spack/cmd/list.py b/lib/spack/spack/cmd/list.py index c921efd1bd..e1389df69f 100644 --- a/lib/spack/spack/cmd/list.py +++ b/lib/spack/spack/cmd/list.py @@ -22,36 +22,51 @@ # License along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ############################################################################## -import sys -import llnl.util.tty as tty import argparse -from llnl.util.tty.colify import colify - -import spack +import cgi import fnmatch import re +import sys +from StringIO import StringIO -description = "List available spack packages" +import llnl.util.tty as tty +import spack +from llnl.util.tty.colify import colify + +description = "Print available spack packages to stdout in different formats" + +formatters = {} + + +def formatter(func): + """Decorator used to register formatters""" + formatters[func.__name__] = func + return func def setup_parser(subparser): subparser.add_argument( 'filter', nargs=argparse.REMAINDER, - help='Optional glob patterns to filter results.') - subparser.add_argument( - '-s', '--sensitive', action='store_true', default=False, - help='Use case-sensitive filtering. Default is case sensitive, ' - 'unless the query contains a capital letter.') + help='Optional case-insensitive glob patterns to filter results.') subparser.add_argument( '-d', '--search-description', action='store_true', default=False, help='Filtering will also search the description for a match.') + subparser.add_argument( + '--format', default='name_only', choices=formatters, + help='Format to be used to print the output [default: name_only]') -def list(parser, args): - # Start with all package names. - pkgs = set(spack.repo.all_package_names()) +def filter_by_name(pkgs, args): + """ + Filters the sequence of packages according to user prescriptions - # filter if a filter arg was provided + Args: + pkgs: sequence of packages + args: parsed command line arguments + + Returns: + filtered and sorted list of packages + """ if args.filter: res = [] for f in args.filter: @@ -60,10 +75,7 @@ def list(parser, args): else: r = fnmatch.translate(f) - re_flags = re.I - if any(l.isupper for l in f) or args.sensitive: - re_flags = 0 - rc = re.compile(r, flags=re_flags) + rc = re.compile(r, flags=re.IGNORECASE) res.append(rc) if args.search_description: @@ -80,11 +92,91 @@ def match(p, f): return f.match(p) pkgs = [p for p in pkgs if any(match(p, f) for f in res)] - # sort before displaying. - sorted_packages = sorted(pkgs, key=lambda s: s.lower()) + return sorted(pkgs, key=lambda s: s.lower()) - # Print all the package names in columns + +@formatter +def name_only(pkgs): indent = 0 if sys.stdout.isatty(): - tty.msg("%d packages." % len(sorted_packages)) - colify(sorted_packages, indent=indent) + tty.msg("%d packages." % len(pkgs)) + colify(pkgs, indent=indent) + + +@formatter +def rst(pkgs): + """Print out information on all packages in restructured text.""" + + def github_url(pkg): + """Link to a package file on github.""" + url = 'https://github.com/LLNL/spack/blob/develop/var/spack/repos/builtin/packages/{0}/package.py' + return url.format(pkg.name) + + def rst_table(elts): + """Print out a RST-style table.""" + cols = StringIO() + ncol, widths = colify(elts, output=cols, tty=True) + header = ' '.join('=' * (w - 1) for w in widths) + return '%s\n%s%s' % (header, cols.getvalue(), header) + + pkg_names = pkgs + pkgs = [spack.repo.get(name) for name in pkg_names] + + print('.. _package-list:') + print('') + print('============') + print('Package List') + print('============') + print('') + print('This is a list of things you can install using Spack. It is') + print('automatically generated based on the packages in the latest Spack') + print('release.') + print('') + print('Spack currently has %d mainline packages:' % len(pkgs)) + print('') + print(rst_table('`%s`_' % p for p in pkg_names)) + print('') + + # Output some text for each package. + for pkg in pkgs: + print('-----') + print('') + print('.. _%s:' % pkg.name) + print('') + # Must be at least 2 long, breaks for single letter packages like R. + print('-' * max(len(pkg.name), 2)) + print(pkg.name) + print('-' * max(len(pkg.name), 2)) + print('') + print('Homepage:') + print(' * `%s <%s>`__' % (cgi.escape(pkg.homepage), pkg.homepage)) + print('') + print('Spack package:') + print(' * `%s/package.py <%s>`__' % (pkg.name, github_url(pkg))) + print('') + if pkg.versions: + print('Versions:') + print(' ' + ', '.join(str(v) for v in + reversed(sorted(pkg.versions)))) + print('') + + for deptype in spack.alldeps: + deps = pkg.dependencies_of_type(deptype) + if deps: + print('%s Dependencies' % deptype.capitalize()) + print(' ' + ', '.join('%s_' % d if d in pkg_names + else d for d in deps)) + print('') + + print('Description:') + print(pkg.format_doc(indent=2)) + print('') + + +def list(parser, args): + # Retrieve the names of all the packages + pkgs = set(spack.repo.all_package_names()) + # Filter the set appropriately + sorted_packages = filter_by_name(pkgs, args) + # Print to stdout + formatters[args.format](sorted_packages) diff --git a/lib/spack/spack/cmd/package_list.py b/lib/spack/spack/cmd/package_list.py deleted file mode 100644 index 42f408af96..0000000000 --- a/lib/spack/spack/cmd/package_list.py +++ /dev/null @@ -1,104 +0,0 @@ -############################################################################## -# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. -# Produced at the Lawrence Livermore National Laboratory. -# -# This file is part of Spack. -# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. -# LLNL-CODE-647188 -# -# For details, see https://github.com/llnl/spack -# Please also see the LICENSE file for our notice and the LGPL. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License (as -# published by the Free Software Foundation) version 2.1, February 1999. -# -# This program 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 terms and -# conditions of the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################## -import cgi -from StringIO import StringIO -from llnl.util.tty.colify import * -import spack - -description = "Print a list of all packages in reStructuredText." - - -def github_url(pkg): - """Link to a package file on github.""" - url = "https://github.com/LLNL/spack/blob/develop/var/spack/repos/builtin/packages/{0}/package.py" - return url.format(pkg.name) - - -def rst_table(elts): - """Print out a RST-style table.""" - cols = StringIO() - ncol, widths = colify(elts, output=cols, tty=True) - header = " ".join("=" * (w - 1) for w in widths) - return "%s\n%s%s" % (header, cols.getvalue(), header) - - -def print_rst_package_list(): - """Print out information on all packages in restructured text.""" - pkgs = sorted(spack.repo.all_packages(), key=lambda s: s.name.lower()) - pkg_names = [p.name for p in pkgs] - - print ".. _package-list:" - print - print "============" - print "Package List" - print "============" - print - print "This is a list of things you can install using Spack. It is" - print "automatically generated based on the packages in the latest Spack" - print "release." - print - print "Spack currently has %d mainline packages:" % len(pkgs) - print - print rst_table("`%s`_" % p for p in pkg_names) - print - - # Output some text for each package. - for pkg in pkgs: - print "-----" - print - print ".. _%s:" % pkg.name - print - # Must be at least 2 long, breaks for single letter packages like R. - print "-" * max(len(pkg.name), 2) - print pkg.name - print "-" * max(len(pkg.name), 2) - print - print "Homepage:" - print " * `%s <%s>`__" % (cgi.escape(pkg.homepage), pkg.homepage) - print - print "Spack package:" - print " * `%s/package.py <%s>`__" % (pkg.name, github_url(pkg)) - print - if pkg.versions: - print "Versions:" - print " " + ", ".join(str(v) for v in - reversed(sorted(pkg.versions))) - print - - for deptype in spack.alldeps: - deps = pkg.dependencies_of_type(deptype) - if deps: - print "%s Dependencies" % deptype.capitalize() - print " " + ", ".join("%s_" % d if d in pkg_names - else d for d in deps) - print - - print "Description:" - print pkg.format_doc(indent=2) - print - - -def package_list(parser, args): - print_rst_package_list()