feat: Add support for action modifier keys like ctrl,shift,alt.
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled

This commit is contained in:
2026-03-15 11:51:17 -04:00
parent 0d241841bc
commit 47437f536b
18 changed files with 1055 additions and 244 deletions

View File

@@ -48,6 +48,43 @@ metadata that came in, plus selection context:
{"label": "beach_sunset.jpg", "sublabel": "/home/maple/walls/nature/", "meta": {"size": "2.4MB"}, "action": "select", "index": 3}
```
When `--structured` is used, the output JSON includes a
`modifiers` field if any modifier keys (shift, ctrl, alt)
were held during confirmation. The value is an array of
strings:
```jsonl
{"label": "firefox", "action": "select", "index": 0, "modifiers": ["shift"]}
{"label": "alacritty", "action": "select", "index": 2, "modifiers": ["ctrl", "alt"]}
```
When no modifiers are held, the field is omitted entirely.
Plain text output is unchanged: modifiers only appear in
structured JSON.
### Working with Structured Output
Check for shift modifier with jq:
```sh
pikl --structured | jq 'if (.modifiers // [] | contains(["shift"])) then "alternate" else "default" end'
```
Extract a field:
```sh
pikl --structured | jq -r '.label'
```
Branch on modifiers in a script:
```sh
result=$(echo -e "a\nb\nc" | pikl --structured)
if echo "$result" | jq -e '.modifiers // [] | contains(["shift"])' > /dev/null 2>&1; then
echo "shift was held"
fi
```
### Streaming
Input can arrive over time. The list populates progressively
@@ -96,6 +133,12 @@ There are two ways to respond to them: **exec hooks** and
| `on-filter` | Filter text changes | Dynamic item reloading |
| `on-toggle` | User toggles an item's selection | Visual feedback (deferred) |
Hook event JSON includes a `modifiers` field on `select`,
`cancel`, `filter`, `hover`, and `quicklist` events when
modifier keys were held. Same format as structured output:
an array of strings like `["shift"]` or `["ctrl", "alt"]`.
Omitted when no modifiers are active.
### Exec Hooks (fire-and-forget)
`--on-<event>-exec` spawns a subprocess for each event.
@@ -770,6 +813,18 @@ Available actions:
| `show-tui` | (none) | Hand off to TUI specifically |
| `show-gui` | (none) | Hand off to GUI specifically |
Actions can include modifier key prefixes with `+`:
```
+shift confirm
+ctrl+alt move-down 3
```
Valid modifiers: `shift`, `ctrl`, `alt`. Multiple modifiers
chain with `+`. Lines without a `+` prefix work exactly as
before. This lets scripts signal intent to hooks and
structured output the same way a user holding Shift would.
`show-ui` auto-detects the appropriate interactive frontend
(Wayland: GUI, X11: GUI, otherwise: TUI). `show-tui` and
`show-gui` are explicit overrides. All three must be the

View File

@@ -349,7 +349,14 @@ navigate directories without spawning new processes.
pass `-la` to it. The output would include both the
selected item and the user-supplied arguments.
Open questions:
**Partially resolved:** modifier key support has landed.
Structured output and hook events now carry a `modifiers`
field when shift/ctrl/alt are held during confirmation.
This covers the signaling side: scripts can detect
Shift+Enter and branch on it. The free-text argument
input (where does the user type `-la`?) is still open.
Remaining open questions:
- UX flow: does the filter text become the args on
Shift+Enter? Or does Shift+Enter open a second input
field for args after selection? The filter-as-args
@@ -363,9 +370,6 @@ navigate directories without spawning new processes.
matches exactly one item just confirm that item (current
behaviour), or should it also treat any "extra" text
as args? Probably not, too implicit.
- Keybind: Shift+Enter is natural, but some terminals
don't distinguish it from Enter. May need a fallback
like Ctrl+Enter or a normal-mode keybind.
This is a core feature (new keybind, new output field),
not just a launcher script concern. Fits naturally after