Exheredludis/paludis/args/args_option.hh
2016-12-04 20:33:50 -08:00

667 lines
22 KiB
C++

/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
* Copyright (c) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Ciaran McCreesh
* Copyright (c) 2006 Stephen Bennett
*
* 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_ARGS_ARGS_OPTION_HH
#define PALUDIS_GUARD_ARGS_ARGS_OPTION_HH 1
#include <paludis/util/iterator_range.hh>
#include <paludis/util/pimp.hh>
#include <paludis/util/wrapped_forward_iterator.hh>
#include <paludis/util/type_list.hh>
#include <paludis/util/named_value.hh>
#include <paludis/util/visitor.hh>
#include <paludis/util/sequence-fwd.hh>
#include <memory>
/** \file
* Declarations for ArgsOption.
*
* \ingroup g_args
*
* \section Examples
*
* - None at this time.
*/
namespace paludis
{
namespace n
{
typedef Name<struct name_description> description;
typedef Name<struct name_long_name> long_name;
typedef Name<struct name_short_name> short_name;
}
namespace args
{
class ArgsGroup;
class StringArg;
class AliasArg;
class SwitchArg;
class IntegerArg;
class EnumArg;
class StringSetArg;
class StringSequenceArg;
enum ArgsOptionSpecifiedness
{
aos_not,
aos_weak,
aos_specified
};
/**
* Base class for a command line option.
*
* \ingroup g_args
*/
class PALUDIS_VISIBLE ArgsOption :
public virtual DeclareAbstractAcceptMethods<ArgsOption, MakeTypeList<
StringArg, AliasArg, SwitchArg, IntegerArg, EnumArg, StringSetArg, StringSequenceArg>::Type>
{
friend class ArgsHandler;
private:
ArgsGroup * const _group;
const std::string _long_name;
const char _short_name;
const std::string _description;
ArgsOptionSpecifiedness _specified;
ArgsOption(const ArgsOption &);
void operator= (const ArgsOption &);
protected:
/**
* Constructor.
*/
ArgsOption(ArgsGroup * const, const std::string & long_name,
const char short_name, const std::string & description);
/**
* Destructor.
*/
virtual ~ArgsOption() = default;
public:
/**
* Remove this option. Removes our group from its
* section if the group would be left empty.
*/
void remove();
/**
* Fetch our long name.
*/
const std::string & long_name() const
{
return _long_name;
}
/**
* Fetch our short name (may be 0).
*/
char short_name() const
{
return _short_name;
}
/**
* Fetch our description.
*/
const std::string & description() const
{
return _description;
}
/**
* Fetch whether or not we were specified on the
* command line (or as an env var).
*/
virtual bool specified() const
{
return _specified != aos_not;
}
/**
* Fetch whether or not we were explicitly (not
* an env var) specified. Used to catch -x y -x z
* where -x takes a single value.
*/
virtual bool explicitly_specified() const
{
return _specified == aos_specified;
}
/**
* Set the value returned by specified().
*/
virtual void set_specified(const ArgsOptionSpecifiedness value)
{
_specified = value;
}
/**
* Fetch our group.
*/
ArgsGroup * group()
{
return _group;
}
/**
* Can we be negated?
*
* Needs to match up with ArgsVisitor logic.
*/
virtual bool can_be_negated() const = 0;
/**
* Ourself as a forwardable string.
*
* For example, '--foo bar' or '--foo bar --foo baz' or '--foo', or
* if not specified, the empty string.
*
* \since 0.40
*/
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
/**
* Ourself as a sequence of strings.
*
* For example, { '--foo', 'bar' } or { '--foo', 'bar', '--foo', 'baz' }
* if not specified, an empty sequence.
*
* \since 0.46
*/
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result)) = 0;
};
/**
* A SwitchArg is an option that can either be specified or not
* specified, and that takes no value (for example, --help).
*
* \ingroup g_args
*/
class PALUDIS_VISIBLE SwitchArg :
public ArgsOption,
public ImplementAcceptMethods<ArgsOption, SwitchArg>
{
private:
bool _can_be_negated;
public:
/**
* Constructor.
*
* \since 0.26
*/
SwitchArg(ArgsGroup * const group, const std::string & long_name, char short_name,
const std::string & description, const bool can_be_negated);
~SwitchArg() = default;
virtual bool can_be_negated() const;
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
/**
* An option that takes a string argument.
*
* \ingroup g_args
*/
class PALUDIS_VISIBLE StringArg :
public ArgsOption,
public ImplementAcceptMethods<ArgsOption, StringArg>
{
private:
std::string _argument;
bool _can_be_negated;
void (* _validator) (const std::string &);
public:
/**
* Constructor
*/
StringArg(ArgsGroup * const, const std::string & long_name,
const char short_name, const std::string & description,
const bool can_be_negated = false);
/**
* Constructor with validator.
*/
StringArg(ArgsGroup * const, const std::string & long_name,
const char short_name, const std::string & description,
void (* validator) (const std::string &),
const bool can_be_negated = false);
/**
* Fetch the argument that was given to this option.
*/
const std::string & argument() const { return _argument; }
/**
* Set the argument returned by argument().
*/
void set_argument(const std::string & arg);
virtual bool can_be_negated() const;
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
/**
* An option that takes a set of strings.
*
* \ingroup g_args
* \nosubgrouping
*/
class PALUDIS_VISIBLE StringSetArg :
public ArgsOption,
public ImplementAcceptMethods<ArgsOption, StringSetArg>
{
private:
Pimp<StringSetArg> _imp;
void (* _validator) (const std::string &);
public:
/**
* Helper class for passing available options and associated descriptions
* to the StringSetArg constructor.
*
* \ingroup grplibpaludisargs
*/
class PALUDIS_VISIBLE StringSetArgOptions
{
friend class StringSetArg;
private:
Pimp<StringSetArgOptions> _imp;
public:
/**
* Constructor
*/
StringSetArgOptions(const std::string &, const std::string &);
/**
* Blank constructor
*/
explicit StringSetArgOptions();
/**
* Copy constructor
*/
StringSetArgOptions(const StringSetArgOptions &);
/**
* Destructor.
*/
~StringSetArgOptions();
/**
* Adds another (option, description) pair.
*/
StringSetArgOptions & operator() (const std::string &, const std::string &);
};
///\name Basic operations
///\{
StringSetArg(ArgsGroup * const, const std::string & long_name,
const char short_name, const std::string & description,
const StringSetArgOptions & options = StringSetArgOptions());
StringSetArg(ArgsGroup * const, const std::string & long_name,
const char short_name, const std::string & description,
const StringSetArgOptions & options,
void (* validator) (const std::string &));
~StringSetArg();
///\}
///\name Iterate over our args.
///\{
struct ConstIteratorTag;
typedef WrappedForwardIterator<ConstIteratorTag, const std::string> ConstIterator;
ConstIterator begin_args() const;
ConstIterator end_args() const;
IteratorRange<ConstIterator> args() const;
///\}
/**
* Add an argument to the set.
*/
void add_argument(const std::string & arg);
///\name Iterate over our allowed arguments and associated descriptions
///\{
struct AllowedArgConstIteratorTag;
typedef WrappedForwardIterator<AllowedArgConstIteratorTag,
const std::pair<std::string, std::string> > AllowedArgConstIterator;
AllowedArgConstIterator begin_allowed_args() const;
AllowedArgConstIterator end_allowed_args() const;
///\}
virtual bool can_be_negated() const;
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
/**
* An option that takes a set of strings.
*
* \since 0.32
* \ingroup g_args
* \nosubgrouping
*/
class PALUDIS_VISIBLE StringSequenceArg :
public ArgsOption,
public ImplementAcceptMethods<ArgsOption, StringSequenceArg>
{
private:
Pimp<StringSequenceArg> _imp;
public:
///\name Basic operations
///\{
StringSequenceArg(ArgsGroup * const, const std::string & long_name,
const char short_name, const std::string & description);
~StringSequenceArg();
///\}
///\name Iterate over our args.
///\{
struct ConstIteratorTag;
typedef WrappedForwardIterator<ConstIteratorTag, const std::string> ConstIterator;
ConstIterator begin_args() const;
ConstIterator end_args() const;
///\}
/**
* Add an argument to the set.
*/
void add_argument(const std::string & arg);
virtual bool can_be_negated() const;
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
/**
* An AliasArg is an alias for another argument.
*
* \ingroup g_args
*/
class PALUDIS_VISIBLE AliasArg :
public ArgsOption,
public ImplementAcceptMethods<ArgsOption, AliasArg>
{
private:
ArgsOption * const _other;
bool _hidden;
public:
/**
* Constructor.
*/
AliasArg(ArgsOption * const other, const std::string & new_long_name, bool is_hidden = false);
virtual bool specified() const
{
return _other->specified();
}
virtual bool explicitly_specified() const
{
return _other->explicitly_specified();
}
virtual void set_specified(const ArgsOptionSpecifiedness value)
{
_other->set_specified(value);
}
virtual bool hidden() const
{
return _hidden;
}
virtual void set_hidden(const bool value)
{
_hidden = value;
}
/**
* Fetch our associated option.
*/
ArgsOption * other() const
{
return _other;
}
virtual bool can_be_negated() const;
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
/**
* An option that takes an integer argument.
*
* \ingroup grplibpaludisargs
*/
class PALUDIS_VISIBLE IntegerArg :
public ArgsOption,
public ImplementAcceptMethods<ArgsOption, IntegerArg>
{
private:
int _argument;
public:
/**
* Constructor
*/
IntegerArg(ArgsGroup * const, const std::string & long_name,
const char short_name, const std::string & description);
/**
* Fetch the argument that was given to this option.
*/
int argument() const { return _argument; }
/**
* Set the argument returned by argument().
*/
void set_argument(const int arg) { _argument = arg; }
virtual bool can_be_negated() const;
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
/**
* An allowed argument for an EnumArg.
*
* \ingroup g_args
* \since 0.40
*/
struct AllowedEnumArg
{
NamedValue<n::description, std::string> description;
NamedValue<n::long_name, std::string> long_name;
/// Might be '\0', for none.
NamedValue<n::short_name, char> short_name;
};
/**
* An option that takes one of a predefined set of string arguments.
*
* \ingroup g_args
* \nosubgrouping
*/
class PALUDIS_VISIBLE EnumArg :
public ArgsOption,
public ImplementAcceptMethods<ArgsOption, EnumArg>
{
private:
Pimp<EnumArg> _imp;
std::string _argument;
std::string _default_arg;
public:
/**
* Helper class for passing available options and associated descriptions
* to the EnumArg constructor.
*
* \ingroup grplibpaludisargs
*/
class PALUDIS_VISIBLE EnumArgOptions
{
friend class EnumArg;
private:
Pimp<EnumArgOptions> _imp;
public:
/**
* Constructor
*/
EnumArgOptions(const std::string &, const std::string &);
/**
* Constructor, with short arg.
*
* \since 0.40
*/
EnumArgOptions(const std::string &, const char, const std::string &);
/**
* Destructor.
*/
~EnumArgOptions();
/**
* Adds another (option, description).
*/
EnumArgOptions & operator() (const std::string &, const std::string &);
/**
* Adds another (option, short-option, description).
*
* \since 0.40
*/
EnumArgOptions & operator() (const std::string &, const char, const std::string &);
};
/**
* Constructor.
*/
EnumArg(ArgsGroup * const group, const std::string & long_name,
const char short_name, const std::string & description,
const EnumArgOptions & opts, const std::string & default_arg);
~EnumArg();
/**
* Fetch the argument that was given to this option.
*/
const std::string & argument() const
{
return _argument;
}
/**
* Set the argument returned by argument(), having verified that
* it is one of the arguments allowed for this option.
*/
void set_argument(const std::string & arg);
/**
* Change the default option (should be called before
* set_argument()).
*/
void set_default_arg(const std::string & arg);
/**
* Fetch the default option, as specified to the
* constructor or set_default_arg().
*/
const std::string & default_arg() const
{
return _default_arg;
}
///\name Iterate over our allowed arguments and associated descriptions
///\{
struct AllowedArgConstIteratorTag;
typedef WrappedForwardIterator<AllowedArgConstIteratorTag,
const AllowedEnumArg> AllowedArgConstIterator;
AllowedArgConstIterator begin_allowed_args() const;
AllowedArgConstIterator end_allowed_args() const;
///\}
virtual bool can_be_negated() const;
virtual const std::string forwardable_string() const PALUDIS_ATTRIBUTE((warn_unused_result));
virtual const std::shared_ptr<Sequence<std::string> > forwardable_args() const PALUDIS_ATTRIBUTE((warn_unused_result));
};
}
extern template class PALUDIS_VISIBLE WrappedForwardIterator<args::StringSetArg::ConstIteratorTag, const std::string>;
extern template class PALUDIS_VISIBLE WrappedForwardIterator<args::StringSetArg::AllowedArgConstIteratorTag,
const std::pair<std::string, std::string> >;
extern template class PALUDIS_VISIBLE WrappedForwardIterator<args::StringSequenceArg::ConstIteratorTag, const std::string>;
extern template class PALUDIS_VISIBLE WrappedForwardIterator<args::EnumArg::AllowedArgConstIteratorTag,
const args::AllowedEnumArg>;
}
#endif