You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by pa...@apache.org on 2015/06/07 11:36:54 UTC
incubator-groovy git commit: GROOVY-6090: Reimplement CliBuilder over
another CLI API (cheat and use CLI 1.3 DefaultParser as the other api)
Repository: incubator-groovy
Updated Branches:
refs/heads/master d94c56585 -> 792027ea0
GROOVY-6090: Reimplement CliBuilder over another CLI API (cheat and use CLI 1.3 DefaultParser as the other api)
Project: http://git-wip-us.apache.org/repos/asf/incubator-groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-groovy/commit/792027ea
Tree: http://git-wip-us.apache.org/repos/asf/incubator-groovy/tree/792027ea
Diff: http://git-wip-us.apache.org/repos/asf/incubator-groovy/diff/792027ea
Branch: refs/heads/master
Commit: 792027ea08746cae15e104662555c890d281e5c4
Parents: d94c565
Author: Paul King <pa...@asert.com.au>
Authored: Sun Jun 7 19:08:10 2015 +1000
Committer: Paul King <pa...@asert.com.au>
Committed: Sun Jun 7 19:36:45 2015 +1000
----------------------------------------------------------------------
src/main/groovy/util/CliBuilder.groovy | 22 +-
.../codehaus/groovy/cli/GroovyPosixParser.java | 11 +-
src/test/groovy/util/CliBuilderTest.groovy | 472 ++++++++-----------
3 files changed, 220 insertions(+), 285 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/792027ea/src/main/groovy/util/CliBuilder.groovy
----------------------------------------------------------------------
diff --git a/src/main/groovy/util/CliBuilder.groovy b/src/main/groovy/util/CliBuilder.groovy
index dd71606..4ecbe82 100644
--- a/src/main/groovy/util/CliBuilder.groovy
+++ b/src/main/groovy/util/CliBuilder.groovy
@@ -18,8 +18,14 @@
*/
package groovy.util
-import org.apache.commons.cli.*
-import org.codehaus.groovy.cli.GroovyPosixParser
+import org.apache.commons.cli.CommandLine
+import org.apache.commons.cli.CommandLineParser
+import org.apache.commons.cli.DefaultParser
+import org.apache.commons.cli.GnuParser
+import org.apache.commons.cli.HelpFormatter
+import org.apache.commons.cli.Option
+import org.apache.commons.cli.Options
+import org.apache.commons.cli.ParseException
import org.codehaus.groovy.runtime.InvokerHelper
/**
@@ -48,9 +54,9 @@ import org.codehaus.groovy.runtime.InvokerHelper
* option exists with value 'alt' and provided that none of 'a', 'l' or 't'
* takes an argument (in fact the last one is allowed to take an argument).
* The bursting behavior can be turned off by using an
- * alternate underlying parser. The simplest way to achieve this is by setting
- * the posix property on the CliBuilder to false, i.e. include
- * <code>posix: false</code> in the constructor call.
+ * alternate underlying parser. The simplest way to achieve this is by using
+ * the deprecated GnuParser from Commons CLI with the parser property on the CliBuilder,
+ * i.e. include <code>parser: new GnuParser()</code> in the constructor call.
* <p>
* Another example (partial emulation of arg processing for 'ant' command line):
* <pre>
@@ -224,7 +230,7 @@ class CliBuilder {
/**
* Allows customisation of the usage message width.
*/
- int width = formatter.defaultWidth
+ int width = HelpFormatter.DEFAULT_WIDTH
/**
* Not normally accessed directly but full access to underlying options if needed.
@@ -259,7 +265,7 @@ class CliBuilder {
OptionAccessor parse(args) {
if (expandArgumentFiles) args = expandArgumentFiles(args)
if (!parser) {
- parser = posix == null ? new GroovyPosixParser() : posix == true ? new PosixParser() : new GnuParser()
+ parser = posix != null && posix == false ? new GnuParser() : new DefaultParser()
}
try {
return new OptionAccessor(parser.parse(options, args as String[], stopAtNonOption))
@@ -274,7 +280,7 @@ class CliBuilder {
* Print the usage message with writer (default: System.out) and formatter (default: HelpFormatter)
*/
void usage() {
- formatter.printHelp(writer, width, usage, header, options, formatter.defaultLeftPad, formatter.defaultDescPad, footer)
+ formatter.printHelp(writer, width, usage, header, options, HelpFormatter.DEFAULT_LEFT_PAD, HelpFormatter.DEFAULT_DESC_PAD, footer)
writer.flush()
}
http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/792027ea/src/main/org/codehaus/groovy/cli/GroovyPosixParser.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/cli/GroovyPosixParser.java b/src/main/org/codehaus/groovy/cli/GroovyPosixParser.java
index cd78c44..e583ac9 100644
--- a/src/main/org/codehaus/groovy/cli/GroovyPosixParser.java
+++ b/src/main/org/codehaus/groovy/cli/GroovyPosixParser.java
@@ -28,15 +28,16 @@ import java.util.Iterator;
import java.util.List;
/**
- * DO NOT USE. Hacked version until Commons CLI 1.3 is released.
- * NOTE: this is a mirror copy of org.apache.commons.cli.GroovyInternalPosixParser
- * DON'T MAKE CHANGES without keeping the other file in sync!
- * The class GroovyPosixParser provides an implementation of the
- * {@link org.apache.commons.cli.Parser#flatten(org.apache.commons.cli.Options,String[],boolean) flatten} method.
+ * This is a hacked version of Commons CLI 1.2 PosixParser with some bug fixes added.
+ * We aren't aware of any use cases where it isn't now preferable to use the
+ * Commons CLI 1.3 DefaultParser but this class is retained for the time being for
+ * backwards compatibility if someone is relying on this class's exact functionality.
*
* @author John Keyes (john at integralsource.com)
* @author Paul King (Groovy hacks/fixes)
+ * @deprecated use the DefaultParser from Commons CLI
*/
+@Deprecated
public class GroovyPosixParser extends Parser
{
/** holder for flattened tokens */
http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/792027ea/src/test/groovy/util/CliBuilderTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/util/CliBuilderTest.groovy b/src/test/groovy/util/CliBuilderTest.groovy
index d1760e1..72fb25d 100644
--- a/src/test/groovy/util/CliBuilderTest.groovy
+++ b/src/test/groovy/util/CliBuilderTest.groovy
@@ -18,39 +18,19 @@
*/
package groovy.util
-import org.codehaus.groovy.cli.GroovyPosixParser
+import org.apache.commons.cli.BasicParser
+import org.apache.commons.cli.DefaultParser
import org.apache.commons.cli.GnuParser
import org.apache.commons.cli.Option
-import org.apache.commons.cli.PosixParser
-import org.apache.commons.cli.BasicParser
+import org.codehaus.groovy.cli.GroovyPosixParser
/**
- * Test class for the CliBuilder -- but then that is obvious from the name :-)
- * <p>
- * There appear to be issues when using the <code>PosixParser</code> in 1.0 and 1.1 – when an
- * option with a parameter is passed using a long form and a single letter parameter of some sort has been
- * declared (the problem does not occur if no single letter option has been declared) then the value "--"
- * is returned instead of the option parameter value. This problem does not happen using the
- * <code>GnuParser</code>.
- * <p>
- * There appears to be an issue with <code>GnuParser</code> in 1.0 and 1.1 – if only a long option
- * is defined then the usual Groovy syntax for accessing the option fails to work. It is fine if a short
- * option of some sort is defined. This must be a <code>CliBuilder</code>/<code>OptionAccessor</code>
- * problem. This problem does not happen with the <code>PosixParser</code>.
- * <p>
- * Commons CLI 1.0 appears not to be able to access arguments using a long name, if that option has a
- * short name -- in this case access is only using a short name. This means it is possible to work with
- * long name option if and only if they have no short name.
+ * Test class for the CliBuilder.
* <p>
- * Commons CLI 1.1 has fixed most of the problems in 1.0, but appears to have a broken getOptionValues
- * -- it returns only the first value -- and so is worse than useless.
- * <p>
- * 1.0 PosixBuilder removes unrecognized single letter options silently. 1.1 version may also do this.
- * GnuParser behaves according to the <code>stopAtNonOption</code> parameter -- throw
- * <code>UnrecognizedOptionException</code> when <code>false</code>, terminate parse leaving everything
- * following unprocessed if <code>true</code>.
- * <p>
- * Commons CLI 1.2 is supposed to fix all the bugs!
+ * Commons CLI has a long history of different parsers with slightly differing behavior and bugs.
+ * In nearly all cases, we now recommend using DefaultParser. In case you have very unique circumstances
+ * and really need behavior that can only be supplied by one of the legacy parsers, we also include
+ * some test case runs against some of the legacy parsers.
*
* @author Dierk König
* @author Russel Winder
@@ -63,29 +43,29 @@ class CliBuilderTest extends GroovyTestCase {
private PrintWriter printWriter
void setUp() {
- stringWriter = new StringWriter()
- printWriter = new PrintWriter(stringWriter)
+ resetPrintWriter()
}
private final expectedParameter = 'ASCII'
private final usageString = 'groovy [option]* filename'
private void runSample(parser, optionList) {
+ resetPrintWriter()
def cli = new CliBuilder(usage: usageString, writer: printWriter, parser: parser)
cli.h(longOpt: 'help', 'usage information')
cli.c(argName: 'charset', args: 1, longOpt: 'encoding', 'character encoding')
cli.i(argName: 'extension', optionalArg: true, 'modify files in place, create backup if extension is given (e.g. \'.bak\')')
def stringified = cli.options.toString()
assert stringified =~ /i=\[ option: i :: modify files in place, create backup if extension is given/
- assert stringified =~ /c=\[ option: c encoding \[ARG] :: character encoding/ // 1.2 behaves differently to 1.0 and 1.1 here.
+ assert stringified =~ /c=\[ option: c encoding \[ARG] :: character encoding/
assert stringified =~ /h=\[ option: h help :: usage information/
- assert stringified =~ /encoding=\[ option: c encoding \[ARG] :: character encoding/ // 1.2 behaves differently to 1.0 and 1.1 here.
+ assert stringified =~ /encoding=\[ option: c encoding \[ARG] :: character encoding/
assert stringified =~ /help=\[ option: h help :: usage information/
def options = cli.parse(optionList)
assert options.hasOption('h')
- assert options.hasOption('help') //// Fails in 1.0, works for 1.x where x > 1.
+ assert options.hasOption('help')
assert options.h
- assert options.help //// Fails in 1.0, works for 1.x where x > 1.
+ assert options.help
if (options.h) { cli.usage() }
def expectedUsage = """usage: $usageString
-c,--encoding <charset> character encoding
@@ -93,258 +73,167 @@ class CliBuilderTest extends GroovyTestCase {
-i modify files in place, create backup if
extension is given (e.g. '.bak')"""
assertEquals(expectedUsage, stringWriter.toString().tokenize('\r\n').join('\n'))
- stringWriter = new StringWriter()
- printWriter = new PrintWriter(stringWriter)
+ resetPrintWriter()
cli.writer = printWriter
- if (options.help) { cli.usage() } //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals(expectedUsage, stringWriter.toString().tokenize('\r\n').join('\n')) //// Fails in 1.0, works for 1.x where x > 1.
+ if (options.help) { cli.usage() }
+ assertEquals(expectedUsage, stringWriter.toString().tokenize('\r\n').join('\n'))
assert options.hasOption('c')
assert options.c
- assert options.hasOption('encoding') //// Fails in 1.0, works for 1.x where x > 1.
- assert options.encoding //// Fails in 1.0, works for 1.x where x > 1.
+ assert options.hasOption('encoding')
+ assert options.encoding
assertEquals(expectedParameter, options.getOptionValue('c'))
assertEquals(expectedParameter, options.c)
- assertEquals(expectedParameter, options.getOptionValue('encoding')) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals(expectedParameter, options.encoding) //// Fails in 1.0, works for 1.x where x > 1.
+ assertEquals(expectedParameter, options.getOptionValue('encoding'))
+ assertEquals(expectedParameter, options.encoding)
assertEquals(false, options.noSuchOptionGiven)
assertEquals(false, options.hasOption('noSuchOptionGiven'))
assertEquals(false, options.x)
assertEquals(false, options.hasOption('x'))
}
- void testSampleShort_BasicParser() {
- runSample(new BasicParser(), ['-h', '-c', expectedParameter])
- }
-
- void testSampleShort_GnuParser() {
- runSample(new GnuParser(), ['-h', '-c', expectedParameter])
- }
-
- void testSampleShort_PosixParser() {
- runSample(new PosixParser(), ['-h', '-c', expectedParameter])
- }
-
- void testSampleShort_DefaultParser() {
- runSample(new GroovyPosixParser(), ['-h', '-c', expectedParameter])
- }
-
- void testSampleLong_BasicParser() {
- runSample(new BasicParser(), ['--help', '--encoding', expectedParameter])
- }
-
- void testSampleLong_GnuParser() {
- runSample(new GnuParser(), ['--help', '--encoding', expectedParameter])
+ private void resetPrintWriter() {
+ stringWriter = new StringWriter()
+ printWriter = new PrintWriter(stringWriter)
}
- void testSampleLong_PosixParser() {
- runSample(new PosixParser(), ['--help', '--encoding', expectedParameter])
+ void testSampleShort() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser ->
+ runSample(parser, ['-h', '-c', expectedParameter])
+ }
}
- void testSampleLong_DefaultParser() {
- runSample(new GroovyPosixParser(), ['--help', '--encoding', expectedParameter])
+ void testSampleLong() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser ->
+ runSample(parser, ['--help', '--encoding', expectedParameter])
+ }
}
- private void multipleArgs(parser) {
- def cli = new CliBuilder(parser: parser)
- cli.a(longOpt: 'arg', args: 2, valueSeparator: ',' as char, 'arguments')
- def options = cli.parse(['-a', '1,2'])
- assertEquals('1', options.a)
- assertEquals(['1', '2'], options.as)
- assertEquals('1', options.arg) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals(['1', '2'], options.args) //// Fails in 1.0, works for 1.x where x > 1.
+ void testSimpleArg() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ cli.a([:], '')
+ def options = cli.parse(['-a', '1', '2'])
+ assertEquals(['1', '2'], options.arguments())
+ }
}
- void testMultipleArgs_BasicParser() { multipleArgs(new BasicParser()) }
-
- void testMultipleArgs_GnuParser() { multipleArgs(new GnuParser()) }
-
- void testMultipleArgs_PosixParser() { multipleArgs(new PosixParser()) }
-
- private void doArgs(parser) {
- def cli = new CliBuilder(parser: parser)
- cli.a([:], '')
- def options = cli.parse(['-a', '1', '2'])
- assertEquals(['1', '2'], options.arguments())
+ void testMultipleArgs() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ cli.a(longOpt: 'arg', args: 2, valueSeparator: ',' as char, 'arguments')
+ def options = cli.parse(['-a', '1,2'])
+ assertEquals('1', options.a)
+ assertEquals(['1', '2'], options.as)
+ assertEquals('1', options.arg)
+ assertEquals(['1', '2'], options.args)
+ }
}
- void testArgs_BasicParser() { doArgs(new BasicParser()) }
-
- void testArgs_GnuParser() { doArgs(new GnuParser()) }
-
- void testArgs_PosixParser() { doArgs(new PosixParser()) }
-
void testFailedParsePrintsUsage() {
def cli = new CliBuilder(writer: printWriter)
cli.x(required: true, 'message')
cli.parse([])
- //
// NB: This test is very fragile and is bound to fail on different locales and versions of commons-cli... :-(
- //
assert stringWriter.toString().normalize() == '''error: Missing required option: x
usage: groovy
-x message
'''
}
- private void checkLongOptsOnly_nonOptionShouldStopArgProcessing(CliBuilder cli) {
- def anOption = Option.builder().longOpt('anOption').hasArg().desc('An option.').build()
- cli.options.addOption(anOption)
- def options = cli.parse(['-v', '--anOption', 'something'])
- // no options should be found
- assert options.getOptionValue('anOption') == null
- assert !options.anOption
- assert !options.v
- // arguments should be still sitting there
- assert options.arguments() == ['-v', '--anOption', 'something']
- }
-
- void testLongOptsOnly_GnuParser() {
- def cli = new CliBuilder(parser: new GnuParser())
- checkLongOptsOnly_nonOptionShouldStopArgProcessing(cli)
- }
-
- void testLongOptsOnly_PosixParser() {
- def cli = new CliBuilder(parser: new PosixParser())
- checkLongOptsOnly_nonOptionShouldStopArgProcessing(cli)
- }
-
- void testLongOptsOnly_GnuParser_settingPosixBooleanFalse() {
- def cli = new CliBuilder(posix: false)
- checkLongOptsOnly_nonOptionShouldStopArgProcessing(cli)
- }
-
- private void checkLongAndShortOpts_allOptionsValid(parser) {
- def cli = new CliBuilder(parser: parser)
- def anOption = Option.builder().longOpt('anOption').hasArg().desc('An option.').build()
- cli.options.addOption(anOption)
- cli.v(longOpt: 'verbose', 'verbose mode')
- def options = cli.parse(['-v', '--anOption', 'something'])
- assert options.v
- assert options.getOptionValue('anOption') == 'something'
- assert options.anOption == 'something'
- assert !options.arguments()
- }
-
- void testLongAndShortOpts_BasicParser() {
- checkLongAndShortOpts_allOptionsValid(new BasicParser())
- }
-
- void testLongAndShortOpts_PosixParser() {
- checkLongAndShortOpts_allOptionsValid(new PosixParser())
- }
-
- void testLongAndShortOpts_GnuParser() {
- checkLongAndShortOpts_allOptionsValid(new GnuParser())
- }
-
- void unknownOptions(parser) {
- def cli = new CliBuilder(parser: parser)
- cli.v(longOpt: 'verbose', 'verbose mode')
- def options = cli.parse(['-x', '-yyy', '--zzz', 'something'])
- assertEquals(['-x', '-yyy', '--zzz', 'something'], options.arguments())
- }
-
- void testUnrecognizedOptions_BasicParser() { unknownOptions(new BasicParser()) }
-
- void testUnrecognizedOptions_GnuParser() { unknownOptions(new GnuParser()) }
-
- void testUnrecognizedOptions_PosixParser() { unknownOptions(new PosixParser()) }
-
- void bizarreProcessing(parser) {
- def cli = new CliBuilder(parser: parser)
- def options = cli.parse(['-xxxx'])
- assertEquals(['-xxxx'], options.arguments())
- }
-
- void testBizarreProcessing_BasicParser() { bizarreProcessing(new BasicParser()) }
-
- void testBizarreProcessing_GnuParser() { bizarreProcessing(new GnuParser()) }
-
- void testPosixBizarreness() {
- def cli = new CliBuilder(parser: new PosixParser())
- def options = cli.parse(['-xxxx'])
- assertEquals(['xxxx'], options.arguments())
- }
-
- private void multipleOccurrencesSeparateSeparate(parser) {
- def cli = new CliBuilder(parser: parser)
- cli.a(longOpt: 'arg', args: Option.UNLIMITED_VALUES, 'arguments')
- def options = cli.parse(['-a', '1', '-a', '2', '-a', '3'])
- assertEquals('1', options.a)
- assertEquals(['1', '2', '3'], options.as)
- assertEquals('1', options.arg) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals(['1', '2', '3'], options.args) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals([], options.arguments())
- }
-
- void testMultipleOccurrencesSeparateSeparate_BasicParser() { multipleOccurrencesSeparateSeparate(new BasicParser()) }
-
- void testMultipleOccurrencesSeparateSeparate_GnuParser() { multipleOccurrencesSeparateSeparate(new GnuParser()) }
-
- void testMultipleOccurrencesSeparateSeparate_PosixParser() { multipleOccurrencesSeparateSeparate(new PosixParser()) }
-
- private void multipleOccurrencesSeparateJuxtaposed(parser) {
- def cli = new CliBuilder(parser: parser)
- //cli.a ( longOpt : 'arg' , args : Option.UNLIMITED_VALUES , 'arguments' )
- cli.a(longOpt: 'arg', args: 1, 'arguments')
- def options = cli.parse(['-a1', '-a2', '-a3'])
- assertEquals('1', options.a)
- assertEquals(['1', '2', '3'], options.as)
- assertEquals('1', options.arg) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals(['1', '2', '3'], options.args) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals([], options.arguments())
- }
- //
- // BasicParser cannot handle this one.
- //
- //void testMultipleOccurrencesSeparateJuxtaposed_BasicParser ( ) { multipleOccurrencesSeparateJuxtaposed ( new BasicParser ( ) ) }
-
- void testMultipleOccurrencesSeparateJuxtaposed_GnuParser() { multipleOccurrencesSeparateJuxtaposed(new GnuParser()) }
-
- void testMultipleOccurrencesSeparateJuxtaposed_PosixParser() { multipleOccurrencesSeparateJuxtaposed(new PosixParser()) }
-
- private void multipleOccurrencesTogetherSeparate(parser) {
- def cli = new CliBuilder(parser: parser)
- cli.a(longOpt: 'arg', args: Option.UNLIMITED_VALUES, valueSeparator: ',' as char, 'arguments')
- def options = cli.parse(['-a 1,2,3'])
- assertEquals(' 1', options.a)
- assertEquals([' 1', '2', '3'], options.as)
- assertEquals(' 1', options.arg) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals([' 1', '2', '3'], options.args) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals([], options.arguments())
- }
- //
- // BasicParser cannot handle this one.
- //
- //void testMultipleOccurrencesTogetherSeparate_BasicParser ( ) { multipleOccurrencesTogetherSeparate ( new BasicParser ( ) ) }
-
- void testMultipleOccurrencesTogetherSeparate_GnuParser() { multipleOccurrencesTogetherSeparate(new GnuParser()) }
-
- void testMultipleOccurrencesTogetherSeparate_PosixParser() { multipleOccurrencesTogetherSeparate(new PosixParser()) }
-
- private void multipleOccurrencesTogetherJuxtaposed(parser) {
- def cli = new CliBuilder(parser: parser)
- cli.a(longOpt: 'arg', args: Option.UNLIMITED_VALUES, valueSeparator: ',' as char, 'arguments')
- def options = cli.parse(['-a1,2,3'])
- assertEquals('1', options.a)
- assertEquals(['1', '2', '3'], options.as)
- assertEquals('1', options.arg) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals(['1', '2', '3'], options.args) //// Fails in 1.0, works for 1.x where x > 1.
- assertEquals([], options.arguments())
- }
- //
- // BasicParser cannot handle this one.
- //
- //void testMultipleOccurrencesTogetherJuxtaposed_BasicParser ( ) { multipleOccurrencesTogetherJuxtaposed ( new BasicParser ( ) ) }
-
- void testMultipleOccurrencesTogetherJuxtaposed_GnuParser() { multipleOccurrencesTogetherJuxtaposed(new GnuParser()) }
-
- void testMultipleOccurrencesTogetherJuxtaposed_PosixParser() { multipleOccurrencesTogetherJuxtaposed(new PosixParser()) }
+ void testLongOptsOnly_nonOptionShouldStopArgProcessing() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ def anOption = Option.builder().longOpt('anOption').hasArg().desc('An option.').build()
+ cli.options.addOption(anOption)
+ def options = cli.parse(['-v', '--anOption', 'something'])
+ // no options should be found
+ assert options.getOptionValue('anOption') == null
+ assert !options.anOption
+ assert !options.v
+ // arguments should be still sitting there
+ assert options.arguments() == ['-v', '--anOption', 'something']
+ }
+ }
+
+ void testLongAndShortOpts_allOptionsValid() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ def anOption = Option.builder().longOpt('anOption').hasArg().desc('An option.').build()
+ cli.options.addOption(anOption)
+ cli.v(longOpt: 'verbose', 'verbose mode')
+ def options = cli.parse(['-v', '--anOption', 'something'])
+ assert options.v
+ assert options.getOptionValue('anOption') == 'something'
+ assert options.anOption == 'something'
+ assert !options.arguments()
+ }
+ }
+
+ void testUnrecognizedOptions() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ cli.v(longOpt: 'verbose', 'verbose mode')
+ def options = cli.parse(['-x', '-yyy', '--zzz', 'something'])
+ assertEquals(['-x', '-yyy', '--zzz', 'something'], options.arguments())
+ }
+ }
+
+ void testMultipleOccurrencesSeparateSeparate() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser(), new BasicParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ cli.a(longOpt: 'arg', args: Option.UNLIMITED_VALUES, 'arguments')
+ def options = cli.parse(['-a', '1', '-a', '2', '-a', '3'])
+ assertEquals('1', options.a)
+ assertEquals(['1', '2', '3'], options.as)
+ assertEquals('1', options.arg)
+ assertEquals(['1', '2', '3'], options.args)
+ assertEquals([], options.arguments())
+ }
+ }
+
+ void testMultipleOccurrencesSeparateJuxtaposed() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ //cli.a ( longOpt : 'arg' , args : Option.UNLIMITED_VALUES , 'arguments' )
+ cli.a(longOpt: 'arg', args: 1, 'arguments')
+ def options = cli.parse(['-a1', '-a2', '-a3'])
+ assertEquals('1', options.a)
+ assertEquals(['1', '2', '3'], options.as)
+ assertEquals('1', options.arg)
+ assertEquals(['1', '2', '3'], options.args)
+ assertEquals([], options.arguments())
+ }
+ }
+
+ void testMultipleOccurrencesTogetherSeparate() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser ->
+ def cli = new CliBuilder(parser: parser)
+ cli.a(longOpt: 'arg', args: Option.UNLIMITED_VALUES, valueSeparator: ',' as char, 'arguments')
+ def options = cli.parse(['-a 1,2,3'])
+ assertEquals(' 1', options.a)
+ assertEquals([' 1', '2', '3'], options.as)
+ assertEquals(' 1', options.arg)
+ assertEquals([' 1', '2', '3'], options.args)
+ assertEquals([], options.arguments())
+ }
+ }
+
+ void testMultipleOccurrencesTogetherJuxtaposed() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser ->
+ def cli1 = new CliBuilder(parser: parser)
+ cli1.a(longOpt: 'arg', args: Option.UNLIMITED_VALUES, valueSeparator: ',' as char, 'arguments')
+ def options = cli1.parse(['-a1,2,3'])
+ assertEquals('1', options.a)
+ assertEquals(['1', '2', '3'], options.as)
+ assertEquals('1', options.arg)
+ assertEquals(['1', '2', '3'], options.args)
+ assertEquals([], options.arguments()) }
+ }
/*
* Behaviour with unrecognized options.
*
- * TODO: Should add the BasicParser here as well.
+ * TODO: Should add the BasicParser here as well?
*/
void testUnrecognizedOptionSilentlyIgnored_GnuParser() {
@@ -358,8 +247,8 @@ usage: groovy
assert stringWriter.toString().tokenize('\r\n').join('\n') == ''''''
}
- void testUnrecognizedOptionSilentlyIgnored_PosixParser() {
- def cli = new CliBuilder(usage: usageString, writer: printWriter, parser: new PosixParser())
+ void testUnrecognizedOptionSilentlyIgnored_DefaultParser() {
+ def cli = new CliBuilder(usage: usageString, writer: printWriter, parser: new DefaultParser())
def options = cli.parse(['-v'])
checkNoOutput()
assert !options.v
@@ -375,8 +264,8 @@ usage: groovy
assertEquals(['-v', '-h'], options.arguments())
}
- void testUnrecognizedOptionTerminatesParse_PosixParser() {
- def cli = new CliBuilder(usage: usageString, writer: printWriter, parser: new PosixParser())
+ void testUnrecognizedOptionTerminatesParse_DefaultParser() {
+ def cli = new CliBuilder(usage: usageString, writer: printWriter, parser: new DefaultParser())
cli.h(longOpt: 'help', 'usage information')
def options = cli.parse(['-v', '-h'])
checkNoOutput()
@@ -385,26 +274,20 @@ usage: groovy
assertEquals(['-v', '-h'], options.arguments())
}
- private checkMultiCharShortOpt(posix) {
- def cli = new CliBuilder(writer: printWriter, posix:posix)
- cli.abc('abc option')
- cli.def(longOpt: 'defdef', 'def option')
- def options = cli.parse(['-abc', '--defdef', 'ghi'])
- assert options
- assert options.arguments() == ['ghi']
- assert options.abc && options.def && options.defdef
- checkNoOutput()
- }
-
- void testMultiCharShortOpt_PosixParser() {
- checkMultiCharShortOpt(true)
+ void testMultiCharShortOpt() {
+ [new DefaultParser(), new GroovyPosixParser(), new GnuParser()].each { parser ->
+ def cli = new CliBuilder(writer: printWriter, parser: parser)
+ cli.abc('abc option')
+ cli.def(longOpt: 'defdef', 'def option')
+ def options = cli.parse(['-abc', '--defdef', 'ghi'])
+ assert options
+ assert options.arguments() == ['ghi']
+ assert options.abc && options.def && options.defdef
+ checkNoOutput()
+ }
}
- void testMultiCharShortOpt_GnuParser() {
- checkMultiCharShortOpt(false)
- }
-
- void testArgumentBursting_PosixParserOnly() {
+ void testArgumentBursting_DefaultParserOnly() {
def cli = new CliBuilder(writer: printWriter)
// must not have longOpt 'abc' and also no args for a or b
cli.a('a')
@@ -496,4 +379,49 @@ usage: groovy
def cli = new CliBuilder(expandArgumentFiles: true)
cli.parse(['something', ''])
}
+
+ void testDoubleHyphenShortOptions() {
+ def cli = new CliBuilder()
+ cli.a([:], '')
+ cli.b([:], '')
+ def options = cli.parse(['-a', '--', '-b', 'foo'])
+ assert options.arguments() == ['-b', 'foo']
+ }
+
+ void testDoubleHyphenLongOptions() {
+ def cli = new CliBuilder()
+ cli._([longOpt:'alpha'], '')
+ cli._([longOpt:'beta'], '')
+ def options = cli.parse(['--alpha', '--', '--beta', 'foo'])
+ assert options.alpha
+ assert options.arguments() == ['--beta', 'foo']
+ }
+
+ void testMixedShortAndLongOptions() {
+ def cli = new CliBuilder()
+ cli.a([longOpt:'alpha', args:1], '')
+ cli.b([:], '')
+ def options = cli.parse(['-b', '--alpha', 'param', 'foo'])
+ assert options.a == 'param'
+ assert options.arguments() == ['foo']
+ }
+
+ void testMixedBurstingAndLongOptions() {
+ def cli = new CliBuilder()
+ cli.a([:], '')
+ cli.b([:], '')
+ cli.c([:], '')
+ cli.d([longOpt:'abacus'], '')
+ def options = cli.parse(['-abc', 'foo'])
+ assert options.a
+ assert options.b
+ assert options.c
+ assert options.arguments() == ['foo']
+ options = cli.parse(['-abacus', 'foo'])
+ assert !options.a
+ assert !options.b
+ assert !options.c
+ assert options.d
+ assert options.arguments() == ['foo']
+ }
}