Skip to content

Commit

Permalink
Revisit posix short handling in Lexer
Browse files Browse the repository at this point in the history
- Posix short style is expected to have only single
  dash and letters so use this style to come up better
  separation between options and arguments.
- Backport #1077
- Fixes #1079
  • Loading branch information
jvalkeal committed May 28, 2024
1 parent 786891f commit d0b0c73
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 the original author or authors.
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -201,12 +201,17 @@ public LexerResult tokenize(List<String> arguments) {
}
}
else if (isLastTokenOfType(tokenList, TokenType.OPTION)) {
if (argument.startsWith("-")) {
// posix short style can only have one or more letters
int decuceArgumentStyle = decuceArgumentStyle(argument);
if (decuceArgumentStyle > 0) {
tokenList.add(Token.of(argument, TokenType.OPTION, i2));
}
else {
else if (decuceArgumentStyle < 0) {
tokenList.add(Token.of(argument, TokenType.ARGUMENT, i2));
}
else {
tokenList.add(Token.of(argument, TokenType.OPTION, i2));
}
}
else if (isLastTokenOfType(tokenList, TokenType.COMMAND)) {
if (argument.startsWith("-")) {
Expand Down Expand Up @@ -243,5 +248,28 @@ private static boolean isLastTokenOfType(List<Token> tokenList, TokenType type)
}
return false;
}

private static int decuceArgumentStyle(String str) {
// positive - looks like posix short
// 0 - looks like long option
// negative - looks like argument, not option
if (str.length() < 2) {
return -1;
}
if (str.charAt(0) != '-') {
return -1;
}
if (str.length() > 1 && str.charAt(0) == '-' && str.charAt(1) == '-') {
return 0;
}
int ret = 1;
for (int i = 1; i < str.length(); i++) {
if (!Character.isLetter(str.charAt(i))) {
ret = -1;
break;
}
}
return ret;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 the original author or authors.
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,8 @@

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import org.springframework.shell.command.parser.Lexer.LexerResult;
import org.springframework.shell.command.parser.ParserConfig.Feature;
Expand Down Expand Up @@ -431,6 +433,42 @@ void commandArgsWithoutOption() {
TokenType.ARGUMENT);
}

@Nested
class ShortOptions {

@ParameterizedTest
@ValueSource(strings = {
"-1",
"-1a",
"-a1",
"-ab1",
"-ab1c"
})
void shouldNotBeOptionWhenDoesntLookLikeShortPosix(String arg) {
register(ROOT6_OPTION_INT);
List<Token> tokens = tokenize("root6", "--arg1", arg);

assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND, TokenType.OPTION,
TokenType.ARGUMENT);
}

@ParameterizedTest
@ValueSource(strings = {
"-a",
"-ab",
"-abc",
"--abc"
})
void shouldBeOptionWhenLooksLikeShortPosix(String arg) {
register(ROOT6_OPTION_INT);
List<Token> tokens = tokenize("root6", "--arg1", arg);

assertThat(tokens).extracting(Token::getType).containsExactly(TokenType.COMMAND, TokenType.OPTION,
TokenType.OPTION);
}
}


@Nested
class Directives {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 the original author or authors.
* Copyright 2023-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -116,6 +116,18 @@ void optionValueFailsFromStringToInteger() {
assertThat(ms.getMessage()).contains("Failed to convert");
});
}

@Test
void optionValueShouldBeNegativeInteger() {
register(ROOT6_OPTION_INT);
ParseResult result = parse("root6", "--arg1", "-1");
assertThat(result).isNotNull();
assertThat(result.commandRegistration()).isNotNull();
assertThat(result.optionResults()).isNotEmpty();
assertThat(result.optionResults().get(0).value()).isEqualTo(-1);
assertThat(result.messageResults()).isEmpty();
}

}

@Nested
Expand Down

0 comments on commit d0b0c73

Please sign in to comment.