Author: ebourg Date: Tue May 26 11:48:44 2009 New Revision: 778664 URL: http://svn.apache.org/viewvc?rev=778664&view=rev Log: Implemented the partial matching for long options in the PosixParser (CLI-160)
Added: commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java (with props) Modified: commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java commons/proper/cli/trunk/xdocs/changes.xml Added: commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java?rev=778664&view=auto ============================================================================== --- commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java (added) +++ commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java Tue May 26 11:48:44 2009 @@ -0,0 +1,53 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.cli; + +import java.util.Collection; + +/** + * Exception thrown when an option can't be identified from a partial name. + * + * @author Emmanuel Bourg + * @version $Revision$, $Date$ + * @since 1.3 + */ +public class AmbiguousOptionException extends UnrecognizedOptionException +{ + /** The list of options matching the partial name specified */ + private Collection matchingOptions; + + /** + * Constructs a new AmbiguousOptionException. + * + * @param option the partial option name + * @param matchingOptions the options matching the name + */ + public AmbiguousOptionException(String option, Collection matchingOptions) + { + super("Ambiguous option: " + option, option); + this.matchingOptions = matchingOptions; + } + + /** + * Returns the options matching the partial name. + */ + public Collection getMatchingOptions() + { + return matchingOptions; + } +} Propchange: commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: commons/proper/cli/trunk/src/java/org/apache/commons/cli/AmbiguousOptionException.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision HeadURL Modified: commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java (original) +++ commons/proper/cli/trunk/src/java/org/apache/commons/cli/Options.java Tue May 26 11:48:44 2009 @@ -214,6 +214,32 @@ } /** + * Returns the options with a long name starting with the name specified. + * + * @param opt the partial name of the option + * @return the options matching the partial name specified, or an empty list if none matches + * @since 1.3 + */ + public List getMatchingOptions(String opt) + { + opt = Util.stripLeadingHyphens(opt); + + List matchingOpts = new ArrayList(); + + Iterator it = longOpts.keySet().iterator(); + while (it.hasNext()) + { + String longOpt = (String) it.next(); + if (longOpt.startsWith(opt)) + { + matchingOpts.add(longOpt); + } + } + + return matchingOpts; + } + + /** * Returns whether the named {...@link Option} is a member of this {...@link Options}. * * @param opt short or long name of the {...@link Option} Modified: commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java (original) +++ commons/proper/cli/trunk/src/java/org/apache/commons/cli/Parser.java Tue May 26 11:48:44 2009 @@ -68,7 +68,7 @@ * flattening when a non option has been encountered * @return a String array of the flattened arguments */ - protected abstract String[] flatten(Options opts, String[] arguments, boolean stopAtNonOption); + protected abstract String[] flatten(Options opts, String[] arguments, boolean stopAtNonOption) throws ParseException; /** * Parses the specified <code>arguments</code> based Modified: commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java (original) +++ commons/proper/cli/trunk/src/java/org/apache/commons/cli/PosixParser.java Tue May 26 11:48:44 2009 @@ -92,7 +92,7 @@ * when an non option is found. * @return The flattened <code>arguments</code> String array. */ - protected String[] flatten(Options options, String[] arguments, boolean stopAtNonOption) + protected String[] flatten(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException { init(); this.options = options; @@ -106,21 +106,33 @@ // get the next command line token String token = (String) iter.next(); + // single or double hyphen + if ("-".equals(token) || "--".equals(token)) + { + tokens.add(token); + } + // handle long option --foo or --foo=bar - if (token.startsWith("--")) + else if (token.startsWith("--")) { int pos = token.indexOf('='); String opt = pos == -1 ? token : token.substring(0, pos); // --foo + + List matchingOpts = options.getMatchingOptions(opt); - if (!options.hasOption(opt)) + if (matchingOpts.isEmpty()) { processNonOptionToken(token, stopAtNonOption); } + else if (matchingOpts.size() > 1) + { + throw new AmbiguousOptionException(opt, matchingOpts); + } else { - currentOption = options.getOption(opt); + currentOption = options.getOption((String) matchingOpts.get(0)); - tokens.add(opt); + tokens.add("--" + currentOption.getLongOpt()); if (pos != -1) { tokens.add(token.substring(pos + 1)); @@ -128,17 +140,25 @@ } } - // single hyphen - else if ("-".equals(token)) - { - tokens.add(token); - } else if (token.startsWith("-")) { if (token.length() == 2 || options.hasOption(token)) { processOptionToken(token, stopAtNonOption); } + else if (!options.getMatchingOptions(token).isEmpty()) + { + List matchingOpts = options.getMatchingOptions(token); + if (matchingOpts.size() > 1) + { + throw new AmbiguousOptionException(token, matchingOpts); + } + else + { + Option opt = options.getOption((String) matchingOpts.get(0)); + processOptionToken("-" + opt.getLongOpt(), stopAtNonOption); + } + } // requires bursting else { Modified: commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java (original) +++ commons/proper/cli/trunk/src/test/org/apache/commons/cli/BasicParserTest.java Tue May 26 11:48:44 2009 @@ -53,4 +53,29 @@ { // not supported by the BasicParser } + + public void testUnambiguousPartialLongOption1() throws Exception + { + // not supported by the BasicParser + } + + public void testUnambiguousPartialLongOption2() throws Exception + { + // not supported by the BasicParser + } + + public void testAmbiguousPartialLongOption1() throws Exception + { + // not supported by the BasicParser + } + + public void testAmbiguousPartialLongOption2() throws Exception + { + // not supported by the BasicParser + } + + public void testPartialLongOptionWithShort() throws Exception + { + // not supported by the BasicParser + } } Modified: commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java (original) +++ commons/proper/cli/trunk/src/test/org/apache/commons/cli/GnuParserTest.java Tue May 26 11:48:44 2009 @@ -24,4 +24,29 @@ super.setUp(); parser = new GnuParser(); } + + public void testUnambiguousPartialLongOption1() throws Exception + { + // not supported by the GnuParser + } + + public void testUnambiguousPartialLongOption2() throws Exception + { + // not supported by the GnuParser + } + + public void testAmbiguousPartialLongOption1() throws Exception + { + // not supported by the GnuParser + } + + public void testAmbiguousPartialLongOption2() throws Exception + { + // not supported by the GnuParser + } + + public void testPartialLongOptionWithShort() throws Exception + { + // not supported by the GnuParser + } } Modified: commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java (original) +++ commons/proper/cli/trunk/src/test/org/apache/commons/cli/OptionsTest.java Tue May 26 11:48:44 2009 @@ -159,4 +159,15 @@ assertNotNull(options.getOptionGroups()); assertEquals(2, options.getOptionGroups().size()); } + + public void testGetMatchingOpts() + { + Options options = new Options(); + options.addOption(OptionBuilder.withLongOpt("version").create()); + options.addOption(OptionBuilder.withLongOpt("verbose").create()); + + assertTrue(options.getMatchingOptions("foo").isEmpty()); + assertEquals(1, options.getMatchingOptions("version").size()); + assertEquals(2, options.getMatchingOptions("ver").size()); + } } Modified: commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java (original) +++ commons/proper/cli/trunk/src/test/org/apache/commons/cli/ParserTestCase.java Tue May 26 11:48:44 2009 @@ -303,4 +303,94 @@ assertEquals("Should be 1 arg left",1,argsleft.size()); assertEquals("Expecting foo","foo",argsleft.get(0)); } + + public void testUnambiguousPartialLongOption1() throws Exception + { + String[] args = new String[] { "--ver" }; + + Options options = new Options(); + options.addOption(OptionBuilder.withLongOpt("version").create()); + options.addOption(OptionBuilder.withLongOpt("help").create()); + + CommandLine cl = parser.parse(options, args); + + assertTrue("Confirm --version is set", cl.hasOption("version")); + } + + public void testUnambiguousPartialLongOption2() throws Exception + { + String[] args = new String[] { "-ver" }; + + Options options = new Options(); + options.addOption(OptionBuilder.withLongOpt("version").create()); + options.addOption(OptionBuilder.withLongOpt("help").create()); + + CommandLine cl = parser.parse(options, args); + + assertTrue("Confirm --version is set", cl.hasOption("version")); + } + + public void testAmbiguousPartialLongOption1() throws Exception + { + String[] args = new String[] { "--ver" }; + + Options options = new Options(); + options.addOption(OptionBuilder.withLongOpt("version").create()); + options.addOption(OptionBuilder.withLongOpt("verbose").create()); + + boolean caught = false; + + try + { + parser.parse(options, args); + } + catch (AmbiguousOptionException e) + { + caught = true; + assertEquals("Partial option", "--ver", e.getOption()); + assertNotNull("Matching options null", e.getMatchingOptions()); + assertEquals("Matching options size", 2, e.getMatchingOptions().size()); + } + + assertTrue( "Confirm MissingArgumentException caught", caught ); + } + + public void testAmbiguousPartialLongOption2() throws Exception + { + String[] args = new String[] { "-ver" }; + + Options options = new Options(); + options.addOption(OptionBuilder.withLongOpt("version").create()); + options.addOption(OptionBuilder.withLongOpt("verbose").create()); + + boolean caught = false; + + try + { + parser.parse(options, args); + } + catch (AmbiguousOptionException e) + { + caught = true; + assertEquals("Partial option", "-ver", e.getOption()); + assertNotNull("Matching options null", e.getMatchingOptions()); + assertEquals("Matching options size", 2, e.getMatchingOptions().size()); + } + + assertTrue( "Confirm MissingArgumentException caught", caught ); + } + + public void testPartialLongOptionWithShort() throws Exception + { + String[] args = new String[] { "-ver" }; + + Options options = new Options(); + options.addOption(OptionBuilder.withLongOpt("version").create()); + options.addOption(OptionBuilder.hasArg().create('v')); + + CommandLine cl = parser.parse(options, args); + + assertTrue("Confirm --version is set", cl.hasOption("version")); + assertTrue("Confirm -v is not set", !cl.hasOption("v")); + } } Modified: commons/proper/cli/trunk/xdocs/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/cli/trunk/xdocs/changes.xml?rev=778664&r1=778663&r2=778664&view=diff ============================================================================== --- commons/proper/cli/trunk/xdocs/changes.xml (original) +++ commons/proper/cli/trunk/xdocs/changes.xml Tue May 26 11:48:44 2009 @@ -21,6 +21,12 @@ <title>Commons CLI Release Notes</title> </properties> <body> + + <release version="1.3" date="in SVN"> + <action type="add" dev="ebourg" issue="CLI-160"> + PosixParser now supports partial long options (--ver instead of --version) + </action> + </release> <release version="1.2" date="2009-03-19" description="This is a maintenance release containing bug fixes."> <action type="fix" dev="oheger" issue="CLI-175"> @@ -38,9 +44,6 @@ <action type="fix" dev="bayard" issue="CLI-170"> TypeHandler prints messages to stderr. </action> - <action type="fix" dev="bayard" issue="CLI-170"> - TypeHandler prints messages to stderr. - </action> <action type="fix" dev="bayard" issue="CLI-162"> Infinite loop in the wrapping code of HelpFormatter. </action>