app.chooser - Quick Chooser API
Provides a Raycast/Alfred-style quick selection interface with search filtering.
Permission: Requires
chooserdeclared in the manifest (L1 standard)
Methods
app.chooser.show(items, options?)
Displays a quick chooser window.
Parameters:
items(array) - Option list, each item is a table:text(string) - Primary text (required)subText(string, optional) - Secondary text/descriptionicon(string, optional) - Icon (usesf:symbol.nameformat for SF Symbols)id(string|number, optional) - Unique identifier
options(table, optional):title(string, optional) - Window titleplaceholder(string, optional) - Search field placeholdermultiSelect(boolean, optional) - Enable multi-select (default false)width(number, optional) - Window width (default 500)maxVisibleItems(number, optional) - Maximum visible items (default 10)
Returns:
- Single-select: The selected item table, or nil (cancelled)
- Multi-select: Array of selected items, or nil (cancelled)
-- Basic usage
local selected = app.chooser.show({
{text = "New File", subText = "Create a blank file", icon = "sf:doc.badge.plus"},
{text = "New Folder", subText = "Create an empty folder", icon = "sf:folder.badge.plus"},
{text = "From Template", subText = "Use a predefined template", icon = "sf:doc.on.doc"},
}, {
title = "Quick Actions",
placeholder = "Search actions..."
})
if selected then
app.log.info("Selected: " .. selected.text)
end
Comparison with dialog.choose
| Feature | app.chooser.show |
app.dialog.choose |
|---|---|---|
| UI style | Standalone floating window + search box | NSAlert dropdown/checkbox list |
| Search filtering | Supports real-time search | Not supported |
| Secondary text | Supports subText | Not supported |
| Icons | Supports SF Symbols | Not supported |
| Use case | Quick filtering from many options | Simple selection from few options |
Examples
Quick open project
function MyPlugin:handleQuickOpen(context)
-- Build project list
local items = {}
local projects = app.file.find("~/Projects", {type = "directory", maxDepth = 1})
for _, path in ipairs(projects) do
table.insert(items, {
id = path,
text = app.path.basename(path),
subText = path,
icon = "sf:folder.fill"
})
end
local selected = app.chooser.show(items, {
title = "Open Project",
placeholder = "Search projects..."
})
if selected then
app.shell.execute("open " .. app.shell.quote(selected.id))
end
end
Command palette
function MyPlugin:handleCommandPalette(context)
local commands = {
{id = "copy_path", text = "Copy Path", subText = "Copy full file path", icon = "sf:doc.on.clipboard"},
{id = "copy_name", text = "Copy File Name", subText = "Copy file name", icon = "sf:textformat"},
{id = "open_term", text = "Open in Terminal", subText = "Open Terminal", icon = "sf:terminal"},
{id = "compress", text = "Compress File", subText = "Create ZIP archive", icon = "sf:archivebox"},
{id = "hash", text = "Calculate Hash", subText = "SHA256 checksum", icon = "sf:number"},
}
local selected = app.chooser.show(commands, {
placeholder = "Enter command..."
})
if selected then
self:executeCommand(selected.id, context)
end
end
Multi-select operation
function MyPlugin:handleSelectTags(context)
local tags = {
{id = "important", text = "Important", icon = "sf:star.fill"},
{id = "urgent", text = "Urgent", icon = "sf:exclamationmark.triangle"},
{id = "review", text = "Pending Review", icon = "sf:eye"},
{id = "archive", text = "Archive", icon = "sf:archivebox"},
}
local selected = app.chooser.show(tags, {
title = "Select Tags",
placeholder = "Search tags...",
multiSelect = true
})
if selected then
for _, tag in ipairs(selected) do
app.log.info("Selected tag: " .. tag.text)
end
end
end
Notes
- Search filtering: Automatically matches against
textandsubTextfields - Blocking call: Blocks the current thread until the user selects or cancels
- Icon format: Use the
sf:prefix to load SF Symbols (e.g.sf:folder.fill)