aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-10-25 11:49:36 +0100
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2008-10-25 11:49:36 +0100
commitbd9aa0272d7e2821074d64479cca90312939621c (patch)
tree0ed5739b60aa57b6f3d72e9983ae2bca36b3048b
parentab50405a661d1e8af907aace115823ccd6be8a10 (diff)
downloadpaludis-bd9aa0272d7e2821074d64479cca90312939621c.tar.gz
paludis-bd9aa0272d7e2821074d64479cca90312939621c.tar.xz
Start work on cave
-rw-r--r--.gitignore18
-rw-r--r--configure.ac10
-rw-r--r--paludis/args/Makefile.am10
-rw-r--r--paludis/args/args_handler.cc45
-rw-r--r--paludis/args/args_handler.hh60
-rw-r--r--paludis/args/args_handler.se12
-rw-r--r--src/clients/cave/Makefile.am147
-rw-r--r--src/clients/cave/cave.cc75
-rw-r--r--src/clients/cave/cmd_print_categories.cc128
-rw-r--r--src/clients/cave/cmd_print_categories.hh44
-rw-r--r--src/clients/cave/cmd_print_commands.cc86
-rw-r--r--src/clients/cave/cmd_print_commands.hh44
-rw-r--r--src/clients/cave/cmd_print_environment_metadata.cc138
-rw-r--r--src/clients/cave/cmd_print_environment_metadata.hh44
-rw-r--r--src/clients/cave/cmd_print_id_contents.cc134
-rw-r--r--src/clients/cave/cmd_print_id_contents.hh44
-rw-r--r--src/clients/cave/cmd_print_id_metadata.cc162
-rw-r--r--src/clients/cave/cmd_print_id_metadata.hh44
-rw-r--r--src/clients/cave/cmd_print_ids.cc311
-rw-r--r--src/clients/cave/cmd_print_ids.hh44
-rw-r--r--src/clients/cave/cmd_show.cc738
-rw-r--r--src/clients/cave/cmd_show.hh44
-rw-r--r--src/clients/cave/colour_formatter.cc213
-rw-r--r--src/clients/cave/colour_formatter.hh101
-rw-r--r--src/clients/cave/command.cc28
-rw-r--r--src/clients/cave/command.hh47
-rw-r--r--src/clients/cave/command_factory.cc106
-rw-r--r--src/clients/cave/command_factory.hh69
-rw-r--r--src/clients/cave/command_line.cc32
-rw-r--r--src/clients/cave/command_line.hh55
-rw-r--r--src/clients/cave/exceptions.cc48
-rw-r--r--src/clients/cave/exceptions.hh58
-rw-r--r--src/clients/cave/format_general.cc64
-rw-r--r--src/clients/cave/format_general.hh45
-rw-r--r--src/clients/cave/format_plain_contents_entry.cc97
-rw-r--r--src/clients/cave/format_plain_contents_entry.hh39
-rw-r--r--src/clients/cave/format_plain_metadata_key.cc171
-rw-r--r--src/clients/cave/format_plain_metadata_key.hh40
-rw-r--r--src/clients/cave/format_string.cc163
-rw-r--r--src/clients/cave/format_string.hh47
-rw-r--r--src/clients/cave/formats.cc396
-rw-r--r--src/clients/cave/formats.hh122
-rw-r--r--src/clients/cave/man_cave.cc88
-rw-r--r--src/clients/cave/select_format_for_spec.cc48
-rw-r--r--src/clients/cave/select_format_for_spec.hh42
45 files changed, 4452 insertions, 49 deletions
diff --git a/.gitignore b/.gitignore
index a8afdf2..79ecda8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -380,23 +380,7 @@ paludis-*.*.*.tar.bz2
/pkg-config/paludis.pc
/src/clients/accerso/accerso
/src/clients/adjutrix/adjutrix
-/src/clients/contrarius/contrarius
-/src/clients/contrarius/version_TEST
-/src/clients/gtkpaludis/gtkpaludis
-/src/clients/gtkpaludis/vtemm/automake-deps-hack.tmp
-/src/clients/gtkpaludis/vtemm/defs/force_automake_to_include_cxxcompile
-/src/clients/gtkpaludis/vtemm/defs/force_automake_to_include_cxxcompile.cc
-/src/clients/gtkpaludis/vtemm/defs/generate_defs_vte
-/src/clients/gtkpaludis/vtemm/defs/vte.defs
-/src/clients/gtkpaludis/vtemm/defs/vte_enums.defs
-/src/clients/gtkpaludis/vtemm/defs/vte_methods.defs
-/src/clients/gtkpaludis/vtemm/defs/vte_signals.defs
-/src/clients/gtkpaludis/vtemm/defs/vte_vfuncs.defs
-/src/clients/gtkpaludis/vtemm/private
-/src/clients/gtkpaludis/vtemm/reaper.cc
-/src/clients/gtkpaludis/vtemm/reaper.hh
-/src/clients/gtkpaludis/vtemm/terminal_widget.cc
-/src/clients/gtkpaludis/vtemm/terminal_widget.hh
+/src/clients/cave/cave
/src/clients/importare/importare
/src/clients/inquisitio/inquisitio
/src/clients/instruo/instruo
diff --git a/configure.ac b/configure.ac
index 9c9caa8..fabd17e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1266,10 +1266,14 @@ AC_DEFINE_UNQUOTED([DEFAULT_DISTRIBUTION], "$DEFAULT_DISTRIBUTION", [Default dis
dnl }}}
dnl {{{ clients
-ALL_CLIENTS="accerso adjutrix importare inquisitio instruo paludis qualudis reconcilio"
+ALL_CLIENTS="accerso adjutrix cave importare inquisitio instruo paludis qualudis reconcilio"
ALL_CLIENTS_HTML=""
for a in $ALL_CLIENTS ; do
- ALL_CLIENTS_HTML="$ALL_CLIENTS_HTML $a.html"
+ if test x$a = xcave ; then
+ true
+ else
+ ALL_CLIENTS_HTML="$ALL_CLIENTS_HTML $a.html"
+ fi
done
DEFAULT_CLIENTS="adjutrix importare paludis reconcilio"
if test x"$ENABLE_QA" = "xyes" ; then
@@ -1285,6 +1289,7 @@ AC_ARG_WITH([clients],
accerso A fetch / mirror client
adjutrix A tool for tree querying
+ cave The modular Paludis client
importare On-the-fly unpackaged installer
inquisitio A search client
instruo A metadata generation client
@@ -1461,6 +1466,7 @@ AC_OUTPUT(
src/clients/Makefile
src/clients/accerso/Makefile
src/clients/adjutrix/Makefile
+ src/clients/cave/Makefile
src/clients/importare/Makefile
src/clients/inquisitio/Makefile
src/clients/instruo/Makefile
diff --git a/paludis/args/Makefile.am b/paludis/args/Makefile.am
index 908f4b8..ed1741d 100644
--- a/paludis/args/Makefile.am
+++ b/paludis/args/Makefile.am
@@ -1,6 +1,9 @@
CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT *.epicfail
MAINTAINERCLEANFILES = Makefile.in
+DISTCLEANFILES = args_handler-se.hh args_handler-se.cc
AM_CXXFLAGS = -I$(top_srcdir) @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_VISIBILITY@
+EXTRA_DIST = args_handler-se.hh args_handler-se.cc args_handler.se
+BUILT_SOURCES = args_handler-se.hh args_handler-se.cc
TESTS = \
args_TEST
@@ -12,6 +15,7 @@ paludis_args_include_HEADERS = \
args_error.hh \
args_group.hh \
args_handler.hh \
+ args_handler-se.hh \
args_option.hh \
bad_argument.hh \
args_visitor.hh \
@@ -79,3 +83,9 @@ distcheck-deps-subdirs :
for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
+args_handler-se.hh : args_handler.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --header $(srcdir)/args_handler.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
+args_handler-se.cc : args_handler.se $(top_srcdir)/misc/make_se.bash
+ if ! $(top_srcdir)/misc/make_se.bash --source $(srcdir)/args_handler.se > $@ ; then rm -f $@ ; exit 1 ; fi
+
diff --git a/paludis/args/args_handler.cc b/paludis/args/args_handler.cc
index e75c94f..44dd36a 100644
--- a/paludis/args/args_handler.cc
+++ b/paludis/args/args_handler.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -24,6 +24,8 @@
#include <paludis/util/private_implementation_pattern-impl.hh>
#include <paludis/util/visitor-impl.hh>
#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/wrapped_output_iterator-impl.hh>
+#include <paludis/util/create_iterator-impl.hh>
#include <algorithm>
#include <sstream>
#include <list>
@@ -104,17 +106,12 @@ ArgsHandler::add(ArgsGroup * const g)
}
void
-ArgsHandler::run(const int argc, const char * const * const argv, const std::string & env_var,
- const std::string & env_prefix)
-{
- run(argc, argv, "", env_var, env_prefix);
-}
-
-void
-ArgsHandler::run(const int argc, const char * const * const argv,
+ArgsHandler::run(
+ const std::tr1::shared_ptr<const Sequence<std::string> > & argseq,
const std::string & client,
const std::string & env_var,
- const std::string & env_prefix)
+ const std::string & env_prefix,
+ const ArgsHandlerOptions & options)
{
std::list<std::string> args;
std::string env_options;
@@ -133,7 +130,7 @@ ArgsHandler::run(const int argc, const char * const * const argv,
args.push_back(option);
}
- args.insert(args.end(), &argv[1], &argv[argc]);
+ args.insert(args.end(), argseq->begin(), argseq->end());
ArgsVisitor::ArgsIterator argit(args.begin()), arge(args.end());
ArgsVisitor visitor(&argit, arge, env_prefix);
@@ -181,7 +178,10 @@ ArgsHandler::run(const int argc, const char * const * const argv,
}
else
{
- _imp->parameters.push_back(arg);
+ if (options[aho_stop_on_first_parameter])
+ break;
+ else
+ _imp->parameters.push_back(arg);
}
}
@@ -190,6 +190,27 @@ ArgsHandler::run(const int argc, const char * const * const argv,
if (! env_prefix.empty())
setenv((env_prefix + "_PARAMS").c_str(), join(_imp->parameters.begin(),
_imp->parameters.end(), " ").c_str(), 1);
+
+ post_run();
+}
+
+void
+ArgsHandler::run(
+ const int argc,
+ const char * const * const argv,
+ const std::string & client,
+ const std::string & env_var,
+ const std::string & env_prefix,
+ const ArgsHandlerOptions & options)
+{
+ std::tr1::shared_ptr<Sequence<std::string> > s(new Sequence<std::string>);
+ std::copy(&argv[1], &argv[argc], create_inserter<std::string>(s->back_inserter()));
+ run(s, client, env_var, env_prefix, options);
+}
+
+void
+ArgsHandler::post_run()
+{
}
void
diff --git a/paludis/args/args_handler.hh b/paludis/args/args_handler.hh
index 20c280c..be0206a 100644
--- a/paludis/args/args_handler.hh
+++ b/paludis/args/args_handler.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh
+ * Copyright (c) 2005, 2006, 2007, 2008 Ciaran McCreesh
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -23,6 +23,8 @@
#include <paludis/args/args_group.hh>
#include <paludis/util/instantiation_policy.hh>
#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/sequence.hh>
#include <iosfwd>
#include <string>
@@ -41,6 +43,11 @@ namespace paludis
{
namespace args
{
+
+#include <paludis/args/args_handler-se.hh>
+
+ typedef Options<ArgsHandlerOption> ArgsHandlerOptions;
+
/**
* Handles command line arguments.
*
@@ -85,6 +92,11 @@ namespace paludis
*/
void dump_to_stream(std::ostream & s) const;
+ /**
+ * Called after run(), for convenience. Does nothing.
+ */
+ virtual void post_run();
+
public:
///\name Basic operations
///\{
@@ -95,23 +107,6 @@ namespace paludis
///\}
- /**
- * \deprecated Use the five arg form.
- */
- void run(const int, const char * const * const, const std::string & env_var = "",
- const std::string & env_prefix = "") PALUDIS_ATTRIBUTE((deprecated));
-
- /**
- * Parse command line arguments. The third argument is used to
- * set PALUDIS_CLIENT. The fourth argument is the name of an
- * environment variable holding arguments which are prepended
- * to the command line arguments. The fifth argument is used as
- * a prefix to export our command line via the environment.
- */
- virtual void run(const int, const char * const * const,
- const std::string & client, const std::string & env_var,
- const std::string & env_prefix);
-
///\name Iterate over our parameters (non - and -- switches and their values)
///\{
@@ -225,6 +220,35 @@ namespace paludis
NotesIterator end_notes() const;
///\}
+
+ /**
+ * Parse command line arguments. The third argument is used to
+ * set PALUDIS_CLIENT. The fourth argument is the name of an
+ * environment variable holding arguments which are prepended
+ * to the command line arguments. The fifth argument is used as
+ * a prefix to export our command line via the environment.
+ */
+ void run(
+ const int argc,
+ const char * const * const argv,
+ const std::string & client,
+ const std::string & env_var,
+ const std::string & env_prefix,
+ const ArgsHandlerOptions & options = ArgsHandlerOptions());
+
+ /**
+ * Parse command line arguments. The third argument is used to
+ * set PALUDIS_CLIENT. The fourth argument is the name of an
+ * environment variable holding arguments which are prepended
+ * to the command line arguments. The fifth argument is used as
+ * a prefix to export our command line via the environment.
+ */
+ void run(
+ const std::tr1::shared_ptr<const Sequence<std::string> > &,
+ const std::string & client,
+ const std::string & env_var,
+ const std::string & env_prefix,
+ const ArgsHandlerOptions & options = ArgsHandlerOptions());
};
/**
diff --git a/paludis/args/args_handler.se b/paludis/args/args_handler.se
new file mode 100644
index 0000000..029e6eb
--- /dev/null
+++ b/paludis/args/args_handler.se
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+# vim: set sw=4 sts=4 et ft=sh :
+
+make_enum_ArgsHandlerOption()
+{
+ prefix dstpo
+ want_destringify
+ namespace paludis::args
+
+ key aho_stop_on_first_parameter "Stop on the first parameter encountered"
+}
+
diff --git a/src/clients/cave/Makefile.am b/src/clients/cave/Makefile.am
new file mode 100644
index 0000000..df3a6dc
--- /dev/null
+++ b/src/clients/cave/Makefile.am
@@ -0,0 +1,147 @@
+AM_CXXFLAGS = -I$(top_srcdir) -I$(top_srcdir)/src \
+ @PALUDIS_CXXFLAGS@ @PALUDIS_CXXFLAGS_NO_WOLD_STYLE_CAST@ @PALUDIS_CXXFLAGS_VISIBILITY@
+DEFS= \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBEXECDIR=\"$(libexecdir)\" \
+ -DLIBDIR=\"$(libdir)\" \
+ -DPYTHONINSTALLDIR=\"$(PYTHON_INSTALL_DIR)\" \
+ -DRUBYINSTALLDIR=\"$(RUBY_INSTALL_DIR)\"
+
+SUBDIRS = .
+
+bin_PROGRAMS = cave
+
+noinst_PROGRAMS = man-cave
+
+command_MANS = \
+ cave-print-categories.1 \
+ cave-print-commands.1 \
+ cave-print-environment-metadata.1 \
+ cave-print-id-contents.1 \
+ cave-print-id-metadata.1 \
+ cave-print-ids.1 \
+ cave-show.1
+
+man_MANS = \
+ cave.1 \
+ $(command_MANS)
+
+cave.1 : man-cave
+ ./man-cave > $@
+
+$(command_MANS) : man-cave
+ if ! ./man-cave `echo $@ | sed -e 's.^cave-..' -e 's,\.1$$,,'` > $@ ; then rm -f $@ ; exit 1 ; fi
+
+cave_SOURCES = \
+ cave.cc
+
+cave_LDADD = \
+ libcave.a \
+ $(top_builddir)/paludis/libpaludis_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/args/libpaludisargs_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/src/output/liboutput.a \
+ $(DYNAMIC_LD_LIBS)
+
+man_cave_SOURCES = \
+ man_cave.cc
+
+man_cave_LDADD = \
+ libcave.a \
+ $(top_builddir)/paludis/args/libpaludisargs_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/args/libpaludisman_@PALUDIS_PC_SLOT@.a \
+ $(top_builddir)/paludis/util/libpaludisutil_@PALUDIS_PC_SLOT@.la \
+ $(top_builddir)/paludis/libpaludismanpagethings_@PALUDIS_PC_SLOT@.la
+
+noinst_LIBRARIES = libcave.a
+
+libcave_a_SOURCES = \
+ colour_formatter.cc colour_formatter.hh \
+ command.cc command.hh \
+ command_line.cc command_line.hh \
+ command_factory.cc command_factory.hh \
+ cmd_print_categories.cc cmd_print_categories.hh \
+ cmd_print_commands.cc cmd_print_commands.hh \
+ cmd_print_id_contents.cc cmd_print_id_contents.hh \
+ cmd_print_environment_metadata.cc cmd_print_environment_metadata.hh \
+ cmd_print_id_metadata.cc cmd_print_id_metadata.hh \
+ cmd_print_ids.cc cmd_print_ids.hh \
+ cmd_show.cc cmd_show.hh \
+ exceptions.cc exceptions.hh \
+ format_general.cc format_general.hh \
+ format_plain_contents_entry.cc format_plain_contents_entry.hh \
+ format_plain_metadata_key.cc format_plain_metadata_key.hh \
+ format_string.cc format_string.hh \
+ formats.cc formats.hh \
+ select_format_for_spec.cc select_format_for_spec.hh
+
+# cmd_config.cc \
+# cmd_contents.cc \
+# cmd_executables.cc \
+# cmd_info.cc \
+# cmd_install.cc \
+# cmd_owner.cc \
+# cmd_print_executables.cc \
+# cmd_print_id_actions.cc \
+# cmd_print_id_masks.cc \
+# cmd_print_owners.cc \
+# cmd_print_packages.cc \
+# cmd_print_repositories.cc \
+# cmd_print_repository_formats.cc \
+# cmd_print_repository_metadata.cc \
+# cmd_print_sets.cc \
+# cmd_print_set.cc \
+# cmd_print_sync_protocol_metadata.cc \
+# cmd_print_sync_protocols.cc \
+# cmd_regenerate_installable_cache.cc \
+# cmd_regenerate_installed_cache.cc \
+# cmd_report.cc \
+# cmd_sync.cc \
+# cmd_uninstall.cc \
+# cmd_uninstall_unused.cc
+
+TESTS_ENVIRONMENT = env \
+ TEST_SCRIPT_DIR="$(srcdir)/" \
+ PALUDIS_NO_GLOBAL_HOOKS="yes" \
+ PALUDIS_NO_XTERM_TITLES="yes" \
+ PALUDIS_OPTIONS="" \
+ PALUDIS_EBUILD_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_srcdir)/paludis/repositories/e/ebuild/`" \
+ PALUDIS_EBUILD_DIR_FALLBACK="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories/e/ebuild/`" \
+ PALUDIS_EXTRA_EBUILD_MODULES_DIRS="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
+ PALUDIS_EAPIS_DIR="$(top_srcdir)/paludis/repositories/e/eapis/" \
+ PALUDIS_SUFFIXES_FILE="$(top_srcdir)/paludis/repositories/e/ebuild_entries_suffixes.conf" \
+ PALUDIS_DISTRIBUTIONS_DIR="$(top_srcdir)/paludis/distributions/" \
+ PALUDIS_DISTRIBUTION="gentoo" \
+ PALUDIS_REPOSITORY_SO_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/repositories`" \
+ PALUDIS_ENVIRONMENT_SO_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/environments`" \
+ PALUDIS_NO_CHOWN="yupyup" \
+ PALUDIS_REDUCED_USERNAME="`id -un`" \
+ PALUDIS_OUTPUTWRAPPER_DIR="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/`" \
+ TEST_OUTPUT_WRAPPER="`$(top_srcdir)/paludis/repositories/e/ebuild/utils/canonicalise $(top_builddir)/paludis/util/outputwrapper`" \
+ SYSCONFDIR="$(sysconfdir)" \
+ bash $(top_srcdir)/test/run_test.sh bash
+
+TESTS =
+
+EXTRA_DIST = \
+ $(man_MANS) \
+ $(TESTS)
+
+CLEANFILES = *~ gmon.out *.gcov *.gcno *.gcda *.loT
+DISTCLEANFILES = $(man_MANS) $(noinst_DATA)
+MAINTAINERCLEANFILES = Makefile.in
+
+built-sources : $(BUILT_SOURCES)
+ for s in `echo $(SUBDIRS) | tr -d .` ; do $(MAKE) -C $$s built-sources || exit 1 ; done
+
+DISTCHECK_DEPS = cave.1
+
+distcheck-deps-local : $(DISTCHECK_DEPS)
+
+distcheck-deps : distcheck-deps-subdirs
+
+distcheck-deps-subdirs :
+ for s in $(SUBDIRS) . ; do if test x$$s = x. ; then $(MAKE) distcheck-deps-local || exit 1 ; \
+ else $(MAKE) -C $$s distcheck-deps || exit 1 ; fi ; done
+
diff --git a/src/clients/cave/cave.cc b/src/clients/cave/cave.cc
new file mode 100644
index 0000000..4d6e7b2
--- /dev/null
+++ b/src/clients/cave/cave.cc
@@ -0,0 +1,75 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <paludis/util/attributes.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/wrapped_output_iterator.hh>
+#include <paludis/util/iterator_funcs.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/environment_factory.hh>
+#include <iostream>
+#include <cstdlib>
+#include <string>
+
+#include "command_factory.hh"
+#include "command_line.hh"
+
+using namespace paludis;
+using std::endl;
+using std::cout;
+using std::cerr;
+
+int main(int argc, char * argv[])
+{
+ Context context(std::string("In program ") + argv[0] + " " + join(argv + 1, argv + argc, " ") + ":");
+
+ try
+ {
+ cave::CaveCommandLine cmdline;
+ cmdline.run(argc, argv, "CAVE", "CAVE_OPTIONS", "CAVE_CMDLINE", args::ArgsHandlerOptions() + args::aho_stop_on_first_parameter);
+
+ if (cmdline.begin_parameters() == cmdline.end_parameters())
+ throw args::DoHelp();
+
+ std::tr1::shared_ptr<Environment> env(EnvironmentFactory::get_instance()->create(cmdline.a_environment.argument()));
+
+ std::tr1::shared_ptr<Sequence<std::string> > seq(new Sequence<std::string>);
+ std::copy(next(cmdline.begin_parameters()), cmdline.end_parameters(), seq->back_inserter());
+
+ return cave::CommandFactory::get_instance()->create(*cmdline.begin_parameters())->run(env, seq);
+ }
+ catch (const args::DoHelp & h)
+ {
+ if (h.message.empty())
+ cout << "Usage: " << argv[0] << " COMMAND [ARGS]" << endl;
+ else
+ cerr << "Usage error: " << h.message << endl;
+
+ return EXIT_FAILURE;
+ }
+ catch (const Exception & e)
+ {
+ cerr << endl;
+ cerr << "Error:" << endl;
+ cerr << " * " << e.backtrace("\n * ") << e.message() << " (" << e.what() << ")" << endl;
+ cerr << endl;
+ return EXIT_FAILURE;
+ }
+}
+
diff --git a/src/clients/cave/cmd_print_categories.cc b/src/clients/cave/cmd_print_categories.cc
new file mode 100644
index 0000000..e69a0e3
--- /dev/null
+++ b/src/clients/cave/cmd_print_categories.cc
@@ -0,0 +1,128 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cmd_print_categories.hh"
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/name.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repository.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <cstdlib>
+#include <iostream>
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct PrintCategoriesCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave print-categories";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Prints a list of known categories.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Prints a list of known categories. No formatting is used, making the output suitable for "
+ "parsing by scripts.";
+ }
+
+ args::ArgsGroup g_filters;
+ args::StringSetArg a_containing;
+ args::StringSetArg a_repository;
+
+ PrintCategoriesCommandLine() :
+ g_filters(this, "Filters", "Filter the output. Each filter may be specified more than once. The object "
+ "specified by the filter does not have to exist."),
+ a_containing(&g_filters, "containing", '\0', "Show only categories containing this package name. If specified "
+ "multiple times, categories containing any of these package names are selected.",
+ args::StringSetArg::StringSetArgOptions(), &PackageNamePartValidator::validate),
+ a_repository(&g_filters, "repository", '\0', "Show only categories in this repository. If specified multiple "
+ "times, categories in any of these repositories are selected.",
+ args::StringSetArg::StringSetArgOptions(), &RepositoryNameValidator::validate)
+ {
+ add_usage_line("[ --containing pkgname ] [ --repository reponame ]");
+ }
+ };
+}
+
+int
+PrintCategoriesCommand::run(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ PrintCategoriesCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_PRINT_CATEGORIES_OPTIONS", "CAVE_PRINT_CATEGORIES_CMDLINE");
+
+ if (cmdline.begin_parameters() != cmdline.end_parameters())
+ throw args::DoHelp("print-categories takes no parameters");
+
+ std::set<CategoryNamePart> categories;
+ for (PackageDatabase::RepositoryConstIterator r(env->package_database()->begin_repositories()),
+ r_end(env->package_database()->end_repositories()) ;
+ r != r_end ; ++r)
+ {
+ if (cmdline.a_repository.specified())
+ if (cmdline.a_repository.end_args() == std::find(cmdline.a_repository.begin_args(),
+ cmdline.a_repository.end_args(), stringify((*r)->name())))
+ continue;
+
+ if (cmdline.a_containing.specified())
+ {
+ for (args::StringSetArg::ConstIterator p(cmdline.a_containing.begin_args()), p_end(cmdline.a_containing.end_args()) ;
+ p != p_end ; ++p)
+ {
+ std::tr1::shared_ptr<const CategoryNamePartSet> cats((*r)->category_names_containing_package(PackageNamePart(*p)));
+ std::copy(cats->begin(), cats->end(), std::inserter(categories, categories.begin()));
+ }
+ }
+ else
+ {
+ std::tr1::shared_ptr<const CategoryNamePartSet> cats((*r)->category_names());
+ std::copy(cats->begin(), cats->end(), std::inserter(categories, categories.begin()));
+ }
+ }
+
+ std::copy(categories.begin(), categories.end(), std::ostream_iterator<CategoryNamePart>(cout, "\n"));
+
+ return EXIT_SUCCESS;
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+PrintCategoriesCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new PrintCategoriesCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_print_categories.hh b/src/clients/cave/cmd_print_categories.hh
new file mode 100644
index 0000000..d451a88
--- /dev/null
+++ b/src/clients/cave/cmd_print_categories.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_CATEGORIES_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_CATEGORIES_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE PrintCategoriesCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+
+#endif
diff --git a/src/clients/cave/cmd_print_commands.cc b/src/clients/cave/cmd_print_commands.cc
new file mode 100644
index 0000000..35262e4
--- /dev/null
+++ b/src/clients/cave/cmd_print_commands.cc
@@ -0,0 +1,86 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cmd_print_commands.hh"
+#include "command_factory.hh"
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <cstdlib>
+#include <iostream>
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct PrintCommandsCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave print-commands";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Prints a list of known cave commands.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Prints a list of known cave commands. No formatting is used, making the output suitable for "
+ "parsing by scripts.";
+ }
+
+ PrintCommandsCommandLine()
+ {
+ add_usage_line("");
+ }
+ };
+}
+
+int
+PrintCommandsCommand::run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ PrintCommandsCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_PRINT_COMMANDS_OPTIONS", "CAVE_PRINT_COMMANDS_CMDLINE");
+
+ if (cmdline.begin_parameters() != cmdline.end_parameters())
+ throw args::DoHelp("print-commands takes no parameters");
+
+ std::copy(CommandFactory::get_instance()->begin(), CommandFactory::get_instance()->end(),
+ std::ostream_iterator<std::string>(cout, "\n"));
+
+ return EXIT_SUCCESS;
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+PrintCommandsCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new PrintCommandsCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_print_commands.hh b/src/clients/cave/cmd_print_commands.hh
new file mode 100644
index 0000000..66a0bb0
--- /dev/null
+++ b/src/clients/cave/cmd_print_commands.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_COMMANDS_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_COMMANDS_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE PrintCommandsCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+
+#endif
diff --git a/src/clients/cave/cmd_print_environment_metadata.cc b/src/clients/cave/cmd_print_environment_metadata.cc
new file mode 100644
index 0000000..bc7740c
--- /dev/null
+++ b/src/clients/cave/cmd_print_environment_metadata.cc
@@ -0,0 +1,138 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cmd_print_environment_metadata.hh"
+#include "format_plain_metadata_key.hh"
+#include "exceptions.hh"
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
+#include <paludis/util/set.hh>
+#include <paludis/environment.hh>
+#include <paludis/metadata_key.hh>
+#include <iostream>
+#include <algorithm>
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct PrintEnvironmentMetadataCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave print-environment-metadata";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Prints environment metadata.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Prints environment metadata. No formatting is used, making the output suitable for "
+ "parsing by scripts.";
+ }
+
+ args::ArgsGroup g_filters;
+ args::StringSetArg a_raw_name;
+ args::StringSetArg a_human_name;
+
+ args::ArgsGroup g_display_options;
+ args::StringArg a_format;
+
+ PrintEnvironmentMetadataCommandLine() :
+ g_filters(this, "Filters", "Filter the output. Each filter may be specified more than once."),
+ a_raw_name(&g_filters, "raw-name", '\0', "Show only keys with this raw name. If specified more than once, "
+ "any name match is accepted."),
+ a_human_name(&g_filters, "human-name", '\0', "Show only keys with this human name. If specified more than once, "
+ "any name match is accepted."),
+ g_display_options(this, "Display Options", "Controls the output format."),
+ a_format(&g_display_options, "format", '\0', "Select the output format. Special tokens recognised are "
+ "%r for raw name, %h for human name, %v for value, %i for one space per subkey level, "
+ "\\n for newline, \\t for tab. Default is '%i%i%r=%v\\n'.")
+ {
+ a_format.set_argument("%i%i%r=%v\\n");
+ add_usage_line("[ --raw-name key ] [ --human-name key ] [ --format format ]");
+ }
+ };
+
+ void do_one_key(
+ const std::tr1::shared_ptr<const MetadataKey> & k,
+ const PrintEnvironmentMetadataCommandLine & cmdline,
+ const std::string & name_prefix
+ )
+ {
+ do
+ {
+ if (cmdline.a_raw_name.specified())
+ if (cmdline.a_raw_name.end_args() == std::find(cmdline.a_raw_name.begin_args(), cmdline.a_raw_name.end_args(),
+ k->raw_name()))
+ continue;
+
+ if (cmdline.a_human_name.specified())
+ if (cmdline.a_human_name.end_args() == std::find(cmdline.a_human_name.begin_args(), cmdline.a_human_name.end_args(),
+ k->human_name()))
+ continue;
+
+ cout << format_plain_metadata_key(k, name_prefix, cmdline.a_format.argument());
+ } while (false);
+
+ const MetadataSectionKey * section(visitor_cast<const MetadataSectionKey>(*k));
+ if (section)
+ {
+ for (MetadataSectionKey::MetadataConstIterator s(section->begin_metadata()), s_end(section->end_metadata()) ;
+ s != s_end ; ++s)
+ do_one_key(*s, cmdline, name_prefix + " ");
+ }
+ }
+}
+
+int
+PrintEnvironmentMetadataCommand::run(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ PrintEnvironmentMetadataCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_PRINT_ENVIRONMENT_METADATA_OPTIONS", "CAVE_PRINT_ENVIRONMENT_METADATA_CMDLINE");
+
+ if (cmdline.begin_parameters() != cmdline.end_parameters())
+ throw args::DoHelp("print-environment-metadata takes no parameters");
+
+ for (Environment::MetadataConstIterator m(env->begin_metadata()), m_end(env->end_metadata()) ;
+ m != m_end ; ++m)
+ do_one_key(*m, cmdline, "");
+
+ return EXIT_SUCCESS;
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+PrintEnvironmentMetadataCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new PrintEnvironmentMetadataCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_print_environment_metadata.hh b/src/clients/cave/cmd_print_environment_metadata.hh
new file mode 100644
index 0000000..e135d49
--- /dev/null
+++ b/src/clients/cave/cmd_print_environment_metadata.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_ENVIRONMENT_METADATA_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_ENVIRONMENT_METADATA_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE PrintEnvironmentMetadataCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+
+#endif
diff --git a/src/clients/cave/cmd_print_id_contents.cc b/src/clients/cave/cmd_print_id_contents.cc
new file mode 100644
index 0000000..9255f81
--- /dev/null
+++ b/src/clients/cave/cmd_print_id_contents.cc
@@ -0,0 +1,134 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cmd_print_id_contents.hh"
+#include "exceptions.hh"
+#include "format_plain_contents_entry.hh"
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/environment.hh>
+#include <paludis/contents.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/iterator_funcs.hh>
+#include <paludis/util/options.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/filter.hh>
+#include <paludis/generator.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/selection.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <iostream>
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct PrintContentsCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave print-id-contents";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Prints the contents of a package ID.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Prints a list of the contents of a given ID. No formatting is used, making the output suitable for "
+ "parsing by scripts.";
+ }
+
+ args::ArgsGroup g_spec_options;
+ args::SwitchArg a_best;
+
+ args::ArgsGroup g_display_options;
+ args::StringArg a_format;
+
+ PrintContentsCommandLine() :
+ g_spec_options(this, "Spec Options", "Alter how the supplied spec is used."),
+ a_best(&g_spec_options, "best", '\0', "If the spec matches multiple IDs, select the best ID rather than giving an error.", true),
+ g_display_options(this, "Display Options", "Controls the output format."),
+ a_format(&g_display_options, "format", '\0', "Select the output format. Special tokens recognised are "
+ "%n for filename, %d for dirname, %b for basename, %t for symlink targets (blank for non-symlinks), "
+ "%a for ' -> ' if we're a symlink and '' otherwise, %/ for '/' if we're a directory and '' otherwise, "
+ "%i for one space for every parent directory, "
+ "\\n for newline, \\t for tab. Default is '%n%a%t\\n'.")
+ {
+ add_usage_line("spec");
+ a_format.set_argument("%n%a%t\\n");
+ }
+ };
+}
+
+int
+PrintIDContentsCommand::run(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ PrintContentsCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_PRINT_ID_CONTENTS_OPTIONS", "CAVE_PRINT_ID_CONTENTS_CMDLINE");
+
+ if (1 != std::distance(cmdline.begin_parameters(), cmdline.end_parameters()))
+ throw args::DoHelp("print-id-contents takes exactly one parameter");
+
+ PackageDepSpec spec(parse_user_package_dep_spec(*cmdline.begin_parameters(), env.get(),
+ UserPackageDepSpecOptions(), filter::InstalledAtRoot(env->root())));
+
+ std::tr1::shared_ptr<const PackageIDSequence> entries(
+ (*env)[selection::AllVersionsSorted(generator::Matches(spec) | filter::InstalledAtRoot(env->root()))]);
+
+ if (entries->empty())
+ throw NothingMatching(spec);
+
+ if ((! cmdline.a_best.specified()) && (next(entries->begin()) != entries->end()))
+ throw BeMoreSpecific(spec, entries);
+
+ const std::tr1::shared_ptr<const PackageID> id(*entries->last());
+ if (! id->contents_key())
+ throw BadIDForCommand(spec, id, "does not support listing contents");
+
+ std::transform(
+ id->contents_key()->value()->begin(),
+ id->contents_key()->value()->end(),
+ std::ostream_iterator<std::string>(cout, ""),
+ std::tr1::bind(format_plain_contents_entry, std::tr1::placeholders::_1, cmdline.a_format.argument()));
+
+ return EXIT_SUCCESS;
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+PrintIDContentsCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new PrintContentsCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_print_id_contents.hh b/src/clients/cave/cmd_print_id_contents.hh
new file mode 100644
index 0000000..c1b5c0f
--- /dev/null
+++ b/src/clients/cave/cmd_print_id_contents.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_ID_CONTENTS_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_ID_CONTENTS_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE PrintIDContentsCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+
+#endif
diff --git a/src/clients/cave/cmd_print_id_metadata.cc b/src/clients/cave/cmd_print_id_metadata.cc
new file mode 100644
index 0000000..ba1cc3f
--- /dev/null
+++ b/src/clients/cave/cmd_print_id_metadata.cc
@@ -0,0 +1,162 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cmd_print_id_metadata.hh"
+#include "format_plain_metadata_key.hh"
+#include "exceptions.hh"
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/iterator_funcs.hh>
+#include <paludis/util/options.hh>
+#include <paludis/environment.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/generator.hh>
+#include <paludis/selection.hh>
+#include <paludis/package_id.hh>
+#include <iostream>
+#include <algorithm>
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct PrintIDMetadataCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave print-id-metadata";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Prints ID metadata.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Prints ID metadata. No formatting is used, making the output suitable for "
+ "parsing by scripts.";
+ }
+
+ args::ArgsGroup g_spec_options;
+ args::SwitchArg a_best;
+
+ args::ArgsGroup g_filters;
+ args::StringSetArg a_raw_name;
+ args::StringSetArg a_human_name;
+
+ args::ArgsGroup g_display_options;
+ args::StringArg a_format;
+
+ PrintIDMetadataCommandLine() :
+ g_spec_options(this, "Spec Options", "Alter how the supplied spec is used."),
+ a_best(&g_spec_options, "best", '\0', "If the spec matches multiple IDs, select the best ID rather than giving an error.", true),
+ g_filters(this, "Filters", "Filter the output. Each filter may be specified more than once."),
+ a_raw_name(&g_filters, "raw-name", '\0', "Show only keys with this raw name. If specified more than once, "
+ "any name match is accepted."),
+ a_human_name(&g_filters, "human-name", '\0', "Show only keys with this human name. If specified more than once, "
+ "any name match is accepted."),
+ g_display_options(this, "Display Options", "Controls the output format."),
+ a_format(&g_display_options, "format", '\0', "Select the output format. Special tokens recognised are "
+ "%r for raw name, %h for human name, %v for value, %i for one space per subkey level, "
+ "\\n for newline, \\t for tab. Default is '%i%i%r=%v\\n'.")
+ {
+ a_format.set_argument("%i%i%r=%v\\n");
+ add_usage_line("[ --raw-name key ] [ --human-name key ] [ --format format ] spec");
+ }
+ };
+
+ void do_one_key(
+ const std::tr1::shared_ptr<const MetadataKey> & k,
+ const PrintIDMetadataCommandLine & cmdline,
+ const std::string & name_prefix
+ )
+ {
+ do
+ {
+ if (cmdline.a_raw_name.specified())
+ if (cmdline.a_raw_name.end_args() == std::find(cmdline.a_raw_name.begin_args(), cmdline.a_raw_name.end_args(),
+ k->raw_name()))
+ continue;
+
+ if (cmdline.a_human_name.specified())
+ if (cmdline.a_human_name.end_args() == std::find(cmdline.a_human_name.begin_args(), cmdline.a_human_name.end_args(),
+ k->human_name()))
+ continue;
+
+ cout << format_plain_metadata_key(k, name_prefix, cmdline.a_format.argument());
+ } while (false);
+
+ const MetadataSectionKey * section(visitor_cast<const MetadataSectionKey>(*k));
+ if (section)
+ {
+ for (MetadataSectionKey::MetadataConstIterator s(section->begin_metadata()), s_end(section->end_metadata()) ;
+ s != s_end ; ++s)
+ do_one_key(*s, cmdline, name_prefix + " ");
+ }
+ }
+}
+
+int
+PrintIDMetadataCommand::run(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ PrintIDMetadataCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_PRINT_ID_METADATA_OPTIONS", "CAVE_PRINT_ID_METADATA_CMDLINE");
+
+ if (1 != std::distance(cmdline.begin_parameters(), cmdline.end_parameters()))
+ throw args::DoHelp("print-id-metadata takes exactly one parameter");
+
+ PackageDepSpec spec(parse_user_package_dep_spec(*cmdline.begin_parameters(), env.get(), UserPackageDepSpecOptions()));
+
+ std::tr1::shared_ptr<const PackageIDSequence> entries(
+ (*env)[selection::AllVersionsSorted(generator::Matches(spec))]);
+
+ if (entries->empty())
+ throw NothingMatching(spec);
+
+ if ((! cmdline.a_best.specified()) && (next(entries->begin()) != entries->end()))
+ throw BeMoreSpecific(spec, entries);
+
+ for (PackageID::MetadataConstIterator m((*entries->last())->begin_metadata()), m_end((*entries->last())->end_metadata()) ;
+ m != m_end ; ++m)
+ do_one_key(*m, cmdline, "");
+
+ return EXIT_SUCCESS;
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+PrintIDMetadataCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new PrintIDMetadataCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_print_id_metadata.hh b/src/clients/cave/cmd_print_id_metadata.hh
new file mode 100644
index 0000000..c17e781
--- /dev/null
+++ b/src/clients/cave/cmd_print_id_metadata.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_ID_METADATA_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_ID_METADATA_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE PrintIDMetadataCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+
+#endif
diff --git a/src/clients/cave/cmd_print_ids.cc b/src/clients/cave/cmd_print_ids.cc
new file mode 100644
index 0000000..e84ca90
--- /dev/null
+++ b/src/clients/cave/cmd_print_ids.cc
@@ -0,0 +1,311 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cmd_print_ids.hh"
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/name.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repository.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
+#include <paludis/generator.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/filter.hh>
+#include <paludis/filter_handler.hh>
+#include <paludis/selection.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/package_id.hh>
+#include <paludis/mask.hh>
+#include <cstdlib>
+#include <iostream>
+#include <algorithm>
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct PrintIDsCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave print-ids";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Prints a list of known IDs.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Prints a list of known IDs. No formatting is used, making the output suitable for "
+ "parsing by scripts.";
+ }
+
+ args::ArgsGroup g_filters;
+ args::StringSetArg a_matching;
+ args::StringSetArg a_supporting;
+ args::StringSetArg a_with_mask;
+
+ PrintIDsCommandLine() :
+ g_filters(this, "Filters", "Filter the output. Each filter may be specified more than once."),
+ a_matching(&g_filters, "matching", '\0', "Show only IDs matching this spec. If specified multiple "
+ "times, only IDs matching every spec are selected.",
+ args::StringSetArg::StringSetArgOptions()),
+ a_supporting(&g_filters, "supporting", '\0', "Show only IDs supporting this action. If specified "
+ "multiple times, all listed actions must be supported.",
+ args::StringSetArg::StringSetArgOptions
+ ("install", "able to be installed")
+ ("installed", "installed")
+ ("uninstall", "able to be uninstalled")
+ ("pretend", "has pretend-install-time checks")
+ ("config", "supports post-install configuration")
+ ("fetch", "able to have sources fetched")
+ ("pretend-fetch", "able to have sources pretend-fetched")
+ ("info", "provides extra pre- or post-install information")
+ ),
+ a_with_mask(&g_filters, "with-mask", '\0', "Show only IDs with this kind of mask. If specified "
+ "multiple times, all listed masks must be present.",
+ args::StringSetArg::StringSetArgOptions
+ ("none", "no mask")
+ ("any", "any kind of mask")
+ ("user", "masked by user")
+ ("unaccepted", "masked by unaccepted key")
+ ("repository", "masked by repository")
+ ("unsupported", "masked because it is unsupported")
+ ("association", "masked by association")
+ )
+ {
+ add_usage_line("[ --matching spec ] [ --supporting action ] [ --with-mask mask-kind ]");
+ }
+ };
+
+ struct WithMaskFilterHandler :
+ FilterHandler
+ {
+ const PrintIDsCommandLine & cmdline;
+ const std::string mask;
+
+ WithMaskFilterHandler(const PrintIDsCommandLine & c, const std::string & f) :
+ cmdline(c),
+ mask(f)
+ {
+ }
+
+ virtual std::string as_string() const
+ {
+ return "with mask '" + mask + "'";
+ }
+
+ virtual std::tr1::shared_ptr<const RepositoryNameSet> repositories(
+ const Environment * const,
+ const std::tr1::shared_ptr<const RepositoryNameSet> & r) const
+ {
+ return r;
+ }
+
+ virtual std::tr1::shared_ptr<const CategoryNamePartSet> categories(
+ const Environment * const,
+ const std::tr1::shared_ptr<const RepositoryNameSet> &,
+ const std::tr1::shared_ptr<const CategoryNamePartSet> & c) const
+ {
+ return c;
+ }
+
+ virtual std::tr1::shared_ptr<const QualifiedPackageNameSet> packages(
+ const Environment * const,
+ const std::tr1::shared_ptr<const RepositoryNameSet> &,
+ const std::tr1::shared_ptr<const QualifiedPackageNameSet> & q) const
+ {
+ return q;
+ }
+
+ virtual std::tr1::shared_ptr<const PackageIDSet> ids(
+ const Environment * const,
+ const std::tr1::shared_ptr<const PackageIDSet> & c) const
+ {
+ std::tr1::shared_ptr<PackageIDSet> result(new PackageIDSet);
+
+ for (PackageIDSet::ConstIterator i(c->begin()), i_end(c->end()) ;
+ i != i_end ; ++i)
+ {
+ if (mask == "none")
+ {
+ if (! (*i)->masked())
+ result->insert(*i);
+ }
+ else if (mask == "any")
+ {
+ if ((*i)->masked())
+ result->insert(*i);
+ }
+ else if (mask == "user")
+ {
+ for (PackageID::MasksConstIterator m((*i)->begin_masks()), m_end((*i)->end_masks()) ;
+ m != m_end ; ++m)
+ if (visitor_cast<const UserMask>(**m))
+ {
+ result->insert(*i);
+ break;
+ }
+ }
+ else if (mask == "unaccepted")
+ {
+ for (PackageID::MasksConstIterator m((*i)->begin_masks()), m_end((*i)->end_masks()) ;
+ m != m_end ; ++m)
+ if (visitor_cast<const UnacceptedMask>(**m))
+ {
+ result->insert(*i);
+ break;
+ }
+ }
+ else if (mask == "repository")
+ {
+ for (PackageID::MasksConstIterator m((*i)->begin_masks()), m_end((*i)->end_masks()) ;
+ m != m_end ; ++m)
+ if (visitor_cast<const RepositoryMask>(**m))
+ {
+ result->insert(*i);
+ break;
+ }
+ }
+ else if (mask == "unsupported")
+ {
+ for (PackageID::MasksConstIterator m((*i)->begin_masks()), m_end((*i)->end_masks()) ;
+ m != m_end ; ++m)
+ if (visitor_cast<const UnsupportedMask>(**m))
+ {
+ result->insert(*i);
+ break;
+ }
+ }
+ else if (mask == "association")
+ {
+ for (PackageID::MasksConstIterator m((*i)->begin_masks()), m_end((*i)->end_masks()) ;
+ m != m_end ; ++m)
+ if (visitor_cast<const AssociationMask>(**m))
+ {
+ result->insert(*i);
+ break;
+ }
+ }
+ else
+ throw args::DoHelp("Unknown --" + cmdline.a_with_mask.long_name() + " value '" + mask + "'");
+ }
+
+ return result;
+ }
+ };
+
+ struct WithMaskFilter :
+ Filter
+ {
+ WithMaskFilter(const PrintIDsCommandLine & c, const std::string & f) :
+ Filter(make_shared_ptr(new WithMaskFilterHandler(c, f)))
+ {
+ }
+ };
+}
+
+int
+PrintIDsCommand::run(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ PrintIDsCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_PRINT_IDS_OPTIONS", "CAVE_PRINT_IDS_CMDLINE");
+
+ if (cmdline.begin_parameters() != cmdline.end_parameters())
+ throw args::DoHelp("print-ids takes no parameters");
+
+ Generator g((generator::All()));
+ if (cmdline.a_matching.specified())
+ {
+ for (args::StringSetArg::ConstIterator m(cmdline.a_matching.begin_args()),
+ m_end(cmdline.a_matching.end_args()) ;
+ m != m_end ; ++m)
+ {
+ PackageDepSpec s(parse_user_package_dep_spec(*m, env.get(), UserPackageDepSpecOptions() + updso_allow_wildcards));
+ g = g & generator::Matches(s);
+ }
+ }
+
+ FilteredGenerator fg(g);
+
+ if (cmdline.a_supporting.specified())
+ {
+ for (args::StringSetArg::ConstIterator m(cmdline.a_supporting.begin_args()),
+ m_end(cmdline.a_supporting.end_args()) ;
+ m != m_end ; ++m)
+ {
+ if (*m == "install")
+ fg = fg | filter::SupportsAction<InstallAction>();
+ else if (*m == "installed")
+ fg = fg | filter::SupportsAction<InstalledAction>();
+ else if (*m == "uninstall")
+ fg = fg | filter::SupportsAction<UninstallAction>();
+ else if (*m == "pretend")
+ fg = fg | filter::SupportsAction<PretendAction>();
+ else if (*m == "config")
+ fg = fg | filter::SupportsAction<ConfigAction>();
+ else if (*m == "fetch")
+ fg = fg | filter::SupportsAction<FetchAction>();
+ else if (*m == "pretend-fetch")
+ fg = fg | filter::SupportsAction<PretendFetchAction>();
+ else if (*m == "info")
+ fg = fg | filter::SupportsAction<InfoAction>();
+ else
+ throw args::DoHelp("Unknown --" + cmdline.a_supporting.long_name() + " value '" + *m + "'");
+ }
+ }
+
+ if (cmdline.a_with_mask.specified())
+ {
+ for (args::StringSetArg::ConstIterator m(cmdline.a_with_mask.begin_args()),
+ m_end(cmdline.a_with_mask.end_args()) ;
+ m != m_end ; ++m)
+ {
+ fg = fg | WithMaskFilter(cmdline, *m);
+ }
+ }
+
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*env)[selection::AllVersionsSorted(fg)]);
+ std::copy(indirect_iterator(ids->begin()), indirect_iterator(ids->end()),
+ std::ostream_iterator<PackageID>(cout, "\n"));
+
+ return EXIT_SUCCESS;
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+PrintIDsCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new PrintIDsCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_print_ids.hh b/src/clients/cave/cmd_print_ids.hh
new file mode 100644
index 0000000..2e6868d
--- /dev/null
+++ b/src/clients/cave/cmd_print_ids.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_IDS_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_PRINT_IDS_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE PrintIDsCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+
+#endif
diff --git a/src/clients/cave/cmd_show.cc b/src/clients/cave/cmd_show.cc
new file mode 100644
index 0000000..cdced07
--- /dev/null
+++ b/src/clients/cave/cmd_show.cc
@@ -0,0 +1,738 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cmd_show.hh"
+#include "colour_formatter.hh"
+#include "format_general.hh"
+#include "formats.hh"
+#include "exceptions.hh"
+#include "select_format_for_spec.hh"
+#include <paludis/args/args.hh>
+#include <paludis/args/do_help.hh>
+#include <paludis/name.hh>
+#include <paludis/environment.hh>
+#include <paludis/package_database.hh>
+#include <paludis/repository.hh>
+#include <paludis/user_dep_spec.hh>
+#include <paludis/filter.hh>
+#include <paludis/generator.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/selection.hh>
+#include <paludis/package_id.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/action.hh>
+#include <paludis/mask.hh>
+#include <cstdlib>
+#include <iostream>
+#include <algorithm>
+#include <set>
+
+using namespace paludis;
+using namespace cave;
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct ShowCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave show";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "Display a summary of a given object.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "Displays a formatted summary of a given object. If the object is a set, the set's "
+ "contents are listed. If the object is a repository name, information about the repository "
+ "is displayed. If the object is a package dep spec with wildcards, possible expansions "
+ "are shown. If the object is a package dep spec without wildcards, information about matching "
+ "IDs are shown.";
+ }
+
+ args::ArgsGroup g_object_options;
+ args::EnumArg a_type;
+
+ args::ArgsGroup g_key_options;
+ args::SwitchArg a_complex_keys;
+ args::SwitchArg a_internal_keys;
+
+ args::ArgsGroup g_display_options;
+ args::SwitchArg a_flat;
+
+ ShowCommandLine() :
+ g_object_options(this, "Object Options", "Alter how objects are interpreted."),
+ a_type(&g_object_options, "type", '\0', "Specify the type of the specified objects.",
+ args::EnumArg::EnumArgOptions
+ ("auto", "Automatically determine the type")
+ ("repository", "Treat the objects as repository names")
+ ("set", "Treat the objects as set names")
+ ("wildcard", "Treat the objects as a wildcarded package spec")
+ ("package", "Treat the objects as an unwildcarded package spec, showing all matches for wildcards"),
+ "auto"),
+ g_key_options(this, "Key Options", "Control which keys are shown."),
+ a_complex_keys(&g_key_options, "complex-keys", 'c',
+ "Show complex keys", true),
+ a_internal_keys(&g_key_options, "internal-keys", 'i',
+ "Show keys regardless of importance, including internal-only values", true),
+ g_display_options(this, "Display Options", "Controls the output format."),
+ a_flat(&g_display_options, "flat", 'f',
+ "Do not spread key values over multiple lines", true)
+ {
+ add_usage_line("spec ...");
+ }
+ };
+
+ struct SetDisplayer :
+ ConstVisitor<SetSpecTree>
+ {
+ const std::tr1::shared_ptr<const Environment> env;
+
+ SetDisplayer(const std::tr1::shared_ptr<const Environment> & e) :
+ env(e)
+ {
+ }
+
+ void visit_leaf(const PackageDepSpec & spec)
+ {
+ cout << format_general_s(select_format_for_spec(env, spec,
+ f::show_set_spec_installed(),
+ f::show_set_spec_installable(),
+ f::show_set_spec_unavailable()),
+ stringify(spec));
+ }
+
+ void visit_leaf(const NamedSetDepSpec & spec)
+ {
+ cout << format_general_s(f::show_set_set(), stringify(spec));
+ }
+
+ void visit_sequence(
+ const AllDepSpec &,
+ SetSpecTree::ConstSequenceIterator cur,
+ SetSpecTree::ConstSequenceIterator end)
+ {
+ std::for_each(cur, end, accept_visitor(*this));
+ }
+ };
+
+ void do_one_set(const std::tr1::shared_ptr<Environment> & env, const SetName & s)
+ {
+ cout << format_general_s(f::show_set_heading(), stringify(s));
+
+ const std::tr1::shared_ptr<const SetSpecTree::ConstItem> set(env->set(s));
+ if (! set)
+ throw NoSuchSetError(stringify(s));
+
+ SetDisplayer d(env);
+ set->accept(d);
+
+ cout << endl;
+ }
+
+ void do_one_wildcard(const std::tr1::shared_ptr<Environment> & env, const PackageDepSpec & s)
+ {
+ cout << format_general_s(f::show_wildcard_heading(), stringify(s));
+
+ const std::tr1::shared_ptr<const PackageIDSequence> names((*env)[selection::BestVersionOnly(generator::Matches(s))]);
+ if (names->empty())
+ throw NothingMatching(s);
+
+ for (PackageIDSequence::ConstIterator i(names->begin()), i_end(names->end()) ;
+ i != i_end ; ++i)
+ {
+ PackageDepSpec name_spec(make_package_dep_spec().package((*i)->name()));
+ cout << format_general_s(select_format_for_spec(env, name_spec,
+ f::show_wildcard_spec_installed(),
+ f::show_wildcard_spec_installable(),
+ f::show_wildcard_spec_unavailable()
+ ),
+ stringify(name_spec));
+ }
+
+ cout << endl;
+ }
+
+ struct MetadataKeyComparator
+ {
+ bool operator() (const std::tr1::shared_ptr<const MetadataKey> & a, const std::tr1::shared_ptr<const MetadataKey> & b) const
+ {
+ bool a_is_section(visitor_cast<const MetadataSectionKey>(*a));
+ bool b_is_section(visitor_cast<const MetadataSectionKey>(*b));
+ if (a_is_section != b_is_section)
+ return b_is_section;
+ if (a->type() != b->type())
+ return a->type() < b->type();
+ return a->human_name() < b->human_name();
+ }
+ };
+
+ struct ContentsDisplayer :
+ ConstVisitor<ContentsVisitorTypes>
+ {
+ const unsigned indent;
+ std::stringstream s;
+
+ ContentsDisplayer(const unsigned i) :
+ indent(i)
+ {
+ }
+
+ void visit(const ContentsFileEntry & e)
+ {
+ s << format_general_rhvib(f::show_contents_file(), e.name(), FSEntry(e.name()).basename(),
+ "", indent, indent);
+ }
+
+ void visit(const ContentsDirEntry & e)
+ {
+ s << format_general_rhvib(f::show_contents_dir(), e.name(), FSEntry(e.name()).basename(),
+ "", indent, indent);
+ }
+
+ void visit(const ContentsMiscEntry & e)
+ {
+ s << format_general_rhvib(f::show_contents_misc(), e.name(), FSEntry(e.name()).basename(),
+ "", indent, indent);
+ }
+
+ void visit(const ContentsDevEntry & e)
+ {
+ s << format_general_rhvib(f::show_contents_dev(), e.name(), FSEntry(e.name()).basename(),
+ "", indent, indent);
+ }
+
+ void visit(const ContentsFifoEntry & e)
+ {
+ s << format_general_rhvib(f::show_contents_fifo(), e.name(), FSEntry(e.name()).basename(),
+ "", indent, indent);
+ }
+
+ void visit(const ContentsSymEntry & e)
+ {
+ s << format_general_rhvib(f::show_contents_sym(), e.name(), FSEntry(e.name()).basename(),
+ e.target(), indent, indent);
+ }
+ };
+
+ struct InfoDisplayer :
+ ConstVisitor<MetadataKeyVisitorTypes>
+ {
+ const ShowCommandLine & cmdline;
+ const int indent;
+ const bool important;
+
+ InfoDisplayer(const ShowCommandLine & c, const int i, const bool m) :
+ cmdline(c),
+ indent(i),
+ important(m)
+ {
+ }
+
+ void visit(const MetadataSectionKey & k)
+ {
+ cout << format_general_rhvib(f::show_metadata_subsection(), k.raw_name(), k.human_name(), "",
+ indent, important);
+ std::set<std::tr1::shared_ptr<const MetadataKey>, MetadataKeyComparator> keys(k.begin_metadata(), k.end_metadata());
+ for (std::set<std::tr1::shared_ptr<const MetadataKey>, MetadataKeyComparator>::const_iterator
+ s(keys.begin()), s_end(keys.end()) ; s != s_end ; ++s)
+ {
+ InfoDisplayer i(cmdline, indent + 1, ((*s)->type() == mkt_significant));
+ if (cmdline.a_internal_keys.specified() || ((*s)->type() != mkt_internal))
+ accept_visitor(i)(**s);
+ }
+ }
+
+ void visit(const MetadataCollectionKey<KeywordNameSet> & k)
+ {
+ ColourFormatter f(indent);
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ }
+
+ void visit(const MetadataCollectionKey<Set<std::string> > & k)
+ {
+ ColourFormatter f(indent);
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ }
+
+ void visit(const MetadataCollectionKey<Sequence<std::string> > & k)
+ {
+ ColourFormatter f(indent);
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ }
+
+ void visit(const MetadataCollectionKey<PackageIDSequence> & k)
+ {
+ ColourFormatter f(indent);
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ }
+
+ void visit(const MetadataCollectionKey<FSEntrySequence> & k)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ join(k.value()->begin(), k.value()->end(), ", "), indent, important);
+ }
+
+ void visit(const MetadataSpecTreeKey<LicenseSpecTree> & k)
+ {
+ ColourFormatter f(indent);
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ }
+
+ void visit(const MetadataSpecTreeKey<SimpleURISpecTree> & k)
+ {
+ if (cmdline.a_complex_keys.specified() || important)
+ {
+ ColourFormatter f(indent);
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ }
+ }
+
+ void visit(const MetadataSpecTreeKey<PlainTextSpecTree> & k)
+ {
+ if (cmdline.a_complex_keys.specified() || important)
+ {
+ ColourFormatter f(indent);
+ if (cmdline.a_flat.specified())
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ else
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ "", indent, important);
+ cout << k.pretty_print(f);
+ }
+ }
+ }
+
+ void visit(const MetadataSpecTreeKey<FetchableURISpecTree> & k)
+ {
+ if (cmdline.a_complex_keys.specified() || important)
+ {
+ ColourFormatter f(indent);
+ if (cmdline.a_flat.specified())
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ else
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ "", indent, important);
+ cout << k.pretty_print(f);
+ }
+ }
+ }
+
+ void visit(const MetadataSpecTreeKey<ProvideSpecTree> & k)
+ {
+ if (cmdline.a_complex_keys.specified() || important)
+ {
+ ColourFormatter f(indent);
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ }
+ }
+
+ void visit(const MetadataSpecTreeKey<DependencySpecTree> & k)
+ {
+ if (cmdline.a_complex_keys.specified() || important)
+ {
+ ColourFormatter f(indent);
+ if (cmdline.a_flat.specified())
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ k.pretty_print_flat(f), indent, important);
+ else
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ "", indent, important);
+ cout << k.pretty_print(f);
+ }
+ }
+ }
+
+ void visit(const MetadataValueKey<std::string> & k)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ stringify(k.value()), indent, important);
+ }
+
+ void visit(const MetadataValueKey<long> & k)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ stringify(k.value()), indent, important);
+ }
+
+ void visit(const MetadataValueKey<bool> & k)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ stringify(k.value() ? "true" : "false"), indent, important);
+ }
+
+ void visit(const MetadataValueKey<FSEntry> & k)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ stringify(k.value()), indent, important);
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > & k)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ stringify(*k.value()), indent, important);
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const Contents> > & k)
+ {
+ if (cmdline.a_complex_keys.specified() || important)
+ {
+ if (cmdline.a_flat.specified())
+ {
+ ContentsDisplayer d(0);
+ std::for_each(indirect_iterator(k.value()->begin()),
+ indirect_iterator(k.value()->end()), accept_visitor(d));
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ d.s.str(), indent, important);
+ }
+ else
+ {
+ ContentsDisplayer d(indent);
+ std::for_each(indirect_iterator(k.value()->begin()),
+ indirect_iterator(k.value()->end()), accept_visitor(d));
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ "", indent, important);
+ cout << d.s.str();
+ }
+ }
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const Choices> > &)
+ {
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const RepositoryMaskInfo> > & k)
+ {
+ if (k.value())
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ stringify(k.value()->mask_file()), indent, important);
+ for (Sequence<std::string>::ConstIterator i(k.value()->comment()->begin()), i_end(k.value()->comment()->end()) ;
+ i != i_end ; ++i)
+ cout << format_general_rhvib(f::show_metadata_continued_value(), k.raw_name(), k.human_name(),
+ *i, 0, important);
+ }
+ }
+
+ void visit(const MetadataTimeKey & k)
+ {
+ char buf[255];
+ time_t t(k.value());
+ if (! strftime(buf, 255, "%c", gmtime(&t)))
+ buf[0] = '\0';
+ cout << format_general_rhvib(f::show_metadata_key_value(), k.raw_name(), k.human_name(),
+ std::string(buf), indent, important);
+ }
+ };
+
+ struct MaskDisplayer :
+ ConstVisitor<MaskVisitorTypes>
+ {
+ const ShowCommandLine & cmdline;
+ const int indent;
+
+ MaskDisplayer(const ShowCommandLine & c, const int i) :
+ cmdline(c),
+ indent(i)
+ {
+ }
+
+ void visit(const UnacceptedMask & m)
+ {
+ if (m.unaccepted_key())
+ {
+ InfoDisplayer i(cmdline, indent, false);
+ m.unaccepted_key()->accept(i);
+ }
+ else
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), "Masked", "Masked",
+ "by " + m.description(), indent, false);
+ }
+ }
+
+ void visit(const UnsupportedMask & m)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), stringify(m.key()),
+ m.description(), m.explanation(), indent, false);
+ }
+
+ void visit(const AssociationMask & m)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), stringify(m.key()),
+ "by " + m.description(), stringify(*m.associated_package()), indent, false);
+ }
+
+ void visit(const UserMask & m)
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), stringify(m.key()),
+ "by " + m.description(), "", indent, false);
+ }
+
+ void visit(const RepositoryMask & m)
+ {
+ if (m.mask_key())
+ {
+ InfoDisplayer i(cmdline, indent, false);
+ m.mask_key()->accept(i);
+ }
+ else
+ {
+ cout << format_general_rhvib(f::show_metadata_key_value(), stringify(m.key()),
+ "by " + m.description(), "", indent, false);
+ }
+ }
+ };
+
+ void do_one_repository(
+ const ShowCommandLine & cmdline,
+ const std::tr1::shared_ptr<Environment> & env,
+ const RepositoryName & s)
+ {
+ cout << format_general_s(f::show_repository_heading(), stringify(s));
+
+ const std::tr1::shared_ptr<const Repository> repo(env->package_database()->fetch_repository(s));
+ std::set<std::tr1::shared_ptr<const MetadataKey>, MetadataKeyComparator> keys(repo->begin_metadata(), repo->end_metadata());
+ for (std::set<std::tr1::shared_ptr<const MetadataKey>, MetadataKeyComparator>::const_iterator
+ k(keys.begin()), k_end(keys.end()) ; k != k_end ; ++k)
+ {
+ InfoDisplayer i(cmdline, 0, ((*k)->type() == mkt_significant));
+ if (cmdline.a_internal_keys.specified() || ((*k)->type() != mkt_internal))
+ accept_visitor(i)(**k);
+ }
+ cout << endl;
+ }
+
+ void do_one_package_id(
+ const ShowCommandLine & cmdline,
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const PackageID> & best)
+ {
+ cout << format_general_s(f::show_package_id_heading(), stringify(*best));
+ std::set<std::tr1::shared_ptr<const MetadataKey>, MetadataKeyComparator> keys(best->begin_metadata(), best->end_metadata());
+ for (std::set<std::tr1::shared_ptr<const MetadataKey>, MetadataKeyComparator>::const_iterator
+ k(keys.begin()), k_end(keys.end()) ; k != k_end ; ++k)
+ {
+ InfoDisplayer i(cmdline, 1, ((*k)->type() == mkt_significant));
+ if (cmdline.a_internal_keys.specified() || ((*k)->type() != mkt_internal))
+ accept_visitor(i)(**k);
+ }
+
+ if (best->masked())
+ {
+ cout << format_general_s(f::show_package_id_masks(), "Masked");
+ MaskDisplayer d(cmdline, 2);
+ std::for_each(indirect_iterator(best->begin_masks()), indirect_iterator(best->end_masks()), accept_visitor(d));
+ }
+ }
+
+ void do_one_package(
+ const ShowCommandLine & cmdline,
+ const std::tr1::shared_ptr<Environment> & env,
+ const PackageDepSpec & s)
+ {
+ cout << format_general_s(f::show_package_heading(), stringify(s));
+
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*env)[selection::AllVersionsGroupedBySlot(generator::Matches(s))]);
+ if (ids->empty())
+ throw NothingMatching(s);
+
+ std::tr1::shared_ptr<const PackageID> best_installable, best_masked_installable;
+ std::tr1::shared_ptr<PackageIDSequence> all_installed(new PackageIDSequence);
+ std::set<RepositoryName, RepositoryNameComparator> repos;
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->supports_action(SupportsActionTest<InstalledAction>()))
+ all_installed->push_back(*i);
+ else if ((*i)->supports_action(SupportsActionTest<InstallAction>()))
+ {
+ if ((*i)->masked())
+ best_masked_installable = *i;
+ else
+ best_installable = *i;
+ }
+
+ repos.insert((*i)->repository()->name());
+ }
+
+ if (! best_installable)
+ best_installable = best_masked_installable;
+
+ for (std::set<RepositoryName, RepositoryNameComparator>::const_iterator r(repos.begin()), r_end(repos.end()) ;
+ r != r_end ; ++r)
+ {
+ cout << format_general_s(f::show_package_repository(), stringify(*r));
+ std::string slot_name;
+ bool need_space(false);
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ {
+ if ((*i)->repository()->name() != *r)
+ continue;
+
+ if (slot_name != stringify((*i)->slot()))
+ {
+ if (! slot_name.empty())
+ cout << format_general_s(f::show_package_slot(), slot_name);
+ slot_name = stringify((*i)->slot());
+ }
+
+ if (need_space)
+ cout << " ";
+ need_space = true;
+
+ if ((*i)->supports_action(SupportsActionTest<InstalledAction>()))
+ cout << format_general_s(f::show_package_version_installed(), stringify((*i)->canonical_form(idcf_version)));
+ else if (! (*i)->masked())
+ cout << format_general_s(f::show_package_version_installable(), stringify((*i)->canonical_form(idcf_version)));
+ else
+ {
+ std::string rr;
+ for (PackageID::MasksConstIterator m((*i)->begin_masks()), m_end((*i)->end_masks()) ;
+ m != m_end ; ++m)
+ rr.append(stringify((*m)->key()));
+ cout << format_general_sr(f::show_package_version_unavailable(), stringify((*i)->canonical_form(idcf_version)), rr);
+ }
+
+ if (best_installable && (**i == *best_installable))
+ cout << format_general_s(f::show_package_best(), "");
+ }
+
+ cout << format_general_s(f::show_package_slot(), slot_name);
+ cout << endl;
+ }
+
+ for (PackageIDSequence::ConstIterator i(all_installed->begin()), i_end(all_installed->end()) ;
+ i != i_end ; ++i)
+ do_one_package_id(cmdline, env, *i);
+ if (best_installable)
+ do_one_package_id(cmdline, env, best_installable);
+
+ cout << endl;
+ }
+
+ void do_all_packages(
+ const ShowCommandLine & cmdline,
+ const std::tr1::shared_ptr<Environment> & env,
+ const PackageDepSpec & s)
+ {
+ const std::tr1::shared_ptr<const PackageIDSequence> ids((*env)[selection::BestVersionOnly(generator::Matches(s))]);
+ if (ids->empty())
+ throw NothingMatching(s);
+
+ for (PackageIDSequence::ConstIterator i(ids->begin()), i_end(ids->end()) ;
+ i != i_end ; ++i)
+ do_one_package(cmdline, env, PartiallyMadePackageDepSpec(s).package((*i)->name()));
+ }
+}
+
+int
+ShowCommand::run(
+ const std::tr1::shared_ptr<Environment> & env,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ )
+{
+ ShowCommandLine cmdline;
+ cmdline.run(args, "CAVE", "CAVE_SHOW_OPTIONS", "CAVE_SHOW_CMDLINE");
+
+ if (cmdline.begin_parameters() == cmdline.end_parameters())
+ throw args::DoHelp("show requires at least one parameter");
+
+ for (ShowCommandLine::ParametersConstIterator p(cmdline.begin_parameters()), p_end(cmdline.end_parameters()) ;
+ p != p_end ; ++p)
+ {
+ if (cmdline.a_type.argument() == "set")
+ do_one_set(env, SetName(*p));
+ else if (cmdline.a_type.argument() == "repository")
+ do_one_repository(cmdline, env, RepositoryName(*p));
+ else if (cmdline.a_type.argument() == "wildcard")
+ do_one_wildcard(env, parse_user_package_dep_spec(
+ *p, env.get(), UserPackageDepSpecOptions() + updso_allow_wildcards));
+ else if (cmdline.a_type.argument() == "package")
+ do_all_packages(cmdline, env, parse_user_package_dep_spec(
+ *p, env.get(), UserPackageDepSpecOptions() + updso_allow_wildcards));
+ else if (cmdline.a_type.argument() == "auto")
+ {
+ try
+ {
+ RepositoryName repo_name(*p);
+ if (env->package_database()->has_repository_named(repo_name))
+ {
+ do_one_repository(cmdline, env, repo_name);
+ continue;
+ }
+ }
+ catch (const RepositoryNameError &)
+ {
+ }
+
+ try
+ {
+ PackageDepSpec spec(parse_user_package_dep_spec(*p, env.get(), UserPackageDepSpecOptions() +
+ updso_throw_if_set + updso_allow_wildcards));
+ if ((! spec.package_ptr()))
+ do_one_wildcard(env, spec);
+ else
+ do_one_package(cmdline, env, spec);
+ }
+ catch (const GotASetNotAPackageDepSpec &)
+ {
+ do_one_set(env, SetName(*p));
+ }
+
+ continue;
+ }
+ else
+ throw args::DoHelp("bad value '" + cmdline.a_type.argument() + "' for --" + cmdline.a_type.long_name());
+ }
+
+ return EXIT_SUCCESS;
+}
+
+std::tr1::shared_ptr<args::ArgsHandler>
+ShowCommand::make_doc_cmdline()
+{
+ return make_shared_ptr(new ShowCommandLine);
+}
+
diff --git a/src/clients/cave/cmd_show.hh b/src/clients/cave/cmd_show.hh
new file mode 100644
index 0000000..c0e794f
--- /dev/null
+++ b/src/clients/cave/cmd_show.hh
@@ -0,0 +1,44 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_SHOW_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_CMD_SHOW_HH 1
+
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE ShowCommand :
+ public Command
+ {
+ public:
+ int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ );
+
+ std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline();
+ };
+ }
+}
+
+
+#endif
diff --git a/src/clients/cave/colour_formatter.cc b/src/clients/cave/colour_formatter.cc
new file mode 100644
index 0000000..7b987e4
--- /dev/null
+++ b/src/clients/cave/colour_formatter.cc
@@ -0,0 +1,213 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "colour_formatter.hh"
+#include "formats.hh"
+#include "format_general.hh"
+#include <paludis/util/stringify.hh>
+#include <paludis/name.hh>
+
+using namespace paludis;
+using namespace cave;
+
+ColourFormatter::ColourFormatter(const int initial_indent) :
+ _initial_indent(initial_indent)
+{
+}
+
+std::string
+ColourFormatter::format(const KeywordName & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_keyword_name_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const KeywordName & s, const format::Accepted &) const
+{
+ return format_general_s(f::colour_formatter_keyword_name_accepted(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const KeywordName & s, const format::Unaccepted &) const
+{
+ return format_general_s(f::colour_formatter_keyword_name_unaccepted(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const std::string & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_string_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const PackageID & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_package_id_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const PackageID & s, const format::Installed &) const
+{
+ return format_general_s(f::colour_formatter_package_id_installed(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const PackageID & s, const format::Installable &) const
+{
+ return format_general_s(f::colour_formatter_package_id_installable(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const LicenseDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_license_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const LicenseDepSpec & s, const format::Accepted &) const
+{
+ return format_general_s(f::colour_formatter_license_dep_spec_accepted(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const LicenseDepSpec & s, const format::Unaccepted &) const
+{
+ return format_general_s(f::colour_formatter_license_dep_spec_unaccepted(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const ConditionalDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_conditional_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const ConditionalDepSpec & s, const format::Enabled &) const
+{
+ return format_general_s(f::colour_formatter_conditional_dep_spec_enabled(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const ConditionalDepSpec & s, const format::Disabled &) const
+{
+ return format_general_s(f::colour_formatter_conditional_dep_spec_disabled(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const ConditionalDepSpec & s, const format::Forced &) const
+{
+ return format_general_s(f::colour_formatter_conditional_dep_spec_forced(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const ConditionalDepSpec & s, const format::Masked &) const
+{
+ return format_general_s(f::colour_formatter_conditional_dep_spec_masked(), stringify(s));
+}
+
+std::string
+ColourFormatter::decorate(const ConditionalDepSpec &, const std::string & s, const format::Added &) const
+{
+ return s;
+}
+
+std::string
+ColourFormatter::decorate(const ConditionalDepSpec &, const std::string & s, const format::Changed &) const
+{
+ return s;
+}
+
+std::string
+ColourFormatter::format(const PlainTextDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_plain_text_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const SimpleURIDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_simple_uri_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const FetchableURIDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_fetchable_uri_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const URILabelsDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_uri_labels_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const PlainTextLabelDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_uri_labels_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const PackageDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_package_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const PackageDepSpec & s, const format::Installed &) const
+{
+ return format_general_s(f::colour_formatter_package_dep_spec_installed(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const PackageDepSpec & s, const format::Installable &) const
+{
+ return format_general_s(f::colour_formatter_package_dep_spec_installable(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const DependencyLabelsDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_dependency_labels_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const BlockDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_block_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::format(const NamedSetDepSpec & s, const format::Plain &) const
+{
+ return format_general_s(f::colour_formatter_named_set_dep_spec_plain(), stringify(s));
+}
+
+std::string
+ColourFormatter::newline() const
+{
+ return "\n";
+}
+
+std::string
+ColourFormatter::indent(const int i) const
+{
+ return format_general_i(f::colour_formatter_indent(), i);
+}
+
diff --git a/src/clients/cave/colour_formatter.hh b/src/clients/cave/colour_formatter.hh
new file mode 100644
index 0000000..e4d638e
--- /dev/null
+++ b/src/clients/cave/colour_formatter.hh
@@ -0,0 +1,101 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_COLOUR_FORMATTER_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_COLOUR_FORMATTER_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/formatter.hh>
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE ColourFormatter :
+ public CanFormat<KeywordName>,
+ public CanFormat<std::string>,
+ public CanFormat<PackageID>,
+ public CanFormat<LicenseDepSpec>,
+ public CanFormat<ConditionalDepSpec>,
+ public CanFormat<PlainTextDepSpec>,
+ public CanFormat<SimpleURIDepSpec>,
+ public CanFormat<FetchableURIDepSpec>,
+ public CanFormat<URILabelsDepSpec>,
+ public CanFormat<PackageDepSpec>,
+ public CanFormat<DependencyLabelsDepSpec>,
+ public CanFormat<BlockDepSpec>,
+ public CanFormat<NamedSetDepSpec>,
+ public CanFormat<PlainTextLabelDepSpec>,
+ public CanSpace
+ {
+ private:
+ const int _initial_indent;
+
+ public:
+ ColourFormatter(const int initial_indent);
+
+ std::string format(const KeywordName &, const format::Plain &) const;
+ std::string format(const KeywordName &, const format::Accepted &) const;
+ std::string format(const KeywordName &, const format::Unaccepted &) const;
+
+ std::string format(const std::string &, const format::Plain &) const;
+
+ std::string format(const PackageID &, const format::Plain &) const;
+ std::string format(const PackageID &, const format::Installed &) const;
+ std::string format(const PackageID &, const format::Installable &) const;
+
+ std::string format(const LicenseDepSpec &, const format::Plain &) const;
+ std::string format(const LicenseDepSpec &, const format::Accepted &) const;
+ std::string format(const LicenseDepSpec &, const format::Unaccepted &) const;
+
+ std::string format(const ConditionalDepSpec &, const format::Plain &) const;
+ std::string format(const ConditionalDepSpec &, const format::Enabled &) const;
+ std::string format(const ConditionalDepSpec &, const format::Disabled &) const;
+ std::string format(const ConditionalDepSpec &, const format::Forced &) const;
+ std::string format(const ConditionalDepSpec &, const format::Masked &) const;
+ std::string decorate(const ConditionalDepSpec &, const std::string &, const format::Added &) const;
+ std::string decorate(const ConditionalDepSpec &, const std::string &, const format::Changed &) const;
+
+ std::string format(const PlainTextDepSpec &, const format::Plain &) const;
+
+ std::string format(const SimpleURIDepSpec &, const format::Plain &) const;
+
+ std::string format(const FetchableURIDepSpec &, const format::Plain &) const;
+
+ std::string format(const URILabelsDepSpec &, const format::Plain &) const;
+
+ std::string format(const PlainTextLabelDepSpec &, const format::Plain &) const;
+
+ std::string format(const PackageDepSpec &, const format::Plain &) const;
+ std::string format(const PackageDepSpec &, const format::Installed &) const;
+ std::string format(const PackageDepSpec &, const format::Installable &) const;
+
+ std::string format(const DependencyLabelsDepSpec &, const format::Plain &) const;
+
+ std::string format(const BlockDepSpec &, const format::Plain &) const;
+
+ std::string format(const NamedSetDepSpec &, const format::Plain &) const;
+
+ std::string newline() const;
+ std::string indent(const int) const;
+ };
+ }
+}
+
+#endif
diff --git a/src/clients/cave/command.cc b/src/clients/cave/command.cc
new file mode 100644
index 0000000..0fb1e6c
--- /dev/null
+++ b/src/clients/cave/command.cc
@@ -0,0 +1,28 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "command.hh"
+
+using namespace paludis;
+using namespace cave;
+
+Command::~Command()
+{
+}
+
diff --git a/src/clients/cave/command.hh b/src/clients/cave/command.hh
new file mode 100644
index 0000000..25bcae9
--- /dev/null
+++ b/src/clients/cave/command.hh
@@ -0,0 +1,47 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_COMMAND_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_COMMAND_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/args/man.hh>
+#include <paludis/environment-fwd.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE Command
+ {
+ public:
+ virtual ~Command() = 0;
+
+ virtual int run(
+ const std::tr1::shared_ptr<Environment> &,
+ const std::tr1::shared_ptr<const Sequence<std::string > > & args
+ ) PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ virtual std::tr1::shared_ptr<args::ArgsHandler> make_doc_cmdline() = 0;
+ };
+ }
+}
+
+#endif
diff --git a/src/clients/cave/command_factory.cc b/src/clients/cave/command_factory.cc
new file mode 100644
index 0000000..0afa094
--- /dev/null
+++ b/src/clients/cave/command_factory.cc
@@ -0,0 +1,106 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "command_factory.hh"
+#include <paludis/util/instantiation_policy-impl.hh>
+#include <paludis/util/private_implementation_pattern-impl.hh>
+#include <paludis/util/make_shared_ptr.hh>
+#include <paludis/util/wrapped_forward_iterator-impl.hh>
+#include <paludis/util/member_iterator-impl.hh>
+#include <tr1/functional>
+#include <map>
+
+#include "cmd_print_categories.hh"
+#include "cmd_print_commands.hh"
+#include "cmd_print_environment_metadata.hh"
+#include "cmd_print_id_contents.hh"
+#include "cmd_print_id_metadata.hh"
+#include "cmd_print_ids.hh"
+#include "cmd_show.hh"
+
+using namespace paludis;
+using namespace cave;
+
+typedef std::map<std::string, std::tr1::function<const std::tr1::shared_ptr<Command> ()> > Handlers;
+
+namespace paludis
+{
+ template <>
+ struct Implementation<CommandFactory>
+ {
+ Handlers handlers;
+ };
+}
+
+namespace
+{
+ template <typename T_>
+ const std::tr1::shared_ptr<T_> make_command()
+ {
+ return make_shared_ptr(new T_);
+ }
+}
+
+CommandFactory::CommandFactory() :
+ PrivateImplementationPattern<CommandFactory>(new Implementation<CommandFactory>)
+{
+ _imp->handlers.insert(std::make_pair("print-categories", make_command<PrintCategoriesCommand>));
+ _imp->handlers.insert(std::make_pair("print-commands", make_command<PrintCommandsCommand>));
+ _imp->handlers.insert(std::make_pair("print-environment-metadata", make_command<PrintEnvironmentMetadataCommand>));
+ _imp->handlers.insert(std::make_pair("print-id-contents", make_command<PrintIDContentsCommand>));
+ _imp->handlers.insert(std::make_pair("print-id-metadata", make_command<PrintIDMetadataCommand>));
+ _imp->handlers.insert(std::make_pair("print-ids", make_command<PrintIDsCommand>));
+ _imp->handlers.insert(std::make_pair("show", make_command<ShowCommand>));
+}
+
+CommandFactory::~CommandFactory()
+{
+}
+
+const std::tr1::shared_ptr<Command>
+CommandFactory::create(const std::string & s) const
+{
+ Handlers::const_iterator i(_imp->handlers.find(s));
+ if (i == _imp->handlers.end())
+ throw UnknownCommand(s);
+ else
+ return i->second();
+}
+
+CommandFactory::ConstIterator
+CommandFactory::begin() const
+{
+ return first_iterator(_imp->handlers.begin());
+}
+
+CommandFactory::ConstIterator
+CommandFactory::end() const
+{
+ return first_iterator(_imp->handlers.end());
+}
+
+UnknownCommand::UnknownCommand(const std::string & s) throw () :
+ Exception("Unknown command '" + s + "'")
+{
+}
+
+template class InstantiationPolicy<CommandFactory, instantiation_method::SingletonTag>;
+template class PrivateImplementationPattern<CommandFactory>;
+template class WrappedForwardIterator<CommandFactory::ConstIteratorTag, const std::string>;
+
diff --git a/src/clients/cave/command_factory.hh b/src/clients/cave/command_factory.hh
new file mode 100644
index 0000000..7e2b7fe
--- /dev/null
+++ b/src/clients/cave/command_factory.hh
@@ -0,0 +1,69 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_COMMAND_FACTORY_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_COMMAND_FACTORY_HH 1
+
+#include <paludis/util/instantiation_policy.hh>
+#include <paludis/util/private_implementation_pattern.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/exception.hh>
+#include <string>
+#include <tr1/memory>
+#include "command.hh"
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE UnknownCommand :
+ public Exception
+ {
+ public:
+ UnknownCommand(const std::string &) throw ();
+ };
+
+ class PALUDIS_VISIBLE CommandFactory :
+ private PrivateImplementationPattern<CommandFactory>,
+ public InstantiationPolicy<CommandFactory, instantiation_method::SingletonTag>
+ {
+ friend class InstantiationPolicy<CommandFactory, instantiation_method::SingletonTag>;
+
+ private:
+ CommandFactory();
+ ~CommandFactory();
+
+ public:
+ const std::tr1::shared_ptr<Command> create(const std::string &)
+ const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ struct ConstIteratorTag;
+ typedef WrappedForwardIterator<ConstIteratorTag, const std::string> ConstIterator;
+ ConstIterator begin() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ ConstIterator end() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ };
+ }
+
+#ifdef PALUDIS_HAVE_EXTERN_TEMPLATE
+ extern template class InstantiationPolicy<cave::CommandFactory, instantiation_method::SingletonTag>;
+ extern template class PrivateImplementationPattern<cave::CommandFactory>;
+#endif
+}
+
+#endif
diff --git a/src/clients/cave/command_line.cc b/src/clients/cave/command_line.cc
new file mode 100644
index 0000000..56468e8
--- /dev/null
+++ b/src/clients/cave/command_line.cc
@@ -0,0 +1,32 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "command_line.hh"
+
+using namespace paludis;
+using namespace cave;
+
+CaveCommandLine::CaveCommandLine() :
+ g_global_options(this, "Global Options", "Global options, used by every subcommand."),
+ a_environment(&g_global_options, "environment", 'E',
+ "Environment specification (class:suffix, both parts optional)")
+{
+ add_usage_line("[ --environment class:suffix ] COMMAND [ARGS...]");
+}
+
diff --git a/src/clients/cave/command_line.hh b/src/clients/cave/command_line.hh
new file mode 100644
index 0000000..7b77a78
--- /dev/null
+++ b/src/clients/cave/command_line.hh
@@ -0,0 +1,55 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_COMMAND_LINE_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_COMMAND_LINE_HH 1
+
+#include <paludis/args/args_handler.hh>
+
+namespace paludis
+{
+ namespace cave
+ {
+ struct CaveCommandLine :
+ args::ArgsHandler
+ {
+ virtual std::string app_name() const
+ {
+ return "cave";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "A commandline client for the other package mangler.";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "The front-end to a number of commands.";
+ }
+
+ args::ArgsGroup g_global_options;
+ args::StringArg a_environment;
+
+ CaveCommandLine();
+ };
+ }
+}
+
+#endif
diff --git a/src/clients/cave/exceptions.cc b/src/clients/cave/exceptions.cc
new file mode 100644
index 0000000..fa8f291
--- /dev/null
+++ b/src/clients/cave/exceptions.cc
@@ -0,0 +1,48 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "exceptions.hh"
+#include <paludis/util/stringify.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/package_id.hh>
+#include <paludis/dep_spec.hh>
+
+using namespace paludis;
+using namespace cave;
+
+NothingMatching::NothingMatching(const PackageDepSpec & spec) throw () :
+ Exception("Found nothing suitable matching '" + stringify(spec) + "'")
+{
+}
+
+BeMoreSpecific::BeMoreSpecific(const PackageDepSpec & spec, const std::tr1::shared_ptr<const PackageIDSequence> & s) throw () :
+ Exception("Found multiple suitable IDs matching '" + stringify(spec) + "': { '" + join(indirect_iterator(s->begin()),
+ indirect_iterator(s->end()), "', '") + "' }")
+{
+}
+
+BadIDForCommand::BadIDForCommand(const PackageDepSpec & spec, const std::tr1::shared_ptr<const PackageID> & s,
+ const std::string & r) throw () :
+ Exception("Spec '" + stringify(spec) + "' resolves to ID '" + stringify(*s) + "', which " + r)
+{
+}
+
diff --git a/src/clients/cave/exceptions.hh b/src/clients/cave/exceptions.hh
new file mode 100644
index 0000000..d714ed0
--- /dev/null
+++ b/src/clients/cave/exceptions.hh
@@ -0,0 +1,58 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_EXCEPTIONS_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_EXCEPTIONS_HH 1
+
+#include <paludis/util/exception.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <paludis/package_id-fwd.hh>
+#include <tr1/memory>
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE NothingMatching :
+ public Exception
+ {
+ public:
+ NothingMatching(const PackageDepSpec &) throw ();
+ };
+
+ class PALUDIS_VISIBLE BeMoreSpecific :
+ public Exception
+ {
+ public:
+ BeMoreSpecific(const PackageDepSpec &, const std::tr1::shared_ptr<const PackageIDSequence> &) throw ();
+ };
+
+ class PALUDIS_VISIBLE BadIDForCommand :
+ public Exception
+ {
+ public:
+ BadIDForCommand(
+ const PackageDepSpec &,
+ const std::tr1::shared_ptr<const PackageID> &,
+ const std::string & r) throw ();
+ };
+ }
+}
+
+#endif
diff --git a/src/clients/cave/format_general.cc b/src/clients/cave/format_general.cc
new file mode 100644
index 0000000..272c219
--- /dev/null
+++ b/src/clients/cave/format_general.cc
@@ -0,0 +1,64 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "format_general.hh"
+#include "format_string.hh"
+#include <paludis/util/map.hh>
+
+using namespace paludis;
+using namespace cave;
+
+std::string
+paludis::cave::format_general_s(const std::string & f, const std::string & s)
+{
+ std::tr1::shared_ptr<Map<char, std::string> > m(new Map<char, std::string>);
+ m->insert('s', s);
+ return format_string(f, m);
+}
+
+std::string
+paludis::cave::format_general_sr(const std::string & f, const std::string & s, const std::string & r)
+{
+ std::tr1::shared_ptr<Map<char, std::string> > m(new Map<char, std::string>);
+ m->insert('s', s);
+ m->insert('r', r);
+ return format_string(f, m);
+}
+
+std::string
+paludis::cave::format_general_rhvib(const std::string & f, const std::string & r, const std::string & h,
+ const std::string & v, const int i, const bool b)
+{
+ std::tr1::shared_ptr<Map<char, std::string> > m(new Map<char, std::string>);
+ m->insert('r', r);
+ m->insert('h', h);
+ m->insert('v', v);
+ m->insert('i', std::string(i, ' '));
+ m->insert('b', b ? "true" : "");
+ return format_string(f, m);
+}
+
+std::string
+paludis::cave::format_general_i(const std::string & f, const int i)
+{
+ std::tr1::shared_ptr<Map<char, std::string> > m(new Map<char, std::string>);
+ m->insert('i', std::string(i, ' '));
+ return format_string(f, m);
+}
+
diff --git a/src/clients/cave/format_general.hh b/src/clients/cave/format_general.hh
new file mode 100644
index 0000000..7e3853b
--- /dev/null
+++ b/src/clients/cave/format_general.hh
@@ -0,0 +1,45 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_GENERAL_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_GENERAL_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace cave
+ {
+ std::string format_general_s(const std::string & f, const std::string & s)
+ PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::string format_general_sr(const std::string & f, const std::string & s, const std::string & r)
+ PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::string format_general_rhvib(const std::string & f, const std::string & r,
+ const std::string & h, const std::string & v, const int i, const bool b)
+ PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ std::string format_general_i(const std::string & f, const int i)
+ PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+}
+
+#endif
diff --git a/src/clients/cave/format_plain_contents_entry.cc b/src/clients/cave/format_plain_contents_entry.cc
new file mode 100644
index 0000000..8174689
--- /dev/null
+++ b/src/clients/cave/format_plain_contents_entry.cc
@@ -0,0 +1,97 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "format_plain_contents_entry.hh"
+#include "format_string.hh"
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/map.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/contents.hh>
+#include <sstream>
+
+using namespace paludis;
+using namespace cave;
+
+namespace
+{
+ struct ValueGetter :
+ ConstVisitor<ContentsVisitorTypes>
+ {
+ std::string target;
+ std::string slash;
+
+ void visit(const ContentsFileEntry &)
+ {
+ }
+
+ void visit(const ContentsDirEntry &)
+ {
+ slash = "/";
+ }
+
+ void visit(const ContentsSymEntry & c)
+ {
+ target = c.target();
+ }
+
+ void visit(const ContentsMiscEntry &)
+ {
+ }
+
+ void visit(const ContentsDevEntry &)
+ {
+ }
+
+ void visit(const ContentsFifoEntry &)
+ {
+ }
+ };
+
+ int number_of_parents(const FSEntry & f)
+ {
+ FSEntry ff(f);
+ int result(0);
+ while (((ff = ff.dirname())) != FSEntry("/"))
+ ++result;
+ return result;
+ }
+}
+
+std::string
+paludis::cave::format_plain_contents_entry(
+ const std::tr1::shared_ptr<const ContentsEntry> & c,
+ const std::string & f)
+{
+ ValueGetter v;
+ c->accept(v);
+
+ std::tr1::shared_ptr<Map<char, std::string> > m(new Map<char, std::string>);
+ m->insert('n', c->name());
+ m->insert('d', stringify(FSEntry(c->name()).dirname()));
+ m->insert('b', stringify(FSEntry(c->name()).basename()));
+ m->insert('t', v.target);
+ m->insert('a', v.target.empty() ? "" : " -> ");
+ m->insert('i', std::string(number_of_parents(FSEntry(c->name())), ' '));
+ m->insert('/', v.slash);
+
+ return format_string(f, m);
+}
+
diff --git a/src/clients/cave/format_plain_contents_entry.hh b/src/clients/cave/format_plain_contents_entry.hh
new file mode 100644
index 0000000..8ed1f2c
--- /dev/null
+++ b/src/clients/cave/format_plain_contents_entry.hh
@@ -0,0 +1,39 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_PLAIN_CONTENTS_ENTRY_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_PLAIN_CONTENTS_ENTRY_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/contents-fwd.hh>
+#include <tr1/memory>
+#include <string>
+
+namespace paludis
+{
+ namespace cave
+ {
+ std::string format_plain_contents_entry(
+ const std::tr1::shared_ptr<const ContentsEntry> &,
+ const std::string & format)
+ PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+}
+
+#endif
diff --git a/src/clients/cave/format_plain_metadata_key.cc b/src/clients/cave/format_plain_metadata_key.cc
new file mode 100644
index 0000000..83ee01c
--- /dev/null
+++ b/src/clients/cave/format_plain_metadata_key.cc
@@ -0,0 +1,171 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "format_plain_metadata_key.hh"
+#include "format_string.hh"
+#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/join.hh>
+#include <paludis/util/set.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/map.hh>
+#include <paludis/stringify_formatter.hh>
+#include <paludis/metadata_key.hh>
+#include <paludis/mask.hh>
+#include <sstream>
+
+using namespace paludis;
+using namespace cave;
+
+namespace
+{
+ struct ValueGetter :
+ ConstVisitor<MetadataKeyVisitorTypes>
+ {
+ std::stringstream s;
+
+ void visit(const MetadataTimeKey & k)
+ {
+ s << k.value();
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const RepositoryMaskInfo> > & k)
+ {
+ if (k.value())
+ {
+ const std::tr1::shared_ptr<const Sequence<std::string> > c(k.value()->comment());
+ s << join(c->begin(), c->end(), " ") << " " << k.value()->mask_file();
+ }
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const Contents> > &)
+ {
+ s << "<unprintable>";
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const Choices> > &)
+ {
+ s << "<unprintable>";
+ }
+
+ void visit(const MetadataValueKey<std::tr1::shared_ptr<const PackageID> > & k)
+ {
+ s << *k.value();
+ }
+
+ void visit(const MetadataValueKey<FSEntry> & k)
+ {
+ s << k.value();
+ }
+
+ void visit(const MetadataValueKey<bool> & k)
+ {
+ s << (k.value() ? "true" : "false");
+ }
+
+ void visit(const MetadataValueKey<long> & k)
+ {
+ s << k.value();
+ }
+
+ void visit(const MetadataValueKey<std::string> & k)
+ {
+ s << k.value();
+ }
+
+ void visit(const MetadataSpecTreeKey<DependencySpecTree> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataSpecTreeKey<ProvideSpecTree> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataSpecTreeKey<FetchableURISpecTree> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataSpecTreeKey<PlainTextSpecTree> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataSpecTreeKey<SimpleURISpecTree> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataSpecTreeKey<LicenseSpecTree> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataCollectionKey<FSEntrySequence> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataCollectionKey<PackageIDSequence> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataCollectionKey<Sequence<std::string> > & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataCollectionKey<Set<std::string> > & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataCollectionKey<KeywordNameSet> & k)
+ {
+ s << k.pretty_print_flat(StringifyFormatter());
+ }
+
+ void visit(const MetadataSectionKey &)
+ {
+ s << "<unprintable>";
+ }
+ };
+}
+
+std::string
+paludis::cave::format_plain_metadata_key(
+ const std::tr1::shared_ptr<const MetadataKey> & k,
+ const std::string & i,
+ const std::string & f)
+{
+ ValueGetter v;
+ k->accept(v);
+
+ std::tr1::shared_ptr<Map<char, std::string> > m(new Map<char, std::string>);
+ m->insert('r', k->raw_name());
+ m->insert('h', k->human_name());
+ m->insert('v', v.s.str());
+ m->insert('i', i);
+
+ return format_string(f, m);
+}
+
diff --git a/src/clients/cave/format_plain_metadata_key.hh b/src/clients/cave/format_plain_metadata_key.hh
new file mode 100644
index 0000000..5484a68
--- /dev/null
+++ b/src/clients/cave/format_plain_metadata_key.hh
@@ -0,0 +1,40 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_PLAIN_METADATA_KEY_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_PLAIN_METADATA_KEY_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/metadata_key-fwd.hh>
+#include <tr1/memory>
+#include <string>
+
+namespace paludis
+{
+ namespace cave
+ {
+ std::string format_plain_metadata_key(
+ const std::tr1::shared_ptr<const MetadataKey> &,
+ const std::string & value_for_i,
+ const std::string & format)
+ PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+}
+
+#endif
diff --git a/src/clients/cave/format_string.cc b/src/clients/cave/format_string.cc
new file mode 100644
index 0000000..aaf8f24
--- /dev/null
+++ b/src/clients/cave/format_string.cc
@@ -0,0 +1,163 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "format_string.hh"
+#include <paludis/util/map-impl.hh>
+#include <paludis/util/stringify.hh>
+#include <paludis/util/tokeniser.hh>
+#include <paludis/util/destringify.hh>
+#include <vector>
+#include <list>
+
+using namespace paludis;
+using namespace cave;
+
+FormatStringError::FormatStringError(const std::string & f, const std::string & m) throw () :
+ Exception("Bad format string '" + f + "': " + m)
+{
+}
+
+std::string
+paludis::cave::format_string(
+ const std::string & f,
+ const std::tr1::shared_ptr<Map<char, std::string> > & m
+ )
+{
+ std::string result;
+ std::list<bool> condition_stack;
+ condition_stack.push_front(true);
+
+ for (std::string::size_type p(0), p_end(f.length()) ; p != p_end ; ++p)
+ {
+ switch (f.at(p))
+ {
+ case '\\':
+ if (++p == p_end)
+ throw FormatStringError(f, "backslash at end of input");
+ switch (f.at(p))
+ {
+ case 'n':
+ if (*condition_stack.begin())
+ result.append("\n");
+ break;
+
+ case 't':
+ if (*condition_stack.begin())
+ result.append("\t");
+ break;
+
+ default:
+ if (*condition_stack.begin())
+ result.append(stringify(f.at(p)));
+ break;
+ }
+ break;
+
+ case '%':
+ if (++p == p_end)
+ throw FormatStringError(f, "percent at end of input");
+ if (f.at(p) == '%')
+ {
+ if (*condition_stack.begin())
+ result.append("%");
+ }
+ else if (f.at(p) == '{')
+ {
+ std::string::size_type pp(f.find('}', p));
+ if (std::string::npos == p)
+ throw FormatStringError(f, "no closing brace found");
+ std::string ff(f.substr(p + 1, pp - p - 1));
+ std::vector<std::string> tokens;
+ tokenise_whitespace(ff, std::back_inserter(tokens));
+
+ if (0 == tokens.size())
+ throw FormatStringError(f, "no command inside {}");
+
+ if ("column" == tokens.at(0))
+ {
+ if (tokens.size() != 2)
+ throw FormatStringError(f, "{column} takes one parameter");
+
+ int c(destringify<unsigned>(tokens.at(1))), l(0);
+ for (int q(0), q_end(result.length()) ; q != q_end ; ++q)
+ if ('\e' == result[q])
+ {
+ for ( ; q != q_end ; ++q)
+ if ('m' == result[q])
+ break;
+ }
+ else
+ ++l;
+
+ if (*condition_stack.begin())
+ result.append(std::string(std::max(1, c - l), ' '));
+ }
+ else if ("endif" == tokens.at(0))
+ {
+ if (tokens.size() != 1)
+ throw FormatStringError(f, "{endif} takes no parameters");
+ if (condition_stack.size() <= 1)
+ throw FormatStringError(f, "{endif} has no matching {if}");
+ condition_stack.pop_front();
+ }
+ else if ("else" == tokens.at(0))
+ {
+ if (tokens.size() != 1)
+ throw FormatStringError(f, "{else} takes no parameters");
+ *condition_stack.begin() = ! *condition_stack.begin();
+ }
+ else if ("if" == tokens.at(0))
+ {
+ if (tokens.size() != 2)
+ throw FormatStringError(f, "{if} takes one parameter");
+ if (tokens.at(1).length() != 1)
+ throw FormatStringError(f, "{if} parameter should be a single character");
+ if (m->end() == m->find(tokens.at(1).at(0)))
+ throw FormatStringError(f, "{if} parameter '" + tokens.at(1) + "' not a variable");
+ condition_stack.push_front(! m->find(tokens.at(1).at(0))->second.empty());
+ }
+ else
+ throw FormatStringError(f, "unknown command '" + tokens.at(0) + "' inside {}");
+
+ p = pp;
+ }
+ else if (m->end() != m->find(f.at(p)))
+ {
+ if (*condition_stack.begin())
+ result.append(stringify(m->find(f.at(p))->second));
+ }
+ else
+ throw FormatStringError(f, "unrecognised format item '%" + stringify(f.at(p)) + "'");
+ break;
+
+ default:
+ if (*condition_stack.begin())
+ result.append(stringify(f.at(p)));
+ break;
+ }
+ }
+
+ if (condition_stack.size() != 1)
+ throw FormatStringError(f, "{if} has no matching {endif}");
+
+ return result;
+}
+
+template class Map<char, std::string>;
+
diff --git a/src/clients/cave/format_string.hh b/src/clients/cave/format_string.hh
new file mode 100644
index 0000000..0678eca
--- /dev/null
+++ b/src/clients/cave/format_string.hh
@@ -0,0 +1,47 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_STRING_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMAT_STRING_HH 1
+
+#include <paludis/util/map-fwd.hh>
+#include <paludis/util/attributes.hh>
+#include <paludis/util/exception.hh>
+#include <tr1/memory>
+#include <string>
+
+namespace paludis
+{
+ namespace cave
+ {
+ class PALUDIS_VISIBLE FormatStringError :
+ public Exception
+ {
+ public:
+ FormatStringError(const std::string & f, const std::string & msg) throw ();
+ };
+
+ std::string format_string(
+ const std::string &,
+ const std::tr1::shared_ptr<Map<char, std::string> > &
+ ) PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+}
+
+#endif
diff --git a/src/clients/cave/formats.cc b/src/clients/cave/formats.cc
new file mode 100644
index 0000000..a41aa52
--- /dev/null
+++ b/src/clients/cave/formats.cc
@@ -0,0 +1,396 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "formats.hh"
+
+using namespace paludis;
+using namespace cave;
+
+const std::string
+paludis::cave::c::bold_blue()
+{
+ return "\e[1;34m";
+}
+
+const std::string
+paludis::cave::c::blue()
+{
+ return "\e[0;34m";
+}
+
+const std::string
+paludis::cave::c::bold_green()
+{
+ return "\e[1;32m";
+}
+
+const std::string
+paludis::cave::c::green()
+{
+ return "\e[0;32m";
+}
+
+const std::string
+paludis::cave::c::red()
+{
+ return "\e[0;31m";
+}
+
+const std::string
+paludis::cave::c::bold_red()
+{
+ return "\e[1;31m";
+}
+
+const std::string
+paludis::cave::c::normal()
+{
+ return "\e[0;0m";
+}
+
+const std::string
+paludis::cave::c::bold_normal()
+{
+ return "\e[1m";
+}
+
+const std::string
+paludis::cave::f::show_set_heading()
+{
+ return "* " + c::bold_blue() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_set_set()
+{
+ return " " + c::blue() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_set_spec_installed()
+{
+ return " " + c::bold_green() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_set_spec_installable()
+{
+ return " " + c::green() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_set_spec_unavailable()
+{
+ return " " + c::red() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_wildcard_heading()
+{
+ return "* " + c::bold_blue() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_wildcard_spec_installed()
+{
+ return " " + c::green() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_wildcard_spec_installable()
+{
+ return " %s\\n";
+}
+
+const std::string
+paludis::cave::f::show_wildcard_spec_unavailable()
+{
+ return " " + c::red() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_repository_heading()
+{
+ return "* " + c::bold_blue() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_metadata_key_value()
+{
+ return " %i%i%i%i%{if b}" + c::bold_normal() + "%{endif}" + "%h" + c::normal() + "%{column 30}%v\\n";
+}
+
+const std::string
+paludis::cave::f::show_metadata_continued_value()
+{
+ return " %{column 30}%i%i%v\\n";
+}
+
+const std::string
+paludis::cave::f::show_metadata_subsection()
+{
+ return " %i%i%i%i" + c::bold_blue() + "%h" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_package_heading()
+{
+ return "* " + c::bold_blue() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_package_version_installed()
+{
+ return c::bold_green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::show_package_version_installable()
+{
+ return c::green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::show_package_version_unavailable()
+{
+ return c::red() + "(%s)%r" + c::normal();
+}
+
+const std::string
+paludis::cave::f::show_package_repository()
+{
+ return " ::%s%{column 30}";
+}
+
+const std::string
+paludis::cave::f::show_package_best()
+{
+ return "*";
+}
+
+const std::string
+paludis::cave::f::show_package_slot()
+{
+ return " {:%s}";
+}
+
+const std::string
+paludis::cave::f::show_package_id_heading()
+{
+ return " " + c::bold_blue() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::show_package_id_masks()
+{
+ return " " + c::bold_red() + "%s" + c::normal() + "\\n";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_keyword_name_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_keyword_name_accepted()
+{
+ return c::green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_keyword_name_unaccepted()
+{
+ return c::red() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_string_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_package_id_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_package_id_installed()
+{
+ return c::bold_green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_package_id_installable()
+{
+ return c::green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_license_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_license_dep_spec_accepted()
+{
+ return c::green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_license_dep_spec_unaccepted()
+{
+ return c::red() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_conditional_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_conditional_dep_spec_enabled()
+{
+ return c::green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_conditional_dep_spec_disabled()
+{
+ return c::red() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_conditional_dep_spec_forced()
+{
+ return c::green() + "(%s)" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_conditional_dep_spec_masked()
+{
+ return c::red() + "(%s)" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_plain_text_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_simple_uri_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_fetchable_uri_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_uri_labels_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_package_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_package_dep_spec_installed()
+{
+ return c::bold_green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_package_dep_spec_installable()
+{
+ return c::green() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::colour_formatter_dependency_labels_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_block_dep_spec_plain()
+{
+ return "%s";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_named_set_dep_spec_plain()
+{
+ return c::blue() + "%s" + c::normal();
+}
+
+const std::string
+paludis::cave::f::show_contents_file()
+{
+ return "%{if b}%{column 30}%{endif}%r%{if b}\\n%{else} %{endif}";
+}
+
+const std::string
+paludis::cave::f::show_contents_dev()
+{
+ return "%{if b}%{column 30}%{endif}%r%{if b}\\n%{else} %{endif}";
+}
+
+const std::string
+paludis::cave::f::show_contents_misc()
+{
+ return "%{if b}%{column 30}%{endif}%r%{if b}\\n%{else} %{endif}";
+}
+
+const std::string
+paludis::cave::f::show_contents_dir()
+{
+ return "%{if b}%{column 30}%{endif}%r%{if b}\\n%{else} %{endif}";
+}
+
+const std::string
+paludis::cave::f::show_contents_fifo()
+{
+ return "%{if b}%{column 30}%{endif}%r%{if b}\\n%{else} %{endif}";
+}
+
+const std::string
+paludis::cave::f::show_contents_sym()
+{
+ return "%{if b}%{column 30}%{endif}%r -> %v%{if b}\\n%{else} %{endif}";
+}
+
+const std::string
+paludis::cave::f::colour_formatter_indent()
+{
+ return "%{column 30}%i%i%i%i";
+}
+
diff --git a/src/clients/cave/formats.hh b/src/clients/cave/formats.hh
new file mode 100644
index 0000000..505bd46
--- /dev/null
+++ b/src/clients/cave/formats.hh
@@ -0,0 +1,122 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMATS_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_FORMATS_HH 1
+
+#include <string>
+
+namespace paludis
+{
+ namespace cave
+ {
+ namespace c
+ {
+ const std::string bold_blue();
+ const std::string blue();
+ const std::string bold_green();
+ const std::string green();
+ const std::string bold_red();
+ const std::string red();
+
+ const std::string bold_normal();
+ const std::string normal();
+ }
+
+ namespace f
+ {
+ const std::string show_set_heading();
+ const std::string show_set_set();
+ const std::string show_set_spec_installed();
+ const std::string show_set_spec_installable();
+ const std::string show_set_spec_unavailable();
+
+ const std::string show_wildcard_heading();
+ const std::string show_wildcard_spec_installed();
+ const std::string show_wildcard_spec_installable();
+ const std::string show_wildcard_spec_unavailable();
+
+ const std::string show_repository_heading();
+
+ const std::string show_package_heading();
+ const std::string show_package_repository();
+ const std::string show_package_version_installed();
+ const std::string show_package_version_installable();
+ const std::string show_package_version_unavailable();
+ const std::string show_package_best();
+ const std::string show_package_slot();
+
+ const std::string show_package_id_heading();
+ const std::string show_package_id_masks();
+
+ const std::string show_metadata_key_value();
+ const std::string show_metadata_continued_value();
+ const std::string show_metadata_subsection();
+
+ const std::string show_contents_file();
+ const std::string show_contents_dir();
+ const std::string show_contents_misc();
+ const std::string show_contents_dev();
+ const std::string show_contents_fifo();
+ const std::string show_contents_sym();
+
+ const std::string colour_formatter_keyword_name_plain();
+ const std::string colour_formatter_keyword_name_accepted();
+ const std::string colour_formatter_keyword_name_unaccepted();
+
+ const std::string colour_formatter_string_plain();
+
+ const std::string colour_formatter_package_id_plain();
+ const std::string colour_formatter_package_id_installed();
+ const std::string colour_formatter_package_id_installable();
+
+ const std::string colour_formatter_license_dep_spec_plain();
+ const std::string colour_formatter_license_dep_spec_accepted();
+ const std::string colour_formatter_license_dep_spec_unaccepted();
+
+ const std::string colour_formatter_conditional_dep_spec_plain();
+ const std::string colour_formatter_conditional_dep_spec_enabled();
+ const std::string colour_formatter_conditional_dep_spec_disabled();
+ const std::string colour_formatter_conditional_dep_spec_forced();
+ const std::string colour_formatter_conditional_dep_spec_masked();
+
+ const std::string colour_formatter_plain_text_dep_spec_plain();
+
+ const std::string colour_formatter_simple_uri_dep_spec_plain();
+
+ const std::string colour_formatter_fetchable_uri_dep_spec_plain();
+
+ const std::string colour_formatter_uri_labels_dep_spec_plain();
+
+ const std::string colour_formatter_package_dep_spec_plain();
+ const std::string colour_formatter_package_dep_spec_installed();
+ const std::string colour_formatter_package_dep_spec_installable();
+
+ const std::string colour_formatter_dependency_labels_dep_spec_plain();
+
+ const std::string colour_formatter_block_dep_spec_plain();
+
+ const std::string colour_formatter_named_set_dep_spec_plain();
+
+ const std::string colour_formatter_indent();
+ }
+ }
+}
+
+#endif
diff --git a/src/clients/cave/man_cave.cc b/src/clients/cave/man_cave.cc
new file mode 100644
index 0000000..79bd1ff
--- /dev/null
+++ b/src/clients/cave/man_cave.cc
@@ -0,0 +1,88 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "command.hh"
+#include "command_factory.hh"
+#include "command_line.hh"
+#include <paludis/args/man.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/stringify.hh>
+
+#include <iostream>
+#include <cstdlib>
+
+using std::cout;
+using std::endl;
+
+namespace
+{
+ struct ManCommandLine :
+ paludis::args::ArgsHandler
+ {
+ paludis::args::ArgsGroup group;
+ paludis::args::SwitchArg a_html;
+
+ ManCommandLine() :
+ group(this, "", ""),
+ a_html(&group, "html", '\0', "", false)
+ {
+ }
+
+ virtual std::string app_name() const
+ {
+ return "";
+ }
+
+ virtual std::string app_description() const
+ {
+ return "";
+ }
+
+ virtual std::string app_synopsis() const
+ {
+ return "";
+ }
+ };
+}
+
+int
+main(int argc, char * argv[])
+{
+ ManCommandLine cmdline;
+ cmdline.run(argc, argv, "", "", "");
+
+ std::tr1::shared_ptr<paludis::args::DocWriter> w;
+ if (cmdline.a_html.specified())
+ w.reset(new paludis::args::HtmlWriter(cout));
+ else
+ w.reset(new paludis::args::ManWriter(cout));
+
+ if (cmdline.begin_parameters() == cmdline.end_parameters())
+ {
+ paludis::cave::CaveCommandLine c;
+ paludis::args::generate_doc(*w, &c);
+ }
+ else
+ paludis::args::generate_doc(*w, paludis::cave::CommandFactory::get_instance()->create(
+ *cmdline.begin_parameters())->make_doc_cmdline().get());
+
+ return EXIT_SUCCESS;
+}
+
+
diff --git a/src/clients/cave/select_format_for_spec.cc b/src/clients/cave/select_format_for_spec.cc
new file mode 100644
index 0000000..6c2f242
--- /dev/null
+++ b/src/clients/cave/select_format_for_spec.cc
@@ -0,0 +1,48 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "select_format_for_spec.hh"
+#include <paludis/environment.hh>
+#include <paludis/util/sequence.hh>
+#include <paludis/util/fs_entry.hh>
+#include <paludis/selection.hh>
+#include <paludis/filter.hh>
+#include <paludis/filtered_generator.hh>
+#include <paludis/generator.hh>
+
+using namespace paludis;
+using namespace cave;
+
+std::string
+paludis::cave::select_format_for_spec(
+ const std::tr1::shared_ptr<const Environment> & env,
+ const PackageDepSpec & spec,
+ const std::string & if_installed,
+ const std::string & if_installable,
+ const std::string & if_unavailable
+ )
+{
+ if (! (*env)[selection::SomeArbitraryVersion(generator::Matches(spec) | filter::InstalledAtRoot(FSEntry("/")))]->empty())
+ return if_installed;
+ if (! (*env)[selection::SomeArbitraryVersion(generator::Matches(spec) | filter::SupportsAction<InstallAction>()
+ | filter::NotMasked())]->empty())
+ return if_installable;
+ return if_unavailable;
+}
+
diff --git a/src/clients/cave/select_format_for_spec.hh b/src/clients/cave/select_format_for_spec.hh
new file mode 100644
index 0000000..64d1aff
--- /dev/null
+++ b/src/clients/cave/select_format_for_spec.hh
@@ -0,0 +1,42 @@
+/* vim: set sw=4 sts=4 et foldmethod=syntax : */
+
+/*
+ * Copyright (c) 2008 Ciaran McCreesh
+ *
+ * This file is part of the Paludis package manager. Paludis is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU General
+ * Public License version 2, as published by the Free Software Foundation.
+ *
+ * Paludis 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
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef PALUDIS_GUARD_SRC_CLIENTS_CAVE_SELECT_FORMAT_FOR_SPEC_HH
+#define PALUDIS_GUARD_SRC_CLIENTS_CAVE_SELECT_FORMAT_FOR_SPEC_HH 1
+
+#include <paludis/util/attributes.hh>
+#include <paludis/environment-fwd.hh>
+#include <paludis/dep_spec-fwd.hh>
+#include <string>
+
+namespace paludis
+{
+ namespace cave
+ {
+ std::string select_format_for_spec(
+ const std::tr1::shared_ptr<const Environment> &,
+ const PackageDepSpec &,
+ const std::string & if_installed,
+ const std::string & if_installable,
+ const std::string & if_unavailable
+ ) PALUDIS_VISIBLE PALUDIS_ATTRIBUTE((warn_unused_result));
+ }
+}
+
+#endif