aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-11-13 16:31:53 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-11-13 16:31:53 +0000
commitc22b445963b1b7d8cf2e45da950c902d63cb837b (patch)
tree8634caa6f371a6018dc1326d4e291da8ebd74168
parent72833626ac5df274e559c3f66720615b26340721 (diff)
downloadpaludis-c22b445963b1b7d8cf2e45da950c902d63cb837b.tar.gz
paludis-c22b445963b1b7d8cf2e45da950c902d63cb837b.tar.xz
Add MetadataSectionKey
-rw-r--r--doc/api/cplusplus/examples/example_metadata_key.cc140
-rw-r--r--paludis/metadata_key-fwd.hh1
-rw-r--r--paludis/metadata_key.cc59
-rw-r--r--paludis/metadata_key.hh73
-rw-r--r--paludis/repositories/e/qa/spec_keys.cc6
-rw-r--r--paludis/repositories/gems/gem_specification_TEST.cc85
-rw-r--r--python/additional_tests.cc31
-rw-r--r--python/metadata_key.cc74
-rwxr-xr-xpython/metadata_key_TEST.py14
-rw-r--r--ruby/metadata_key.cc5
-rw-r--r--src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc4
-rw-r--r--src/clients/inquisitio/key_extractor.cc6
-rw-r--r--src/clients/instruo/instruo.cc97
-rw-r--r--src/clients/qualudis/qualudis.cc11
-rw-r--r--src/output/console_query_task.cc96
-rw-r--r--src/output/console_task.cc4
-rw-r--r--src/output/console_task.hh2
-rw-r--r--src/output/mask_displayer.cc27
18 files changed, 463 insertions, 272 deletions
diff --git a/doc/api/cplusplus/examples/example_metadata_key.cc b/doc/api/cplusplus/examples/example_metadata_key.cc
index ea3a355..8df5d15 100644
--- a/doc/api/cplusplus/examples/example_metadata_key.cc
+++ b/doc/api/cplusplus/examples/example_metadata_key.cc
@@ -30,6 +30,8 @@ using std::setw;
namespace
{
+ void show_key(const MetadataKey & key, const std::string & indent = "");
+
/* We use this visitor to display extra information about a MetadataKey,
* depending upon its type. */
class MetadataKeyInformationVisitor :
@@ -40,40 +42,49 @@ namespace
* "example_stringify_formatter.cc" for more details. */
StringifyFormatter formatter;
+ /* Because of MetadataSectionKey, we can be called recursively. We add a level
+ * of indenting each time. */
+ std::string indent;
+
public:
+ MetadataKeyInformationVisitor(const std::string & i = "") :
+ indent(i)
+ {
+ }
+
void visit(const MetadataStringKey & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataStringKey" << endl;
- cout << left << setw(30) << " Value:" << " " << key.value() << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataStringKey" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.value() << endl;
}
void visit(const MetadataFSEntryKey & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataFSEntryKey" << endl;
- cout << left << setw(30) << " Value:" << " " << key.value() << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataFSEntryKey" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.value() << endl;
}
void visit(const MetadataPackageIDKey & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataPackageIDKey" << endl;
- cout << left << setw(30) << " Value:" << " " << *key.value() << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataPackageIDKey" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << *key.value() << endl;
}
void visit(const MetadataTimeKey & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataTimeKey" << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataTimeKey" << endl;
/* Yay horrible C formatting routines! */
time_t t(key.value());
char buf[255];
if (! strftime(buf, 254, "%c", gmtime(&t)))
buf[0] = '\0';
- cout << left << setw(30) << " Value:" << " " << buf << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << buf << endl;
}
void visit(const MetadataContentsKey &)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataContentsKey" << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataContentsKey" << endl;
/* We won't display the contents of the contents key here, since
* it involves creating another visitor. See \ref
* example_contents.cc "example_contents.cc" for that. */
@@ -81,23 +92,23 @@ namespace
void visit(const MetadataRepositoryMaskInfoKey & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataRepositoryMaskInfoKey" << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataRepositoryMaskInfoKey" << endl;
/* MetadataRepositoryMaskInfoKey::value() can return a zero
* pointer. Other keys can't. */
if (key.value())
{
- cout << left << setw(30) << " Mask file:" << " " << key.value()->mask_file << endl;
+ cout << indent << left << setw(30) << " Mask file:" << " " << key.value()->mask_file << endl;
/* Comment looks best if it's outputted over multiple lines,
* as that's how it tends to be stored in package.mask. */
- cout << left << setw(30) << " Comment:" << " ";
+ cout << indent << left << setw(30) << " Comment:" << " ";
bool first(true);
for (Sequence<std::string>::ConstIterator i(key.value()->comment->begin()),
i_end(key.value()->comment->end()) ;
i != i_end ; ++i)
{
if (! first)
- cout << left << setw(30) << " ..." << " ";
+ cout << indent << left << setw(30) << " ..." << " ";
cout << *i << endl;
first = false;
}
@@ -106,75 +117,111 @@ namespace
void visit(const MetadataSpecTreeKey<RestrictSpecTree> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<RestrictSpecTree>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<RestrictSpecTree>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSpecTreeKey<ProvideSpecTree> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<ProvideSpecTree>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<ProvideSpecTree>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSpecTreeKey<LicenseSpecTree> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<LicenseSpecTree>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<LicenseSpecTree>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSpecTreeKey<SimpleURISpecTree> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<SimpleURISpecTree>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<SimpleURISpecTree>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSpecTreeKey<DependencySpecTree> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<DependencySpecTree>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<DependencySpecTree>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSpecTreeKey<FetchableURISpecTree> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<FetchableURISpecTree>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
- cout << left << setw(30) << " Initial label:" << " " << key.initial_label()->text() << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<FetchableURISpecTree>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Initial label:" << " " << key.initial_label()->text() << endl;
}
void visit(const MetadataSetKey<IUseFlagSet> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<IUseFlagSet>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<IUseFlagSet>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSetKey<KeywordNameSet> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<KeywordNameSet>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<KeywordNameSet>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSetKey<UseFlagNameSet> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<UseFlagNameSet>" << endl;
- cout << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<UseFlagNameSet>" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << key.pretty_print_flat(formatter) << endl;
}
void visit(const MetadataSetKey<Set<std::string> > & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<Set<std::string> >" << endl;
- cout << left << setw(30) << " Value:" << " " << join(key.value()->begin(), key.value()->end(), " ") << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<Set<std::string> >" << endl;
+ cout << indent << left << setw(30) << " Value:" << " " << join(key.value()->begin(), key.value()->end(), " ") << endl;
}
void visit(const MetadataSetKey<PackageIDSequence> & key)
{
- cout << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<PackageIDSequence>" << endl;
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSpecTreeKey<PackageIDSequence>" << endl;
/* Slight trickery: a PackageIDSequence stores shared pointers
* to PackageID instances, so we need indirect_iterator to get
* an extra level of dereferencing. */
- cout << left << setw(30) << " Value:" << " " << join(indirect_iterator(key.value()->begin()),
+ cout << indent << left << setw(30) << " Value:" << " " << join(indirect_iterator(key.value()->begin()),
indirect_iterator(key.value()->end()), " ") << endl;
}
+
+ void visit(const MetadataSectionKey & key)
+ {
+ cout << indent << left << setw(30) << " Class:" << " " << "MetadataSectionKey" << endl;
+
+ /* A MetadataSectionKey contains other keys. It has one potentially special
+ * key, for the title, which if it exists is always a MetadataStringKey. */
+ if (key.title_key())
+ cout << indent << left << setw(30) << " Title:" << " " << key.title_key()->value() << endl;
+
+ for (MetadataSectionKey::MetadataConstIterator k(key.begin_metadata()), k_end(key.end_metadata()) ;
+ k != k_end ; ++k)
+ show_key(**k, indent + " ");
+ }
};
+
+ /* Display as much as we can about a key. */
+ void show_key(const MetadataKey & key, const std::string & indent)
+ {
+ /* All MetadataKey instances have a raw name, a human readable
+ * name and a type. The type is a hint to clients as to whether
+ * the key should be displayed when outputting the package (for
+ * example, 'paludis --query' shows mkt_significant keys first,
+ * then mkt_normal keys, and doesn't show mkt_dependencies
+ * without '--show-deps' or mkt_internal without
+ * '--show-metadata'. */
+ cout << indent << left << setw(30) << " Raw name:" << " " << key.raw_name() << endl;
+ cout << indent << left << setw(30) << " Human name:" << " " << key.human_name() << endl;
+ cout << indent << left << setw(30) << " Type:" << " " << key.type() << endl;
+
+ /* To get any more information out of a MetadataKey we have to
+ * use a visitor. This lets us write type-safe handling code for
+ * the appropriate MetadataKey subclass without the need for any
+ * runtime type information queries. */
+ MetadataKeyInformationVisitor v;
+ key.accept(v);
+ }
}
int main(int argc, char * argv[])
@@ -205,24 +252,9 @@ int main(int argc, char * argv[])
for (PackageID::MetadataConstIterator k((*i)->begin_metadata()), k_end((*i)->end_metadata()) ;
k != k_end ; ++k)
{
- /* All MetadataKey instances have a raw name, a human readable
- * name and a type. The type is a hint to clients as to whether
- * the key should be displayed when outputting the package (for
- * example, 'paludis --query' shows mkt_significant keys first,
- * then mkt_normal keys, and doesn't show mkt_dependencies
- * without '--show-deps' or mkt_internal without
- * '--show-metadata'. */
- cout << left << setw(30) << " Raw name:" << " " << (*k)->raw_name() << endl;
- cout << left << setw(30) << " Human name:" << " " << (*k)->human_name() << endl;
- cout << left << setw(30) << " Type:" << " " << (*k)->type() << endl;
-
- /* To get any more information out of a MetadataKey we have to
- * use a visitor. This lets us write type-safe handling code for
- * the appropriate MetadataKey subclass without the need for any
- * runtime type information queries. */
- MetadataKeyInformationVisitor v;
- (*k)->accept(v);
-
+ /* Display it. Note that PackageID::MetadataConstIterator returns a tr1::shared_ptr
+ * to a key, so we dereference twice (or we could have used IndirectIterator). */
+ show_key(**k);
cout << endl;
}
diff --git a/paludis/metadata_key-fwd.hh b/paludis/metadata_key-fwd.hh
index f9e5eca..2beca7c 100644
--- a/paludis/metadata_key-fwd.hh
+++ b/paludis/metadata_key-fwd.hh
@@ -41,6 +41,7 @@ namespace paludis
class MetadataTimeKey;
class MetadataRepositoryMaskInfoKey;
class MetadataFSEntryKey;
+ class MetadataSectionKey;
template <typename C_> class MetadataSetKey;
template <> class MetadataSetKey<IUseFlagSet>;
template <typename C_> class MetadataSpecTreeKey;
diff --git a/paludis/metadata_key.cc b/paludis/metadata_key.cc
index b19e1db..902d289 100644
--- a/paludis/metadata_key.cc
+++ b/paludis/metadata_key.cc
@@ -24,7 +24,10 @@
#include <paludis/util/stringify.hh>
#include <paludis/util/set.hh>
#include <paludis/util/sequence.hh>
+#include <paludis/util/tr1_functional.hh>
#include <paludis/name.hh>
+#include <list>
+#include <algorithm>
using namespace paludis;
@@ -105,6 +108,62 @@ MetadataRepositoryMaskInfoKey::MetadataRepositoryMaskInfoKey(const std::string &
{
}
+namespace paludis
+{
+ template <>
+ struct Implementation<MetadataSectionKey>
+ {
+ mutable std::list<tr1::shared_ptr<const MetadataKey> > keys;
+ };
+}
+
+MetadataSectionKey::MetadataSectionKey(const std::string & r, const std::string & h, const MetadataKeyType t) :
+ MetadataKey(r, h, t),
+ PrivateImplementationPattern<MetadataSectionKey>(new Implementation<MetadataSectionKey>),
+ _imp(PrivateImplementationPattern<MetadataSectionKey>::_imp.get())
+{
+}
+
+MetadataSectionKey::~MetadataSectionKey()
+{
+}
+
+void
+MetadataSectionKey::add_metadata_key(const tr1::shared_ptr<const MetadataKey> & k) const
+{
+ using namespace tr1::placeholders;
+
+ if (_imp->keys.end() != std::find_if(_imp->keys.begin(), _imp->keys.end(),
+ tr1::bind(std::equal_to<std::string>(), k->raw_name(), tr1::bind(tr1::mem_fn(&MetadataKey::raw_name), _1))))
+ throw ConfigurationError("Tried to add duplicate key '" + k->raw_name() + "'");
+
+ _imp->keys.push_back(k);
+}
+
+MetadataSectionKey::MetadataConstIterator
+MetadataSectionKey::begin_metadata() const
+{
+ need_keys_added();
+ return MetadataConstIterator(_imp->keys.begin());
+}
+
+MetadataSectionKey::MetadataConstIterator
+MetadataSectionKey::end_metadata() const
+{
+ need_keys_added();
+ return MetadataConstIterator(_imp->keys.end());
+}
+
+MetadataSectionKey::MetadataConstIterator
+MetadataSectionKey::find_metadata(const std::string & s) const
+{
+ using namespace tr1::placeholders;
+
+ need_keys_added();
+ return std::find_if(begin_metadata(), end_metadata(),
+ tr1::bind(std::equal_to<std::string>(), s, tr1::bind(tr1::mem_fn(&MetadataKey::raw_name), _1)));
+}
+
template <typename C_>
MetadataSetKey<C_>::MetadataSetKey(const std::string & r, const std::string & h, const MetadataKeyType t) :
MetadataKey(r, h, t)
diff --git a/paludis/metadata_key.hh b/paludis/metadata_key.hh
index 7efce3e..c3619a3 100644
--- a/paludis/metadata_key.hh
+++ b/paludis/metadata_key.hh
@@ -75,7 +75,8 @@ namespace paludis
MetadataContentsKey,
MetadataTimeKey,
MetadataRepositoryMaskInfoKey,
- MetadataFSEntryKey
+ MetadataFSEntryKey,
+ MetadataSectionKey
>
{
};
@@ -304,6 +305,76 @@ namespace paludis
};
/**
+ * A MetadataSectionKey is a MetadataKey that has a title and holds a number of other
+ * MetadataKey instances.
+ *
+ * \ingroup g_metadata_key
+ * \since 0.26
+ * \nosubgrouping
+ */
+ class PALUDIS_VISIBLE MetadataSectionKey :
+ public MetadataKey,
+ public ConstAcceptInterfaceVisitsThis<MetadataKeyVisitorTypes, MetadataSectionKey>,
+ private PrivateImplementationPattern<MetadataSectionKey>
+ {
+ private:
+ Implementation<MetadataSectionKey> * const _imp;
+
+ protected:
+ ///\name Basic operations
+ ///\{
+
+ MetadataSectionKey(const std::string &, const std::string &, const MetadataKeyType);
+
+ ///\}
+
+ /**
+ * Add a new MetadataKey, which must not use the same raw name as
+ * any previous MetadataKey added to this key.
+ */
+ virtual void add_metadata_key(const tr1::shared_ptr<const MetadataKey> &) const;
+
+ /**
+ * This method will be called before any of the metadata key
+ * iteration methods does its work. It can be used by subclasses to
+ * implement as-needed loading of keys.
+ */
+ virtual void need_keys_added() const = 0;
+
+ public:
+ ///\name Basic operations
+ ///\{
+
+ virtual ~MetadataSectionKey();
+
+ ///\}
+
+ ///\name Specific metadata keys
+ ///\{
+
+ /**
+ * Our title key.
+ *
+ * May be a zero pointer for untitled sections.
+ */
+ virtual const tr1::shared_ptr<const MetadataStringKey> title_key() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
+
+ ///\}
+
+ ///\name Finding and iterating over metadata keys
+ ///\{
+
+ struct MetadataConstIteratorTag;
+ typedef WrappedForwardIterator<MetadataConstIteratorTag, tr1::shared_ptr<const MetadataKey> > MetadataConstIterator;
+
+ MetadataConstIterator begin_metadata() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ MetadataConstIterator end_metadata() const PALUDIS_ATTRIBUTE((warn_unused_result));
+ MetadataConstIterator find_metadata(const std::string &) const PALUDIS_ATTRIBUTE((warn_unused_result));
+
+ ///\}
+ };
+
+ /**
* A MetadataSetKey is a MetadataKey that holds a Set of some kind of item
* as its value.
*
diff --git a/paludis/repositories/e/qa/spec_keys.cc b/paludis/repositories/e/qa/spec_keys.cc
index a7b130f..2f8441d 100644
--- a/paludis/repositories/e/qa/spec_keys.cc
+++ b/paludis/repositories/e/qa/spec_keys.cc
@@ -306,6 +306,12 @@ namespace
{
}
+ void visit(const MetadataSectionKey & k)
+ {
+ std::for_each(indirect_iterator(k.begin_metadata()),
+ indirect_iterator(k.end_metadata()), accept_visitor(*this));
+ }
+
void visit(const MetadataSpecTreeKey<FetchableURISpecTree> & k)
{
try
diff --git a/paludis/repositories/gems/gem_specification_TEST.cc b/paludis/repositories/gems/gem_specification_TEST.cc
index a7cedf3..7340df2 100644
--- a/paludis/repositories/gems/gem_specification_TEST.cc
+++ b/paludis/repositories/gems/gem_specification_TEST.cc
@@ -23,6 +23,8 @@
#include <paludis/repositories/gems/yaml.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
+#include <paludis/util/set.hh>
#include <paludis/name.hh>
#include <paludis/metadata_key.hh>
#include <paludis/version_spec.hh>
@@ -31,84 +33,6 @@ using namespace test;
using namespace paludis;
using namespace paludis::gems;
-namespace
-{
- struct ExtractValueVisitor :
- ConstVisitor<MetadataKeyVisitorTypes>
- {
- std::string s;
-
- void visit(const MetadataStringKey & k)
- {
- s = k.value();
- }
-
- void visit(const MetadataPackageIDKey &)
- {
- }
-
- void visit(const MetadataSetKey<KeywordNameSet> &)
- {
- }
-
- void visit(const MetadataSetKey<UseFlagNameSet> &)
- {
- }
-
- void visit(const MetadataSetKey<IUseFlagSet> &)
- {
- }
-
- void visit(const MetadataSetKey<Set<std::string> > &)
- {
- }
-
- void visit(const MetadataSetKey<PackageIDSequence> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<DependencySpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<LicenseSpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<ProvideSpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<RestrictSpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<FetchableURISpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<SimpleURISpecTree> &)
- {
- }
-
- void visit(const MetadataContentsKey &)
- {
- }
-
- void visit(const MetadataTimeKey &)
- {
- }
-
- void visit(const MetadataRepositoryMaskInfoKey &)
- {
- }
-
- void visit(const MetadataFSEntryKey &)
- {
- }
- };
-}
-
namespace test_cases
{
struct SpecificationTest : TestCase
@@ -146,9 +70,8 @@ namespace test_cases
TEST_CHECK_EQUAL(spec.long_description_key()->value(), "A longer description");
TEST_CHECK(spec.find_metadata("authors") != spec.end_metadata());
- ExtractValueVisitor v;
- (*spec.find_metadata("authors"))->accept(v);
- TEST_CHECK_EQUAL(v.s, "Fred, Barney");
+ TEST_CHECK(visitor_cast<const MetadataStringKey>(**spec.find_metadata("authors")));
+ TEST_CHECK_EQUAL(visitor_cast<const MetadataStringKey>(**spec.find_metadata("authors"))->value(), "Fred, Barney");
#if 0
TEST_CHECK_EQUAL(spec.homepage(), "");
diff --git a/python/additional_tests.cc b/python/additional_tests.cc
index 76d9a6e..5cdc1ae 100644
--- a/python/additional_tests.cc
+++ b/python/additional_tests.cc
@@ -23,6 +23,8 @@
#include <paludis/util/tr1_memory.hh>
#include <paludis/util/set.hh>
+#include <paludis/util/wrapped_forward_iterator.hh>
+#include <paludis/util/indirect_iterator-impl.hh>
#include <paludis/environment.hh>
#include <paludis/environments/test/test_environment.hh>
#include <paludis/package_database.hh>
@@ -136,45 +138,52 @@ namespace mask
namespace metadata_key
{
- void test_metadata_key(MetadataKey & m)
+ void test_metadata_key(const MetadataKey & m)
{
m.raw_name();
m.human_name();
MetadataKeyType foo(m.type());
}
- void test_metadata_package_id_key(MetadataPackageIDKey & m)
+ void test_metadata_package_id_key(const MetadataPackageIDKey & m)
{
test_metadata_key(m);
m.value();
}
- void test_metadata_string_key(MetadataStringKey & m)
+ void test_metadata_string_key(const MetadataStringKey & m)
{
test_metadata_key(m);
m.value();
}
- void test_metadata_time_key(MetadataTimeKey & m)
+ void test_metadata_section_key(const MetadataSectionKey & m)
+ {
+ test_metadata_key(m);
+ std::for_each(indirect_iterator(m.begin_metadata()), indirect_iterator(m.end_metadata()),
+ &test_metadata_key);
+ }
+
+ void test_metadata_time_key(const MetadataTimeKey & m)
{
test_metadata_key(m);
time_t PALUDIS_ATTRIBUTE((unused)) t(m.value());
}
- void test_metadata_contents_key(MetadataContentsKey & m)
+ void test_metadata_contents_key(const MetadataContentsKey & m)
{
test_metadata_key(m);
m.value();
}
- void test_metadata_repository_mask_info_key(MetadataRepositoryMaskInfoKey & m)
+ void test_metadata_repository_mask_info_key(const MetadataRepositoryMaskInfoKey & m)
{
test_metadata_key(m);
m.value();
}
template <typename C_>
- void test_metadata_set_key(MetadataSetKey<C_> & m)
+ void test_metadata_set_key(const MetadataSetKey<C_> & m)
{
test_metadata_key(m);
m.value();
@@ -183,7 +192,7 @@ namespace metadata_key
}
template <>
- void test_metadata_set_key(MetadataSetKey<IUseFlagSet> & m)
+ void test_metadata_set_key(const MetadataSetKey<IUseFlagSet> & m)
{
test_metadata_key(m);
m.value();
@@ -198,7 +207,7 @@ namespace metadata_key
}
template <typename C_>
- void test_metadata_spec_tree_key(MetadataSpecTreeKey<C_> & m)
+ void test_metadata_spec_tree_key(const MetadataSpecTreeKey<C_> & m)
{
test_metadata_key(m);
m.value();
@@ -208,7 +217,7 @@ namespace metadata_key
}
template <>
- void test_metadata_spec_tree_key(MetadataSpecTreeKey<FetchableURISpecTree> & m)
+ void test_metadata_spec_tree_key(const MetadataSpecTreeKey<FetchableURISpecTree> & m)
{
test_metadata_key(m);
m.value();
@@ -314,6 +323,7 @@ void expose_additional_tests()
bp::def("test_metadata_restrict_spec_tree_key", &metadata_key::test_metadata_spec_tree_key<RestrictSpecTree>);
bp::def("test_metadata_fetchable_uri_spec_tree_key", &metadata_key::test_metadata_spec_tree_key<FetchableURISpecTree>);
bp::def("test_metadata_simple_uri_spec_tree_key", &metadata_key::test_metadata_spec_tree_key<SimpleURISpecTree>);
+ bp::def("test_metadata_section_key", &metadata_key::test_metadata_section_key);
/**
* Formatter tests
@@ -325,3 +335,4 @@ void expose_additional_tests()
bp::def("test_package_roles", &formatter::test_package_roles);
bp::def("test_can_space", &formatter::test_can_space);
}
+
diff --git a/python/metadata_key.cc b/python/metadata_key.cc
index 4df0d4f..b5e866d 100644
--- a/python/metadata_key.cc
+++ b/python/metadata_key.cc
@@ -133,6 +133,11 @@ class MetadataKeySptrToPythonVisitor :
{
obj = bp::object(tr1::static_pointer_cast<const MetadataSetKey<PackageIDSequence> >(_m_ptr));
}
+
+ void visit(const MetadataSectionKey & k)
+ {
+ obj = bp::object(tr1::static_pointer_cast<const MetadataSectionKey>(_m_ptr));
+ }
};
struct MetadataKeySptrToPython
@@ -193,6 +198,46 @@ struct MetadataStringKeyWrapper :
}
};
+struct MetadataSectionKeyWrapper :
+ MetadataSectionKey,
+ bp::wrapper<MetadataSectionKey>
+{
+ MetadataSectionKeyWrapper(const std::string & r, const std::string & h, const MetadataKeyType t) :
+ MetadataSectionKey(r, h, t)
+ {
+ }
+
+ static PyObject *
+ find_metadata(const MetadataSectionKey & self, const std::string & key)
+ {
+ MetadataSectionKey::MetadataConstIterator i(self.find_metadata(key));
+ if (i != self.end_metadata())
+ return bp::incref(bp::object(*i).ptr());
+ else
+ return Py_None;
+ }
+
+ virtual void need_keys_added() const
+ {
+ Lock l(get_mutex());
+
+ if (bp::override f = get_override("need_keys_added"))
+ f();
+ else
+ throw PythonMethodNotImplemented("MetadataSectionKey", "need_keys_added");
+ }
+
+ virtual const tr1::shared_ptr<const MetadataStringKey> title_key() const
+ {
+ Lock l(get_mutex());
+
+ if (bp::override f = get_override("title_key"))
+ return f();
+ else
+ throw PythonMethodNotImplemented("MetadataSectionKey", "title_key");
+ }
+};
+
struct MetadataTimeKeyWrapper :
MetadataTimeKey,
bp::wrapper<MetadataTimeKey>
@@ -727,6 +772,35 @@ void expose_metadata_key()
;
/**
+ * MetadataSectionKey
+ */
+ bp::register_ptr_to_python<tr1::shared_ptr<const MetadataSectionKey> >();
+ bp::implicitly_convertible<tr1::shared_ptr<MetadataSectionKeyWrapper>,
+ tr1::shared_ptr<MetadataKey> >();
+ bp::class_<MetadataSectionKeyWrapper, tr1::shared_ptr<MetadataSectionKeyWrapper>,
+ bp::bases<MetadataKey>, boost::noncopyable>
+ (
+ "MetadataSectionKey",
+ "A MetadataSectionKey holds a number of other MetadataKey instances, and\n"
+ "may have a title.\n\n"
+
+ "This class can be subclassed in Python.",
+ bp::init<const std::string &, const std::string &, MetadataKeyType>(
+ "__init__(raw_name, human_name, MetadataKeyType)"
+ )
+ )
+ .add_property("metadata", bp::range(&MetadataSectionKey::begin_metadata, &MetadataSectionKey::end_metadata),
+ "[ro] Iterable of MetadataKey\n"
+ "NEED_DOC"
+ )
+
+ .def("find_metadata", &MetadataSectionKeyWrapper::find_metadata,
+ "find_metadata(string) -> MetadataKey\n"
+ "NEED_DOC"
+ )
+ ;
+
+ /**
* MetadataTimeKey
*/
bp::register_ptr_to_python<tr1::shared_ptr<const MetadataTimeKey> >();
diff --git a/python/metadata_key_TEST.py b/python/metadata_key_TEST.py
index d9beeb1..cc55b74 100755
--- a/python/metadata_key_TEST.py
+++ b/python/metadata_key_TEST.py
@@ -298,6 +298,20 @@ class TestCase_02_MetadataKeys_suclassing(unittest.TestCase):
test_metadata_simple_uri_spec_tree_key(TestKey())
+ def test_16_section(self):
+ class TestKey(MetadataSectionKey):
+ def __init__(self):
+ MetadataSectionKey.__init__(self, "raw", "human", MetadataKeyType.NORMAL)
+
+ def need_keys_added(self):
+ return
+
+ def title_key(self):
+ return None
+
+ test_metadata_section_key(TestKey())
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/ruby/metadata_key.cc b/ruby/metadata_key.cc
index 1d150e2..5171b5d 100644
--- a/ruby/metadata_key.cc
+++ b/ruby/metadata_key.cc
@@ -122,6 +122,11 @@ namespace
value = Qnil;
}
+ void visit(const MetadataSectionKey &)
+ {
+ value = Qnil;
+ }
+
void visit(const MetadataRepositoryMaskInfoKey &)
{
value = Data_Wrap_Struct(c_metadata_repository_mask_info_key, 0, &Common<tr1::shared_ptr<const MetadataContentsKey> >::free,
diff --git a/src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc b/src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc
index 200f4cd..0a08f6c 100644
--- a/src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc
+++ b/src/clients/gtkpaludis/libgtkpaludis/version_info_model.cc
@@ -196,6 +196,10 @@ namespace gtkpaludis
void visit(const MetadataContentsKey &)
{
}
+
+ void visit(const MetadataSectionKey &)
+ {
+ }
};
struct VersionInfoModel::KeyMetadataPopulator :
diff --git a/src/clients/inquisitio/key_extractor.cc b/src/clients/inquisitio/key_extractor.cc
index 436501b..7f384ef 100644
--- a/src/clients/inquisitio/key_extractor.cc
+++ b/src/clients/inquisitio/key_extractor.cc
@@ -385,6 +385,12 @@ namespace
result = v.result;
}
}
+
+ void visit(const MetadataSectionKey & k)
+ {
+ std::for_each(indirect_iterator(k.begin_metadata()),
+ indirect_iterator(k.end_metadata()), accept_visitor(*this));
+ }
};
}
diff --git a/src/clients/instruo/instruo.cc b/src/clients/instruo/instruo.cc
index 5a21cfc..015a37b 100644
--- a/src/clients/instruo/instruo.cc
+++ b/src/clients/instruo/instruo.cc
@@ -30,6 +30,7 @@
#include <paludis/util/map.hh>
#include <paludis/util/tr1_functional.hh>
#include <paludis/util/visitor-impl.hh>
+#include <paludis/util/visitor_cast.hh>
#include <paludis/util/set.hh>
#include <paludis/environments/no_config/no_config_environment.hh>
#include <paludis/package_database.hh>
@@ -46,88 +47,6 @@ using std::endl;
namespace
{
- struct EAPIFinder :
- ConstVisitor<MetadataKeyVisitorTypes>
- {
- bool ok;
- std::string s;
-
- EAPIFinder() :
- ok(false)
- {
- }
-
- void visit(const MetadataStringKey & k)
- {
- s = k.value();
- ok = true;
- }
-
- void visit(const MetadataPackageIDKey &)
- {
- }
-
- void visit(const MetadataTimeKey &)
- {
- }
-
- void visit(const MetadataContentsKey &)
- {
- }
-
- void visit(const MetadataFSEntryKey &)
- {
- }
-
- void visit(const MetadataRepositoryMaskInfoKey &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<RestrictSpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<ProvideSpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<FetchableURISpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<SimpleURISpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<LicenseSpecTree> &)
- {
- }
-
- void visit(const MetadataSpecTreeKey<DependencySpecTree> &)
- {
- }
-
- void visit(const MetadataSetKey<PackageIDSequence> &)
- {
- }
-
- void visit(const MetadataSetKey<Set<std::string> > &)
- {
- }
-
- void visit(const MetadataSetKey<KeywordNameSet> &)
- {
- }
-
- void visit(const MetadataSetKey<IUseFlagSet> &)
- {
- }
-
- void visit(const MetadataSetKey<UseFlagNameSet> &)
- {
- }
- };
-
struct KeyValidator :
ConstVisitor<MetadataKeyVisitorTypes>
{
@@ -215,6 +134,12 @@ namespace
{
const tr1::shared_ptr<const UseFlagNameSet> & PALUDIS_ATTRIBUTE((unused)) s(k.value());
}
+
+ void visit(const MetadataSectionKey & k)
+ {
+ std::for_each(indirect_iterator(k.begin_metadata()),
+ indirect_iterator(k.end_metadata()), accept_visitor(*this));
+ }
};
}
@@ -315,17 +240,15 @@ main(int argc, char *argv[])
continue;
}
- EAPIFinder f;
- (*eapi_i)->accept(f);
- if (! f.ok)
+ if (! visitor_cast<const MetadataStringKey>(**eapi_i))
{
results.insert(std::make_pair(*i, "EAPI metadata key is not a string key"));
continue;
}
- if (f.s == "UNKNOWN")
+ if (visitor_cast<const MetadataStringKey>(**eapi_i)->value() == "UNKNOWN")
{
- results.insert(std::make_pair(*i, "EAPI is '" + f.s + "'"));
+ results.insert(std::make_pair(*i, "EAPI is 'UNKNOWN'"));
continue;
}
diff --git a/src/clients/qualudis/qualudis.cc b/src/clients/qualudis/qualudis.cc
index 860b6cf..ab2496b 100644
--- a/src/clients/qualudis/qualudis.cc
+++ b/src/clients/qualudis/qualudis.cc
@@ -144,8 +144,17 @@ namespace
stream << k.raw_name() << "\n";
}
- void visit(const MetadataContentsKey &)
+ void visit(const MetadataContentsKey & k)
{
+ stream << k.raw_name() << "\n";
+ }
+
+ void visit(const MetadataSectionKey & k)
+ {
+ if (k.title_key())
+ stream << k.raw_name() << ": " << k.title_key()->value() << "\n";
+ else
+ stream << k.raw_name() << "\n";
}
};
diff --git a/src/output/console_query_task.cc b/src/output/console_query_task.cc
index 2e60fb5..f5719a0 100644
--- a/src/output/console_query_task.cc
+++ b/src/output/console_query_task.cc
@@ -242,14 +242,17 @@ namespace
const Environment * const env;
const tr1::shared_ptr<const PackageID> id;
const MetadataKeyType type;
+ const unsigned in;
public:
Displayer(const ConsoleQueryTask * const t, const Environment * const e,
- const tr1::shared_ptr<const PackageID> & i, const MetadataKeyType k) :
+ const tr1::shared_ptr<const PackageID> & i, const MetadataKeyType k,
+ const unsigned ind = 0) :
task(t),
env(e),
id(i),
- type(k)
+ type(k),
+ in(ind)
{
}
@@ -260,12 +263,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
}
@@ -278,12 +281,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
}
@@ -296,12 +299,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
}
@@ -314,12 +317,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
}
@@ -332,12 +335,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column("");
task->output_stream() << k.pretty_print(formatter);
}
@@ -351,12 +354,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_stream() << k.pretty_print_flat(formatter);
task->output_right_column("");
}
@@ -370,12 +373,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_stream() << k.pretty_print_flat(formatter);
task->output_right_column("");
}
@@ -389,12 +392,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
ComplexLicenseFinder is_complex;
k.value()->accept(is_complex);
if (is_complex)
@@ -415,12 +418,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column("");
task->output_stream() << k.pretty_print(formatter);
}
@@ -434,12 +437,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column("");
task->output_stream() << k.pretty_print(formatter);
}
@@ -453,12 +456,12 @@ namespace
ColourFormatter formatter;
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(k.pretty_print_flat(formatter));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column("");
task->output_stream() << k.pretty_print_flat(formatter);
task->output_endl();
@@ -472,12 +475,12 @@ namespace
{
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(stringify(*k.value()));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(stringify(*k.value()));
}
}
@@ -489,17 +492,40 @@ namespace
{
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(stringify(k.value()));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(stringify(k.value()));
}
}
}
+ void visit(const MetadataSectionKey & k)
+ {
+ if (k.type() == type)
+ {
+ if (task->want_raw())
+ {
+ task->output_left_column(k.raw_name() + ":", in);
+ task->output_right_column("");
+ }
+ else
+ {
+ task->output_left_column((k.title_key() ? k.title_key()->value() : k.human_name()) + ":", in);
+ task->output_right_column("");
+ }
+
+ Displayer v(task, env, id, type, in + 4);
+ for (MetadataSectionKey::MetadataConstIterator kk(k.begin_metadata()), kk_end(k.end_metadata()) ;
+ kk != kk_end ; ++kk)
+ if (*kk != k.title_key())
+ (*kk)->accept(v);
+ }
+ }
+
void visit(const MetadataTimeKey & k)
{
if (0 == k.value())
@@ -514,12 +540,12 @@ namespace
{
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(stringify(buf));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(stringify(buf));
}
}
@@ -531,18 +557,18 @@ namespace
{
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(stringify(k.value()->mask_file) + ": " +
join(k.value()->comment->begin(), k.value()->comment->end(), " "));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(stringify(k.value()->mask_file) + ":");
for (Sequence<std::string>::ConstIterator it(k.value()->comment->begin()),
it_end(k.value()->comment->end()); it_end != it; ++it)
{
- task->output_left_column("");
+ task->output_left_column("", in);
task->output_right_column(*it);
}
}
@@ -555,12 +581,12 @@ namespace
{
if (task->want_raw())
{
- task->output_left_column(k.raw_name() + ":");
+ task->output_left_column(k.raw_name() + ":", in);
task->output_right_column(stringify(k.value()));
}
else
{
- task->output_left_column(k.human_name() + ":");
+ task->output_left_column(k.human_name() + ":", in);
task->output_right_column(stringify(k.value()));
}
}
diff --git a/src/output/console_task.cc b/src/output/console_task.cc
index 42dab4a..09f066d 100644
--- a/src/output/console_task.cc
+++ b/src/output/console_task.cc
@@ -168,9 +168,9 @@ ConsoleTask::render_plural(int c, const std::string & s, const std::string & p)
}
void
-ConsoleTask::output_left_column(const std::string & s) const
+ConsoleTask::output_left_column(const std::string & s, const unsigned indent) const
{
- output_stream() << " " << std::setw(left_column_width()) << std::left << s << " ";
+ output_stream() << " " << std::string(indent, ' ') << std::setw(left_column_width()) << std::left << s << " ";
}
void
diff --git a/src/output/console_task.hh b/src/output/console_task.hh
index 5d86800..8a5e3f6 100644
--- a/src/output/console_task.hh
+++ b/src/output/console_task.hh
@@ -57,7 +57,7 @@ namespace paludis
virtual void output_no_endl(const std::string &) const;
virtual void output_endl() const;
- virtual void output_left_column(const std::string &) const;
+ virtual void output_left_column(const std::string &, const unsigned indent = 0) const;
virtual void output_right_column(const std::string &) const;
///\}
diff --git a/src/output/mask_displayer.cc b/src/output/mask_displayer.cc
index 0c2db4e..5d664e2 100644
--- a/src/output/mask_displayer.cc
+++ b/src/output/mask_displayer.cc
@@ -69,6 +69,33 @@ namespace
s << k.value();
}
+ void visit(const MetadataSectionKey & k)
+ {
+ if (k.title_key())
+ s << k.title_key()->value() << ": ";
+ s << "(";
+
+ bool need_comma(false);
+ for (MetadataSectionKey::MetadataConstIterator m(k.begin_metadata()), m_end(k.end_metadata()) ;
+ m != m_end ; ++m)
+ if ((*m) != k.title_key())
+ {
+ if (need_comma)
+ s << ", ";
+ else
+ s << " ";
+
+ KeyPrettyPrinter p;
+ (*m)->accept(p);
+ s << p.s.str();
+ need_comma = true;
+ }
+ s << " )";
+
+ std::for_each(indirect_iterator(k.begin_metadata()),
+ indirect_iterator(k.end_metadata()), accept_visitor(*this));
+ }
+
void visit(const MetadataTimeKey & k)
{
time_t t(k.value());