User Defined Tab Completion

You can provide a tab key completion function for the commands you define with alias and beacon_command_register by using a convention of: a function named
ExampleCmd_BEACON_CONSOLE_TAB_KEY
where ExampleCmd is your command name appended with "_BEACON_CONSOLE_TAB_KEY".

The function name is called when Beacon Console users use tab completion for that command.

The function must respond with a list of tab character delimited responses to use based on the command entered on the command line.

Example

            debug(5);
# =====================================================
# ExampleCmd: Three parameters with static values
# =====================================================
# $1 = bid [Beacon ID]
# $2 = parm1 [first1|first2|first3]
# $3 = parm2 [second1|second2|second3]
# $4 = parm3 [third1|third2|third3]
# =====================================================
alias ExampleCmd {
    blog($1, "Running Example Command 1: " . @_);
    return;
}
 
beacon_command_register(
    "ExampleCmd",
    "Description of ExampleCmd",
    "Synopsis: ExampleCmd [first1|first2|first3] [second1|second2|second3] [third1|third2|third3]"
);
 
# =====================================================
# Customize beacon console tab key completion responses
# =====================================================
# Returns: Tab character delimiter set of responses for the beacon console
#          to use as it cycles through the tab key presses.
#
# Response Details:
#  - Each "response-item" must contain the complete/current command text.
#  - Responses are filtered when cmd line ends with partial parameter
#
# Response format: "[response-item-1][tab][response-item-2][tab][response-item-3][tab]..."
#
# Command: ExampleCmd [first1|first2|first3] [second1|second2|second3] [third1|third2|third3]
#
# When Tab pressed for command line: "ExampleCmd first2 "
# Response: "ExampleCmd first2 second1" + [tab]
#           "ExampleCmd first2 second2" + [tab]
#           "ExampleCmd first2 second3"
# =====================================================
# $1 = BID (Beacon ID)
# $2 = command line text from beacon console...
# =====================================================
set ExampleCmd_BEACON_CONSOLE_TAB_KEY {
    blog($1, "Processing ExampleCmd_BEACON_CONSOLE_TAB_KEY tab completion BID: $1 Text: \'$2\'");
    return tabkey_ExampleCmd($1, $2);
}
 
# =====================================================
# Process Tab Key for ExampleCmd
# =====================================================
# $1 = BID (Beacon ID)
# $2 = command line text from beacon console...
# =====================================================
sub tabkey_ExampleCmd {
    local('$filtering $prefix');
    local('@tokenz');
 
    local('@p1 @p2 @p3');
    @p1 = @("first1", "first2", "first3");
    @p2 = @("second1", "second2", "second3");
    @p3 = @("third1", "third2", "third3");
 
    # ------------------------------------------------------
    # blog($1, "ExampleCmd Prompt Text: \'$2\'");
    # ------------------------------------------------------
 
    @tokenz = split(" ", $2);
 
    # Does the text end with a "space"?
    if ($2 ismatch '^.* $') {
        # If SO, we are prompting for the next parameter WITHOUT USING a filter...
        $filtering = false;
    } else {
        # If NOT, we are prompting for the next parameter USING a filter...
        $filtering = true;
    }
 
    # =====================================
    # Prompting the command's FIRST parameter WITHOUT a filter...
    # =====================================
    if (size(@tokenz) == 1) {
        $prefix = @tokenz[0] . " ";
        return filterArgs($1, $prefix, "", @p1);
    }
 
    # =====================================
    # Prompting the command's FIRST parameter WITH a filter...
    # =====================================
    if ((size(@tokenz) == 2) && ($filtering == true)) {
        $prefix = @tokenz[0] . " ";
        return filterArgs($1, $prefix, @tokenz[1], @p1);
    }
 
    # =====================================
    # Prompting the command's SECOND parameter WITHOUT a filter...
    # =====================================
    if (size(@tokenz) == 2 && ($filtering == false)) {
        $prefix = @tokenz[0] . " " .@tokenz[1] . " ";
        return filterArgs($1, $prefix, "", @p2);
    }
 
    # =====================================
    # Prompting the command's SECOND parameter WITH a filter...
    # =====================================
    if ((size(@tokenz) == 3) && ($filtering == true)) {
        $prefix = @tokenz[0] . " " . @tokenz[1] . " ";
        return filterArgs($1, $prefix, @tokenz[2], @p2);
    } 
 
    # =====================================
    # Prompting the command's THIRD parameter WITHOUT a filter...
    # =====================================
    if (size(@tokenz) == 3 && ($filtering == false)) {
        $prefix = @tokenz[0] . " " . @tokenz[1] . " " . @tokenz[2] . " ";
        return filterArgs($1, $prefix, "", @p3);
    }
 
    # =====================================
    # Prompting the command's THIRD parameter WITH a filter...
    # =====================================
    if ((size(@tokenz) == 4) && ($filtering == true)) {
        $prefix = @tokenz[0] . " " .@tokenz[1] . " " . @tokenz[2] . " ";
        return filterArgs($1, $prefix, @tokenz[3], @p3);
    }
 
    return "";
}
 
# =====================================================
# Return a set of responses for the pressed tab key...
# =====================================================
# $1 = BID (Beacon ID)
# $2 = $prefix [pre-pended to command line items in the response]
# $3 = $filter [subsets response items using "starts with filter"]
# $4 = @values [list of potential parameter values to filter]
# =====================================================
sub filterArgs {
    local('$bid $prefix $filter $output');
    local('$x $delimiter $findex');
    local('@values');
 
    $bid = $1;
    $prefix = $2;
    $filter = $3;
    @values = $4;
 
    # blog($1, "Filtering Values BID: $bid Prefix: \'$prefix\' Filter: $filter Values: " . @values);
    $output = "";
    $delimiter = "";
 
    # Check each parameter value to see if it should be in the response...
    for ($x = 0; $x < size(@values); $x++) {
        if (strlen($filter) > 0) {
            $findex = indexOf(@values[$x], $filter);
            if (($findex is $null) || ($findex > 0)) {
                # Value does not start with filter...
                continue;
            } else {
                # Value starts with filter...
            }
        }
 
        # Append the next value to the output list...
        $output = $output . $delimiter . $prefix . @values[$x];
         
        # Subsequent items should have a tab delimiter...
        $delimiter = "	";
    }
 
    # blog($1, "Filtered Output: \'$output\'");
 
    return $output;
}