Revisit posix short handling in Lexer

- 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 #1078
This commit is contained in:
Janne Valkealahti
2024-05-28 10:07:38 +01:00
parent b67b3010f2
commit ee1b4f2092
3 changed files with 83 additions and 5 deletions

View File

@@ -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.
@@ -201,12 +201,17 @@ public interface Lexer {
}
}
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("-")) {
@@ -243,5 +248,28 @@ public interface Lexer {
}
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;
}
}
}

View File

@@ -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.
@@ -19,6 +19,8 @@ import java.util.List;
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;
@@ -431,6 +433,42 @@ class LexerTests extends AbstractParsingTests {
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 {

View File

@@ -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.
@@ -116,6 +116,18 @@ class ParserTests extends AbstractParsingTests {
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