Search code examples
powershelltab-completionprogrammable-completion

Cycle through only specific file types in PS using custom tab completion on the command line


I use PowerShell's PSReadline-based tab completion and I'm looking to implement the following custom completion behavior:

In a folder I have

File1.java
File1.class
File2.java
File2.class

If I use tab after java I got a list of the files:

java .\File
File1.java
File1.class
File2.java
File2.class

But I want to use a shortcut so I can scroll through only the .java-files but without the extension shown. I also want to get rid of ".\" in the name.

So if I write java and use tab I want to have

java File1

And next tab gives

java File2

And so forth (with tab or some other key).

I also wondering, before compling the java-files I have the folder

File1.java
File2.java

I now want to write javac and use tab so I get

javac File1.java

And tab again gives

javac File2.java

And so forth.

Is this possible?


Solution

  • Use the Register-ArgumentCompleter cmdlet (PSv5+):

    # With `java`, cycle through *.java files, but without the extension.
    Register-ArgumentCompleter -Native -CommandName java -ScriptBlock {
        param($wordToComplete)
        (Get-ChildItem $wordToComplete*.java).BaseName
    }
    
    # With `javac`, cycle through *.java files, but *with* the extension.
    Register-ArgumentCompleter -Native -CommandName javac -ScriptBlock {
        param($wordToComplete)
        (Get-ChildItem $wordToComplete*.java).Name
    }
    

    To define an alternative key or chord for invoking completion, use Set-PSReadLineKeyHandler; e.g., to make Ctrl+K invoke completions:

    Set-PSReadLineKeyHandler -Key ctrl+k -Function TabCompleteNext
    Set-PSReadLineKeyHandler -Key ctrl+shift+k -Function TabCompletePrevious
    

    Note that this affects completion globally - you cannot implement a command-specific completion key that way.