I'm trying to modify PowerShell's tab completion behavior so that it doesn't just match from the beginning of a word but also allows substring matching
Example
- Normally, if I type
under<TAB>
, PowerShell won't suggestcode-understanding
because it doesn't start withunder
- I would like PowerShell to suggest any word that contains my input anywhere (e.g.,
code-understanding
,file-underlined
, etc.)
What I've Tried
I've already set up PSReadLine
enhancements for better menu-style completion :
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
This improves predictions but still only matches the start of words
My Question
Is there a native way in PowerShell 7+ to make TAB
completion match substrings instead of just the start of a word ?
I'm trying to modify PowerShell's tab completion behavior so that it doesn't just match from the beginning of a word but also allows substring matching
Example
- Normally, if I type
under<TAB>
, PowerShell won't suggestcode-understanding
because it doesn't start withunder
- I would like PowerShell to suggest any word that contains my input anywhere (e.g.,
code-understanding
,file-underlined
, etc.)
What I've Tried
I've already set up PSReadLine
enhancements for better menu-style completion :
Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
This improves predictions but still only matches the start of words
My Question
Is there a native way in PowerShell 7+ to make TAB
completion match substrings instead of just the start of a word ?
1 Answer
Reset to default 1tl;dr
Mathias has provided the crucial pointer:
PowerShell's tab completion (aka command completion) supports wildcard expressions so that - rather than trying to roll a complication custom solution - you can simply prefix your substring with *
; to use your example:
*under
Tab will complete to both code-understanding
and file-underlined
(repeatedly pressing Tab cycles through the matches; with your custom Set-PSReadLineKeyHandler -Key Tab -Function MenuComplete
, all completions will be presented in a menu).
Background information:
Wildcard-based command completion:
With literal strings, PowerShell's command completion uses prefix matching, i.e. the input string must match the start of commands.
- Expressed in wildcard terms,
under
Tab behaves like(Get-Command).Name -like 'under*'
, i.e. a trailing*
is implied.
- Expressed in wildcard terms,
Wildcard expressions are matched as such (except that a trailing
*
is always implied), and a preceding*
therefore effectively performs substring matching, i.e. the literal part is matched anywhere in command names.- You can even use wildcard metacharacters multiple times; e.g.,
*readl*handler
Tab completes toGet-PSReadLineKeyHandler
,Remove-PSReadLineKeyHandler
, andSet-PSReadLineKeyHandler
.
- You can even use wildcard metacharacters multiple times; e.g.,
Capitals-based command completion:
PowerShell (Core) 7 offers a little-known command-completion method based on matching capital letters in command names.
E.g., t-mm
completes Test-ModuleManifest
, but note the following:
The capital of the verb part of the command name (
Test
in this example) must be followed by-
Every capital letter must be specified (in order) in order to match a command name; e.g.,
s-t
completes toStart-Transcript
andStop-Transcript
, but not toStart-ThreadJob
, because the latter has one additional capital,J
(that is,s-tj
is needed to match it).This approach can not be combined with wildcards.
Also note that many built-in cmdlets come with superficially similar aliases that use a standardized alias prefix that is defined for each approved verb, e.g. sa
for Start-
, followed by - without an intervening -
- a non-standardized (sequence of) letter(s) for the noun part. E.g., jb
is used to represent the Job
part in Start-Job
.
That is, submitting alias sajb
as-is is an alternative to using capital-based command completion with
s-j
Tab.
To see which alias(es), if any, are defined for a given command, use
Get-Alias -Definition <command-name>
[1] Note that the completion works even with non-approved verbs.
*code<TAB>
undesirable? – Mathias R. Jessen Commented Feb 3 at 13:03*
:) – Mathias R. Jessen Commented Feb 4 at 19:00