Commit graph

128 commits

Author SHA1 Message Date
skim-rs-bot[bot] 01be03f0d5
release: v5.6.4 (#1153)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-10 10:39:35 +00:00
skim-rs-bot[bot] 5fc3b0c1a0
release: v5.6.3 (#1152)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-07 14:07:35 +02:00
skim-rs-bot[bot] f3c03000b3
release: v5.6.2 (#1145)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-07 10:43:53 +00:00
skim-rs-bot[bot] c398374a85
release: v5.6.1 (#1143)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 17:18:04 +00:00
skim-rs-bot[bot] 794ddddb71
release: v5.6.0 (#1140)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-27 17:49:35 +02:00
skim-rs-bot[bot] 9016a712a2
release: v5.5.0 (#1135)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-23 12:16:07 +00:00
skim-rs-bot[bot] b2a732efa0
release: v5.4.0 (#1133)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-21 12:43:12 +00:00
LoricAndre 776d708ede
feat: allow binding actions & more events (#1125)
* Add `start` and `load` events alongside `change`

Introduce `start` and `load` bindable events, mirroring the existing
`change` event, so `--bind start:<action>` and `--bind load:<action>`
work.

To avoid scattering magic high-F-key literals (`F(255)` for `change`),
add a `SkimEvent` enum in `binds.rs` with `Start`, `Load` and `Change`
variants that transparently convert to the reserved `KeyEvent`s used to
route them through the keymap. `parse_key` now accepts the friendly
names `start`, `load` and `change` via `SkimEvent::from_name`. The keymap
key type stays `KeyEvent`, so the public API is unchanged.

Firing:
- `change` is emitted by `on_query_changed` (now via the named variant).
- `start` fires exactly once when skim enters its event loop
  (`Skim::fire_start_event`).
- `load` fires once the reader has finished AND the freshly-read items
  have been rendered into the list, so a `load` binding acts on a
  fully-populated, stable list. It is re-armed on `reload`.

Add unit coverage for the event-name round-trip and integration tests
for `start` and `load` bindings, and document the events in
ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QKxusGbxLxqWdYyeqrb68

* Add result/focus/zero/one events and action follow-up bindings

Extend the bindable-event set and generalise binding so that actions can
themselves be bound.

New finder events (fired from the post-draw `Event::Render` path, so a
binding sees a stable, up-to-date list):
- `result` — filtering for the current query completed
- `focus`  — the focused item changed (cursor move or result update)
- `zero`   — a completed search has no matches
- `one`    — a completed search has exactly one match

`zero`/`one` read `MatcherControl::get_num_matched()` rather than the
rendered list count, which can briefly lag the matcher.

Actions as events: any action can be bound as if it were an event, so a
follow-up chain runs after it (e.g. `reload:first`, `first:last`). This is
parsed by `parse_action_binds` into `SkimOptions::action_binds` (keyed by
`Action::name`) and applied in `handle_action`, which now wraps the
per-variant `dispatch_action`.

- Keys win: a name shared by a key and an action binds the key; use an
  `act-` prefix to target the action (`act-up:down`).
- New `skip` action suppresses the triggering action's own behaviour, so
  `act-up:skip+down` remaps the up action to down and `up:skip` disables
  the up key.

Also fixes `parse_key` so a non-numeric `f…` name (e.g. `focus`, `first`)
falls through to name/event matching instead of erroring on the function-
key branch.

Adds unit and snapshot tests and documents everything in ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QKxusGbxLxqWdYyeqrb68

* Rename skip action to suppress and document it in the manpage

Rename the `skip` action to `suppress`, which more clearly conveys that
it cancels the triggering action's default behaviour. Add it to the
manpage actions list, noting that when bound to an action it suppresses
that action's default (so the rest of the chain runs in its place), and
when bound to a key it is equivalent to `ignore`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QKxusGbxLxqWdYyeqrb68

* Fire finder events from callbacks instead of the render path

Move the synthetic finder events off the per-render check:

- `focus` now rides along with `App::on_selection_changed` (via a small
  `take_focus_event` helper), firing only when the focused item actually
  changes on cursor movement.
- `load`/`result`/`zero`/`one` track async reader/matcher completion, which
  has no synchronous callback, so `App::poll_completion_events` edge-triggers
  them from the `Heartbeat` handler rather than the render path. A `Render`
  is queued just before them so a list-inspecting binding (e.g. `load:first`)
  still sees the finished results.

This removes the branching that previously ran on every render tick and
keeps the event logic out of the unrelated `dispatch_action` arms.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QKxusGbxLxqWdYyeqrb68

* misc tweaks incl. noremap

* fixes

* docs: document new binds

* coderabbit review

* fix: address Copilot review comments on action binds

- Split `--bind` specs with top-level comma splitting in `SkimOptions::build`
  so commas inside parenthesized action arguments (e.g.
  `act-up:execute(echo a,b)`) no longer garble follow-up bindings. Reuses the
  existing `split_top_level` helper (now `pub(crate)`), matching
  `KeyMap::add_keymaps_str`.
- Correct the misleading `load` event comment in `check_reader`: the event is
  fired from `App::poll_completion_events` (the heartbeat handler), not the
  render path.
- Add a unit test covering commas inside action arguments.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pxems1gNKKezFcxtZfURJp

* fix: harden action-trigger binds (logging, runtime bind/unbind, API surface)

Address three review findings on the action-trigger feature:

- Log dropped `--bind` specs: an unknown trigger name or an invalid
  follow-up chain in parse_action_binds is now reported via debug!
  instead of vanishing silently, matching the keymap path's behavior.
- Make the runtime `bind`/`unbind` actions manage action triggers as
  well as keys: `bind(act-up:last)` merges into action_binds and
  `unbind(act-up)` removes the trigger, with the same keys-win
  precedence as `--bind`. Trigger-name resolution is shared through a
  new binds::action_trigger_name helper.
- Narrow the new App fields (reader_done, load_event_fired,
  result_pending) to pub(crate): they are a Skim<->App coordination
  protocol, not public API.

Update the manpage (regenerated sk.1) and ARCHITECTURE.md accordingly,
and cover the new behavior with unit tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgSqqsXn1GfQRZhQWAWi7t

* fix: don't abort the event loop on an invalid if-* branch chain

`if-*` branch chains are stored unparsed by `parse_action`, so an invalid
action name only surfaces when the binding fires. `dispatch_conditional`
propagated that parse error out of `App::handle_event`, killing the whole
finder mid-session on a bind typo. Log and skip the chain instead,
matching the invalid-chain handling of `parse_action_binds`.

Also refresh the stale line numbers in the ARCHITECTURE.md
cross-reference table.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TgSqqsXn1GfQRZhQWAWi7t

* fix: make sure to render before start in sync mode

* chore: push snaps

* fix: misc

* fix: address review comments on start event, if-* logging and docs

- skim.rs: retry the one-shot `start` event from `tick()` so a momentarily
  full bounded `event_tx` at the `start()`/`enter()` call sites can no longer
  drop it permanently. Idempotent via the `start_fired` guard.
- app.rs: log an invalid `if-*` conditional action chain at `warn!` instead of
  `debug!` so a misconfigured binding is discoverable by default.
- ARCHITECTURE.md: clarify that `Skim::check_reader` only records `reader_done`;
  `App::poll_completion_events` owns and emits `load`/`result`/`zero`/`one`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QKxusGbxLxqWdYyeqrb68

* chore: minor formatting

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-21 11:42:47 +00:00
skim-rs-bot[bot] 5c1c3379fb
release: v5.3.2 (#1130)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-20 22:37:12 +00:00
skim-rs-bot[bot] 6dbe37a7fa
release: v5.3.1 (#1128)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-19 21:42:17 +00:00
skim-rs-bot[bot] 4d093a42e1
release: v5.3.0 (#1123)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-19 15:25:03 +02:00
LoricAndre dce26d622a
feat: add --hide-nth to hide fields from display but keep them searchable (#1122)
* Add --hide-nth flag to hide fields while keeping them searchable

Introduce a `--hide-nth <fieldspec>` option that takes the same
comma-separated field index expressions as `--nth`/`--with-nth`. The
listed fields are removed from the displayed line but remain part of the
text used for matching, so a query can still match them. Characters in
the hidden fields are ignored for match highlighting and horizontal
scrolling.

Implementation:
- Resolve the fieldspec to byte ranges in the same coordinate space as
  the matching/display text and store them as `hidden_ranges` in
  DefaultSkimItem metadata, exposed via a new `SkimItem::hidden_ranges()`
  trait method. text()/output() keep the full text so hidden fields stay
  searchable and are preserved on output.
- DefaultSkimItem::display() removes hidden characters and remaps match
  highlight positions into visible coordinates (project_visible_text /
  project_match_indices); this path takes precedence over ANSI styling.
- ItemRenderer::render_item applies the same projection to derive the
  visible sub-line text and hscroll match range, so hidden characters are
  ignored for horizontal scrolling.

Add unit tests for range normalization/projection and item behavior,
plus insta snapshot tests covering display removal, searchability, and
hscroll. Update ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCunXeAFMYAFduTc8SNjSM

* Preserve ANSI colors for surviving text under --hide-nth

Previously the hidden-field rendering path was applied ahead of the ANSI
display branch and rebuilt the line from the ANSI-stripped text, so
combining --hide-nth with --ansi dropped the colors of the visible
fields.

Integrate hidden-field removal into the ANSI branch instead: after
parsing the styled spans, drop the hidden characters while preserving
each span's style (retain_visible_spans) and remap the match positions
into the resulting visible coordinate space, then run the normal
highlighting. The plain (non-ANSI) branch keeps its project-and-to_line
handling. Surviving characters now keep their ANSI colors while hidden
fields stay searchable.

Add unit tests for ANSI color preservation and remapped highlighting,
plus ANSI color-snapshot integration tests. Update ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCunXeAFMYAFduTc8SNjSM

* Set hidden fields via builder instead of DefaultSkimItem::new param

Remove the `hidden_fields` parameter from `DefaultSkimItem::new` and set
the hidden fields through a `hidden_fields(&[FieldRange], &Regex)`
builder method instead. The builder resolves the fields against the
item's own `text()` (the same coordinate space `new` would have used),
so the result is identical while keeping `new`'s signature unchanged for
its many existing call sites.

The reader chains `.hidden_fields(&opt.hidden_fields, &opt.delimiter)`
onto construction. Revert the extra `&[]` argument at the other call
sites (selector, fuzz target, tests) and update the hide-nth tests to
use the builder. Update ARCHITECTURE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCunXeAFMYAFduTc8SNjSM

* chore: generate files

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-18 13:13:43 +00:00
skim-rs-bot[bot] 57a7487323
release: v5.2.0 (#1119)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-17 17:58:07 +00:00
LoricAndre 21f7ef8795
feat: collapsed borders by default and --border-no-collapse flag (#1117)
* feat: collapsed borders by default and `--border-no-collapse` flag

* chore: generate files
2026-07-17 16:59:14 +00:00
skim-rs-bot[bot] f87ce2075d
release: v5.1.4 (#1116)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-17 12:45:54 +00:00
skim-rs-bot[bot] b41a724a2a
release: v5.1.3 (#1112)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-16 21:58:51 +00:00
skim-rs-bot[bot] 4047a5e3fd
release: v5.1.2 (#1111)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-16 12:36:16 +02:00
Loric ANDRE 8ea0afb63e release: v5.1.1 2026-07-16 10:55:28 +02:00
Loric ANDRE c4bc5e1be4 release: v5.1.0 2026-07-09 14:34:06 +02:00
Liam Dyer 8a1f2783a8
feat: bump frizbee to 0.10.0, thread local matcher (#1105)
* feat: bump frizbee to 0.10.0, thread local matcher

* feat: use frizbee on all architectures

* feat: use frizbee feature

* refactor: simplify frizbee config mutation

* docs: simplify frizbee thread local comment

* fixup! feat: use frizbee feature

* fixup! feat: use frizbee feature
2026-07-03 16:20:05 +00:00
Loric ANDRE 5a2dde8018 release: v5.0.0 2026-07-02 20:01:20 +02:00
Loric ANDRE aeba919fab release: v4.10.0 2026-06-28 19:00:17 +02:00
Loric ANDRE d14407196b release: v4.9.0 2026-06-26 00:53:37 +02:00
Loric ANDRE fbd426f569 release: v4.8.0 2026-06-17 14:31:28 +02:00
LoricAndre a5ca0c8885
feat: add image preview support & preview spinner while loading (#1081)
* chore: generate manpage

* feat: image preview

* feat: add spinner while preview loads

* chore: misc

* chore: generate files

* chore: review

* chore: generate lockfile

* feat: allow forcing halfblock backend for weird envs

* chore: generate files

* fix: avoid race conditions in preview
2026-06-17 08:21:44 +00:00
Loric ANDRE 7e6115070b release: v4.7.0 2026-05-21 23:13:25 +02:00
LoricAndre 5ac979d42d
feat: add --disable-pattern option to selectively disable items (#1077)
* feat: add `--disable-pattern` option to selectively disable items

* chore: generate files

* fix: do not pre-select disabled items

* tests
2026-05-21 20:56:44 +00:00
Loric ANDRE cb8becdc77 release: v4.6.3 2026-05-20 15:41:48 +02:00
LoricAndre e361a8dec0
chore(ci): readd PR check (#1068)
* chore(ci): readd PR check

* fix(ci): use pull_request event

* fix(ci): bash syntax

* fix(ci): pass git cliff context as jq-generated file

* fix(ci): simpler check for changes

* fix(ci): output message if no diff too

* fix(ci): rerun on edit

* fix(ci): exit codes

* chore: fix typos (ci should fail)

* chore: generate files
2026-05-07 12:20:49 +00:00
Loric ANDRE ec77fa7245 release: v4.6.2 2026-05-02 19:55:45 +02:00
Loric ANDRE 8d92d05b8e release: v4.6.1 2026-04-26 19:59:49 +02:00
Loric ANDRE ca986f444c release: v4.6.0 2026-04-14 13:52:54 +02:00
Loric ANDRE 475dd515e5 fix: ignore missing files for ssh completion (closes #1054) 2026-04-14 11:52:23 +02:00
LoricAndre 7375d30bf1
feat: add more info variants (closes #1042) (#1048)
* feat: add more info variants (closes #1042)

* chore: generate completions & manpage

* docs: update info docs

---------

Co-authored-by: Skim bot <skim-bot@skim-rs.github.io>
2026-04-11 14:12:22 +02:00
LoricAndre 4997e2d253
feat: add border none (closes #1041) (#1044)
* feat: add border none (closes #1041)

* chore: generate completions & manpage

* fix: add BorderType::ForceOff to handle popup and no-border

* chore: generate completions & manpage

---------

Co-authored-by: Skim bot <skim-bot@skim-rs.github.io>
2026-04-10 17:44:45 +02:00
Loric ANDRE ada7cc6264 release: v4.5.1 2026-04-07 20:33:07 +02:00
Loric ANDRE 1eb51eecca release: v4.5.0 2026-04-07 11:15:39 +02:00
Xeonacid 40f0e29448
chore: deps: Only use frizbee on x86_64 and aarch64 (#1028)
* chore: deps: Only use frizbee on x86_64 and aarch64

* chore: update docs for frizbee support

* chore: docs [skip ci]

---------

Co-authored-by: LoricAndre <57358788+LoricAndre@users.noreply.github.com>
2026-04-04 14:32:57 +02:00
LoricAndre 6b355e144a
feat: rename tmux -> popup and add zellij (#1027)
* feat: rename tmux -> popup and add zellij

* chore: generate completions & manpage

* Apply suggestions from code review

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* chore: fixes

* chore: generate completions & manpage

* chore: misc, windows todo

* chore: disable popup on windows for now

* chore: generate completions & manpage

* fix: always quote using sh

* chore: expect

* fix: avoid nested popup invocations

* fix: tests

* fix: correctly gate popup

* chore(docs): update ARCHITECTURE.md [skip ci]

---------

Co-authored-by: Skim bot <skim-bot@skim-rs.github.io>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-04-03 13:46:12 +02:00
Loric ANDRE a18e88aafd release: v4.4.0 2026-04-02 19:55:42 +02:00
LoricAndre 91e090e813
chore: better CI caching (#1026)
* chore: better CI caching

* chore: generate completions & manpage

* chore: add platform based key

* cache by runner os

* chore: trigger ci

* feat(bench): measure startup time

---------

Co-authored-by: Skim bot <skim-bot@skim-rs.github.io>
2026-04-02 19:29:46 +02:00
Loric ANDRE 39b120fbd8 release: v4.3.0 2026-03-31 19:29:36 +02:00
Loric ANDRE 94c132a94f release: v4.2.0 2026-03-30 13:58:19 +02:00
LoricAndre 987d2a5ca7
feat: add multiline item rendering (#999)
* feat: add multiline item rendering

* chore: generate completions & manpage

* chore: use newline as default for multiline when read0 is set

* chore: generate completions & manpage

* chore: add `highlight-line'

* chore: generate completions & manpage

* feat: use multiline in history widgets

* feat: better snap tests

* feat(ci): show snap failures

* fix(ci): cross platform tests

---------

Co-authored-by: Skim bot <skim-bot@skim-rs.github.io>
2026-03-30 13:57:09 +02:00
Loric ANDRE 7e5d441e4c release: v4.1.0 2026-03-30 10:09:55 +02:00
Loric ANDRE 65c2dcde11 fix: trim whitespace in zsh hist widget (closes #1019) 2026-03-29 23:14:44 +02:00
Loric ANDRE 6332195605 fix: broken pipe in bash alt-c (closes #1018) 2026-03-29 17:57:56 +02:00
Loric ANDRE 90e23eb86e release: v4.0.1 2026-03-28 10:10:50 +01:00
Douglas Griffith b9c3de302b
replace undefined awk behaviour (#1016)
I encountered a bug with the CTRL-R history behaviour in bash, and tracked it down to these awk commands. I'm not sure what changed, but according to the documentation `\0` is undefined behaviour:
https://pubs.opengroup.org/onlinepubs/9799919799/utilities/awk.html#tagtcjh_15

I've replaced the `\0` escape sequences with the `%c` conversion which converts the int argument to a single byte character. Ref:
https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap05.html
2026-03-26 23:20:43 +01:00
Loric ANDRE c0a9be6b5f fix(keybindings): make sure we use the correct filtering fields 2026-03-23 23:19:10 +01:00