diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..7723335e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,248 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +max_line_length = 120 +tab_width = 4 +ij_continuation_indent_size = 8 +ij_formatter_off_tag = @formatter:off +ij_formatter_on_tag = @formatter:on +ij_formatter_tags_enabled = true +ij_smart_tabs = false +ij_visual_guides = 130 +ij_wrap_on_typing = false + +[*.java] +max_line_length = 130 +ij_java_align_consecutive_assignments = false +ij_java_align_consecutive_variable_declarations = false +ij_java_align_group_field_declarations = false +ij_java_align_multiline_annotation_parameters = true +ij_java_align_multiline_array_initializer_expression = true +ij_java_align_multiline_assignment = false +ij_java_align_multiline_binary_operation = false +ij_java_align_multiline_chained_methods = true +ij_java_align_multiline_extends_list = false +ij_java_align_multiline_for = true +ij_java_align_multiline_method_parentheses = false +ij_java_align_multiline_parameters = true +ij_java_align_multiline_parameters_in_calls = true +ij_java_align_multiline_parenthesized_expression = false +ij_java_align_multiline_records = true +ij_java_align_multiline_resources = true +ij_java_align_multiline_ternary_operation = true +ij_java_align_multiline_text_blocks = false +ij_java_align_multiline_throws_list = false +ij_java_align_subsequent_simple_methods = false +ij_java_align_throws_keyword = false +ij_java_annotation_parameter_wrap = off +ij_java_array_initializer_new_line_after_left_brace = true +ij_java_array_initializer_right_brace_on_new_line = true +ij_java_array_initializer_wrap = on_every_item +ij_java_assert_statement_colon_on_next_line = false +ij_java_assert_statement_wrap = off +ij_java_assignment_wrap = off +ij_java_binary_operation_sign_on_next_line = false +ij_java_binary_operation_wrap = off +ij_java_blank_lines_after_anonymous_class_header = 0 +ij_java_blank_lines_after_class_header = 0 +ij_java_blank_lines_after_imports = 1 +ij_java_blank_lines_after_package = 1 +ij_java_blank_lines_around_class = 1 +ij_java_blank_lines_around_field = 0 +ij_java_blank_lines_around_field_in_interface = 0 +ij_java_blank_lines_around_initializer = 1 +ij_java_blank_lines_around_method = 1 +ij_java_blank_lines_around_method_in_interface = 1 +ij_java_blank_lines_before_class_end = 0 +ij_java_blank_lines_before_imports = 1 +ij_java_blank_lines_before_method_body = 0 +ij_java_blank_lines_before_package = 0 +ij_java_block_brace_style = end_of_line +ij_java_block_comment_at_first_column = true +ij_java_call_parameters_new_line_after_left_paren = false +ij_java_call_parameters_right_paren_on_new_line = false +ij_java_call_parameters_wrap = normal +ij_java_case_statement_on_separate_line = true +ij_java_catch_on_new_line = false +ij_java_class_annotation_wrap = split_into_lines +ij_java_class_brace_style = end_of_line +ij_java_class_count_to_use_import_on_demand = 9999999 +ij_java_class_names_in_javadoc = 1 +ij_java_do_not_indent_top_level_class_members = false +ij_java_do_not_wrap_after_single_annotation = true +ij_java_do_while_brace_force = always +ij_java_doc_add_blank_line_after_description = true +ij_java_doc_add_blank_line_after_param_comments = false +ij_java_doc_add_blank_line_after_return = false +ij_java_doc_add_p_tag_on_empty_lines = true +ij_java_doc_align_exception_comments = true +ij_java_doc_align_param_comments = true +ij_java_doc_do_not_wrap_if_one_line = false +ij_java_doc_enable_formatting = true +ij_java_doc_enable_leading_asterisks = true +ij_java_doc_indent_on_continuation = false +ij_java_doc_keep_empty_lines = true +ij_java_doc_keep_empty_parameter_tag = true +ij_java_doc_keep_empty_return_tag = true +ij_java_doc_keep_empty_throws_tag = true +ij_java_doc_keep_invalid_tags = true +ij_java_doc_param_description_on_new_line = false +ij_java_doc_preserve_line_breaks = false +ij_java_doc_use_throws_not_exception_tag = true +ij_java_else_on_new_line = false +ij_java_enum_constants_wrap = split_into_lines +ij_java_extends_keyword_wrap = off +ij_java_extends_list_wrap = normal +ij_java_field_annotation_wrap = split_into_lines +ij_java_finally_on_new_line = false +ij_java_for_brace_force = always +ij_java_for_statement_new_line_after_left_paren = false +ij_java_for_statement_right_paren_on_new_line = false +ij_java_for_statement_wrap = off +ij_java_generate_final_locals = true +ij_java_generate_final_parameters = true +ij_java_if_brace_force = always +ij_java_imports_layout = *, |, javax.**, java.**, |, $* +ij_java_indent_case_from_switch = true +ij_java_insert_inner_class_imports = false +ij_java_insert_override_annotation = true +ij_java_keep_blank_lines_before_right_brace = 2 +ij_java_keep_blank_lines_between_package_declaration_and_header = 2 +ij_java_keep_blank_lines_in_code = 2 +ij_java_keep_blank_lines_in_declarations = 2 +ij_java_keep_control_statement_in_one_line = true +ij_java_keep_first_column_comment = true +ij_java_keep_indents_on_empty_lines = false +ij_java_keep_line_breaks = true +ij_java_keep_multiple_expressions_in_one_line = false +ij_java_keep_simple_blocks_in_one_line = false +ij_java_keep_simple_classes_in_one_line = false +ij_java_keep_simple_lambdas_in_one_line = false +ij_java_keep_simple_methods_in_one_line = false +ij_java_label_indent_absolute = false +ij_java_label_indent_size = 0 +ij_java_lambda_brace_style = end_of_line +ij_java_layout_static_imports_separately = true +ij_java_line_comment_add_space = false +ij_java_line_comment_at_first_column = true +ij_java_method_annotation_wrap = split_into_lines +ij_java_method_brace_style = end_of_line +ij_java_method_call_chain_wrap = on_every_item +ij_java_method_parameters_new_line_after_left_paren = false +ij_java_method_parameters_right_paren_on_new_line = false +ij_java_method_parameters_wrap = on_every_item +ij_java_modifier_list_wrap = false +ij_java_names_count_to_use_import_on_demand = 9999999 +ij_java_new_line_after_lparen_in_record_header = false +ij_java_parameter_annotation_wrap = on_every_item +ij_java_parentheses_expression_new_line_after_left_paren = false +ij_java_parentheses_expression_right_paren_on_new_line = false +ij_java_place_assignment_sign_on_next_line = false +ij_java_prefer_longer_names = true +ij_java_prefer_parameters_wrap = false +ij_java_record_components_wrap = normal +ij_java_repeat_synchronized = true +ij_java_replace_instanceof_and_cast = false +ij_java_replace_null_check = true +ij_java_replace_sum_lambda_with_method_ref = true +ij_java_resource_list_new_line_after_left_paren = false +ij_java_resource_list_right_paren_on_new_line = false +ij_java_resource_list_wrap = off +ij_java_rparen_on_new_line_in_record_header = false +ij_java_space_after_closing_angle_bracket_in_type_argument = false +ij_java_space_after_colon = true +ij_java_space_after_comma = true +ij_java_space_after_comma_in_type_arguments = true +ij_java_space_after_for_semicolon = true +ij_java_space_after_quest = true +ij_java_space_after_type_cast = true +ij_java_space_before_annotation_array_initializer_left_brace = false +ij_java_space_before_annotation_parameter_list = false +ij_java_space_before_array_initializer_left_brace = false +ij_java_space_before_catch_keyword = true +ij_java_space_before_catch_left_brace = true +ij_java_space_before_catch_parentheses = true +ij_java_space_before_class_left_brace = true +ij_java_space_before_colon = true +ij_java_space_before_colon_in_foreach = true +ij_java_space_before_comma = false +ij_java_space_before_do_left_brace = true +ij_java_space_before_else_keyword = true +ij_java_space_before_else_left_brace = true +ij_java_space_before_finally_keyword = true +ij_java_space_before_finally_left_brace = true +ij_java_space_before_for_left_brace = true +ij_java_space_before_for_parentheses = true +ij_java_space_before_for_semicolon = false +ij_java_space_before_if_left_brace = true +ij_java_space_before_if_parentheses = true +ij_java_space_before_method_call_parentheses = false +ij_java_space_before_method_left_brace = true +ij_java_space_before_method_parentheses = false +ij_java_space_before_opening_angle_bracket_in_type_parameter = false +ij_java_space_before_quest = true +ij_java_space_before_switch_left_brace = true +ij_java_space_before_switch_parentheses = true +ij_java_space_before_synchronized_left_brace = true +ij_java_space_before_synchronized_parentheses = true +ij_java_space_before_try_left_brace = true +ij_java_space_before_try_parentheses = true +ij_java_space_before_type_parameter_list = false +ij_java_space_before_while_keyword = true +ij_java_space_before_while_left_brace = true +ij_java_space_before_while_parentheses = true +ij_java_space_inside_one_line_enum_braces = false +ij_java_space_within_empty_array_initializer_braces = false +ij_java_space_within_empty_method_call_parentheses = false +ij_java_space_within_empty_method_parentheses = false +ij_java_spaces_around_additive_operators = true +ij_java_spaces_around_assignment_operators = true +ij_java_spaces_around_bitwise_operators = true +ij_java_spaces_around_equality_operators = true +ij_java_spaces_around_lambda_arrow = true +ij_java_spaces_around_logical_operators = true +ij_java_spaces_around_method_ref_dbl_colon = false +ij_java_spaces_around_multiplicative_operators = true +ij_java_spaces_around_relational_operators = true +ij_java_spaces_around_shift_operators = true +ij_java_spaces_around_type_bounds_in_type_parameters = true +ij_java_spaces_around_unary_operator = false +ij_java_spaces_within_angle_brackets = false +ij_java_spaces_within_annotation_parentheses = false +ij_java_spaces_within_array_initializer_braces = false +ij_java_spaces_within_braces = false +ij_java_spaces_within_brackets = false +ij_java_spaces_within_cast_parentheses = false +ij_java_spaces_within_catch_parentheses = false +ij_java_spaces_within_for_parentheses = false +ij_java_spaces_within_if_parentheses = false +ij_java_spaces_within_method_call_parentheses = false +ij_java_spaces_within_method_parentheses = false +ij_java_spaces_within_parentheses = false +ij_java_spaces_within_switch_parentheses = false +ij_java_spaces_within_synchronized_parentheses = false +ij_java_spaces_within_try_parentheses = false +ij_java_spaces_within_while_parentheses = false +ij_java_special_else_if_treatment = true +ij_java_subclass_name_suffix = Impl +ij_java_ternary_operation_signs_on_next_line = false +ij_java_ternary_operation_wrap = on_every_item +ij_java_test_name_suffix = Test +ij_java_throws_keyword_wrap = off +ij_java_throws_list_wrap = normal +ij_java_use_external_annotations = false +ij_java_use_fq_class_names = false +ij_java_use_relative_indents = false +ij_java_use_single_class_imports = true +ij_java_variable_annotation_wrap = on_every_item +ij_java_visibility = public +ij_java_while_brace_force = always +ij_java_while_on_new_line = false +ij_java_wrap_comments = false +ij_java_wrap_first_method_in_call_chain = false +ij_java_wrap_long_lines = false diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 76e22beb..45f317c5 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ version: 2 updates: - - package-ecosystem: "maven" # See documentation for possible values - directory: "/" # Location of package manifests - schedule: - interval: "daily" + - package-ecosystem: "maven" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "daily" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8eeebdca..c27a2aad 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,54 +1,54 @@ name: "CodeQL" on: - push: - branches: [master, ] - pull_request: - # The branches below must be a subset of the branches above - branches: [master] - schedule: - - cron: '0 18 * * 3' + push: + branches: [master, ] + pull_request: + # The branches below must be a subset of the branches above + branches: [master] + schedule: + - cron: '0 18 * * 3' jobs: - analyse: - name: Analyse - runs-on: ubuntu-latest + analyse: + name: Analyse + runs-on: ubuntu-latest - steps: - - name: Checkout repository - uses: actions/checkout@v2 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v1 - # Override language selection by uncommenting this and choosing your languages - with: - languages: java + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages + with: + languages: java - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v1 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # âœī¸ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index c8aeb3a2..556452ee 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -4,21 +4,21 @@ name: Java CI with Maven on: - push: - branches: [ master ] - pull_request: - branches: [ master ] + push: + branches: [ master ] + pull_request: + branches: [ master ] jobs: - build: + build: - runs-on: ubuntu-latest + runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 - with: - java-version: 1.8 - - name: Build with Maven - run: mvn -B package --file pom.xml + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/commands-jline/pom.xml b/commands-jline/pom.xml index 4870c29c..b117fd18 100644 --- a/commands-jline/pom.xml +++ b/commands-jline/pom.xml @@ -1,6 +1,6 @@ - Commands diff --git a/commands-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java b/commands-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java index 99c6f43b..b266faef 100644 --- a/commands-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java +++ b/commands-jline/src/main/java/com/intellectualsites/commands/jline/JLineCommandManager.java @@ -27,12 +27,17 @@ import com.intellectualsites.commands.Command; import com.intellectualsites.commands.CommandManager; import com.intellectualsites.commands.CommandTree; import com.intellectualsites.commands.components.CommandComponent; +import com.intellectualsites.commands.components.StaticComponent; import com.intellectualsites.commands.exceptions.InvalidSyntaxException; import com.intellectualsites.commands.exceptions.NoSuchCommandException; import com.intellectualsites.commands.execution.CommandExecutionCoordinator; import com.intellectualsites.commands.internal.CommandRegistrationHandler; import com.intellectualsites.commands.parser.ComponentParseResult; -import org.jline.reader.*; +import org.jline.reader.Candidate; +import org.jline.reader.Completer; +import org.jline.reader.LineReader; +import org.jline.reader.LineReaderBuilder; +import org.jline.reader.ParsedLine; import org.jline.terminal.Terminal; import org.jline.terminal.TerminalBuilder; @@ -45,34 +50,63 @@ import java.util.function.Function; */ public class JLineCommandManager extends CommandManager implements Completer { + public JLineCommandManager(@Nonnull + final Function, CommandExecutionCoordinator> executionCoordinatorFunction) { + super(executionCoordinatorFunction, CommandRegistrationHandler.NULL_COMMAND_REGISTRATION_HANDLER); + } + public static void main(String[] args) throws Exception { // TODO: REMOVE THIS!!!! final JLineCommandManager jLineCommandManager = new JLineCommandManager(CommandExecutionCoordinator.simpleCoordinator()); - final Terminal terminal = TerminalBuilder.builder().dumb(true).build(); + final Terminal terminal = TerminalBuilder.builder().build(); LineReader lineReader = LineReaderBuilder.builder() - .completer(jLineCommandManager).terminal(terminal).appName("Test").build(); - boolean[] shouldStop = new boolean[] { false }; + .completer(jLineCommandManager) + .option(LineReader.Option.INSERT_TAB, false) + .terminal(terminal) + .appName("Test") + .build(); + boolean[] shouldStop = new boolean[]{false}; jLineCommandManager.registerCommand(Command.newBuilder("stop").withHandler(commandContext -> - shouldStop[0] = true).build()).registerCommand(Command.newBuilder("echo") - .withComponent(CommandComponent.ofType(String.class).named("string").asRequired() - .withParser(((commandContext, inputQueue) -> { - final StringBuilder stringBuilder = new StringBuilder(); - while (!inputQueue.isEmpty()) { - stringBuilder.append(inputQueue.remove()); - if (!inputQueue.isEmpty()) { - stringBuilder.append(" "); - } - } - return ComponentParseResult.success(stringBuilder.toString()); - })).build()) - .withHandler(commandContext -> commandContext.get("string").ifPresent(System.out::println)).build()); + shouldStop[0] = true).build()) + .registerCommand(Command.newBuilder("echo") + .withComponent( + CommandComponent.ofType(String.class).named("string").asRequired() + .withParser(((commandContext, inputQueue) -> { + final StringBuilder stringBuilder = new StringBuilder(); + while (!inputQueue.isEmpty()) { + stringBuilder.append(inputQueue.remove()); + if (!inputQueue.isEmpty()) { + stringBuilder.append(" "); + } + } + return ComponentParseResult.success( + stringBuilder.toString()); + })).build()) + .withHandler(commandContext -> commandContext.get("string") + .ifPresent(System.out::println)) + .build()) + .registerCommand(Command.newBuilder("test") + .withComponent(StaticComponent.required("one")) + .withHandler(commandContext -> System.out.println("Test (1)")) + .build()) + .registerCommand(Command.newBuilder("test") + .withComponent(StaticComponent.required("two")) + .withHandler(commandContext -> System.out.println("Test (2)")) + .build()); + System.out.println("Ready..."); while (!shouldStop[0]) { final String line = lineReader.readLine(); if (line == null || line.isEmpty() || !line.startsWith("/")) { + System.out.println("Empty line"); continue; } try { - jLineCommandManager.executeCommand(new JLineCommandSender(), line.substring(1)).join(); + final List suggestions = jLineCommandManager.suggest(new JLineCommandSender(), line.substring(1)); + for (final String suggestion : suggestions) { + System.out.printf("> %s\n", suggestion); + } + // jLineCommandManager.executeCommand(new JLineCommandSender(), line.substring(1)).join(); + // System.out.println("Successfully executed " + line); } catch (RuntimeException runtimeException) { if (runtimeException.getCause() instanceof NoSuchCommandException) { System.out.println("No such command"); @@ -89,13 +123,16 @@ public class JLineCommandManager extends CommandManager impl } } - public JLineCommandManager(@Nonnull final Function, CommandExecutionCoordinator> executionCoordinatorFunction) { - super(executionCoordinatorFunction, CommandRegistrationHandler.NULL_COMMAND_REGISTRATION_HANDLER); - } - @Override - public void complete(@Nonnull final LineReader lineReader, @Nonnull final ParsedLine parsedLine, @Nonnull final List list) { - // TODO: Implement + public void complete(@Nonnull final LineReader lineReader, + @Nonnull final ParsedLine parsedLine, + @Nonnull final List list) { + final String line = parsedLine.line(); + if (line == null || line.isEmpty() || !line.startsWith("/")) { + System.out.println("Cannot suggest: empty line"); + return; + } + System.out.printf("Trying to complete '%s'\n", line); } } diff --git a/pom.xml b/pom.xml index ad5a1636..e9bcfc3a 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ - 4.0.0 diff --git a/src/main/java/com/intellectualsites/commands/Command.java b/src/main/java/com/intellectualsites/commands/Command.java index 1fe8ed7a..5e74dcd9 100644 --- a/src/main/java/com/intellectualsites/commands/Command.java +++ b/src/main/java/com/intellectualsites/commands/Command.java @@ -29,7 +29,13 @@ import com.intellectualsites.commands.execution.CommandExecutionHandler; import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; -import java.util.*; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; /** * A command consists out of a chain of {@link com.intellectualsites.commands.components.CommandComponent command components}. @@ -38,10 +44,13 @@ import java.util.*; */ public class Command { - private final CommandComponent[] components; - private final CommandExecutionHandler commandExecutionHandler; + @Nonnull private final CommandComponent[] components; + @Nonnull private final CommandExecutionHandler commandExecutionHandler; + @Nullable private final Class senderType; - protected Command(@Nonnull final CommandComponent[] commandComponents, @Nonnull final CommandExecutionHandler commandExecutionHandler) { + protected Command(@Nonnull final CommandComponent[] commandComponents, + @Nonnull final CommandExecutionHandler commandExecutionHandler, + @Nullable final Class senderType) { this.components = Objects.requireNonNull(commandComponents, "Command components may not be null"); if (this.components.length == 0) { throw new IllegalArgumentException("At least one command component is required"); @@ -50,12 +59,15 @@ public class Command { boolean foundOptional = false; for (final CommandComponent component : this.components) { if (foundOptional && component.isRequired()) { - throw new IllegalArgumentException(String.format("Command component '%s' cannot be placed after an optional component", component.getName())); + throw new IllegalArgumentException( + String.format("Command component '%s' cannot be placed after an optional component", + component.getName())); } else if (!component.isRequired()) { foundOptional = true; } } this.commandExecutionHandler = commandExecutionHandler; + this.senderType = senderType; } /** @@ -66,8 +78,8 @@ public class Command { */ @Nonnull public static Builder newBuilder(@Nonnull final String commandName) { - return new Builder<>(Collections.singletonList(StaticComponent.required(commandName)), - new CommandExecutionHandler.NullCommandExecutionHandler<>()); + return new Builder<>(null, Collections.singletonList(StaticComponent.required(commandName)), + new CommandExecutionHandler.NullCommandExecutionHandler<>()); } /** @@ -75,7 +87,8 @@ public class Command { * * @return Copy of the command component array */ - @Nonnull @SuppressWarnings("ALL") + @Nonnull + @SuppressWarnings("ALL") public CommandComponent[] getComponents() { return (CommandComponent[]) Arrays.asList(this.components).toArray(); } @@ -85,10 +98,21 @@ public class Command { * * @return Command execution handler */ - @Nonnull public CommandExecutionHandler getCommandExecutionHandler() { + @Nonnull + public CommandExecutionHandler getCommandExecutionHandler() { return this.commandExecutionHandler; } + /** + * Get the required sender type, if one has been specified + * + * @return Required sender type + */ + @Nonnull + public Optional> getSenderType() { + return Optional.ofNullable(this.senderType); + } + /** * Get the longest chain of similar components for * two commands @@ -110,12 +134,16 @@ public class Command { public static class Builder { - private final List> commandComponents; - private final CommandExecutionHandler commandExecutionHandler; + @Nonnull private final List> commandComponents; + @Nonnull private final CommandExecutionHandler commandExecutionHandler; + @Nullable private final Class senderType; - private Builder(@Nonnull final List> commandComponents, @Nonnull final CommandExecutionHandler commandExecutionHandler) { + private Builder(@Nullable final Class senderType, + @Nonnull final List> commandComponents, + @Nonnull final CommandExecutionHandler commandExecutionHandler) { this.commandComponents = commandComponents; this.commandExecutionHandler = commandExecutionHandler; + this.senderType = senderType; } /** @@ -129,7 +157,7 @@ public class Command { public Builder withComponent(@Nonnull final CommandComponent component) { final List> commandComponents = new LinkedList<>(this.commandComponents); commandComponents.add(component); - return new Builder<>(commandComponents, this.commandExecutionHandler); + return new Builder<>(this.senderType, commandComponents, this.commandExecutionHandler); } /** @@ -140,7 +168,18 @@ public class Command { */ @Nonnull public Builder withHandler(@Nonnull final CommandExecutionHandler commandExecutionHandler) { - return new Builder<>(this.commandComponents, commandExecutionHandler); + return new Builder<>(this.senderType, this.commandComponents, commandExecutionHandler); + } + + /** + * Specify a required sender type + * + * @param senderType Required sender type + * @return New builder instance using the command execution handler + */ + @Nonnull + public Builder withSenderType(@Nonnull final Class senderType) { + return new Builder<>(senderType, this.commandComponents, this.commandExecutionHandler); } /** @@ -150,7 +189,8 @@ public class Command { */ @Nonnull public Command build() { - return new Command<>(this.commandComponents.toArray(new CommandComponent[0]), this.commandExecutionHandler); + return new Command<>(this.commandComponents.toArray(new CommandComponent[0]), this.commandExecutionHandler, + this.senderType); } } diff --git a/src/main/java/com/intellectualsites/commands/CommandManager.java b/src/main/java/com/intellectualsites/commands/CommandManager.java index 510b42af..b2a3996e 100644 --- a/src/main/java/com/intellectualsites/commands/CommandManager.java +++ b/src/main/java/com/intellectualsites/commands/CommandManager.java @@ -32,6 +32,7 @@ import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; import java.util.LinkedList; +import java.util.List; import java.util.Queue; import java.util.StringTokenizer; import java.util.concurrent.CompletableFuture; @@ -56,13 +57,23 @@ public abstract class CommandManager { } public CompletableFuture executeCommand(@Nonnull final C commandSender, @Nonnull final String input) { + final CommandContext context = new CommandContext<>(commandSender); + return this.commandExecutionCoordinator.coordinateExecution(context, tokenize(input)); + } + + public List suggest(@Nonnull final C commandSender, @Nonnull final String input) { + final CommandContext context = new CommandContext<>(commandSender); + return this.commandTree.getSuggestions(context, tokenize(input)); + } + + @Nonnull + private Queue tokenize(@Nonnull final String input) { final StringTokenizer stringTokenizer = new StringTokenizer(input, " "); final Queue tokens = new LinkedList<>(); while (stringTokenizer.hasMoreElements()) { tokens.add(stringTokenizer.nextToken()); } - final CommandContext context = new CommandContext<>(commandSender); - return this.commandExecutionCoordinator.coordinateExecution(context, tokens); + return tokens; } /** @@ -81,7 +92,8 @@ public abstract class CommandManager { * * @return Command syntax formatter */ - @Nonnull public CommandSyntaxFormatter getCommandSyntaxFormatter() { + @Nonnull + public CommandSyntaxFormatter getCommandSyntaxFormatter() { return this.commandSyntaxFormatter; } diff --git a/src/main/java/com/intellectualsites/commands/CommandTree.java b/src/main/java/com/intellectualsites/commands/CommandTree.java index 5909e6a0..c7385743 100644 --- a/src/main/java/com/intellectualsites/commands/CommandTree.java +++ b/src/main/java/com/intellectualsites/commands/CommandTree.java @@ -36,7 +36,14 @@ import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; +import java.util.Queue; import java.util.stream.Collectors; /** @@ -50,7 +57,8 @@ public class CommandTree { private final CommandManager commandManager; private final CommandRegistrationHandler commandRegistrationHandler; - private CommandTree(@Nonnull final CommandManager commandManager, @Nonnull final CommandRegistrationHandler commandRegistrationHandler) { + private CommandTree(@Nonnull final CommandManager commandManager, + @Nonnull final CommandRegistrationHandler commandRegistrationHandler) { this.commandManager = commandManager; this.commandRegistrationHandler = commandRegistrationHandler; } @@ -65,17 +73,19 @@ public class CommandTree { */ @Nonnull public static CommandTree newTree(@Nonnull final CommandManager commandManager, - @Nonnull final CommandRegistrationHandler commandRegistrationHandler) { + @Nonnull + final CommandRegistrationHandler commandRegistrationHandler) { return new CommandTree<>(commandManager, commandRegistrationHandler); } - public Optional> parse(@Nonnull final CommandContext commandContext, @Nonnull final Queue args) throws NoSuchCommandException { + public Optional> parse(@Nonnull final CommandContext commandContext, @Nonnull final Queue args) throws + NoSuchCommandException { return parseCommand(commandContext, args, this.internalTree); } - private Optional> parseCommand(@Nonnull final CommandContext commandContext, @Nonnull final Queue commandQueue, - @Nonnull final Node> root) throws NoSuchCommandException { - + private Optional> parseCommand(@Nonnull final CommandContext commandContext, + @Nonnull final Queue commandQueue, + @Nonnull final Node> root) throws NoSuchCommandException { final List>> children = root.getChildren(); if (children.size() == 1 && !(children.get(0).getValue() instanceof StaticComponent)) { // The value has to be a variable @@ -84,12 +94,21 @@ public class CommandTree { if (commandQueue.isEmpty()) { if (child.isLeaf()) { /* Not enough arguments */ - throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter().apply(Arrays.asList(child.getValue().getOwningCommand().getComponents())), - commandContext.getCommandSender(), this.getChain(root).stream().map(Node::getValue).collect(Collectors.toList())); + throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() + .apply(Arrays.asList(child.getValue() + .getOwningCommand() + .getComponents())), + commandContext.getCommandSender(), this.getChain(root) + .stream() + .map(Node::getValue) + .collect(Collectors.toList())); } else { throw new NoSuchCommandException(commandContext.getCommandSender(), - this.getChain(root).stream().map(Node::getValue).collect(Collectors.toList()), - ""); + this.getChain(root) + .stream() + .map(Node::getValue) + .collect(Collectors.toList()), + ""); } } final ComponentParseResult result = child.getValue().getParser().parse(commandContext, commandQueue); @@ -100,8 +119,15 @@ public class CommandTree { return Optional.ofNullable(child.getValue().getOwningCommand()); } else { /* Too many arguments. We have a unique path, so we can send the entire context */ - throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter().apply(Arrays.asList(child.getValue().getOwningCommand().getComponents())), - commandContext.getCommandSender(), this.getChain(root).stream().map(Node::getValue).collect(Collectors.toList())); + throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() + .apply(Arrays.asList(child.getValue() + .getOwningCommand() + .getComponents())), + commandContext.getCommandSender(), this.getChain(root) + .stream() + .map(Node::getValue) + .collect( + Collectors.toList())); } } else { return this.parseCommand(commandContext, commandQueue, child); @@ -111,7 +137,6 @@ public class CommandTree { } } } - /* There are 0 or more static components as children. No variable child components are present */ if (children.isEmpty()) { /* We are at the bottom. Check if there's a command attached, in which case we're done */ @@ -120,44 +145,23 @@ public class CommandTree { return Optional.of(root.getValue().getOwningCommand()); } else { /* Too many arguments. We have a unique path, so we can send the entire context */ - throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter().apply(Arrays.asList(root.getValue().getOwningCommand().getComponents())), - commandContext.getCommandSender(), this.getChain(root).stream().map(Node::getValue).collect(Collectors.toList())); + throw new InvalidSyntaxException(this.commandManager.getCommandSyntaxFormatter() + .apply(Arrays.asList(root.getValue() + .getOwningCommand() + .getComponents())), + commandContext.getCommandSender(), this.getChain(root) + .stream() + .map(Node::getValue) + .collect(Collectors.toList())); } } else { /* TODO: Indicate that we could not resolve the command here */ - final List> components = this.getChain(root).stream().map(Node::getValue).collect(Collectors.toList()); + final List> components = this.getChain(root) + .stream() + .map(Node::getValue) + .collect(Collectors.toList()); } } else { - /* - final String popped = commandQueue.poll(); - if (popped == null) { - return Optional.empty(); - } - - int low = 0; - int high = children.size() - 1; - - while (low <= high) { - int mid = (low + high) / 2; - - final Node> node = children.get(mid); - assert node.getValue() != null; - - final int comparison = node.getValue().getName().compareToIgnoreCase(popped); - if (comparison < 0) { - low = mid + 1; - } else if (comparison > 0) { - high = mid - 1; - } else { - if (node.isLeaf()) { - return Optional.ofNullable(node.getValue().getOwningCommand()); - } else { - return parseCommand(commandSender, commandQueue, node); - } - } - } - */ - final Iterator>> childIterator = root.getChildren().iterator(); if (childIterator.hasNext()) { while (childIterator.hasNext()) { @@ -171,16 +175,86 @@ public class CommandTree { } } } - /* We could not find a match */ throw new NoSuchCommandException(commandContext.getCommandSender(), - getChain(root).stream().map(Node::getValue).collect(Collectors.toList()), - java.util.Objects.requireNonNull(commandQueue.peek())); + getChain(root).stream().map(Node::getValue).collect(Collectors.toList()), + stringOrEmpty(commandQueue.peek())); } - return Optional.empty(); } + public List getSuggestions(@Nonnull final CommandContext context, @Nonnull final Queue commandQueue) { + return getSuggestions(context, commandQueue, this.internalTree); + } + + public List getSuggestions(@Nonnull final CommandContext commandContext, + @Nonnull final Queue commandQueue, + @Nonnull final Node> root) { + final List>> children = root.getChildren(); + if (children.size() == 1 && !(children.get(0).getValue() instanceof StaticComponent)) { + // The value has to be a variable + final Node> child = children.get(0); + if (child.getValue() != null) { + if (commandQueue.isEmpty()) { + if (child.isLeaf()) { + /* Child is leaf, and so no suggestions should be sent */ + return Collections.emptyList(); + } else { + /* Send all suggestions */ + return child.getValue().getParser().suggestions(commandContext, ""); + } + } + final ComponentParseResult result = child.getValue().getParser().parse(commandContext, commandQueue); + if (result.getParsedValue().isPresent()) { + if (child.isLeaf()) { + /* Child is leaf, and so no suggestions should be sent */ + return Collections.emptyList(); + } + commandContext.store(child.getValue().getName(), result.getParsedValue().get()); + return this.getSuggestions(commandContext, commandQueue, child); + } else if (result.getFailure().isPresent()) { + /* TODO: Return error */ + return Collections.emptyList(); + } + } + } + /* There are 0 or more static components as children. No variable child components are present */ + if (children.isEmpty()) { + return Collections.emptyList(); + } else { + final Iterator>> childIterator = root.getChildren().iterator(); + if (childIterator.hasNext()) { + while (childIterator.hasNext()) { + final Node> child = childIterator.next(); + if (child.getValue() != null) { + final ComponentParseResult result = child.getValue().getParser().parse(commandContext, commandQueue); + if (result.getParsedValue().isPresent()) { + return this.getSuggestions(commandContext, commandQueue, child); + } else if (result.getFailure().isPresent() && root.children.size() == 1) { + } + } + } + } + final List suggestions = new LinkedList<>(); + for (final Node> component : root.getChildren()) { + if (component.getValue() == null) { + continue; + } + suggestions.addAll( + component.getValue().getParser().suggestions(commandContext, stringOrEmpty(commandQueue.peek()))); + } + return suggestions; + } + } + + @Nonnull + private String stringOrEmpty(@Nullable final String string) { + if (string == null) { + return ""; + } + return string; + } + /** * Insert a new command into the command tree * @@ -196,6 +270,7 @@ public class CommandTree { if (node.children.size() > 0) { node.children.sort(Comparator.comparing(Node::getValue)); } + tempNode.setParent(node); node = tempNode; } if (node.getValue() != null) { @@ -260,7 +335,7 @@ public class CommandTree { Node> tail = end; while (tail != null) { chain.add(tail); - tail = end.getParent(); + tail = tail.getParent(); } return Lists.reverse(chain); } @@ -324,15 +399,15 @@ public class CommandTree { return Objects.hashCode(getChildren(), getValue()); } - public void setParent(@Nullable final Node parent) { - this.parent = parent; - } - @Nullable public Node getParent() { return this.parent; } + public void setParent(@Nullable final Node parent) { + this.parent = parent; + } + } } diff --git a/src/main/java/com/intellectualsites/commands/components/CommandComponent.java b/src/main/java/com/intellectualsites/commands/components/CommandComponent.java index 1d4575af..43e904eb 100644 --- a/src/main/java/com/intellectualsites/commands/components/CommandComponent.java +++ b/src/main/java/com/intellectualsites/commands/components/CommandComponent.java @@ -64,11 +64,11 @@ public class CommandComponent implements Comparable< private Command owningCommand; CommandComponent(final boolean required, @Nonnull final String name, - @Nonnull final ComponentParser parser) { + @Nonnull final ComponentParser parser) { this.required = required; this.name = Objects.requireNonNull(name, "Name may not be null"); if (!NAME_PATTERN.asPredicate().test(name)) { - throw new IllegalArgumentException("Name must be alphanumeric"); + throw new IllegalArgumentException("Name must be alphanumeric"); } this.parser = Objects.requireNonNull(parser, "Parser may not be null"); } @@ -77,11 +77,12 @@ public class CommandComponent implements Comparable< * Create a new command component * * @param clazz Argument class - * @param Command sender type - * @param Argument Type + * @param Command sender type + * @param Argument Type * @return Component builder */ - @Nonnull public static CommandComponent.Builder ofType(@Nonnull final Class clazz) { + @Nonnull + public static CommandComponent.Builder ofType(@Nonnull final Class clazz) { return new Builder<>(); } @@ -99,7 +100,8 @@ public class CommandComponent implements Comparable< * * @return Component name */ - @Nonnull public String getName() { + @Nonnull + public String getName() { return this.name; } @@ -109,11 +111,14 @@ public class CommandComponent implements Comparable< * * @return Command parser */ - @Nonnull public ComponentParser getParser() { + @Nonnull + public ComponentParser getParser() { return this.parser; } - @Nonnull @Override public String toString() { + @Nonnull + @Override + public String toString() { return String.format("CommandComponent{name=%s}", this.name); } @@ -122,7 +127,8 @@ public class CommandComponent implements Comparable< * * @return Owning command */ - @Nullable public Command getOwningCommand() { + @Nullable + public Command getOwningCommand() { return this.owningCommand; } @@ -188,7 +194,8 @@ public class CommandComponent implements Comparable< * @param name Alphanumeric component name * @return Builder instance */ - @Nonnull public Builder named(@Nonnull final String name) { + @Nonnull + public Builder named(@Nonnull final String name) { this.name = name; return this; } @@ -202,7 +209,8 @@ public class CommandComponent implements Comparable< * * @return Builder instance */ - @Nonnull public Builder asRequired() { + @Nonnull + public Builder asRequired() { this.required = true; return this; } @@ -216,7 +224,8 @@ public class CommandComponent implements Comparable< * * @return Builder instance */ - @Nonnull public Builder asOptional() { + @Nonnull + public Builder asOptional() { this.required = false; return this; } @@ -227,7 +236,8 @@ public class CommandComponent implements Comparable< * @param parser Component parser * @return Builder instance */ - @Nonnull public Builder withParser(@Nonnull final ComponentParser parser) { + @Nonnull + public Builder withParser(@Nonnull final ComponentParser parser) { this.parser = Objects.requireNonNull(parser, "Parser may not be null"); return this; } @@ -237,7 +247,8 @@ public class CommandComponent implements Comparable< * * @return Constructed component */ - @Nonnull public CommandComponent build() { + @Nonnull + public CommandComponent build() { return new CommandComponent<>(this.required, this.name, this.parser); } diff --git a/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java b/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java index 39ff537a..bea60d9f 100644 --- a/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java +++ b/src/main/java/com/intellectualsites/commands/components/CommandSyntaxFormatter.java @@ -27,10 +27,13 @@ import javax.annotation.Nonnull; import java.util.List; import java.util.function.Function; -@FunctionalInterface public interface CommandSyntaxFormatter extends Function>, String> { +@FunctionalInterface +public interface CommandSyntaxFormatter extends Function>, String> { CommandSyntaxFormatter STANDARD_COMMAND_SYNTAX_FORMATTER = new StandardCommandSyntaxFormatter(); - @Override @Nonnull String apply(@Nonnull List> commandComponents); + @Override + @Nonnull + String apply(@Nonnull List> commandComponents); } diff --git a/src/main/java/com/intellectualsites/commands/components/StaticComponent.java b/src/main/java/com/intellectualsites/commands/components/StaticComponent.java index 029891ab..3a1238d8 100644 --- a/src/main/java/com/intellectualsites/commands/components/StaticComponent.java +++ b/src/main/java/com/intellectualsites/commands/components/StaticComponent.java @@ -30,21 +30,28 @@ import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; +import java.util.List; +import java.util.Locale; import java.util.Queue; import java.util.Set; public final class StaticComponent extends CommandComponent { - private StaticComponent(final boolean required, @Nonnull final String name, @Nonnull final String ... aliases) { + private StaticComponent(final boolean required, @Nonnull final String name, @Nonnull final String... aliases) { super(required, name, new StaticComponentParser<>(name, aliases)); } - @Nonnull public static StaticComponent required(@Nonnull final String name, @Nonnull final String ... aliases) { + @Nonnull + public static StaticComponent required(@Nonnull final String name, + @Nonnull final String... aliases) { return new StaticComponent<>(true, name, aliases); } - @Nonnull public static StaticComponent optional(@Nonnull final String name, @Nonnull final String ... aliases) { + @Nonnull + public static StaticComponent optional(@Nonnull final String name, + @Nonnull final String... aliases) { return new StaticComponent<>(false, name, aliases); } @@ -54,12 +61,15 @@ public final class StaticComponent extends CommandCompo private final String name; private final Set acceptedStrings = new HashSet<>(); - private StaticComponentParser(@Nonnull final String name, @Nonnull final String ... aliases) { + private StaticComponentParser(@Nonnull final String name, @Nonnull final String... aliases) { this.acceptedStrings.add(this.name = name); this.acceptedStrings.addAll(Arrays.asList(aliases)); } - @Nonnull @Override public ComponentParseResult parse(@Nonnull final CommandContext commandContext, @Nonnull final Queue inputQueue) { + @Nonnull + @Override + public ComponentParseResult parse(@Nonnull final CommandContext commandContext, + @Nonnull final Queue inputQueue) { final String string = inputQueue.peek(); if (string == null) { return ComponentParseResult.failure(this.name); @@ -74,6 +84,15 @@ public final class StaticComponent extends CommandCompo return ComponentParseResult.failure(this.name); } + @Nonnull + @Override + public List suggestions(@Nonnull final CommandContext commandContext, @Nonnull final String input) { + if (this.name.toLowerCase(Locale.ENGLISH).startsWith(input)) { + return Collections.singletonList(this.name); + } + return Collections.emptyList(); + } + } } diff --git a/src/main/java/com/intellectualsites/commands/context/CommandContext.java b/src/main/java/com/intellectualsites/commands/context/CommandContext.java index ef07fed2..4f3e78a3 100644 --- a/src/main/java/com/intellectualsites/commands/context/CommandContext.java +++ b/src/main/java/com/intellectualsites/commands/context/CommandContext.java @@ -70,8 +70,7 @@ public class CommandContext { public Optional get(@Nonnull final String key) { final Object value = this.internalStorage.get(key); if (value != null) { - @SuppressWarnings("ALL") - final T castedValue = (T) value; + @SuppressWarnings("ALL") final T castedValue = (T) value; return Optional.of(castedValue); } else { return Optional.empty(); diff --git a/src/main/java/com/intellectualsites/commands/exceptions/CommandParseException.java b/src/main/java/com/intellectualsites/commands/exceptions/CommandParseException.java index 3584c188..6c62c670 100644 --- a/src/main/java/com/intellectualsites/commands/exceptions/CommandParseException.java +++ b/src/main/java/com/intellectualsites/commands/exceptions/CommandParseException.java @@ -44,7 +44,8 @@ public class CommandParseException extends IllegalArgumentException { * @param commandSender Sender who executed the command * @param currentChain Chain leading up to the exception */ - protected CommandParseException(@Nonnull final CommandSender commandSender, @Nonnull final List> currentChain) { + protected CommandParseException(@Nonnull final CommandSender commandSender, + @Nonnull final List> currentChain) { this.commandSender = commandSender; this.currentChain = currentChain; } diff --git a/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java b/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java index 0a7eb8f2..3b575004 100644 --- a/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java +++ b/src/main/java/com/intellectualsites/commands/exceptions/InvalidSyntaxException.java @@ -33,12 +33,15 @@ public class InvalidSyntaxException extends CommandParseException { private final String correctSyntax; - public InvalidSyntaxException(@Nonnull final String correctSyntax, @Nonnull final CommandSender commandSender, @Nonnull final List> currentChain) { + public InvalidSyntaxException(@Nonnull final String correctSyntax, + @Nonnull final CommandSender commandSender, + @Nonnull final List> currentChain) { super(commandSender, currentChain); this.correctSyntax = correctSyntax; } - @Nonnull public String getCorrectSyntax() { + @Nonnull + public String getCorrectSyntax() { return this.correctSyntax; } diff --git a/src/main/java/com/intellectualsites/commands/exceptions/NoSuchCommandException.java b/src/main/java/com/intellectualsites/commands/exceptions/NoSuchCommandException.java index 92b025b3..407d9f33 100644 --- a/src/main/java/com/intellectualsites/commands/exceptions/NoSuchCommandException.java +++ b/src/main/java/com/intellectualsites/commands/exceptions/NoSuchCommandException.java @@ -44,8 +44,9 @@ public class NoSuchCommandException extends CommandParseException { * @param currentChain Chain leading up to the exception * @param command Entered command (following the command chain) */ - public NoSuchCommandException(@Nonnull final CommandSender commandSender, @Nonnull final List> currentChain, - @Nonnull final String command) { + public NoSuchCommandException(@Nonnull final CommandSender commandSender, + @Nonnull final List> currentChain, + @Nonnull final String command) { super(commandSender, currentChain); this.suppliedCommand = command; } @@ -55,7 +56,8 @@ public class NoSuchCommandException extends CommandParseException { * * @return Supplied command */ - @Nonnull public String getSuppliedCommand() { + @Nonnull + public String getSuppliedCommand() { return this.suppliedCommand; } diff --git a/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java b/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java index c6e6fa17..2d102c8b 100644 --- a/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java +++ b/src/main/java/com/intellectualsites/commands/execution/CommandExecutionCoordinator.java @@ -71,7 +71,8 @@ public abstract class CommandExecutionCoordinator { * * @return Command tree */ - @Nonnull protected CommandTree getCommandTree() { + @Nonnull + protected CommandTree getCommandTree() { return this.commandTree; } @@ -83,7 +84,8 @@ public abstract class CommandExecutionCoordinator { } @Override - public CompletableFuture coordinateExecution(@Nonnull CommandContext commandContext, @Nonnull Queue input) { + public CompletableFuture coordinateExecution(@Nonnull CommandContext commandContext, + @Nonnull Queue input) { final CompletableFuture completableFuture = new CompletableFuture<>(); try { this.getCommandTree().parse(commandContext, input).ifPresent( diff --git a/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java b/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java index 7b805ac2..2da19edd 100644 --- a/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java +++ b/src/main/java/com/intellectualsites/commands/execution/CommandExecutionHandler.java @@ -34,7 +34,8 @@ import javax.annotation.Nonnull; * * @param Command sender type */ -@FunctionalInterface public interface CommandExecutionHandler { +@FunctionalInterface +public interface CommandExecutionHandler { /** * Handle command execution diff --git a/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java b/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java index a2cbb03c..c8150bda 100644 --- a/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java +++ b/src/main/java/com/intellectualsites/commands/internal/CommandRegistrationHandler.java @@ -32,7 +32,8 @@ import javax.annotation.Nonnull; * platform the library is used in. This can do nothing, if * the target platform does not have its own concept of commands */ -@FunctionalInterface public interface CommandRegistrationHandler { +@FunctionalInterface +public interface CommandRegistrationHandler { /** * Command registration handler that does nothing @@ -44,7 +45,7 @@ import javax.annotation.Nonnull; * * @param command Command to register * @return {@code true} if the command was registered successfully, - * else {@code false} + * else {@code false} */ boolean registerCommand(@Nonnull final Command command); diff --git a/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java b/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java index aa07116c..637310eb 100644 --- a/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java +++ b/src/main/java/com/intellectualsites/commands/parser/ComponentParseResult.java @@ -31,17 +31,21 @@ public abstract class ComponentParseResult { private ComponentParseResult() { } - @Nonnull public static ComponentParseResult failure(@Nonnull final String failure) { + @Nonnull + public static ComponentParseResult failure(@Nonnull final String failure) { return new ParseFailure<>(failure); } - @Nonnull public static ComponentParseResult success(@Nonnull final T value) { + @Nonnull + public static ComponentParseResult success(@Nonnull final T value) { return new ParseSuccess<>(value); } - @Nonnull public abstract Optional getParsedValue(); + @Nonnull + public abstract Optional getParsedValue(); - @Nonnull public abstract Optional getFailure(); + @Nonnull + public abstract Optional getFailure(); private static final class ParseSuccess extends ComponentParseResult { @@ -52,11 +56,15 @@ public abstract class ComponentParseResult { this.value = value; } - @Nonnull @Override public Optional getParsedValue() { + @Nonnull + @Override + public Optional getParsedValue() { return Optional.of(this.value); } - @Nonnull @Override public Optional getFailure() { + @Nonnull + @Override + public Optional getFailure() { return Optional.empty(); } @@ -71,11 +79,15 @@ public abstract class ComponentParseResult { this.failure = failure; } - @Nonnull @Override public Optional getParsedValue() { + @Nonnull + @Override + public Optional getParsedValue() { return Optional.empty(); } - @Nonnull @Override public Optional getFailure() { + @Nonnull + @Override + public Optional getFailure() { return Optional.of(this.failure); } } diff --git a/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java b/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java index 64d600cf..6d330c90 100644 --- a/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java +++ b/src/main/java/com/intellectualsites/commands/parser/ComponentParser.java @@ -27,6 +27,8 @@ import com.intellectualsites.commands.context.CommandContext; import com.intellectualsites.commands.sender.CommandSender; import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.List; import java.util.Queue; @FunctionalInterface @@ -42,4 +44,9 @@ public interface ComponentParser { @Nonnull ComponentParseResult parse(@Nonnull CommandContext commandContext, @Nonnull Queue inputQueue); + @Nonnull + default List suggestions(@Nonnull final CommandContext commandContext, @Nonnull final String input) { + return Collections.emptyList(); + } + }