source: trunk/lib/yat/CommandLine.h @ 1064

Last change on this file since 1064 was 1064, checked in by Peter Johansson, 11 years ago

sort options alphabetically. refs #307

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