Tab Completion - LilBroCodes/commander GitHub Wiki

Tab Completion

Tab completion is a powerful feature of Commander that helps players discover and use your commands more easily. This page explains how tab completion works in Commander and how to customize it for your commands.

Automatic Tab Completion

Commander provides automatic tab completion for your command structure. When you create a CommanderCommand with tab completion enabled, Commander will:

  1. Automatically complete subcommand names
  2. Provide parameter suggestions based on parameter types
  3. Show custom suggestions for parameters when provided

Enabling Tab Completion

Tab completion is enabled when you create a CommanderCommand by setting the tabComplete parameter to true:

// Create the command with tab completion enabled
CommanderCommand command = new CommanderCommand(rootNode, true);
command.register(plugin, "mycommand");

How Tab Completion Works

When a player starts typing a command and presses the Tab key, Commander processes the request as follows:

  1. For the first argument, Commander suggests available subcommands
  2. For subsequent arguments, Commander delegates to the appropriate subcommand node
  3. For CommandActionNode parameters, Commander provides suggestions based on the parameter type and any custom suggestion provider

Custom Parameter Suggestions

You can provide custom tab completion suggestions for parameters by supplying a suggestion provider when creating a TypedParameter.

Static Suggestions

// Parameter with static suggestions
TypedParameter colorParam = new TypedParameter(
    "color",
    ParameterType.STRING,
    () -> List.of("red", "green", "blue", "yellow")
);

Dynamic Suggestions

// Parameter with dynamic suggestions (online players)
TypedParameter playerParam = new TypedParameter(
    "player",
    ParameterType.STRING,
    () -> {
        // Return a list of online player names
        return Bukkit.getOnlinePlayers().stream()
            .map(Player::getName)
            .collect(Collectors.toList());
    }
);

Context-Aware Suggestions

While the suggestion provider doesn't have access to the command sender or current arguments, you can create context-aware suggestions by using class fields or other mechanisms.

public class MyPlugin extends JavaPlugin {
    private final Map<String, List<String>> contextualSuggestions = new HashMap<>();
    
    @Override
    public void onEnable() {
        // Initialize suggestions
        contextualSuggestions.put("world", List.of("overworld", "nether", "end"));
        contextualSuggestions.put("gamemode", List.of("survival", "creative", "adventure", "spectator"));
        
        // Create command with contextual suggestions
        List<TypedParameter> parameters = List.of(
            new TypedParameter("type", ParameterType.STRING, () -> {
                return List.of("world", "gamemode");
            }),
            new TypedParameter("value", ParameterType.STRING, () -> {
                // This is a simplification - in a real implementation,
                // you would need to track the current command context
                String currentType = getCurrentType();
                return contextualSuggestions.getOrDefault(currentType, List.of());
            })
        );
        
        // Create and register command
        // ...
    }
    
    private String getCurrentType() {
        // In a real implementation, you would track the current command context
        // This is just a placeholder
        return "world";
    }
}

Tab Completion for Special Parameter Types

By default, Commander doesn't provide suggestions. You can provide custom suggestions if needed, but Commander won't on it's own. There is one exception for this - for boolean type parameters, Commander automatically adds the "true" and "false" suggestion if you don't provide any.

Help Command Tab Completion

Commander automatically provides tab completion for the built-in help command:

  • When the player types /mycommand h and presses Tab, Commander will suggest help
  • When the player types /mycommand help and presses Tab, Commander will suggest tree

Best Practices

Suggestion Performance

  • Keep suggestion lists reasonably sized
  • Avoid expensive operations in suggestion providers
  • Cache suggestions when appropriate

User Experience

  • Provide meaningful suggestions that help players understand what's expected
  • Use consistent suggestion patterns across your plugin
  • Consider providing examples in your command descriptions

Testing

  • Test tab completion for all your commands
  • Verify that suggestions are appropriate for each parameter
  • Check that suggestions update correctly as the player types

Examples

Command with Multiple Parameters and Suggestions

// Define parameters with suggestions
List<TypedParameter> parameters = List.of(
    new TypedParameter("player", ParameterType.STRING, () -> {
        return Bukkit.getOnlinePlayers().stream()
            .map(Player::getName)
            .collect(Collectors.toList());
    }),
    new TypedParameter("item", ParameterType.STRING, () -> {
        return Arrays.stream(Material.values())
            .filter(Material::isItem)
            .map(Material::name)
            .map(String::toLowerCase)
            .collect(Collectors.toList());
    }),
    new TypedParameter("amount", ParameterType.INT, () -> {
        return List.of("1", "8", "16", "32", "64");
    })
);

// Create the command
CommandActionNode giveCommand = new CommandActionNode(
    "give",
    "Give items to a player",
    "MyPlugin",
    parameters,
    (sender, args) -> {
        // Command logic
    }
);

Command with Contextual Suggestions

// Define a map of regions and their teleport points
Map<String, List<String>> regionTeleports = new HashMap<>();
regionTeleports.put("spawn", List.of("hub", "shop", "pvp"));
regionTeleports.put("mines", List.of("coal", "iron", "gold", "diamond"));
regionTeleports.put("dungeons", List.of("easy", "medium", "hard", "boss"));

// Track the current region selection for each player
Map<UUID, String> playerRegionSelections = new HashMap<>();

// Define parameters with contextual suggestions
List<TypedParameter> parameters = List.of(
    new TypedParameter("region", ParameterType.STRING, () -> {
        return new ArrayList<>(regionTeleports.keySet());
    }),
    new TypedParameter("location", ParameterType.STRING, () -> {
        // This is simplified - in a real implementation,
        // you would need to track the current command context per player
        String currentRegion = getCurrentRegion();
        return regionTeleports.getOrDefault(currentRegion, List.of());
    })
);

// Create the command
CommandActionNode teleportCommand = new CommandActionNode(
    "teleport",
    "Teleport to a location",
    "MyPlugin",
    parameters,
    (sender, args) -> {
        if (sender instanceof Player player) {
            String region = (String) args.get(0);
            String location = (String) args.get(1);
            
            // Update the player's region selection for future tab completion
            playerRegionSelections.put(player.getUniqueId(), region);
            
            // Teleport logic
            player.sendMessage("Teleporting to " + location + " in " + region);
        }
    }
);

// Helper method to get the current region
private String getCurrentRegion() {
    // In a real implementation, you would get this from the player's context
    return "spawn";
}

Next Steps

Now that you understand tab completion, check out these pages for more information:

⚠️ **GitHub.com Fallback** ⚠️