@@ -12,7 +12,7 @@ const fs = require('fs');
12
12
// Although this is a class, methods are static in style to allow override using subclass or just functions.
13
13
class Help {
14
14
constructor ( ) {
15
- this . columns = process . stdout . columns || 80 ;
15
+ this . columns = undefined ;
16
16
this . sortSubcommands = false ;
17
17
this . sortOptions = false ;
18
18
}
@@ -243,7 +243,7 @@ class Help {
243
243
244
244
formatHelp ( cmd , helper ) {
245
245
const termWidth = helper . padWidth ( cmd , helper ) ;
246
- const columns = helper . columns ;
246
+ const columns = helper . columns || 80 ;
247
247
const itemIndentWidth = 2 ;
248
248
const itemSeparatorWidth = 2 ;
249
249
// itemIndent term itemSeparator description
@@ -543,6 +543,15 @@ class Command extends EventEmitter {
543
543
this . _description = '' ;
544
544
this . _argsDescription = undefined ;
545
545
546
+ // see .configureOutput() for docs
547
+ this . _outputConfiguration = {
548
+ writeOut : ( str ) => process . stdout . write ( str ) ,
549
+ writeErr : ( str ) => process . stderr . write ( str ) ,
550
+ getOutColumns : ( ) => process . stdout . isTTY ? process . stdout . columns : undefined ,
551
+ getErrColumns : ( ) => process . stderr . isTTY ? process . stderr . columns : undefined ,
552
+ outputError : ( str , write ) => write ( str )
553
+ } ;
554
+
546
555
this . _hidden = false ;
547
556
this . _hasHelpOption = true ;
548
557
this . _helpFlags = '-h, --help' ;
@@ -663,6 +672,32 @@ class Command extends EventEmitter {
663
672
return this ;
664
673
}
665
674
675
+ /**
676
+ * The default output goes to stdout and stderr. You can customise this for special
677
+ * applications. You can also customise the display of errors by overriding outputError.
678
+ *
679
+ * The configuration properties are all functions:
680
+ *
681
+ * // functions to change where being written, stdout and stderr
682
+ * writeOut(str)
683
+ * writeErr(str)
684
+ * // matching functions to specify columns for wrapping help
685
+ * getOutColumns()
686
+ * getErrColumns()
687
+ * // functions based on what is being written out
688
+ * outputError(str, write) // used for displaying errors, and not used for displaying help
689
+ *
690
+ * @param {Object } [configuration] - configuration options
691
+ * @return {Command|Object } `this` command for chaining, or stored configuration
692
+ */
693
+
694
+ configureOutput ( configuration ) {
695
+ if ( configuration === undefined ) return this . _outputConfiguration ;
696
+
697
+ Object . assign ( this . _outputConfiguration , configuration ) ;
698
+ return this ;
699
+ }
700
+
666
701
/**
667
702
* Add a prepared subcommand.
668
703
*
@@ -968,8 +1003,7 @@ Read more on https://git.io/JJc0W`);
968
1003
val = option . parseArg ( val , oldValue === undefined ? defaultValue : oldValue ) ;
969
1004
} catch ( err ) {
970
1005
if ( err . code === 'commander.optionArgumentRejected' ) {
971
- console . error ( err . message ) ;
972
- this . _exit ( err . exitCode , err . code , err . message ) ;
1006
+ this . _displayError ( err . exitCode , err . code , err . message ) ;
973
1007
}
974
1008
throw err ;
975
1009
}
@@ -1639,6 +1673,16 @@ Read more on https://git.io/JJc0W`);
1639
1673
return this . _optionValues ;
1640
1674
} ;
1641
1675
1676
+ /**
1677
+ * Internal bottleneck for handling of parsing errors.
1678
+ *
1679
+ * @api private
1680
+ */
1681
+ _displayError ( exitCode , code , message ) {
1682
+ this . _outputConfiguration . outputError ( `${ message } \n` , this . _outputConfiguration . writeErr ) ;
1683
+ this . _exit ( exitCode , code , message ) ;
1684
+ }
1685
+
1642
1686
/**
1643
1687
* Argument `name` is missing.
1644
1688
*
@@ -1648,8 +1692,7 @@ Read more on https://git.io/JJc0W`);
1648
1692
1649
1693
missingArgument ( name ) {
1650
1694
const message = `error: missing required argument '${ name } '` ;
1651
- console . error ( message ) ;
1652
- this . _exit ( 1 , 'commander.missingArgument' , message ) ;
1695
+ this . _displayError ( 1 , 'commander.missingArgument' , message ) ;
1653
1696
} ;
1654
1697
1655
1698
/**
@@ -1667,8 +1710,7 @@ Read more on https://git.io/JJc0W`);
1667
1710
} else {
1668
1711
message = `error: option '${ option . flags } ' argument missing` ;
1669
1712
}
1670
- console . error ( message ) ;
1671
- this . _exit ( 1 , 'commander.optionMissingArgument' , message ) ;
1713
+ this . _displayError ( 1 , 'commander.optionMissingArgument' , message ) ;
1672
1714
} ;
1673
1715
1674
1716
/**
@@ -1680,8 +1722,7 @@ Read more on https://git.io/JJc0W`);
1680
1722
1681
1723
missingMandatoryOptionValue ( option ) {
1682
1724
const message = `error: required option '${ option . flags } ' not specified` ;
1683
- console . error ( message ) ;
1684
- this . _exit ( 1 , 'commander.missingMandatoryOptionValue' , message ) ;
1725
+ this . _displayError ( 1 , 'commander.missingMandatoryOptionValue' , message ) ;
1685
1726
} ;
1686
1727
1687
1728
/**
@@ -1694,8 +1735,7 @@ Read more on https://git.io/JJc0W`);
1694
1735
unknownOption ( flag ) {
1695
1736
if ( this . _allowUnknownOption ) return ;
1696
1737
const message = `error: unknown option '${ flag } '` ;
1697
- console . error ( message ) ;
1698
- this . _exit ( 1 , 'commander.unknownOption' , message ) ;
1738
+ this . _displayError ( 1 , 'commander.unknownOption' , message ) ;
1699
1739
} ;
1700
1740
1701
1741
/**
@@ -1712,8 +1752,7 @@ Read more on https://git.io/JJc0W`);
1712
1752
const fullCommand = partCommands . join ( ' ' ) ;
1713
1753
const message = `error: unknown command '${ this . args [ 0 ] } '.` +
1714
1754
( this . _hasHelpOption ? ` See '${ fullCommand } ${ this . _helpLongFlag } '.` : '' ) ;
1715
- console . error ( message ) ;
1716
- this . _exit ( 1 , 'commander.unknownCommand' , message ) ;
1755
+ this . _displayError ( 1 , 'commander.unknownCommand' , message ) ;
1717
1756
} ;
1718
1757
1719
1758
/**
@@ -1739,7 +1778,7 @@ Read more on https://git.io/JJc0W`);
1739
1778
this . _versionOptionName = versionOption . attributeName ( ) ;
1740
1779
this . options . push ( versionOption ) ;
1741
1780
this . on ( 'option:' + versionOption . name ( ) , ( ) => {
1742
- process . stdout . write ( str + '\n' ) ;
1781
+ this . _outputConfiguration . writeOut ( ` ${ str } \n` ) ;
1743
1782
this . _exit ( 0 , 'commander.version' , str ) ;
1744
1783
} ) ;
1745
1784
return this ;
@@ -1841,11 +1880,15 @@ Read more on https://git.io/JJc0W`);
1841
1880
/**
1842
1881
* Return program help documentation.
1843
1882
*
1883
+ * @param {{ error: boolean } } [contextOptions] - pass {error:true} to wrap for stderr instead of stdout
1844
1884
* @return {string }
1845
1885
*/
1846
1886
1847
- helpInformation ( ) {
1887
+ helpInformation ( contextOptions ) {
1848
1888
const helper = this . createHelp ( ) ;
1889
+ if ( helper . columns === undefined ) {
1890
+ helper . columns = ( contextOptions && contextOptions . error ) ? this . _outputConfiguration . getErrColumns ( ) : this . _outputConfiguration . getOutColumns ( ) ;
1891
+ }
1849
1892
return helper . formatHelp ( this , helper ) ;
1850
1893
} ;
1851
1894
@@ -1858,9 +1901,9 @@ Read more on https://git.io/JJc0W`);
1858
1901
const context = { error : ! ! contextOptions . error } ;
1859
1902
let write ;
1860
1903
if ( context . error ) {
1861
- write = ( arg , ... args ) => process . stderr . write ( arg , ... args ) ;
1904
+ write = ( arg ) => this . _outputConfiguration . writeErr ( arg ) ;
1862
1905
} else {
1863
- write = ( arg , ... args ) => process . stdout . write ( arg , ... args ) ;
1906
+ write = ( arg ) => this . _outputConfiguration . writeOut ( arg ) ;
1864
1907
}
1865
1908
context . write = contextOptions . write || write ;
1866
1909
context . command = this ;
@@ -1893,7 +1936,7 @@ Read more on https://git.io/JJc0W`);
1893
1936
groupListeners . slice ( ) . reverse ( ) . forEach ( command => command . emit ( 'beforeAllHelp' , context ) ) ;
1894
1937
this . emit ( 'beforeHelp' , context ) ;
1895
1938
1896
- let helpInformation = this . helpInformation ( ) ;
1939
+ let helpInformation = this . helpInformation ( context ) ;
1897
1940
if ( deprecatedCallback ) {
1898
1941
helpInformation = deprecatedCallback ( helpInformation ) ;
1899
1942
if ( typeof helpInformation !== 'string' && ! Buffer . isBuffer ( helpInformation ) ) {
0 commit comments