Source for net.dpml.cli.util.HelpFormatter

   1: /*
   2:  * Copyright 2003-2005 The Apache Software Foundation
   3:  * Copyright 2005 Stephen McConnell
   4:  *
   5:  * Licensed under the Apache License, Version 2.0 (the "License");
   6:  * you may not use this file except in compliance with the License.
   7:  * You may obtain a copy of the License at
   8:  *
   9:  *     http://www.apache.org/licenses/LICENSE-2.0
  10:  *
  11:  * Unless required by applicable law or agreed to in writing, software
  12:  * distributed under the License is distributed on an "AS IS" BASIS,
  13:  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14:  * See the License for the specific language governing permissions and
  15:  * limitations under the License.
  16:  */
  17: package net.dpml.cli.util;
  18: 
  19: import java.io.IOException;
  20: import java.io.PrintWriter;
  21: import java.io.Writer;
  22: 
  23: import java.util.ArrayList;
  24: import java.util.Collections;
  25: import java.util.Comparator;
  26: import java.util.HashSet;
  27: import java.util.Iterator;
  28: import java.util.List;
  29: import java.util.Set;
  30: 
  31: import net.dpml.cli.DisplaySetting;
  32: import net.dpml.cli.Group;
  33: import net.dpml.cli.HelpLine;
  34: import net.dpml.cli.Option;
  35: import net.dpml.cli.OptionException;
  36: import net.dpml.cli.resource.ResourceConstants;
  37: import net.dpml.cli.resource.ResourceHelper;
  38: 
  39: /**
  40:  * Presents on screen help based on the application's Options
  41:  *
  42:  * @author <a href="@PUBLISHER-URL@">@PUBLISHER-NAME@</a>
  43:  * @version @PROJECT-VERSION@
  44:  */
  45: public class HelpFormatter 
  46: {
  47:     /**
  48:      * The default screen width
  49:      */
  50:     public static final int DEFAULT_FULL_WIDTH = 80;
  51: 
  52:     /**
  53:      * The default minimum description width.
  54:      */
  55:     public static final int DEFAULT_DESCRIPTION_WIDTH = -1;
  56: 
  57:     /**
  58:      * The default screen furniture left of screen
  59:      */
  60:     public static final String DEFAULT_GUTTER_LEFT = "";
  61: 
  62:     /**
  63:      * The default screen furniture right of screen
  64:      */
  65:     public static final String DEFAULT_GUTTER_CENTER = "    ";
  66: 
  67:     /**
  68:      * The default screen furniture between columns
  69:      */
  70:     public static final String DEFAULT_GUTTER_RIGHT = "";
  71: 
  72:     /**
  73:      * The default DisplaySettings used to select the elements to display in the
  74:      * displayed line of full usage information.
  75:      *
  76:      * @see DisplaySetting
  77:      */
  78:     public static final Set DEFAULT_FULL_USAGE_SETTINGS;
  79: 
  80:     /**
  81:      * The default DisplaySettings used to select the elements of usage per help
  82:      * line in the main body of help
  83:      *
  84:      * @see DisplaySetting
  85:      */
  86:     public static final Set DEFAULT_LINE_USAGE_SETTINGS;
  87: 
  88:     /**
  89:      * The default DisplaySettings used to select the help lines in the main
  90:      * body of help
  91:      */
  92:     public static final Set DEFAULT_DISPLAY_USAGE_SETTINGS;
  93: 
  94:     static 
  95:     {
  96:         final Set fullUsage = new HashSet( DisplaySetting.ALL );
  97:         fullUsage.remove( DisplaySetting.DISPLAY_ALIASES );
  98:         fullUsage.remove( DisplaySetting.DISPLAY_GROUP_NAME );
  99:         DEFAULT_FULL_USAGE_SETTINGS = Collections.unmodifiableSet( fullUsage );
 100: 
 101:         final Set lineUsage = new HashSet();
 102:         lineUsage.add( DisplaySetting.DISPLAY_ALIASES );
 103:         lineUsage.add( DisplaySetting.DISPLAY_GROUP_NAME );
 104:         lineUsage.add( DisplaySetting.DISPLAY_PARENT_ARGUMENT );
 105:         DEFAULT_LINE_USAGE_SETTINGS = Collections.unmodifiableSet( lineUsage );
 106: 
 107:         final Set displayUsage = new HashSet( DisplaySetting.ALL );
 108:         displayUsage.remove( DisplaySetting.DISPLAY_PARENT_ARGUMENT );
 109:         DEFAULT_DISPLAY_USAGE_SETTINGS = Collections.unmodifiableSet( displayUsage );
 110:     }
 111: 
 112:     private Set m_fullUsageSettings = new HashSet( DEFAULT_FULL_USAGE_SETTINGS );
 113:     private Set m_lineUsageSettings = new HashSet( DEFAULT_LINE_USAGE_SETTINGS );
 114:     private Set m_displaySettings = new HashSet( DEFAULT_DISPLAY_USAGE_SETTINGS );
 115:     private OptionException m_exception = null;
 116:     private Group m_group;
 117:     private Comparator m_comparator = null;
 118:     private String m_divider = null;
 119:     private String m_header = null;
 120:     private String m_footer = null;
 121:     private String m_shellCommand = "";
 122:     private PrintWriter m_out = new PrintWriter( System.out );
 123: 
 124:     //or should this default to .err?
 125:     private final String m_gutterLeft;
 126:     private final String m_gutterCenter;
 127:     private final String m_gutterRight;
 128:     private final int m_pageWidth;
 129:     private final int m_descriptionWidth;
 130: 
 131:     /**
 132:      * Creates a new HelpFormatter using the defaults
 133:      */
 134:     public HelpFormatter()
 135:     {
 136:         this( 
 137:           DEFAULT_GUTTER_LEFT, DEFAULT_GUTTER_CENTER, DEFAULT_GUTTER_RIGHT, 
 138:           DEFAULT_FULL_WIDTH, DEFAULT_DESCRIPTION_WIDTH );
 139:     }
 140: 
 141:     /**
 142:      * Creates a new HelpFormatter using the specified parameters
 143:      * @param gutterLeft the string marking left of screen
 144:      * @param gutterCenter the string marking center of screen
 145:      * @param gutterRight the string marking right of screen
 146:      * @param fullWidth the width of the screen
 147:      */
 148:     public HelpFormatter(
 149:       final String gutterLeft, final String gutterCenter, final String gutterRight, 
 150:       final int fullWidth )
 151:     {
 152:         this( gutterLeft, gutterCenter, gutterRight, fullWidth, DEFAULT_DESCRIPTION_WIDTH );
 153:     }
 154:     
 155:     /**
 156:      * Creates a new HelpFormatter using the specified parameters
 157:      * @param gutterLeft the string marking left of screen
 158:      * @param gutterCenter the string marking center of screen
 159:      * @param gutterRight the string marking right of screen
 160:      * @param fullWidth the width of the screen
 161:      * @param descriptionWidth the minimum description width
 162:      */
 163:     public HelpFormatter(
 164:       final String gutterLeft, final String gutterCenter, final String gutterRight, 
 165:       final int fullWidth, final int descriptionWidth )
 166:     {
 167:         // default the left gutter to empty string
 168:         if( null == gutterLeft )
 169:         {
 170:             m_gutterLeft = DEFAULT_GUTTER_LEFT;
 171:         }
 172:         else
 173:         {
 174:             m_gutterLeft = gutterLeft;
 175:         }
 176:         
 177:         if( null == gutterCenter )
 178:         {
 179:             m_gutterCenter = DEFAULT_GUTTER_CENTER;
 180:         }
 181:         else
 182:         {
 183:             m_gutterCenter = gutterCenter;
 184:         }
 185:         
 186:         if( null == gutterRight )
 187:         {
 188:             m_gutterRight = DEFAULT_GUTTER_RIGHT;
 189:         }
 190:         else
 191:         {
 192:             m_gutterRight = gutterRight;
 193:         }
 194: 
 195:         m_descriptionWidth = descriptionWidth;
 196:         
 197:         // calculate the available page width
 198:         m_pageWidth = fullWidth - m_gutterLeft.length() - m_gutterRight.length();
 199: 
 200:         // check available page width is valid
 201:         int availableWidth = fullWidth - m_pageWidth + m_gutterCenter.length();
 202: 
 203:         if( availableWidth < 2 )
 204:         {
 205:             throw new IllegalArgumentException(
 206:               ResourceHelper.getResourceHelper().getMessage(
 207:                 ResourceConstants.HELPFORMATTER_GUTTER_TOO_LONG ) );
 208:         }
 209:     }
 210: 
 211:     /**
 212:      * Prints the Option help.
 213:      * @throws IOException if an error occurs
 214:      */
 215:     public void print() throws IOException
 216:     {
 217:         printHeader();
 218:         printException();
 219:         printUsage();
 220:         printHelp();
 221:         printFooter();
 222:         m_out.flush();
 223:     }
 224: 
 225:     /**
 226:      * Prints any error message.
 227:      * @throws IOException if an error occurs
 228:      */
 229:     public void printException() throws IOException
 230:     {
 231:         if( m_exception != null )
 232:         {
 233:             printDivider();
 234:             printWrapped( m_exception.getMessage() );
 235:         }
 236:     }
 237: 
 238:     /**
 239:      * Prints detailed help per option.
 240:      * @throws IOException if an error occurs
 241:      */
 242:     public void printHelp() throws IOException
 243:     {
 244:         printDivider();
 245:         final Option option;
 246:         if( ( m_exception != null ) && ( m_exception.getOption() != null ) )
 247:         {
 248:             option = m_exception.getOption();
 249:         } 
 250:         else
 251:         {
 252:             option = m_group;
 253:         }
 254: 
 255:         // grab the HelpLines to display
 256:         final List helpLines = option.helpLines( 0, m_displaySettings, m_comparator );
 257: 
 258:         // calculate the maximum width of the usage strings
 259:         int usageWidth = 0;
 260: 
 261:         for( final Iterator i = helpLines.iterator(); i.hasNext();)
 262:         {
 263:             final HelpLine helpLine = (HelpLine) i.next();
 264:             final String usage = helpLine.usage( m_lineUsageSettings, m_comparator );
 265:             usageWidth = Math.max( usageWidth, usage.length() );
 266:         }
 267:         
 268:         //
 269:         // add check for an overriding description max width (needed in complex 
 270:         // usage scenarios)
 271:         //
 272:         
 273:         if( m_descriptionWidth > -1 )
 274:         {
 275:             int max = m_pageWidth - m_descriptionWidth;
 276:             if( usageWidth > max )
 277:             {
 278:                 usageWidth = max;
 279:             }
 280:         }
 281:         
 282:         // build a blank string to pad wrapped descriptions
 283:         final StringBuffer blankBuffer = new StringBuffer();
 284: 
 285:         for( int i = 0; i < usageWidth; i++ )
 286:         {
 287:             blankBuffer.append( ' ' );
 288:         }
 289: 
 290:         // determine the width available for descriptions
 291:         final int descriptionWidth = 
 292:           Math.max( 1, m_pageWidth - m_gutterCenter.length() - usageWidth );
 293: 
 294:         // display each HelpLine
 295:         for( final Iterator i = helpLines.iterator(); i.hasNext();)
 296:         {
 297:             // grab the HelpLine
 298:             final HelpLine helpLine = (HelpLine) i.next();
 299: 
 300:             // wrap the description
 301:             final List descList = wrap( helpLine.getDescription(), descriptionWidth );
 302:             final Iterator descriptionIterator = descList.iterator();
 303: 
 304:             // display usage + first line of description
 305:             printGutterLeft();
 306:             pad( helpLine.usage( m_lineUsageSettings, m_comparator ), usageWidth, m_out );
 307:             m_out.print( m_gutterCenter );
 308:             pad( (String) descriptionIterator.next(), descriptionWidth, m_out );
 309:             printGutterRight();
 310:             m_out.println();
 311: 
 312:             // display padding + remaining lines of description
 313:             while( descriptionIterator.hasNext() )
 314:             {
 315:                 printGutterLeft();
 316: 
 317:                 //pad(helpLine.getUsage(),usageWidth,m_out);
 318:                 m_out.print( blankBuffer );
 319:                 m_out.print( m_gutterCenter );
 320:                 pad( (String) descriptionIterator.next(), descriptionWidth, m_out );
 321:                 printGutterRight();
 322:                 m_out.println();
 323:             }
 324:         }
 325:         printDivider();
 326:     }
 327: 
 328:     /**
 329:      * Prints a single line of usage information (wrapping if necessary)
 330:      * @throws IOException if an error occurs
 331:      */
 332:     public void printUsage() throws IOException
 333:     {
 334:         printDivider();
 335:         final StringBuffer buffer = new StringBuffer( "Usage:\n" );
 336:         buffer.append( m_shellCommand ).append( ' ' );
 337:         String separator = getSeparator();
 338:         m_group.appendUsage( buffer, m_fullUsageSettings, m_comparator, separator );
 339:         printWrapped( buffer.toString() );
 340:     }
 341:     
 342:     private String getSeparator()
 343:     {
 344:         if( m_group.getMaximum() == 1 )
 345:         {
 346:             return " | ";
 347:         }
 348:         else
 349:         {
 350:             return " ";
 351:         }
 352:     }
 353: 
 354:     /**
 355:      * Prints a m_header string if necessary
 356:      * @throws IOException if an error occurs
 357:      */
 358:     public void printHeader() throws IOException
 359:     {
 360:         if( m_header != null )
 361:         {
 362:             printDivider();
 363:             printWrapped( m_header );
 364:         }
 365:     }
 366: 
 367:     /**
 368:      * Prints a m_footer string if necessary
 369:      * @throws IOException if an error occurs
 370:      */
 371:     public void printFooter() throws IOException
 372:     {
 373:         if( m_footer != null )
 374:         {
 375:             printWrapped( m_footer );
 376:             printDivider();
 377:         }
 378:     }
 379: 
 380:     /**
 381:      * Prints a string wrapped if necessary
 382:      * @param text the string to wrap
 383:      * @throws IOException if an error occurs
 384:      */
 385:     protected void printWrapped( final String text ) throws IOException
 386:     {
 387:         for( final Iterator i = wrap( text, m_pageWidth ).iterator(); i.hasNext();)
 388:         {
 389:             printGutterLeft();
 390:             pad( (String) i.next(), m_pageWidth, m_out );
 391:             printGutterRight();
 392:             m_out.println();
 393:         }
 394:     }
 395: 
 396:     /**
 397:      * Prints the left gutter string
 398:      */
 399:     public void printGutterLeft()
 400:     {
 401:         if( m_gutterLeft != null )
 402:         {
 403:             m_out.print( m_gutterLeft );
 404:         }
 405:     }
 406: 
 407:     /**
 408:      * Prints the right gutter string
 409:      */
 410:     public void printGutterRight()
 411:     {
 412:         if( m_gutterRight != null )
 413:         {
 414:             m_out.print( m_gutterRight );
 415:         }
 416:     }
 417: 
 418:     /**
 419:      * Prints the m_divider text
 420:      */
 421:     public void printDivider()
 422:     {
 423:         if( m_divider != null )
 424:         {
 425:             m_out.println( m_divider );
 426:         }
 427:     }
 428: 
 429:    /**
 430:     * Pad the supplied string.
 431:     * @param text the text to pad
 432:     * @param width the padding width
 433:     * @param writer the writer
 434:     * @exception IOException if an I/O error occurs
 435:     */
 436:     protected static void pad(
 437:       final String text, final int width, final Writer writer )
 438:       throws IOException
 439:     {
 440:         final int left;
 441: 
 442:         // write the text and record how many characters written
 443:         if ( text == null )
 444:         {
 445:             left = 0;
 446:         }
 447:         else
 448:         {
 449:             writer.write( text );
 450:             left = text.length();
 451:         }
 452: 
 453:         // pad remainder with spaces
 454:         for( int i = left; i < width; ++i )
 455:         {
 456:             writer.write( ' ' );
 457:         }
 458:     }
 459: 
 460:    /**
 461:     * Return a list of strings resulting from the wrapping of a supplied
 462:     * target string.
 463:     * @param text the target string to wrap
 464:     * @param width the wrappping width
 465:     * @return the list of wrapped fragments
 466:     */
 467:     protected static List wrap( final String text, final int width ) 
 468:     {
 469:         // check for valid width
 470:         if( width < 1 ) 
 471:         {
 472:             throw new IllegalArgumentException(
 473:               ResourceHelper.getResourceHelper().getMessage(
 474:                 ResourceConstants.HELPFORMATTER_WIDTH_TOO_NARROW,
 475:                 new Object[]{new Integer( width )} ) );
 476:         }
 477: 
 478:         // handle degenerate case
 479:         if( text == null )
 480:         {
 481:             return Collections.singletonList( "" );
 482:         }
 483: 
 484:         final List lines = new ArrayList();
 485:         final char[] chars = text.toCharArray();
 486:         int left = 0;
 487: 
 488:         // for each character in the string
 489:         while( left < chars.length )
 490:         {
 491:             // sync left and right indeces
 492:             int right = left;
 493: 
 494:             // move right until we run m_out of characters, width or find a newline
 495:             while( 
 496:               ( right < chars.length ) 
 497:               && ( chars[right] != '\n' ) 
 498:               && ( right < ( left + width + 1 ) ) ) 
 499:             {
 500:                 right++;
 501:             }
 502: 
 503:             // if a newline was found
 504:             if( ( right < chars.length ) && ( chars[right] == '\n' ) )
 505:             {
 506:                 // record the substring
 507:                 final String line = new String( chars, left, right - left );
 508:                 lines.add( line );
 509: 
 510:                 // move to the end of the substring
 511:                 left = right + 1;
 512: 
 513:                 if( left == chars.length )
 514:                 {
 515:                     lines.add( "" );
 516:                 }
 517: 
 518:                 // restart the loop
 519:                 continue;
 520:             }
 521: 
 522:             // move to the next ideal wrap point 
 523:             right = ( left + width ) - 1;
 524: 
 525:             // if we have run m_out of characters
 526:             if( chars.length <= right )
 527:             {
 528:                 // record the substring
 529:                 final String line = new String( chars, left, chars.length - left );
 530:                 lines.add( line );
 531: 
 532:                 // abort the loop
 533:                 break;
 534:             }
 535: 
 536:             // back track the substring end until a space is found
 537:             while( ( right >= left ) && ( chars[right] != ' ' ) )
 538:             {
 539:                 right--;
 540:             }
 541: 
 542:             // if a space was found
 543:             if( right >= left ) 
 544:             {
 545:                 // record the substring to space
 546:                 final String line = new String( chars, left, right - left );
 547:                 lines.add( line );
 548: 
 549:                 // absorb all the spaces before next substring
 550:                 while( ( right < chars.length ) && ( chars[right] == ' ' ) )
 551:                 {
 552:                     right++;
 553:                 }
 554: 
 555:                 left = right;
 556: 
 557:                 // restart the loop
 558:                 continue;
 559:             }
 560: 
 561:             // move to the wrap position irrespective of spaces
 562:             right = Math.min( left + width, chars.length );
 563: 
 564:             // record the substring
 565:             final String line = new String( chars, left, right - left );
 566:             lines.add( line );
 567: 
 568:             // absorb any the spaces before next substring
 569:             while( ( right < chars.length ) && ( chars[right] == ' ' ) ) 
 570:             {
 571:                 right++;
 572:             }
 573: 
 574:             left = right;
 575:         }
 576: 
 577:         return lines;
 578:     }
 579: 
 580:     /**
 581:      * The Comparator to use when sorting Options
 582:      * @param comparator Comparator to use when sorting Options
 583:      */
 584:     public void setComparator( Comparator comparator ) 
 585:     {
 586:         m_comparator = comparator;
 587:     }
 588: 
 589:     /**
 590:      * The DisplaySettings used to select the help lines in the main body of
 591:      * help
 592:      *
 593:      * @param displaySettings the settings to use
 594:      * @see DisplaySetting
 595:      */
 596:     public void setDisplaySettings( Set displaySettings )
 597:     {
 598:         m_displaySettings = displaySettings;
 599:     }
 600: 
 601:     /**
 602:      * Sets the string to use as a m_divider between sections of help
 603:      * @param divider the dividing string
 604:      */
 605:     public void setDivider( String divider ) 
 606:     {
 607:         m_divider = divider;
 608:     }
 609: 
 610:     /**
 611:      * Sets the exception to document
 612:      * @param exception the exception that occured
 613:      */
 614:     public void setException( OptionException exception ) 
 615:     {
 616:         m_exception = exception;
 617:     }
 618: 
 619:     /**
 620:      * Sets the footer text of the help screen
 621:      * @param footer the footer text
 622:      */
 623:     public void setFooter( String footer )
 624:     {
 625:         m_footer = footer;
 626:     }
 627: 
 628:     /**
 629:      * The DisplaySettings used to select the elements to display in the
 630:      * displayed line of full usage information.
 631:      * @see DisplaySetting
 632:      * @param fullUsageSettings the full usage settings
 633:      */
 634:     public void setFullUsageSettings( Set fullUsageSettings )
 635:     {
 636:         m_fullUsageSettings = fullUsageSettings;
 637:     }
 638: 
 639:     /**
 640:      * Sets the Group of Options to document
 641:      * @param group the options to document
 642:      */
 643:     public void setGroup( Group group )
 644:     {
 645:         m_group = group;
 646:     }
 647: 
 648:     /**
 649:      * Sets the header text of the help screen
 650:      * @param header the m_footer text
 651:      */
 652:     public void setHeader( String header ) 
 653:     {
 654:         m_header = header;
 655:     }
 656: 
 657:     /**
 658:      * Sets the DisplaySettings used to select elements in the per helpline
 659:      * usage strings.
 660:      * @see DisplaySetting
 661:      * @param lineUsageSettings the DisplaySettings to use
 662:      */
 663:     public void setLineUsageSettings( Set lineUsageSettings ) 
 664:     {
 665:         m_lineUsageSettings = lineUsageSettings;
 666:     }
 667: 
 668:     /**
 669:      * Sets the command string used to invoke the application
 670:      * @param shellCommand the invocation command
 671:      */
 672:     public void setShellCommand( String shellCommand )
 673:     {
 674:         m_shellCommand = shellCommand;
 675:     }
 676: 
 677:     /**
 678:     * Return the comparator.
 679:      * @return the Comparator used to sort the Group
 680:      */
 681:     public Comparator getComparator() 
 682:     {
 683:         return m_comparator;
 684:     }
 685: 
 686:     /**
 687:      * Return the display settings.
 688:      * @return the DisplaySettings used to select HelpLines
 689:      */
 690:     public Set getDisplaySettings() 
 691:     {
 692:         return m_displaySettings;
 693:     }
 694: 
 695:     /**
 696:      * Return the divider.
 697:      * @return the String used as a horizontal section m_divider
 698:      */
 699:     public String getDivider() 
 700:     {
 701:         return m_divider;
 702:     }
 703: 
 704:     /**
 705:     * Return the option exception
 706:     * @return the Exception being documented by this HelpFormatter
 707:     */
 708:     public OptionException getException() 
 709:     {
 710:         return m_exception;
 711:     }
 712: 
 713:    /**
 714:     * Return the footer text.
 715:     * @return the help screen footer text
 716:     */
 717:     public String getFooter() 
 718:     {
 719:         return m_footer;
 720:     }
 721: 
 722:     /**
 723:      * Return the full usage display settings.
 724:      * @return the DisplaySettings used in the full usage string
 725:      */
 726:     public Set getFullUsageSettings() 
 727:     {
 728:         return m_fullUsageSettings;
 729:     }
 730: 
 731:    /**
 732:     * Return the group.
 733:     * @return the group documented by this HelpFormatter
 734:     */
 735:     public Group getGroup()
 736:     {
 737:         return m_group;
 738:     }
 739: 
 740:    /**
 741:     * Return the gutter center string.
 742:     * @return the String used as the central gutter
 743:     */
 744:     public String getGutterCenter() 
 745:     {
 746:         return m_gutterCenter;
 747:     }
 748: 
 749:    /**
 750:     * Return the gutter left string.
 751:     * @return the String used as the left gutter
 752:     */
 753:     public String getGutterLeft()
 754:     {
 755:         return m_gutterLeft;
 756:     }
 757: 
 758:    /**
 759:     * Return the gutter right string.
 760:     * @return the String used as the right gutter
 761:     */
 762:     public String getGutterRight() 
 763:     {
 764:         return m_gutterRight;
 765:     }
 766: 
 767:    /**
 768:     * Return the header string.
 769:     * @return the help screen header text
 770:     */
 771:     public String getHeader()
 772:     {
 773:         return m_header;
 774:     }
 775: 
 776:    /**
 777:     * Return the line usage settings.
 778:     * @return the DisplaySettings used in the per help line usage strings
 779:     */
 780:     public Set getLineUsageSettings() 
 781:     {
 782:         return m_lineUsageSettings;
 783:     }
 784: 
 785:    /**
 786:     * Return the page width.
 787:     * @return the width of the screen in characters
 788:     */
 789:     public int getPageWidth()
 790:     {
 791:         return m_pageWidth;
 792:     }
 793: 
 794:    /**
 795:     * Return the shell command.
 796:     * @return the command used to execute the application
 797:     */
 798:     public String getShellCommand() 
 799:     {
 800:         return m_shellCommand;
 801:     }
 802: 
 803:    /**
 804:     * Set the print writer.
 805:     * @param out the PrintWriter to write to
 806:     */
 807:     public void setPrintWriter( PrintWriter out ) 
 808:     {
 809:         m_out = out;
 810:     }
 811: 
 812:    /**
 813:     * Return the print writer.
 814:     * @return the PrintWriter that will be written to
 815:     */
 816:     public PrintWriter getPrintWriter() 
 817:     {
 818:         return m_out;
 819:     }
 820: }