Question

Discussion in 'CommandHelper' started by Tikkle, Aug 8, 2017.

  1. Tikkle

    Tikkle New Member

    How can i make my custom commands have a tab-complete option?
  2. PseudoKnight

    PseudoKnight Well-Known Member

    You need to use register_command() with a 'tabcompleter' closure. Return an array of tab completions appropriate for the arguments sent to the closure. By default registered commands will tab complete player names.
    PHP:
    register_command('worldborder', array(
        'tabcompleter': closure(@alias, @sender, @args, @info) {
            if(array_size(@args) == 1) {
                return(array('set', 'center', 'damage', 'warning', 'get', 'add'));
            }
        }
    ));
    This is a simplistic example and will always return that list regardless of what they entered first. So we have to filter strings in the list that start with what is entered as the argument if we want to do true tab completion.
    PHP:
    register_command('worldborder', array(
        'tabcompleter': closure(@alias, @sender, @args, @info) {
            if(array_size(@args) == 1) {
                @options = array_filter(array('set', 'center', 'damage', 'warning', 'get', 'add'), closure(@key, @value) {
                    return(string_starts_with(@value, @args[0]));
                });
                return(@options);
            }
        }
    ));
    This might look complicated, depending on your proficiency and familiarity with closures in particular. To break it down, register_command() i sent an array of options for the command. One of those is 'tabcompleter', which requires a closure. A closure is a section of code that you can pass around and run at a different time you created it -- in this case, when someone tries to tabcomplete the command. This particular closure always has 3 values sent to it (@info isn't used yet). You can name these whatever you want, but I went with @alias, @sender, and @args. @args are what the player entered after the command. So, we check if the number of @args is 1, so we know it's the first part of the command after /worldborder that they're tab completing. So we create an array of possible options. (eg. set, center, damage, etc) Then we use array_filter() or other method to reduce it to only the strings that start with the first argument as it was entered by the player. Like tabcompleter, array_filter()'s closure is always given 2 variables, which we name @key and @value. And if we return() true in this closure, that value is kept in the array.

    If you want to tabcomplete player names only, then good news: you don't need to set a tabcompleter at all. You just need to register the command.

    I hope this makes sense. I think this is one of the more unnecessarily complicated bits for commands. I wouldn't mind adding a simpler way to do it for most commands that only need to filter an array for a given argument.
  3. Tikkle

    Tikkle New Member


    Which file am i putting this in? aliases.msa?
  4. PseudoKnight

    PseudoKnight Well-Known Member

    No, *.msa files are for alias definitions only. So unless you want to run an alias to register this command, you want to put it in a *.ms file that isn't auto_include.ms.