In the third post in this series we covered the basics of navigation. Now we are going to implement tab completion in the provider. While doing this may seem simple and a small task, it makes your provider feel more integrated with PowerShell.

The final working code for this project can be found at the github depot under the TabCompletion tag.

Adding Tab Support is actually pretty easy (as are most things in the PowerShell Provider world, once you know what to do). To start, we will modify our CmdletProvider attribute to include capabilities. We are going to add the ExpandWildcards capability to our provider:

[CmdletProvider("MyPowerShellProvider", ProviderCapabilities.ExpandWildcards)]

Next, we will modify our ItemExists method to properly validate the tag actually exists:

protected override bool ItemExists(string path)
{
    if (tags == null)
        return true;

    if (String.IsNullOrEmpty(path))
        return true;

    var itemFromTag = from tag in tags.Data.Items
                      where tag.Name.Equals(path, StringComparison.CurrentCultureIgnoreCase)
                      select tag;
    return itemFromTag.Any();
}

Now we will provide a helper method to convert a path from PowerShell into an array of valid tags. This method will handle the wildcards sent in from PowerShell, so it does some basic Regex parsing:

private string[] TagsFromPath(string path)
{
    if (tags == null)
        return null;

    var regexString = Regex.Escape(path).Replace("\*", ".*");
    regexString = "^" + regexString + "$";
    var regex = new Regex(regexString);

    var itemFromTag = from tag in tags.Data.Items
                      where regex.IsMatch(tag.Name)
                      select tag.Name;

    if (itemFromTag.Any())
        return itemFromTag.ToArray();

    return null;
}

Finally, we will override the ExpandPath method in the base provider:

protected override string[] ExpandPath(string path)
{
    return TagsFromPath(path);
}

Simple enough, if you compile and run, tab completion should now work.

For example, if you go to your SO: drive and do a cd jTab, you will see that the ExpandPath method is called with a path parameter of j*. If you press Tab multiple times, you will see it iterate over the various options (.\java, .\javascript, .\jquery, ...).

You could also use your own wildcard, so cd j*vTab and it will only iterate over the matches of java and javascript.

As you have seen implementing tab completion in PowerShell is just as easy as everything else we have done (if not easier), it is just knowing the correct methods to implement. At this point we have a rather functional sample provider. Sure, it doesn't do much, but this should give you most of what you need to implement your own provider with whatever backend API you need.

For now, this will be the last of the navigation provider posts. If you find something that should be added, leave a comment below and maybe I will add it to the series.