0

     private boolean relatedCommand(String input) {
            // make sure the split afterwards has at least size one
            if (input.matches(" .*")) {
                return false;
            }
            final String command = input.split(" ".toString())[0];
            return COMMAND_PACKAGE
                    .keySet()
                    .stream()
                    .map(Pattern::toString)
                    .anyMatch(patternText -> patternText.startsWith(command + " "));
      }


    public Command getCommand(final String input) throws InvalidInputException {
            if (relatedCommand(input)) {
                Terminal.printError("test");
                throw new InvalidInputException("invalid arguments");
            } else {
                throw new InvalidInputException("unknown command");
            }
            ...
     }

I am having trouble with giving the user a more specific error message. For example I have the commands add track <argument1> and add switch <argument1>. If the user just types in "add" he shouldn't get the error message "invalid arguments". Instead it should be "invalid command: either use add track or add switch). Since relatedCommand() is a boolean. How do I implement this efficiently?

  • Also, if you are looking just for the way of parsing the user input commands, have a look at this question: https://stackoverflow.com/questions/12595270/java-command-line-shell-with-auto-complete – shpikachu Feb 17 '20 at 12:02

1 Answers1

0

As you mentioned, currently the method returns a boolean, which is a two-state outcome. At the same time you are seeking for three-state outcome:

  1. command is known
  2. command is unknown
  3. there are several commands known for the prefix.

For the question given in regards to the way of returning the proper result, one option would be to return the collection of possible commands, which can represent the required three states:

  1. the collection consists of one element
  2. the collection is empty
  3. the collection consists of more than one element.

The changes to your original code can be like these:

private Collection<String> relatedCommand(String input) {
        // make sure the split afterwards has at least size one
        if (input.matches(" .*")) {
            return Collections.emptyList();
        }
        final String command = input.split(" ".toString())[0];
        return COMMAND_PACKAGE
                .keySet()
                .stream()
                .map(Pattern::toString)
                .filter(patternText -> patternText.startsWith(comman))
                .collect(Collectors.toList());
  }


public Command getCommand(final String input) throws InvalidInputException {
        Collection<String> commands = relatedCommand(input)
        if (commands.size() == 1) {
            Terminal.printError("test");
            throw new InvalidInputException("invalid arguments");
        } else if (commands.isEmpty()) {
            throw new InvalidInputException("unknown command");
        } else {
            ...
        }
 }
shpikachu
  • 147
  • 1
  • 3
  • 12
  • I appreciate your help. But what if the user just types in "add"? The output is invalid arguments then. It should tell the user that he typed the command incorrectly or "unknown command". –  Feb 17 '20 at 11:41
  • 1
    Do you mean, as there is no _space_ symbol, the `relatedCommand` method will exit soon, returning empty collection? In this case, that's the different logic should be taken care of: what is the reason of checking the space presence and checking the `COMMAND_PACKAGE` against the `command + " "`? We can continue the discussion in [chat] if you like. – shpikachu Feb 17 '20 at 11:50
  • Yes, I would love to. How can I join? –  Feb 17 '20 at 11:53
  • 1
    Sorry, looks like I don't have enough reputation for that, so we have to continue here in comments. As long as you need to map the first word of any command, you should't include a space symbol into the matching, I'll update my suggested solution. – shpikachu Feb 17 '20 at 11:59
  • The problem is that there are one-word, two-word and even three-word commands. For example "add track", "quit", "delete rolling stock". I don't know how to get the word-amount of every command. I created the method "getCommandNumber" which would return 2 in case of "add track". However, I am not sure how to implement that into the above methods –  Feb 17 '20 at 12:02
  • https://chat.stackoverflow.com/rooms/info/207979/display-better-error-messages-for-the-user?tab=general - Can you join via this link? –  Feb 17 '20 at 12:04
  • Could you please join the chat room again. I’ve another question. –  Feb 18 '20 at 16:49