KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > cli > HelpFormatter


1 /*
2  * $Header: /home/cvs/jakarta-commons-sandbox/cli/src/java/org/apache/commons/cli/CommandLine.java,v 1.4 2002/06/06 22:32:37 bayard Exp $
3  * $Revision: 1.4 $
4  * $Date: 2002/06/06 22:32:37 $
5  *
6  * ====================================================================
7  *
8  * The Apache Software License, Version 1.1
9  *
10  * Copyright (c) 1999-2001 The Apache Software Foundation. All rights
11  * reserved.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  *
17  * 1. Redistributions of source code must retain the above copyright
18  * notice, this list of conditions and the following disclaimer.
19  *
20  * 2. Redistributions in binary form must reproduce the above copyright
21  * notice, this list of conditions and the following disclaimer in
22  * the documentation and/or other materials provided with the
23  * distribution.
24  *
25  * 3. The end-user documentation included with the redistribution, if
26  * any, must include the following acknowlegement:
27  * "This product includes software developed by the
28  * Apache Software Foundation (http://www.apache.org/)."
29  * Alternately, this acknowlegement may appear in the software itself,
30  * if and wherever such third-party acknowlegements normally appear.
31  *
32  * 4. The names "The Jakarta Project", "Commons", and "Apache Software
33  * Foundation" must not be used to endorse or promote products derived
34  * from this software without prior written permission. For written
35  * permission, please contact apache@apache.org.
36  *
37  * 5. Products derived from this software may not be called "Apache"
38  * nor may "Apache" appear in their names without prior written
39  * permission of the Apache Group.
40  *
41  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  * ====================================================================
54  *
55  * This software consists of voluntary contributions made by many
56  * individuals on behalf of the Apache Software Foundation. For more
57  * information on the Apache Software Foundation, please see
58  * <http://www.apache.org/>.
59  *
60  */

61
62 package org.apache.commons.cli;
63
64 import java.io.PrintWriter JavaDoc;
65 import java.util.ArrayList JavaDoc;
66 import java.util.Collection JavaDoc;
67 import java.util.Collections JavaDoc;
68 import java.util.Comparator JavaDoc;
69 import java.util.Iterator JavaDoc;
70 import java.util.List JavaDoc;
71
72 /**
73  * A formatter of help messages for the current command line options
74  *
75  * @author Slawek Zachcial
76  * @author John Keyes (john at integralsource.com)
77  **/

