Command
Fast, composable, unstyled command menu for GPUI.
Overview
cmdk 风格命令面板:顶部搜索框 + 常驻过滤列表,↑/↓ 移动高亮,Enter/点击执行。
Installation
Command 是单个 Rust 文件(src/command.rs)—— 文本编辑复用 gpui-base 的 InputState,行图标用 PathBuilder 手绘,列表滚动走 ScrollHandle,dialog 变体用 deferred() 把面板画到 overlay pass。
[dependencies]gpui-kit = "0.6.6"# command.rs builds on gpui-base primitives:# InputState (editing) + ScrollHandle — no extra deps.# Download the runnable example crate, then:cargo run --locked -- --command# Other demos:cargo run --locked -- --command shortcutscargo run --locked -- --command groupscargo run --locked -- --command scrollablecargo run --locked -- --command dialogUsage
Command 是实体:输入框是一个真实的 InputState(先 new 出来再传进构造器),实体自持过滤结果与高亮行。输入即过滤(label/value/group/keywords 子串匹配),Enter 或点击发出 CommandSelectEvent。
use justdo_command::command::{Command, CommandItem, CommandSelectEvent};use gpui_kit::base::input::InputState;// The input entity is created with a Window, then the// command entity wraps it and owns filtering + highlight.let input = cx.new(|cx| { InputState::new(window, cx).placeholder("Type a command or search…")});let command = cx.new(|cx| { Command::new(input, cx) .items(vec![ CommandItem::new("Calendar").group("Suggestions"), CommandItem::new("Profile") .group("Settings") .shortcut("⌘P") .icon(CommandIcon::User), ]) .empty_text("No results found.")});cx.subscribe(&command, |view, _, ev: &CommandSelectEvent, cx| { view.run_command(&ev.value); cx.notify();});div().child(command)// Filtering is substring match over label, value, group// and hidden keywords — items can expose extra match-only// terms that never render:CommandItem::new("Command Palette") .keywords(&["palette", "commands"]) .shortcut("⇧⌘P")网页预览与桌面端运行同一份 Rust / GPUI 组件。
Composition
结构对应 Command → CommandInput + CommandList → CommandGroup + CommandItem + CommandSeparator + CommandShortcut:组头与分隔线由 CommandItem::group(..) 在渲染时自动推导,过滤后空组自动消失。
Command entity — input + list + active row├── CommandInput Entity<InputState> — real text editing (gpui-base)│ magnifier glyph, 44px row, bottom border├── CommandList filtered rows — scrollable (list_max_h)│ ├── CommandGroup heading per CommandItem::group(..)│ ├── CommandSeparator auto line between different groups│ ├── CommandItem icon + label + optional shortcut│ │ .value(..) .keywords(..) .disabled(..)│ ├── CommandShortcut trailing muted ⌘P / ⌘B / ⌘S│ └── CommandEmpty .empty_text(..) — no-match state└── emits CommandSelectEvent { value }Keyboard
单行输入框不注册上下方向 handler —— 方向键以 input::MoveDown/MoveUp action 冒泡出来,组件在外层接住并移动高亮行(跳过 disabled)。Enter 走 input::Enter 提交;Escape 先清空查询,空查询时再按则向上冒泡,方便 CommandDialog 宿主关闭。
// Keyboard semantics ride GPUI's action system, not raw// key capture. A focused single-line input registers no// up/down handlers, so input::MoveUp / input::MoveDown// bubble out — the command listens for them and moves the// highlighted row (skipping disabled items).//// Enter propagates as input::Enter and commits the active// row. Escape clears the query first; on an empty query it// propagates so a CommandDialog host can close.Accessibility
Semantics
禁用行渲染为半透明且不进入高亮序列;空结果有明确的 empty_text 状态而非空白;列表高度受限时高亮行自动滚入视野。
Keyboard
输入保持焦点:↓/↑ 循环移动高亮、Enter 执行、Escape 清空/关闭;鼠标 hover 同步高亮,点击直接提交。
API Reference
实体暴露的 builder 方法与事件。
| API | Signature | Notes |
|---|---|---|
Command::new(..) | Entity<InputState> | Wraps a caller-created input entity. |
.items(..) | Vec<CommandItem> | The collection; filtered as you type. |
CommandItem::new(..) | &str label | .value(..) .group(..) .shortcut(..) .icon(..) .keywords(..) .disabled(..) |
.empty_text(..) | &str | Shown when the query matches nothing. |
.list_max_h(..) | Pixels | List viewport cap before scrolling. |
.query() | -> String | Current filter text. |
CommandSelectEvent | { value } | Emitted on Enter / click commit. |
Source & inspiration
结构与交互参考 shadcn/ui Command (React Aria / cmdk) 。本页交互由 Rust / GPUI 绘制,基础原语来自 gpui-kit 。