{"id":10471,"date":"2006-04-26T17:24:00","date_gmt":"2006-04-26T17:24:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2006\/04\/26\/the-new-tabexpansion-feature\/"},"modified":"2019-02-18T13:24:51","modified_gmt":"2019-02-18T20:24:51","slug":"the-new-tabexpansion-feature","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/the-new-tabexpansion-feature\/","title":{"rendered":"The new TabExpansion feature&#8230;"},"content":{"rendered":"<p class=\"MsoNormal\">One of the nicest new features in the latest drop of Windows PowerShell is enhanced tab-completion. We now tab-complete properties on variables and parameters on cmdlets in addition to the old filename completion. But that&#8217;s not the interesting part. The cool bit is that it&#8217;s done through a user-definable function. In the same way that you can redefine your prompt, you can also define custom tab completion. <span>&nbsp;<\/span>Here\u2019s how it works:<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">When you hit tab after typing some text, the function <strong><font face=\"Courier New\" size=\"2\">TabExpansion<\/font><\/strong> is called to generate the list of possible completion matches. You can find this function by doing:<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\">PS (16) &gt; ls function:*tab*<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\">CommandType<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Name<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Definition<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\">&#8212;&#8212;&#8212;&#8211;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>&#8212;-<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>&#8212;&#8212;&#8212;-<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\" size=\"2\">Function<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>TabExpansion<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>&#8230;<\/font><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">And see the current definition:<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\">PS (17) &gt; $function:tabexpansion<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\" size=\"2\">&nbsp;<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\">&nbsp; # This is the default function to use for tab expansion. <\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\" size=\"2\">&nbsp; :<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\" size=\"2\">&nbsp; :<\/font><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">Or save it to a text file so you can edit it:<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\">PS (18) &gt; $function:tabexpansion &gt; c:\\temp\\tabexpansion.ps1<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\" size=\"2\">PS (19) &gt; notepad $$<\/font><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">(The $$ above refers to the last token in the previous command \u2013 in this case, it\u2019s the name of the file we saved the function too.)<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">The parameter declaration for this function is<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>param($line, $lastWord)<\/font><\/font><\/p>\n<p class=\"MsoNormal\"><span><\/span>&nbsp;<\/p>\n<p class=\"MsoNormal\">where $line is the full command line as typed, and $lastWord is the last word or token in the line. So \u2013 if the line is:<\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>cd c:\\windows<\/font><\/font><\/p>\n<p class=\"MsoNormal\">then the last word would be \u201cc:\\windows\u201d. If the line is<\/p>\n<p class=\"MsoNormal\"><font face=\"Courier New\"><font size=\"2\"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>cd \u201cc:\\program files\u201d<\/font><\/font><\/p>\n<p class=\"MsoNormal\">the last word would be \u201cc:\\program files\u201d.<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">These two pieces are provided because most expansions work on the last token (e.g. property name expansion) but some require the entire line (e.g. parameter expansion.)<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">The <font face=\"Courier New\" size=\"2\">TabExpansion<\/font> function should return an array of strings representing the possible matches. The host will store these strings in a circular buffer the first time you hit tab after typing some text. Subsequent tabs will step you through the list of possible matches. Typing anything other than a tab will reset the sequence.<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">If this function returns null, then the expansion process will fall through to the old built-in file-name completion code to try and generate a match. (The file name completion stuff is still implemented in the host as compiled code. It was too much work to migrate it to the script for v1.)<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">Since TabExpansion is a function, it can do anything \u2013 pop up menus, create GUIs, talk to the user, or whatever. The one thing to keep in mind is performance \u2013 you want to get the results back quickly. If you have a complex completion scenario that is too slow in script then you might need to write a helper cmdlet.<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">I\u2019m really looking forward to seeing what the community can do with this feature!<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">Bruce Payette<\/p>\n<p class=\"MsoNormal\">Windows PowerShell Technical Lead<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\">PSMDTAG:INTERNAL: Tab Expansion, Tab Completion<\/p>\n<p class=\"MsoNormal\">PSMDTAG:SHELL: Tab Expansion, Tab Completion<br \/>PSMDTAG:FAQ: Why doesn&#8217;t tab completion do xxxx?<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the nicest new features in the latest drop of Windows PowerShell is enhanced tab-completion. We now tab-complete properties on variables and parameters on cmdlets in addition to the old filename completion. But that&#8217;s not the interesting part. The cool bit is that it&#8217;s done through a user-definable function. In the same way that [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[10,21],"class_list":["post-10471","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-faq","tag-shell"],"acf":[],"blog_post_summary":"<p>One of the nicest new features in the latest drop of Windows PowerShell is enhanced tab-completion. We now tab-complete properties on variables and parameters on cmdlets in addition to the old filename completion. But that&#8217;s not the interesting part. The cool bit is that it&#8217;s done through a user-definable function. In the same way that [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=10471"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10471\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=10471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=10471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=10471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}