source: trunk/yat/utility/CommandLine.h

Last change on this file was 3188, checked in by Peter, 7 years ago

merge patch release 0.11.2

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.2 KB
Line 
1#ifndef _theplu_yat_utility_commandline_
2#define _theplu_yat_utility_commandline_
3
4//$Id: CommandLine.h 3188 2014-03-25 10:24:29Z peter $
5
6/*
7  Copyright (C) 2007, 2008, 2009 Jari Häkkinen, Peter Johansson
8  Copyright (C) 2010, 2011, 2012, 2013, 2014 Peter Johansson
9
10  This file is part of the yat library, http://dev.thep.lu.se/yat
11
12  The yat library is free software; you can redistribute it and/or
13  modify it under the terms of the GNU General Public License as
14  published by the Free Software Foundation; either version 3 of the
15  License, or (at your option) any later version.
16
17  The yat library is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  General Public License for more details.
21
22  You should have received a copy of the GNU General Public License
23  along with yat. If not, see <http://www.gnu.org/licenses/>.
24*/
25
26#include <algorithm>
27#include <cctype>
28#include <map>
29#include <iosfwd>
30#include <sstream>
31#include <stdexcept>
32#include <string>
33#include <typeinfo>
34#include <utility>
35#include <vector>
36
37namespace theplu {
38namespace yat {
39namespace utility {
40
41  class Option;
42
43  /**
44     @brief Class for parsing the command line.
45     
46     Provides parsing and storage of command line arguments. The class
47     is typically used by hooking a number of Option objects to
48     CommandLine, and then call the parse() function. Here is a short
49     example how the class may be used:
50 
51     \code
52 
53     CommandLine cmd;
54     OptionHelp help(cmd);
55     OptionFile in(cmd, "i,in",
56                   "Read input from file (rather than standard input)",
57                   false, true, "r");
58     OptionFile out(cmd, "o,out", "Place the output to file", false, false, "w");
59     OptionSwitch target(cmd, "T,target", "treat DEST as a normal file", true);
60     OptionSwitch verbose(cmd, "v,verbose", "explain what is being done");
61     OptionSwitch version(cmd, "version", "output version and exit");
62     std::stringstream copyright;
63     copyright << "example 1.0\n"
64               << "Copyright (C) 2007 Peter Johansson\n\n"
65               << "This is free software see the source for copying "
66               << "conditions. There is NO\nwarranty; not even for "
67               << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n";
68     try {
69       cmd.parse(argc, argv);
70     }
71     catch (cmd_error& e){
72       if (version.present()){
73         std::cout << copyright.str();     
74         return EXIT_SUCCESS;
75       }
76       std::cerr << e.what() << std::endl;
77       return EXIT_FAILURE;
78     } 
79     if (version.present()){
80       std::cout << copyright.str();     
81       return EXIT_SUCCESS;
82     }
83     StreamRedirect sr_out(std::cout, out.value(), out.present());
84     StreamRedirect sr_in(std::cin, in.value(), in.present());
85     ...
86     \endcode
87
88     After creation a number of Option classes are hooked up to the
89     CommandLine object in their constructors.
90
91     Each parameter is associated to a one-character flag and/or a
92     longer string flag. The longer flag expects to be preceded by
93     '--' as e.g. '--help' for help. The shorter flag expects to be
94     preceded by '-' as e.g. '-h', and can also be concatenated like
95     "program -vf", which is equivalent to "program -v -f". or
96     its sibblings for different types.
97  */
98  class CommandLine
99  {
100  public:
101    /**
102       \brief default constructor
103
104       \param str text preceeding the list of option in output
105    */
106    CommandLine(std::string str="Available options are:");
107
108    /**
109       \brief Destructor
110    */
111    virtual ~CommandLine(void);
112
113    /**
114       \brief Function to add an option.
115    */
116    void add(Option&);
117
118    /**
119       \brief Allow at most \a n free arguments.
120
121       A free argument is an argument not associated with an Option,
122       allowing commandlines such as \code prog foo bar \endcode
123     */
124    void allow_free_args(size_t n);
125
126    /**
127       \brief Arguments not associated with an Option
128
129       \see allow_free_args(size_t n)
130    */
131    const std::vector<std::string>& free_args(void) const;
132
133    /**
134       \brief parse the commandline
135
136       First the commandline is parsed to detect which options are
137       present, then each Option parses the its relevant part of
138       commandline (Option::parse()), and finally each Option is
139       validated (Option::validate()).
140
141       throw cmd_error if an error is detected.
142    */
143    void parse(int argc, char* argv[]);
144
145    /**
146       \brief has the commandline been parsed already
147
148       \return true if parse function has already been called
149
150       \since New in yat 0.5
151    */
152    bool parsed(void) const;
153
154    /**
155       @return Name of more; more specifically argv[0] is
156       stripped so only string after the last '/' remains.
157     */
158    std::string program_name(void) const;
159
160    /**
161       \brief Sort Options how they will appear in (help) output.
162
163       This function will sort the Options in alphabetical order. If
164       the Option has a long_name, it is used for the sorting;
165       otherwise, the short_name is used.
166
167       \since New in yat 0.7
168     */
169    void sort(void);
170
171    /**
172       Like sort(void) but using \a compare to sort Options.
173
174       The functor Compare must be a <a
175       href="http://www.sgi.com/tech/stl/BinaryPredicate.html">Binary
176       Predicate</a> with both argument types \c const \c Option*.
177
178       \since New in yat 0.7
179     */
180    template<class Compare>
181    void sort(Compare compare);
182
183    /**
184       \return something like "Try '<program_name()> --help' for
185       more information."
186     */
187    std::string try_help(void) const;
188
189  private:
190    friend std::ostream& operator<<(std::ostream& os, const CommandLine& cl);
191    bool is_long_option(std::string str) const;
192    bool is_short_option(std::string str) const;
193    void parse(std::vector<std::string>::iterator& first,
194               std::vector<std::string>::iterator& last);
195    void parse_long(std::vector<std::string>::iterator& first,
196                    std::vector<std::string>::iterator& last);
197    void parse_short(std::vector<std::string>::iterator& first,
198                     std::vector<std::string>::iterator& last);
199    void parse_free_arg(std::vector<std::string>::iterator& first,
200                        std::vector<std::string>::iterator& last);
201    std::string description_;
202    std::vector<std::string> free_arg_;
203    size_t free_arg_max_;
204    std::vector<Option*> options_;
205    std::map<char, Option*> short_options_;
206    std::map<std::string, Option*> long_options_;
207    bool parsed_;
208    std::string program_name_;
209
210    // use cond to make doxygen ignore this privat class
211    /// \cond IGNORE_DOXYGEN
212    struct OptionCompare
213    {
214      bool operator()(const Option*, const Option*) const;
215    };
216    /// \endcond
217
218  };
219
220  /**
221     \brief CommandLine output operator
222
223     A typical output may look like this
224     \verbatim
225     Available options are:
226     -h, --help      display this help and exit
227     -v, --verbose   explain what is being done
228     \endverbatim
229     The output starts with a descriptive line such as "Available
230     options are:" (default) that can be set in constructor. Then follows the
231     options described in the order they were added to
232     Commandline. Each Option is described according to
233     Option::print(void) function.
234     \see OptionHelp
235
236     \relates CommandLine
237  */
238  std::ostream& operator<<(std::ostream&, const CommandLine&);
239
240  template<class Compare>
241  void CommandLine::sort(Compare compare)
242  {
243    std::sort(options_.begin(), options_.end(), compare);
244  }
245
246}}} // end of namespace utility, yat, and theplu
247
248#endif
Note: See TracBrowser for help on using the repository browser.