Skip to content

Commit 3bc9b84

Browse files
committed
Merge branch 'master' of https://github.com/rubin55/commons-cli
2 parents ccc2b43 + 3d9587c commit 3bc9b84

3 files changed

Lines changed: 126 additions & 14 deletions

File tree

.gitignore

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
### https://raw.github.com/github/gitignore/f2ce448f2ba7a092da05482ceca99209127c0884/maven.gitignore
2-
1+
# maven
32
target/
43
pom.xml.tag
54
pom.xml.releaseBackup
@@ -9,9 +8,14 @@ release.properties
98
dependency-reduced-pom.xml
109
buildNumber.properties
1110
.mvn/timing.properties
12-
13-
# Exclude maven wrapper
1411
!/.mvn/wrapper/maven-wrapper.jar
1512

16-
site-content
13+
# vscode/eclipse/idea
14+
*.iml
15+
.idea/
16+
.classpath
17+
.project
18+
.settings/
1719

20+
# other
21+
site-content

src/main/java/org/apache/commons/cli/DefaultParser.java

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,24 @@ public class DefaultParser implements CommandLineParser
5353

5454
/** The required options and groups expected to be found when parsing the command line. */
5555
protected List expectedOpts;
56-
56+
57+
/** Flag indicating if partial matching of long options is supported. */
58+
private boolean allowPartialMatching;
59+
60+
/** Creates a new DefaultParser instance with partial matching enabled. */
61+
public DefaultParser() {
62+
this.allowPartialMatching = true;
63+
}
64+
65+
/**
66+
* Create a new DefaultParser instance with the specified partial matching policy.
67+
*
68+
* @param allowPartialMatching if partial matching of long options shall be enabled
69+
*/
70+
public DefaultParser(final boolean allowPartialMatching) {
71+
this.allowPartialMatching = allowPartialMatching;
72+
}
73+
5774
public CommandLine parse(final Options options, final String[] arguments) throws ParseException
5875
{
5976
return parse(options, arguments, null);
@@ -329,7 +346,7 @@ private boolean isLongOption(final String token)
329346
final int pos = token.indexOf("=");
330347
final String t = pos == -1 ? token : token.substring(0, pos);
331348

332-
if (!options.getMatchingOptions(t).isEmpty())
349+
if (!getMatchingLongOptions(t).isEmpty())
333350
{
334351
// long or partial long options (--L, -L, --L=V, -L=V, --l, --l=V)
335352
return true;
@@ -400,18 +417,19 @@ private void handleLongOption(final String token) throws ParseException
400417
*/
401418
private void handleLongOptionWithoutEqual(final String token) throws ParseException
402419
{
403-
final List<String> matchingOpts = options.getMatchingOptions(token);
420+
final List<String> matchingOpts = getMatchingLongOptions(token);
404421
if (matchingOpts.isEmpty())
405422
{
406423
handleUnknownToken(currentToken);
407424
}
408-
else if (matchingOpts.size() > 1)
425+
else if (matchingOpts.size() > 1 && !options.hasLongOption(token))
409426
{
410427
throw new AmbiguousOptionException(token, matchingOpts);
411428
}
412429
else
413430
{
414-
handleOption(options.getOption(matchingOpts.get(0)));
431+
final String key = options.hasLongOption(token) ? token : matchingOpts.get(0);
432+
handleOption(options.getOption(key));
415433
}
416434
}
417435

@@ -433,18 +451,19 @@ private void handleLongOptionWithEqual(final String token) throws ParseException
433451

434452
final String opt = token.substring(0, pos);
435453

436-
final List<String> matchingOpts = options.getMatchingOptions(opt);
454+
final List<String> matchingOpts = getMatchingLongOptions(opt);
437455
if (matchingOpts.isEmpty())
438456
{
439457
handleUnknownToken(currentToken);
440458
}
441-
else if (matchingOpts.size() > 1)
459+
else if (matchingOpts.size() > 1 && !options.hasLongOption(opt))
442460
{
443461
throw new AmbiguousOptionException(opt, matchingOpts);
444462
}
445463
else
446464
{
447-
final Option option = options.getOption(matchingOpts.get(0));
465+
final String key = options.hasLongOption(opt) ? opt : matchingOpts.get(0);
466+
final Option option = options.getOption(key);
448467

449468
if (option.acceptsArg())
450469
{
@@ -503,7 +522,7 @@ else if (pos == -1)
503522
{
504523
handleOption(options.getOption(t));
505524
}
506-
else if (!options.getMatchingOptions(t).isEmpty())
525+
else if (!getMatchingLongOptions(t).isEmpty())
507526
{
508527
// -L or -l
509528
handleLongOptionWithoutEqual(token);
@@ -652,6 +671,32 @@ private void updateRequiredOptions(final Option option) throws AlreadySelectedEx
652671
}
653672
}
654673

674+
/**
675+
* Returns a list of matching option strings for the given token, depending
676+
* on the selected partial matching policy.
677+
*
678+
* @param token the token (may contain leading dashes)
679+
* @return the list of matching option strings or an empty list if no matching option could be found
680+
*/
681+
private List<String> getMatchingLongOptions(final String token)
682+
{
683+
if (allowPartialMatching)
684+
{
685+
return options.getMatchingOptions(token);
686+
}
687+
else
688+
{
689+
List<String> matches = new ArrayList<String>(1);
690+
if (options.hasLongOption(token))
691+
{
692+
Option option = options.getOption(token);
693+
matches.add(option.getLongOpt());
694+
}
695+
696+
return matches;
697+
}
698+
}
699+
655700
/**
656701
* Breaks <code>token</code> into its constituent parts
657702
* using the following algorithm.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. 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+
18+
package org.apache.commons.cli;
19+
20+
import org.junit.Before;
21+
import org.junit.Test;
22+
23+
import static org.junit.Assert.*;
24+
25+
public class DisablePartialMatchingTest
26+
{
27+
@Test
28+
public void testDisablePartialMatching() throws Exception
29+
{
30+
CommandLineParser parser = new DefaultParser(false);
31+
32+
final Options options = new Options();
33+
34+
options.addOption(new Option("d", "debug", false, "Turn on debug."));
35+
options.addOption(new Option("e", "extract", false, "Turn on extract."));
36+
options.addOption(new Option("o", "option", true, "Turn on option with argument."));
37+
38+
CommandLine line = parser.parse(options, new String[]{"-de", "--option=foobar"});
39+
40+
assertTrue("There should be an option debug in any case...", line.hasOption("debug"));
41+
assertTrue("There should be an extract option because partial matching is off", line.hasOption("extract"));
42+
assertTrue("There should be an option option with a argument value", line.hasOption("option"));
43+
}
44+
45+
@Test
46+
public void testRegularPartialMatching() throws Exception
47+
{
48+
CommandLineParser parser = new DefaultParser();
49+
50+
final Options options = new Options();
51+
52+
options.addOption(new Option("d", "debug", false, "Turn on debug."));
53+
options.addOption(new Option("e", "extract", false, "Turn on extract."));
54+
options.addOption(new Option("o", "option", true, "Turn on option with argument."));
55+
56+
57+
CommandLine line = parser.parse(options, new String[]{"-de", "--option=foobar"});
58+
59+
assertTrue("There should be an option debug in any case...", line.hasOption("debug"));
60+
assertFalse("There should not be an extract option because partial matching only selects debug", line.hasOption("extract"));
61+
assertTrue("There should be an option option with a argument value", line.hasOption("option"));
62+
}
63+
}

0 commit comments

Comments
 (0)