78 public class HelpFormatter
79 {
80    // --------------------------------------------------------------- Constants
81

82    public static final int DEFAULT_WIDTH = 74;
83    public static final int DEFAULT_LEFT_PAD = 1;
84    public static final int DEFAULT_DESC_PAD = 3;
85    public static final String JavaDoc DEFAULT_SYNTAX_PREFIX = "usage: ";
86    public static final String JavaDoc DEFAULT_OPT_PREFIX = "-";
87    public static final String JavaDoc DEFAULT_LONG_OPT_PREFIX = "--";
88    public static final String JavaDoc DEFAULT_ARG_NAME = "arg";
89
90    // ------------------------------------------------------------------ Static
91

92    // -------------------------------------------------------------- Attributes
93

94    public int defaultWidth;
95    public int defaultLeftPad;
96    public int defaultDescPad;
97    public String JavaDoc defaultSyntaxPrefix;
98    public String JavaDoc defaultNewLine;
99    public String JavaDoc defaultOptPrefix;
100    public String JavaDoc defaultLongOptPrefix;
101    public String JavaDoc defaultArgName;
102
103    // ------------------------------------------------------------ Constructors
104
public HelpFormatter()
105    {
106       defaultWidth = DEFAULT_WIDTH;
107       defaultLeftPad = DEFAULT_LEFT_PAD;
108       defaultDescPad = DEFAULT_DESC_PAD;
109       defaultSyntaxPrefix = DEFAULT_SYNTAX_PREFIX;
110       defaultNewLine = System.getProperty("line.separator");
111       defaultOptPrefix = DEFAULT_OPT_PREFIX;
112       defaultLongOptPrefix = DEFAULT_LONG_OPT_PREFIX;
113       defaultArgName = DEFAULT_ARG_NAME;
114    }
115
116    // ------------------------------------------------------------------ Public
117

118    public void printHelp( String JavaDoc cmdLineSyntax,
119                           Options options )
120    {
121        printHelp( defaultWidth, cmdLineSyntax, null, options, null, false );
122    }
123
124    public void printHelp( String JavaDoc cmdLineSyntax,
125                           Options options,
126                           boolean autoUsage )
127    {
128        printHelp( defaultWidth, cmdLineSyntax, null, options, null, autoUsage );
129    }
130
131    public void printHelp( String JavaDoc cmdLineSyntax,
132                           String JavaDoc header,
133                           Options options,
134                           String JavaDoc footer )
135    {
136        printHelp( cmdLineSyntax, header, options, footer, false );
137    }
138
139    public void printHelp( String JavaDoc cmdLineSyntax,
140                           String JavaDoc header,
141                           Options options,
142                           String JavaDoc footer,
143                           boolean autoUsage )
144    {
145       printHelp(defaultWidth, cmdLineSyntax, header, options, footer, autoUsage );
146    }
147    
148    public void printHelp( int width,
149                           String JavaDoc cmdLineSyntax,
150                           String JavaDoc header,
151                           Options options,
152                           String JavaDoc footer )
153    {
154        printHelp( width, cmdLineSyntax, header, options, footer, false );
155    }
156
157    public void printHelp( int width,
158                           String JavaDoc cmdLineSyntax,
159                           String JavaDoc header,
160                           Options options,
161                           String JavaDoc footer,
162                           boolean autoUsage )
163    {
164       PrintWriter JavaDoc pw = new PrintWriter JavaDoc(System.out);
165       printHelp( pw, width, cmdLineSyntax, header,
166                  options, defaultLeftPad, defaultDescPad, footer, autoUsage );
167       pw.flush();
168    }
169    public void printHelp( PrintWriter JavaDoc pw,
170                           int width,
171                           String JavaDoc cmdLineSyntax,
172                           String JavaDoc header,
173                           Options options,
174                           int leftPad,
175                           int descPad,
176                           String JavaDoc footer )
177    throws IllegalArgumentException JavaDoc
178    {
179        printHelp( pw, width, cmdLineSyntax, header, options, leftPad, descPad, footer, false );
180    }
181
182    public void printHelp( PrintWriter JavaDoc pw,
183                           int width,
184                           String JavaDoc cmdLineSyntax,
185                           String JavaDoc header,
186                           Options options,
187                           int leftPad,
188                           int descPad,
189                           String JavaDoc footer,
190                           boolean autoUsage )
191       throws IllegalArgumentException JavaDoc
192    {
193       if ( cmdLineSyntax == null || cmdLineSyntax.length() == 0 )
194       {
195          throw new IllegalArgumentException JavaDoc("cmdLineSyntax not provided");
196       }
197
198       if ( autoUsage ) {
199           printUsage( pw, width, cmdLineSyntax, options );
200       }
201       else {
202           printUsage( pw, width, cmdLineSyntax );
203       }
204
205       if ( header != null && header.trim().length() > 0 )
206       {
207          printWrapped( pw, width, header );
208       }
209       printOptions( pw, width, options, leftPad, descPad );
210       if ( footer != null && footer.trim().length() > 0 )
211       {
212          printWrapped( pw, width, footer );
213       }
214    }
215
216    /**
217     * <p>Prints the usage statement for the specified application.</p>
218     *
219     * @param pw The PrintWriter to print the usage statement
220     * @param width ??
221     * @param appName The application name
222     * @param options The command line Options
223     *
224     */

225    public void printUsage( PrintWriter JavaDoc pw, int width, String JavaDoc app, Options options )
226    {
227        // initialise the string buffer
228
StringBuffer JavaDoc buff = new StringBuffer JavaDoc( defaultSyntaxPrefix ).append( app ).append( " " );
229        
230        // create a list for processed option groups
231
ArrayList JavaDoc list = new ArrayList JavaDoc();
232
233        // temp variable
234
Option option;
235
236        // iterate over the options
237
for ( Iterator JavaDoc i = options.getOptions().iterator(); i.hasNext(); )
238        {
239            // get the next Option
240
option = (Option) i.next();
241
242            // check if the option is part of an OptionGroup
243
OptionGroup group = options.getOptionGroup( option );
244
245            // if the option is part of a group and the group has not already
246
// been processed
247
if( group != null && !list.contains(group)) {
248
249                // add the group to the processed list
250
list.add( group );
251
252                // get the names of the options from the OptionGroup
253
Collection JavaDoc names = group.getNames();
254
255                buff.append( "[" );
256
257                // for each option in the OptionGroup
258
for( Iterator JavaDoc iter = names.iterator(); iter.hasNext(); ) {
259                    buff.append( iter.next() );
260                    if( iter.hasNext() ) {
261                        buff.append( " | " );
262                    }
263                }
264                buff.append( "]" );
265            }
266            // if the Option is not part of an OptionGroup
267
else {
268                // if the Option is not a required option
269
if( !option.isRequired() ) {
270                    buff.append( "[" );
271                }
272                
273                if( !" ".equals( option.getOpt() ) ) {
274                    buff.append( "-" ).append( option.getOpt() );
275                }
276                else {
277                    buff.append( "--" ).append( option.getLongOpt() );
278                }
279
280                if( option.hasArg() ){
281                    buff.append( " " );
282                }
283
284                // if the Option has a value
285
if( option.hasArg() ) {
286                    buff.append( option.getArgName() );
287                }
288
289                // if the Option is not a required option
290
if( !option.isRequired() ) {
291                    buff.append( "]" );
292                }
293                buff.append( " " );
294            }
295        }
296
297        // call printWrapped
298
printWrapped( pw, width, buff.toString().indexOf(' ')+1,
299                      buff.toString() );
300    }
301
302    public void printUsage( PrintWriter JavaDoc pw, int width, String JavaDoc cmdLineSyntax )
303    {
304       int argPos = cmdLineSyntax.indexOf(' ') + 1;
305       printWrapped(pw, width, defaultSyntaxPrefix.length() + argPos,
306                    defaultSyntaxPrefix + cmdLineSyntax);
307    }
308
309    public void printOptions( PrintWriter JavaDoc pw, int width, Options options, int leftPad, int descPad )
310    {
311       StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
312       renderOptions(sb, width, options, leftPad, descPad);
313       pw.println(sb.toString());
314    }
315
316    public void printWrapped( PrintWriter JavaDoc pw, int width, String JavaDoc text )
317    {
318       printWrapped(pw, width, 0, text);
319    }
320
321    public void printWrapped( PrintWriter JavaDoc pw, int width, int nextLineTabStop, String JavaDoc text )
322    {
323       StringBuffer JavaDoc sb = new StringBuffer JavaDoc(text.length());
324       renderWrappedText(sb, width, nextLineTabStop, text);
325       pw.println(sb.toString());
326    }
327
328    // --------------------------------------------------------------- Protected
329

330    protected StringBuffer JavaDoc renderOptions( StringBuffer JavaDoc sb,
331                                          int width,
332                                          Options options,
333                                          int leftPad,
334                                          int descPad )
335    {
336       final String JavaDoc lpad = createPadding(leftPad);
337       final String JavaDoc dpad = createPadding(descPad);
338
339       //first create list containing only <lpad>-a,--aaa where -a is opt and --aaa is
340
//long opt; in parallel look for the longest opt string
341
//this list will be then used to sort options ascending
342
int max = 0;
343       StringBuffer JavaDoc optBuf;
344       List JavaDoc prefixList = new ArrayList JavaDoc();
345       Option option;
346       List JavaDoc optList = options.helpOptions();
347       Collections.sort( optList, new StringBufferComparator() );
348       for ( Iterator JavaDoc i = optList.iterator(); i.hasNext(); )
349       {
350          option = (Option) i.next();
351          optBuf = new StringBuffer JavaDoc(8);
352
353          if (option.getOpt().equals(" "))
354          {
355              optBuf.append(lpad).append(" " + defaultLongOptPrefix).append(option.getLongOpt());
356          }
357          else
358          {
359              optBuf.append(lpad).append(defaultOptPrefix).append(option.getOpt());
360              if ( option.hasLongOpt() )
361              {
362                 optBuf.append(',').append(defaultLongOptPrefix).append(option.getLongOpt());
363              }
364
365          }
366
367          if( option.hasArg() ) {
368              if( option.hasArgName() ) {
369                  optBuf.append(" <").append( option.getArgName() ).append( '>' );
370              }
371              else {
372                  optBuf.append(' ');
373              }
374          }
375
376          prefixList.add(optBuf);
377          max = optBuf.length() > max ? optBuf.length() : max;
378       }
379       int x = 0;
380       for ( Iterator JavaDoc i = optList.iterator(); i.hasNext(); )
381       {
382          option = (Option) i.next();
383          optBuf = new StringBuffer JavaDoc( prefixList.get( x++ ).toString() );
384
385          if ( optBuf.length() < max )
386          {
387              optBuf.append(createPadding(max - optBuf.length()));
388          }
389          optBuf.append( dpad );
390          
391          int nextLineTabStop = max + descPad;
392          renderWrappedText(sb, width, nextLineTabStop,
393                            optBuf.append(option.getDescription()).toString());
394          if ( i.hasNext() )
395          {
396              sb.append(defaultNewLine);
397          }
398       }
399
400       return sb;
401    }
402
403    protected StringBuffer JavaDoc renderWrappedText( StringBuffer JavaDoc sb,
404                                              int width,
405                                              int nextLineTabStop,
406                                              String JavaDoc text )
407    {
408       int pos = findWrapPos( text, width, 0);
409       if ( pos == -1 )
410       {
411          sb.append(rtrim(text));
412          return sb;
413       }
414       else
415       {
416          sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
417       }
418
419       //all following lines must be padded with nextLineTabStop space characters
420
final String JavaDoc padding = createPadding(nextLineTabStop);
421
422       while ( true )
423       {
424          text = padding + text.substring(pos).trim();
425          pos = findWrapPos( text, width, nextLineTabStop );
426          if ( pos == -1 )
427          {
428             sb.append(text);
429             return sb;
430          }
431
432          sb.append(rtrim(text.substring(0, pos))).append(defaultNewLine);
433       }
434
435    }
436
437    /**
438     * Finds the next text wrap position after <code>startPos</code> for the text
439     * in <code>sb</code> with the column width <code>width</code>.
440     * The wrap point is the last postion before startPos+width having a whitespace
441     * character (space, \n, \r).
442     *
443     * @param sb text to be analyzed
444     * @param width width of the wrapped text
445     * @param startPos position from which to start the lookup whitespace character
446     * @return postion on which the text must be wrapped or -1 if the wrap position is at the end
447     * of the text
448     */

449    protected int findWrapPos( String JavaDoc text, int width, int startPos )
450    {
451       int pos = -1;
452       // the line ends before the max wrap pos or a new line char found
453
if ( ((pos = text.indexOf('\n', startPos)) != -1 && pos <= width) ||
454            ((pos = text.indexOf('\t', startPos)) != -1 && pos <= width) )
455       {
456          return pos;
457       }
458       else if ( (startPos + width) >= text.length() )
459       {
460          return -1;
461       }
462
463       //look for the last whitespace character before startPos+width
464
pos = startPos + width;
465       char c;
466       while ( pos >= startPos && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r' )
467       {
468          --pos;
469       }
470       //if we found it - just return
471
if ( pos > startPos )
472       {
473          return pos;
474       }
475       else
476       {
477          //must look for the first whitespace chearacter after startPos + width
478
pos = startPos + width;
479          while ( pos <= text.length() && (c = text.charAt(pos)) != ' ' && c != '\n' && c != '\r' )
480          {
481             ++pos;
482          }
483          return pos == text.length() ? -1 : pos;
484       }
485    }
486
487    protected String JavaDoc createPadding(int len)
488    {
489       StringBuffer JavaDoc sb = new StringBuffer JavaDoc(len);
490       for ( int i = 0; i < len; ++i )
491       {
492          sb.append(' ');
493       }
494       return sb.toString();
495    }
496
497    protected String JavaDoc rtrim( String JavaDoc s )
498    {
499       if ( s == null || s.length() == 0 )
500       {
501          return s;
502       }
503
504       int pos = s.length();
505       while ( pos >= 0 && Character.isWhitespace(s.charAt(pos-1)) )
506       {
507          --pos;
508       }
509       return s.substring(0, pos);
510    }
511
512    // ------------------------------------------------------- Package protected
513

514    // ----------------------------------------------------------------- Private
515

516    // ----------------------------------------------------------- Inner classes
517

518     private static class StringBufferComparator
519     implements Comparator JavaDoc
520     {
521         public int compare( Object JavaDoc o1, Object JavaDoc o2 )
522         {
523             String JavaDoc str1 = stripPrefix(o1.toString());
524             String JavaDoc str2 = stripPrefix(o2.toString());
525             return (str1.compareTo(str2));
526         }
527
528         private String JavaDoc stripPrefix(String JavaDoc strOption)
529         {
530             // Strip any leading '-' characters
531
int iStartIndex = strOption.lastIndexOf('-');
532             if (iStartIndex == -1)
533             {
534               iStartIndex = 0;
535             }
536             return strOption.substring(iStartIndex);
537
538         }
539     }
540 }
541
Popular Tags