1 /***************************************************************************
2                                 commandline.h
3                                W. Michael Brown
4                              -------------------
5 
6   Command line parsing stuff..
7 
8     begin                : Sun Jun 11 2003
9     copyright            : (C) 2003 by W. Michael Brown
10     email                : mbrown@nirvana.unm.edu
11  ***************************************************************************/
12 
13 #ifndef COMMANDLINE_H
14 #define COMMANDLINE_H
15 
16 #include "error.h"
17 #include "misc.h"
18 #include <map>
19 #include <vector>
20 #include <string>
21 #include <stdlib.h>
22 #include <iostream>
23 using namespace std;
24 
25 /// Parsing of command-line parameters and automatic man page generation
26 /** Allows manditory and optional command line arguments to be specified along
27   * with parameters set using flags. For arguments that do not require flags,
28   * a space char is used to set the flag. To specify the command line:
29   *
30   *   foo input_file output_file -t signed_number [-o]
31   *
32   * \verbatim CommandLine cl;
33   cl.addmanditory(' ',2);
34   cl.addargname(' ',"input_file"); cl.addargname(' ',"output_file");
35   cl.addsigned('t',1,1);
36   cl.addargname('t',"arg_name");
37   cl.adddescription('t',"Manditory parameter allowing signed_numbers");
38   cl.add('o',0);
39   \endverbatim
40   * To instead specify that the outputfile is an optional argument:
41   * \verbatim cl.addmanditory(' ',2,1) \endverbatim
42   *
43   * A help flag can also be set which does not require other command line
44   * arguments to be set
45   *
46   * When the commandline is parsed, it is asserted that all manditory arguments
47   * and flags are set, that each flag is set with the correct number of
48   * parameters, and that no unknown flags have been set.
49   *
50   * One can check whether or not optional flags have been set using set() or
51   * the [] operator:
52   * \verbatim cl.set('o')  <-->  cl['o']  \endverbatim
53   *
54   * Man pages can be generated automatically by adding chapters. The SYNOPSIS
55   * and description of commandline arguments and flags is generated
56   * automatically. Examples of chapters that are consistently used are
57   * NAME, VERSION, DESCRIPTION, PARAMETERS, USAGE, EXAMPLES, AUTHORS, BUGS,
58   * SEE ALSO.
59   *
60   * The following characters can be used for formatting in parameter
61   * descriptions and chapters:
62   * \verbatim
63   \t		tab
64   \n		forced newline
65   .TP		new paragraph (margin indented)
66   \\fB  all following text is bold
67   \\fI	all following text is italic
68   \\fR	all following text is regular
69   \endverbatim
70   *
71   * The arguments, flags and parameter_names are automatically formatted
72   * throughout the man page with bold and italic typeface.
73   **/
74 class CommandLine {
75  public:
76   CommandLine();
77   ~CommandLine();
78 
79   /// Add an optional argument which takes num parameters
80   /** \note Use ' ' for n to specify an argument with no flag
81     * \param n flag used to pass arguments (i.e. -f)
82     * \param num the number of arguments that must be specified after flag */
83   void add(char n, unsigned num);
84   /// Add a manditory argument which takes num parameters
85   /** \sa add() **/
86   void addmanditory(char n, unsigned num);
87   /// Add a flag which can take signed numbers as parameters
88   /** \sa add() **/
89   void addsigned(char n, unsigned num);
90 
91  	/// Add an optional flag with minimum and maximum number of args
92   /** \sa add() **/
93 	void add(char n, unsigned num, unsigned man_num);
94  	/// Add a manditory flag with minimum and maximum number of args
95   /** \sa add() **/
96   void addmanditory(char n, unsigned num, unsigned man_num);
97  	/// Add a flag with minimum and maximum number of args that takes signed nums
98   /** \sa add() **/
99   void addsigned(char n, unsigned num, unsigned man_num);
100 
101   /// Add a help argument (does not require other manditory arguments be set)
102   /** \sa add() **/
103   void addhelp(char n, unsigned num);
104 
105   /// Specify the names for arguments in the synopsis (for man page)
106   /** The names can be added one by one in the order of the flag parameters **/
107   void addargname(char n, const string &an);
108   /// Specify the names for arguments in the synopsis (for man page)
109   void addargnames(char n, unsigned num, const string args[]);
110   /// Specify the description for an argument (for the man page SYNOPSIS)
111   /** See the class description for formating characters **/
112   void adddescription(char n, const string &d);
113   /// Specify the description for an argument (for the man page SYNOPSIS)
114   /** See the class description for formating characters **/
115   void adddescription(char n, unsigned num, const string d[]);
116   /// Add a man page chapter with title 'name'
117   void addtoman_chapter(const string &name,const string &body);
118   /// Add a man page chapter with title 'name'
119   void addtoman_chapter(const string &name,unsigned line_count,
120   											const string body[]);
121 
122   /// Returns the number of arguments that are not flags (char n=' ')
123   unsigned argsize();
124   /// Returns the number of parameters passed for a given flag
125   unsigned argsize(char n);
126   /// Returns true if the optional flag was set on the commandline
127   bool set(char n);
128   /// Returns true if the optional flag was set on the commandline
129   bool operator [](char n);
130 
131   /// Force a parameter to be unset
132   void unset(char n);
133 
134   /// Return flag parameter or argument as a cstring (0-based index)
135   char *arg(char n, unsigned num);
136   /// Return flag parameter or argument as a integer (0-based index)
137   int argint(char n, unsigned num);
138   /// Return flag parameter or argument as a double (0-based index)
139   double argdouble(char n, unsigned num);
140   /// Return flag parameter or argument as a string (0-based index)
141   string argstring(char n, unsigned num);
142 
143   /// Parse the command line arguments
144   bool parse(int argc, char* argv[], Error *error);
145 
146   /// Return the program name
147   string program_name();
148   /// Return a string with the entire commandline as entered
149   string full_command_line();
150   /// Write out a man_page
151 	void write_man_page(ostream & out, const string &version,
152  											const string &header);
153 
154   /// Advanced writing of man page
155   void writeman_chapter(ostream &out, const string &name, const string &bold,
156 												const string &italic, const string &regular);
157 
158   /// Return a string with all of the options in a man page synopsis format
159   string format_synopsis(const string &bold, const string &italic,
160   											 const string &regular);
161   /// Write a synopsis in plain text format fitted to a given column width
162   void write_text_synopsis(ostream &out, unsigned column_width);
163 
164  private:
165   string full_line;
166   void check(char n);
167   // Returns true if parameters have been set with optional arguments
168   bool optargparams();
169 
170   class Parameter;
171   map<char,Parameter> parameters;
172 
173   bool help_set;		// True if there is a parameter for getting help
174   char help_param;  // Parameter for help
175 
176   // Stuff for man page
177   string progname; // The name for the program (argv[0])
178   unsigned man_numchapters; // Number of chapters in man page
179   map<string,vector<string> > man_chapters;
180   map<unsigned, string> manchapter_order;
181 
182   // Format a parameter as a string with argument names
183   string format_parameter(char param, const string &bold, const string &italic,
184 													const string &regular);
185   // Formats the strings in input for a man page by replacing newlines and
186   // adding bold and italic fonts to parameters and arguments respectively
187 	vector<string> man_format(const vector<string> &input, const string &bold,
188 														const string &italic, const string &regular);
189 
190 };
191 
192 // This class is for internal use within CommandLine
193 class CommandLine::Parameter {
194  public:
195   friend class CommandLine;
196   Parameter();
197   ~Parameter();
198 
199  private:
200   unsigned num_args;       // Maximum number of arguments for the parameter
201   unsigned manditory_args; // Minimum number of arguments for the parameter
202   bool manditory;			     // This parameter MUST be set
203 
204   bool dash;  				     // Allow for signed numbers (dashes in args)
205 
206   bool set;                // This parameter has been set
207   vector<char *> args;
208 
209   // Strings for man page description
210   vector<string> argnames; // Names for each argument to the parameter
211   vector<string> description; // Description for how to set this parameter
212 };
213 
214 #endif
215