以下为本文档的中文说明
该技能指导开发者如何为VS Code命令面板(Command Palette)扩展添加后备命令功能,实现全面搜索行为。当用户在命令面板中输入的查询无法匹配任何顶层命令时,后备命令会被触发,使扩展能充当全面处理器。使用场景包括:创建公式计算器(输入即计算)、网页搜索扩展(对未匹配的查询直接发起搜索)、文件路径打开器(直接解析输入为路径)、shell命令执行器(从搜索栏运行系统命令),以及任何需要捕获用户全部输入的场景。核心特点在于其无干扰的触发机制:用户无需选择特定扩展或调用特定命令,只要输入的查询没有命中其他扩展的顶层命令,后备命令就会自动生效。Microsoft官方内置的20个扩展中有14个使用了该机制,足以证明其成熟度。工作流程简单清晰:用户在命令面板键入查询,如果无顶层命令匹配,CmdPal向扩展请求后备结果,扩展通过FallbackCommands()提供匹配项并显示给用户。核心原则是’最后的匹配者’——后备命令应当处理其他扩展都不处理的搜索查询,而非抢在常规命令之前拦截输入。该技能还涵盖如何控制后备命令的触发优先级、如何显示进度反馈以应对耗时的后备查询,以及如何避免与现有命令产生冲突的最佳实践。
Add Fallback Commands
Fallback commands are shown in Command Palette when no other results match the user’s query. They enable your extension to act as a catch-all handler — perfect for calculators, web search, command execution, file path opening, and more.
When to Use This Skill
- Adding search functionality that responds to any user input
- Creating a calculator that evaluates expressions as the user types
- Building a web search that triggers on unmatched queries
- Opening files or URLs typed directly into the palette
- Executing shell commands from the search bar
How Fallback Commands Work
- User types a query in Command Palette
- If no top-level commands match, CmdPal asks extensions for fallback results
- Your extension’s
FallbackCommands()provides items that respond to the query - The fallback items can be static (always shown) or dynamic (filtered by query)
Quick Start: Static Fallback
OverrideFallbackCommands()in yourCommandProvider:
publicpartialclassMyCommandsProvider:CommandProvider{privatereadonlyICommandItem[]_commands;privatereadonlyFallbackCommandItem[]_fallbacks;publicMyCommandsProvider(){DisplayName="Web Search";Icon=newIconInfo("\\uE721");// Search iconvarsearchPage=newWebSearchPage();_commands=[newCommandItem(searchPage){Title=DisplayName}];_fallbacks=[newFallbackCommandItem(searchPage){Title="Search the web"}];}publicoverrideICommandItem[]TopLevelCommands()=>_commands;publicoverrideIFallbackCommandItem[]FallbackCommands()=>_fallbacks;}Dynamic Fallback with DynamicListPage
For fallbacks that filter results based on the query, useDynamicListPage:
internalsealedpartialclassWebSearchPage:DynamicListPage{privatestring_query=string.Empty;publicWebSearchPage(){Icon=newIconInfo("\\uE721");Title="Web Search";Name="Search";PlaceholderText="Type to search...";}publicoverridevoidUpdateSearchText(stringoldSearch,stringnewSearch){_query=newSearch;RaiseItemsChanged();}publicoverrideIListItem[]GetItems(){if(string.IsNullOrWhiteSpace(_query))return[];return[newListItem(newOpenUrlCommand($"https://www.google.com/search?q={Uri.EscapeDataString(_query)}")){Title=$"Search Google for \\"{_query}\\"",Icon=newIconInfo("\\uE721"),},newListItem(newOpenUrlCommand($"https://www.bing.com/search?q={Uri.EscapeDataString(_query)}")){Title=$"Search Bing for \\"{_query}\\"",Icon=newIconInfo("\\uE721"),},];}}Responsive Fallback with Cancellation
For expensive operations (API calls, file searches), use cancellation to stay responsive:
internalsealedpartialclassSmartSearchPage:DynamicListPage{privateCancellationTokenSource?_cts;privateIListItem[]_results=[];publicoverridevoidUpdateSearchText(stringoldSearch,stringnewSearch){// Cancel any in-flight search_cts?.Cancel();_cts=newCancellationTokenSource();vartoken=_cts.Token;_=Task.Run(async()=>{// Debounce: wait for user to stop typingawaitTask.Delay(300,token);if(token.IsCancellationRequested)return;// Perform search_results=awaitSearchAsync(newSearch,token);RaiseItemsChanged();},token);}publicoverrideIListItem[]GetItems()=>_results;privateasyncTask<IListItem[]>SearchAsync(stringquery,CancellationTokentoken){// Your search logic here// Check token.IsCancellationRequested periodicallyreturn[];}}Real-World Examples (from built-in extensions)
| Extension | Fallback Be
havior |
|-----------|------------------|
|Apps| Search installed applications by name |
|Calc| Evaluate mathematical expressions directly |
|Shell| Execute command-line commands |
|WebSearch| Search the web with configured engine |
|Indexer| Open files by path |
|TimeDate| Parse time/date queries |
|WindowsSettings| Jump to Windows Settings pages |
|WinGet| Search WinGet packages |
|WindowWalker| Find and switch to open windows |
Key Points
FallbackCommands()returnsIFallbackCommandItem[](notICommandItem[])- Use
FallbackCommandItemwrapper (notCommandItem) - Wrap a
DynamicListPagefor query-reactive results - Cancel previous searches when new input arrives
- Keep fallback responses fast — users expect instant results
- Use
PlaceholderTexton your page to guide users
Documentation
- Extension samples
- Extensibility overview
3c:[“" , " ","","L3f”,null,{“content”:“$40”,“frontMatter”:{“name”:“add-fallback-commands”,“description”:“Add fallback commands to your Command Palette extension for catch-all search behavior. Use when asked to add search functionality, query matching, direct input handling, calculator-style evaluation, URL opening, command execution, or results that appear when no other extension matches. Used by 14 of 20 built-in extensions.”}}]
3d:[“KaTeX parse error: Expected '}', got 'EOF' at end of input: …,"children":[["”,“div”,null,{“className”:“flex items-center justify-between border-b border-border bg-muted/30 px-4 py-2.5”,“children”:[[“KaTeX parse error: Expected '}', got 'EOF' at end of input: …","children":["”,“span”,null,{“className”:“truncate text-xs font-medium text-muted-foreground”,“children”:“同仓库更多 Skills”}]}],[“KaTeX parse error: Expected 'EOF', got '}' at position 88: …ldren":"同仓库"}]]}̲],["”,“div”,null,{“className”:“p-4 sm:p-5”,“children”:[[“" , " h 2 " , n u l l , " i d " : " r e l a t e d − s k i l l s − h e a d i n g " , " c l a s s N a m e " : " t e x t − 2 x l f o n t − s e m i b o l d t r a c k i n g − n o r m a l t e x t − f o r e g r o u n d " , " c h i l d r e n " : " 同仓库更多 S k i l l s " ] , [ " ","h2",null,{"id":"related-skills-heading","className":"text-2xl font-semibold tracking-normal text-foreground","children":"同仓库更多 Skills"}],["","h2",null,"id":"related−skills−heading","className":"text−2xlfont−semiboldtracking−normaltext−foreground","children":"同仓库更多Skills"],["”,“div”,null,{“className”:“mt-4 grid gap-3 sm:grid-cols-2”,“children”:[“L 41 " , " L41","L41","L42”,“L 43 " , " L43","L43","L44”,“L 45 " , " L45","L45","L46”]}]]}]]}]
47:I[206516,[“/_next/static/chunks/051aanbhrv4br.js”,“/_next/static/chunks/0mizr60h7ayzt.js”,“/_next/static/chunks/0v9lm1dmbdoo-.js”,“/_next/static/chunks/0rxr1j1j3j-.r.js”,“/_next/static/chunks/02ftybezfvqjd.js”,“/_next/static/chunks/0.v9ksvnnj8ia.js”,“/_next/static/chunks/0bn6id96nx3k.js",“/_next/static/chunks/13ybnhn37c.tc.js”,“/_next/static/chunks/0_fnrdtruz8uf.js”,“/_next/static/chunks/0r6l15utt1mwb.js”,“/_next/static/chunks/0dm9a5into854.js”,"/_next/static/chunks/07k6hqoibtcn.js”,“/next/static/chunks/0b4cao.4y…j.js”,“/_next/static/chunks/02i-n28z7kjd0.js”],“default”]