helix-editor/helix
Pickers
Pickers are the fuzzy-search modal dialogs Helix uses for files, buffers, symbols, diagnostics, themes, registers, and more. They are the most-used non-trivial UI in the editor and the largest single component in helix-term/src/ui/.
Anatomy
A picker is a Picker<T, D> (helix-term/src/ui/picker.rs, ~43,000 chars + ~12,500 in the picker/ subdirectory) parameterized over:
T— the item type (path, symbol, diagnostic, …).D— extra data carried alongside the items.
The picker shows a prompt, a column-aware results table, an optional preview pane, and supports:
- Fuzzy filtering via nucleo.
- Multi-column queries (e.g.
%filename %lineto filter by both). - Preview rendering for paths, snippet diffs, and document positions.
- Keyboard and mouse selection.
- Per-action key bindings (
Enteropens,Ctrl-sopens in horizontal split,Ctrl-vin vertical split,Alt-Enterreplaces the current view,Tabtoggles selection in pickers that support it).
Core types
| Type | Purpose |
|---|---|
Picker<T, D> |
The component. Owns the prompt, the matcher, the items, the preview cache, and the column definitions. |
Column<T, D> |
A column with a header, getter, and width hint. Values are filtered against the prompt query. |
PickerColumn |
Shorthand alias used by callers. |
FileLocation |
An item that carries a path and an optional line range — drives the file preview. |
PickerQuery |
The parsed multi-column query. |
DynamicQueryHandler |
An AsyncHook that lets pickers backed by an LSP/grep/etc. refetch results when the query changes. |
PreviewHighlightHandler |
An AsyncHook that highlights the preview document on the side. |
Built-in pickers
Most pickers are constructed in helpers in helix-term/src/ui/mod.rs and exposed as commands in helix-term/src/commands.rs.
| Command | Default key | Source |
|---|---|---|
| File picker | space f |
file_picker (commands.rs) — walks the workspace using ignore |
| Workspace file explorer | space e |
file_explorer |
| Buffer picker | space b |
buffer_picker |
| Jumplist picker | space j |
jumplist_picker |
| Recent files / changed files | space ' |
LSP-aware recent picker |
| Document symbol picker | space s |
symbol_picker (uses LSP documentSymbol) |
| Workspace symbol picker | space S |
workspace_symbol_picker |
| Diagnostics picker (current doc) | space d |
diagnostics_picker |
| Workspace diagnostics picker | space D |
workspace_diagnostics_picker |
| Global search | space / |
global_search (uses grep-regex + grep-searcher) |
| Theme picker | :theme |
theme_picker |
| Register picker | space y |
select_register |
| Code-action picker | space a |
LSP code actions |
| LSP workspace command picker | space w |
lsp_workspace_command_picker |
| Marks (bookmarks) picker | space m |
bookmark navigation |
Filtering
Filtering is done by nucleo, the same fuzzy matcher Telescope uses. The matcher runs on a thread pool and pushes results back as they arrive — pickers feel instant on workspaces with hundreds of thousands of files. Configuration:
editor.file-pickercontrols hidden-file behaviour, parent ignore files, max depth, etc. (seeFilePickerConfiginhelix-view/src/editor.rs).- The matcher itself is a static
MATCHERinhelix-core/src/fuzzy.rs.
Multi-column query syntax
Typing %filename %line switches the rest of the query to filter by the named columns. The parser is PickerQuery::parse in picker/query.rs. Columns are introspectable via Picker::with_columns.
Preview pane
A picker with T: FileLocation-shaped items renders a side preview when the terminal is wider than MIN_AREA_WIDTH_FOR_PREVIEW (72 cols). Previews are cached to avoid re-reading huge files; binary files and files larger than MAX_PREVIEW_FILE_SIZE are skipped. Preview rendering uses the same render_document function as the main editor, so highlights are consistent.
Performance
- Fuzzy matching runs on
nucleo's rayon-style thread pool. - Items are streamed in via
Picker::push(orPicker::add_options) so the picker is responsive even before the workspace walk finishes. - Preview highlight runs on
PreviewHighlightHandler, anAsyncHookthat debounces by ~50ms to avoid re-highlighting the preview while the user navigates.
Extension points
- Adding a new picker: build it in
helix-term/src/ui/mod.rs(or alongside the source it derives from), expose a command incommands.rs, and bind it inkeymap/default.rs. - Adding a column: implement
Column::with_datareturningCellcontent; mark whether it should be filterable. - Adding a dynamic backing source (e.g. for ripgrep-style results): implement an
AsyncHookthat producesPickerEvents and pass it as thedynamic_query_handler.
See also
- packages/helix-term — overall UI architecture.
- features/language-servers — pickers backed by LSP
workspaceSymboland friends.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.