String[] splitValue(String value, ParserSpec parser, Range arity, int consumed) { if (splitRegex().length() == 0) { return new String[] {value}; } int limit = parser.limitSplit() ? Math.max(arity.max - consumed, 0) : 0; if (parser.splitQuotedStrings()) { return debug(value.split(splitRegex(), limit), "Split (ignoring quotes)", value); } return debug(splitRespectingQuotedStrings(value, limit, parser, this, splitRegex()), "Split", value); } private String[] debug(String[] result, String msg, String value) {
/** Sets whether the parser is allowed to split quoted Strings. The default is {@code false}. * <p>The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands <em>at the moment this method is called</em>. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.</p> * @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @see ArgSpec#splitRegex() * @since 3.7 */ public CommandLine setSplitQuotedStrings(boolean newValue) { getCommandSpec().parser().splitQuotedStrings(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setSplitQuotedStrings(newValue); } return this; }
@Test public void testArgSpecSplitWithEscapedBackslashInsideQuote() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\\\\\";def\""; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\\\\\";def\""}, values); }
/** Sets whether the parser is allowed to split quoted Strings. The default is {@code false}. * <p>The specified setting will be registered with this {@code CommandLine} and the full hierarchy of its * subcommands and nested sub-subcommands <em>at the moment this method is called</em>. Subcommands added * later will have the default setting. To ensure a setting is applied to all * subcommands, call the setter last, after adding subcommands.</p> * @param newValue the new setting * @return this {@code CommandLine} object, to allow method chaining * @see ArgSpec#splitRegex() * @since 3.7 */ public CommandLine setSplitQuotedStrings(boolean newValue) { getCommandSpec().parser().splitQuotedStrings(newValue); for (CommandLine command : getCommandSpec().subcommands().values()) { command.setSplitQuotedStrings(newValue); } return this; }
@Test public void testArgSpecSplitUnbalancedQuotedValueDebug() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\";def"; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\"", "def"}, values); } @Test
@Test public void testArgSpecSplitValueDebug() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex("b").build(); System.setProperty("picocli.trace", "DEBUG"); String[] values = positional.splitValue("abc", new CommandLine.Model.ParserSpec().splitQuotedStrings(true), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"a", "c"}, values); }
@Test public void testArgSpecSplitValue_SplitsQuotedValuesIfConfigured() { ParserSpec parser = new ParserSpec().splitQuotedStrings(true); ArgSpec spec = PositionalParamSpec.builder().splitRegex(",").build(); String[] actual = spec.splitValue("a,b,\"c,d,e\",f", parser, Range.valueOf("0"), 0); assertArrayEquals(new String[]{"a", "b", "\"c", "d" , "e\"", "f"}, actual); }
@Test public void testArgSpecSplitWithEscapedBackslashOutsideQuote() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\\\\\"abc\\\";def\";\\\"a\\"; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\\\\\"abc\\\";def\"", "\\\"a\\"}, values); }
@Test public void testArgSpecSplitBalancedQuotedValueDebug() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\";def\""; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\";def\""}, values); }
@Test public void testArgSpecSplitWithEscapedBackslashInsideQuote() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\\\\\";def\""; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\\\\\";def\""}, values); }
String[] splitValue(String value, ParserSpec parser, Range arity, int consumed) { if (splitRegex().length() == 0) { return new String[] {value}; } int limit = parser.limitSplit() ? Math.max(arity.max - consumed, 0) : 0; if (parser.splitQuotedStrings()) { return debug(value.split(splitRegex(), limit), "Split (ignoring quotes)", value); } return debug(splitRespectingQuotedStrings(value, limit, parser), "Split", value); } private String[] debug(String[] result, String msg, String value) {
/** Returns whether the parser is allowed to split quoted Strings or not. The default is {@code false}, * so quoted strings are treated as a single value that cannot be split. * @return {@code true} if the parser is allowed to split quoted Strings, {@code false} otherwise; * @see ArgSpec#splitRegex() * @since 3.7 */ public boolean isSplitQuotedStrings() { return getCommandSpec().parser().splitQuotedStrings(); }
@Test public void testArgSpecSplitUnbalancedQuotedValueDebug() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\";def"; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\"", "def"}, values); } @Test
@Test public void testArgSpecSplitValue_SplitsQuotedValuesIfConfigured() { ParserSpec parser = new ParserSpec().splitQuotedStrings(true); ArgSpec spec = PositionalParamSpec.builder().splitRegex(",").build(); String[] actual = spec.splitValue("a,b,\"c,d,e\",f", parser, Range.valueOf("0"), 0); assertArrayEquals(new String[]{"a", "b", "\"c", "d" , "e\"", "f"}, actual); }
@Test public void testArgSpecSplitBalancedQuotedValueDebug() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\"abc\\\";def\""; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\"abc\\\";def\""}, values); }
/** Returns whether the parser is allowed to split quoted Strings or not. The default is {@code false}, * so quoted strings are treated as a single value that cannot be split. * @return {@code true} if the parser is allowed to split quoted Strings, {@code false} otherwise; * @see ArgSpec#splitRegex() * @since 3.7 */ public boolean isSplitQuotedStrings() { return getCommandSpec().parser().splitQuotedStrings(); }
@Test public void testArgSpecSplitWithEscapedBackslashOutsideQuote() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex(";").build(); System.setProperty("picocli.trace", "DEBUG"); String value = "\\\\\"abc\\\";def\";\\\"a\\"; String[] values = positional.splitValue(value, new CommandLine.Model.ParserSpec().splitQuotedStrings(false), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"\\\\\"abc\\\";def\"", "\\\"a\\"}, values); }
@Test public void testArgSpecSplitValueDebug() { PositionalParamSpec positional = PositionalParamSpec.builder().splitRegex("b").build(); System.setProperty("picocli.trace", "DEBUG"); String[] values = positional.splitValue("abc", new CommandLine.Model.ParserSpec().splitQuotedStrings(true), CommandLine.Range.valueOf("1"), 1); System.clearProperty("picocli.trace"); assertArrayEquals(new String[] {"a", "c"}, values); }