Commit graph

1685 commits

Author SHA1 Message Date
Claude 0279c0349a 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
2026-07-18 19:13:16 +02:00
LoricAndre ad97bfa7de
feat: add bind and unbind actions (#1121)
* feat: add `bind` and `unbind` actions

Add two new actions that allow programmatic (re)binding of keys at
runtime, both through `--bind` keybindings and the IPC/listen socket:

- `bind(key:action[+action][,key:action…])` adds one or more bindings,
  reusing the same parsing/merging logic as the `--bind` CLI option.
  Existing bindings for the same key are replaced.
- `unbind(key[,key…])` removes the bindings for a comma-separated list
  of keys, mirroring fzf's `unbind(...)` semantics.

Because the `Action` enum derives serde when the `listen` feature is
enabled, both actions are drivable over the IPC socket for free.

Covered by unit tests for parsing (`event_tests.rs`) and dispatch
(`app_tests.rs`), plus IPC integration tests (`listen.rs`). Manpage and
ARCHITECTURE.md updated with the new actions.

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

* feat: add `bind` and `unbind` actions

* chore: generate files

* fixes

* fixes

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-18 14:22:41 +00:00
LoricAndre ff98133bbd
ci: add public-api check (#1124)
* ci: add public-api check

* test: try pushing an API breaking change

* fix: install nightly

* test: revert breaking
2026-07-18 15:57:01 +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
LoricAndre 55aa7dacd5
feat: add 'left' and right info display modes (#1120) 2026-07-18 12:34:21 +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 bb6c03f377
feat: reduce binary size by removing uncommon image formats and color_eyre (#1118)
* Shrink binary: trim image decoders and swap color-eyre for eyre

Two dependency changes that cut the default `sk` binary from 13.6 MiB to
8.55 MiB (-5.06 MiB, -37%) with no loss of core functionality:

- image: build the `image` crate with only the common decoders (png,
  jpeg, gif, webp) instead of its full default format set, and drop
  ratatui-image's `image-defaults`. This removes AVIF encoding (ravif,
  avif-serialize), OpenEXR (exr), TIFF, QOI and other decoders that are
  irrelevant to terminal image previews. Previewing those formats now
  falls back to the normal command preview.

- error handling: replace color-eyre with plain eyre. color-eyre only
  provided colored panic/error backtraces; skim used none of its
  Section/Help extension APIs. This drops the backtrace/gimli/addr2line/
  color-spantrace stack. `color_eyre::install()` is no longer needed.

Tests, benches and examples are migrated from color_eyre to eyre so the
crate is fully removed from the dependency graph.

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

* chore: fmt

* docs: ARCHITECTURE.md

* chore(flake): add cargo-bloat

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-17 17:29:43 +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
juneboku 29ca6f22bd
fix: preserve input order with --no-sort (#1115)
* fix: preserve input order with --no-sort

Workers grab 4096-item chunks from a shared queue, so the order in
which worker results are concatenated is nondeterministic. With
--no-sort the merged list was left in that arrival order, which
scrambles the display order once the item count exceeds
num_workers * chunk_size (~24k items on a 10-core machine) and makes
--filter output nondeterministic for large inputs.

Sort matched items by rank.index (the original input position) when
no_sort is set: each worker sorts its accumulator in prepare, and the
final merge exploits the k sorted runs, mirroring the sorted path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* avoid extra sorts by exploiting the thread_pool stability

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Loric ANDRE <loric.andre@pm.me>
2026-07-17 12:16:46 +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
LoricAndre 04c0a5b6c8
ci: fix fixed viewport resize test in non-interactive env (#1114) 2026-07-16 21:30:34 +00:00
Loric ANDRE 9be7392911 fix: manually resize the Tui when not in fullscreen mode
closes #113
2026-07-16 22:14:17 +02:00
Loric ANDRE b1aa46917b chore: fix CHANGELOG duplication 2026-07-16 14:29:18 +02: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 95c360996a ci: add changelog as job output 2026-07-16 12:06:48 +02:00
Loric ANDRE 09479547eb ci: update app-id to client-id 2026-07-16 11:51:24 +02:00
Loric ANDRE 44b9cf2011 ci: add Release PR workflow 2026-07-16 11:43:44 +02:00
Loric ANDRE 8ea0afb63e release: v5.1.1 2026-07-16 10:55:28 +02:00
Lei Zhang 974bd267cc
fix: handle deprecated --expect flag in sk 4.x vim plugin (#1057)
* fix: handle deprecated --expect flag in sk 4.x vim plugin

sk 4.x deprecated --expect and no longer outputs the pressed key name
as the first line of results. This caused s:common_sink to silently
return without opening files, since it expected at least 2 lines
(key + filename). Now handles both old and new output formats.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(vim): replace deprecated expect with accept bindings

* fix(vim): shell-escape accept bindings

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Loric ANDRE <loric.andre@pm.me>
2026-07-16 10:19:04 +02:00
dependabot[bot] 815a9b4f94
chore(deps): bump the cargo-prod group with 3 updates (#1109)
* chore(deps): bump the cargo-prod group with 3 updates

Bumps the cargo-prod group with 3 updates: [frizbee](https://github.com/saghen/frizbee), [gungraun](https://github.com/gungraun/gungraun) and [thread_local](https://github.com/Amanieu/thread_local-rs).


Updates `frizbee` from 0.10.0 to 0.11.0
- [Commits](https://github.com/saghen/frizbee/compare/v0.10.0...v0.11.0)

Updates `gungraun` from 0.19.3 to 0.19.4
- [Release notes](https://github.com/gungraun/gungraun/releases)
- [Changelog](https://github.com/gungraun/gungraun/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gungraun/gungraun/compare/v0.19.3...v0.19.4)

Updates `thread_local` from 1.1.9 to 1.1.10
- [Release notes](https://github.com/Amanieu/thread_local-rs/releases)
- [Changelog](https://github.com/Amanieu/thread_local-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/thread_local-rs/compare/v1.1.9...v1.1.10)

---
updated-dependencies:
- dependency-name: frizbee
  dependency-version: 0.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo-prod
- dependency-name: gungraun
  dependency-version: 0.19.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: thread_local
  dependency-version: 1.1.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: frizbee

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Loric ANDRE <loric.andre@pm.me>
2026-07-16 10:01:35 +02:00
Loric ANDRE c4bc5e1be4 release: v5.1.0 2026-07-09 14:34:06 +02:00
Loric ANDRE ef59339727 fix: unknown border values fallback to plain (closes #1107) 2026-07-09 13:58:59 +02:00
Loric ANDRE 1effd9a69d test: fix arinae max pat len test after constant update 2026-07-09 12:41:38 +02:00
Loric ANDRE 0a4d4b2ea0 fix: less restrictive max pattern in ari matcher 2026-07-09 12:00:38 +02:00
LoricAndre 026a622a9d
feat: add cargo-fuzz targets for hand-rolled text parsers (#1106)
* feat: add cargo-fuzz targets for hand-rolled text parsers

Skim's most panic-prone code is the hand-written byte/char-index
bookkeeping over untrusted input: ANSI stripping, --nth/--with-nth field
extraction, the fuzzy matching algorithms, the query->engine->match
pipeline, and the --bind key-map parser. Add five cargo-fuzz (libFuzzer)
targets covering each, asserting real invariants (char-boundary safety,
monotonic index mappings, match indices in bounds) rather than just
catching panics, plus a CI workflow that runs them on every push/PR
touching src/ or fuzz/ and a longer nightly session via cron.

* ci: wire fuzz targets into the existing test matrix

Replace the standalone fuzz.yml workflow with a `fuzz` job in the main
test.yml matrix, running each of the 5 fuzz targets for 60s (5 minutes
total per CI run) alongside nextest/clippy/msrv.

* ci: remove standalone fuzz workflow

Superseded by the fuzz job now in test.yml.

* ci: run fuzz job as a single job on the platform matrix

Reuse the existing linux/macos/windows matrix instead of a separate
per-target matrix; run all 5 fuzz targets sequentially in one step
(60s each, 5 minutes total). cargo-fuzz doesn't support Windows, so
the fuzzing step is skipped there while still installing the
toolchain for consistency with the rest of the matrix.

* ci: reuse existing yaml anchors in the fuzz job

Use *toolchain instead of a bespoke nightly-install step, matching
the coverage job's pattern of letting `cargo +nightly` auto-provision
the toolchain on demand.

* nix: add cargo-fuzz to the tests devShell

Makes cargo-fuzz available via `nix develop` alongside the other test
tooling, matching what CI installs for the fuzz job.

* ci: install cargo-fuzz via taiki-e/install-action

Matches how the other CI-only cargo subcommands (nextest, cargo-msrv,
cargo-llvm-cov) are installed, and is faster than compiling it from
source with cargo install.

* ci: force the native host target for cargo-fuzz

cargo-fuzz was picking a statically-linked musl target on the runner,
which fails since ASan can't link against a static libc. Pass the
actual host triple (from `rustc -vV`) explicitly so the sanitizer
build always targets the dynamically-linked gnu/darwin toolchain.

* ci: skip the whole fuzz job on windows

Rather than skipping just the fuzzing step, exclude the job entirely
for the windows-latest matrix entry via a job-level `if`, since
cargo-fuzz/libFuzzer has no Windows support.

* ci: gate the fuzz job with runner.os instead of matrix.os

Matches the runner.os-based conditionals already used elsewhere in
this workflow (the linux/macos dependency install steps) rather than
comparing matrix.os directly.

* ci: enable the fuzz job on windows without ASan

cargo-fuzz does support Windows, but AddressSanitizer on the MSVC
target needs the separate "C++ AddressSanitizer" VS component plus a
PATH tweak for its DLL, which this runner doesn't have configured.
Rather than skip the job, disable the sanitizer on Windows only
(--sanitizer none) and keep coverage-guided fuzzing there; our
targets assert via plain Rust panics so they don't depend on ASan.

* test: assert exact char_idx correctness in ansi_strip fuzz target

Replace the bounds-only char_idx check with an exact-equality check
against the char position of byte_pos in the original string. This
subsumes (and is stronger than) the monotonicity CodeRabbit flagged,
since strictly-increasing byte positions on char boundaries always
imply strictly-increasing char positions.

* ci: skip windows in fuzz job, scope job permissions

CI showed the Windows fuzz build fails with a real MSVC linker error
(LNK2001: unresolved __start/__stop___sancov_pcs) even with
--sanitizer none: MSVC's linker doesn't synthesize the section
boundary symbols that libFuzzer's coverage instrumentation requires,
so this is unrelated to the earlier ASan/PATH discussion and isn't
fixable by a sanitizer flag. Skip Windows via step-level `if`
(job-level `if` can't reference runner/matrix contexts). Also add an
explicit contents:read permissions block to the job.

* fix(fzy): fix unicode case-folding inconsistency causing overflow panic

The new fuzzy_match fuzz target found a real crash: FzyMatcher panicked
with "attempt to multiply with overflow" on choice="ű\0\0\0\u{1e}ű",
pattern="Űű".

Root cause: fzy_score's case-insensitive comparison used
char::to_ascii_lowercase (a no-op on non-ASCII letters like Ű/ű), while
the shared cheap_matches() prefilter (and the other matchers) use the
Unicode-aware char_equal(). This let cheap_matches accept a pattern
that fzy_score's own DP could then never actually align, since needle
char 'Ű' never matched any haystack position under ASCII-only folding.
The DP's SCORE_MIN sentinel ("impossible") isn't an absorbing element
under plain integer addition, so the broken alignment accumulated to a
value close to, but not exactly, SCORE_MIN, which then overflowed on
the final *SCORE_TO_SKIM conversion since only the exact sentinel was
special-cased.

Fix is_match to use the shared char_equal() so fzy.rs's case folding
matches cheap_matches and the other two matchers (skim.rs, clangd.rs
already do this). Also switch internal_to_skim_score to saturating_mul
as defense in depth, since fzy_score structurally always returns
Some(..) and has no other way to signal "no valid alignment" to the
caller.

* ci: try lld-link to get windows fuzzing working (no ASan)

MSVC ASan is documented broken on GitHub-hosted Windows runners
(actions/runner-images#8891 — ASan binaries crash with
STATUS_DLL_INIT_FAILED even with the runtime DLL on PATH, unresolved
upstream), so it's not viable here regardless of our config. Separately,
the sancov coverage instrumentation cargo-fuzz needs doesn't link with
MSVC's link.exe at all (missing __start/__stop section symbols).
Try switching the Windows leg to rustc's bundled LLD linker
(-C linker-flavor=lld-link -C link-self-contained=+linker) with
--sanitizer none, to at least get coverage-guided fuzzing (no ASan)
working there. Validating live against this PR's CI.

* ci: revert windows fuzzing attempt, exclude it again

The lld-link experiment ruled out the remaining option: LLD's COFF
driver hit the exact same missing __start/__stop___sancov_* symbols as
MSVC's link.exe. This confirms the section-boundary-symbol synthesis
libFuzzer's coverage instrumentation needs simply isn't implemented
for the COFF/Windows target in current LLVM/rustc — an upstream gap,
not a linker choice or CI config problem. Combined with MSVC ASan
being separately documented broken on GH-hosted Windows runners
(actions/runner-images#8891), there's no remaining avenue to try from
the workflow side. Back to excluding Windows from the fuzz job.

* ci: try windows fuzzing with default sanitizer + msvc dev env

Previous Windows attempts both used --sanitizer none, which removes
the ASan runtime that (on Windows) supplies the __start/__stop section
symbol shims libFuzzer's coverage instrumentation needs -- neither
linker synthesizes those on COFF. That's very likely why they failed
to link. Revert to the default sanitizer (address) and add
ilammy/msvc-dev-cmd to put the MSVC ASan DLL directory on PATH, per
the cargo-fuzz Windows setup guide and actions/runner-images#8891.
Testing live whether this builds, and whether the previously-reported
STATUS_DLL_INIT_FAILED runtime crash still reproduces on this runner
image.

* ci: point cargo at the real MSVC linker on windows

msvc-dev-cmd correctly set up Path, but Git Bash prepends its own
usr/bin ahead of it, so cargo picked up Git's coreutils `link`
(hardlink tool) instead of MSVC's link.exe. Set
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER explicitly using
VCToolsInstallDir (set by msvc-dev-cmd) to sidestep PATH ordering
entirely.

* fix(event): parse_action returns None instead of panicking on missing args

The keymap_parse fuzz target found a real crash: KeyMap::from("/:if-")
panicked ("no arg specified for event if-") since parse_action's
documented behavior was to panic on if-* actions missing their
argument, even though the function already returns Option<Action> and
every other malformed/unrecognized action already resolves to None
via the surrounding parse_action_chain/KeyMap plumbing.

Fixed that case, and while checking for the same pattern elsewhere in
the function found four more reachable panics of the same kind
(add-char, execute, execute-silent, set-preview-cmd, set-query parsed
without their required argument), confirmed each panics via a small
repro before fixing. All now return None like every other malformed
action, consistent with the function's existing contract, instead of
panicking on user-supplied --bind strings.

* ci: add a single aggregate status check for branch rulesets

Add a ci-success job that depends on every other job in the workflow
and fails if any of them failed or were cancelled (tolerating
deploy-coverage-page's expected skip off master). This gives branch
protection / repository rulesets one stable check name to require,
instead of enumerating every matrix leg (nextest (linux), fuzz
(windows), etc.) individually.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-07-04 18:01:46 +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
dependabot[bot] 6c08be00c9
chore(deps): bump the gha-prod group with 4 updates (#1104)
Bumps the gha-prod group with 4 updates: [actions/checkout](https://github.com/actions/checkout), [emibcn/badge-action](https://github.com/emibcn/badge-action), [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) and [actions/deploy-pages](https://github.com/actions/deploy-pages).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v6...v7)

Updates `emibcn/badge-action` from 2.0.2 to 2.0.4
- [Release notes](https://github.com/emibcn/badge-action/releases)
- [Commits](https://github.com/emibcn/badge-action/compare/v2.0.2...v2.0.4)

Updates `actions/upload-pages-artifact` from 3 to 5
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v3...v5)

Updates `actions/deploy-pages` from 4 to 5
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](https://github.com/actions/deploy-pages/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gha-prod
- dependency-name: emibcn/badge-action
  dependency-version: 2.0.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: gha-prod
- dependency-name: actions/upload-pages-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gha-prod
- dependency-name: actions/deploy-pages
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gha-prod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-02 19:52:53 +02:00
LoricAndre f2ca01e187
feat!: feature-gate listen and image to allow opting out (#1103)
* feat!: feature-gate listen and image to allow opting out

This is breaking since disabling the default features now also disables
those. It is NOT breaking for cli users, only for library ones.

* fix: add warn on listener transfer failure
2026-06-29 15:35:50 +02:00
Loric ANDRE aeba919fab release: v4.10.0 2026-06-28 19:00:17 +02:00
Maximilian Roos bfec6e198d
feat(theme): add a themeable scrollbar color for the item list (#1101)
* feat(theme): add a themeable scrollbar color for the item list

The item-list scrollbar was the only rendered UI element without a
ColorTheme entry. ratatui's Scrollbar defaults thumb_style to an empty
Style, so the thumb merged nothing onto the cells it drew over and
inherited their fg/bg — most visibly the current-line highlight, which
the thumb adopted as the cursor scrolled past it.

Add a `scrollbar` color to ColorTheme, parse it from `--color`
(`scrollbar:<spec>`), default it per theme to the border color (the four
catppuccin themes use their muted `overlay0` instead), and pass it as the
Scrollbar thumb style. The thumb now reads as uniform chrome instead of
tracking whatever row sits under it. The colorless `none` theme leaves it
unset, so NO_COLOR still renders no thumb styling.

Documented in the README color table and the manpage; covered by theme
unit tests and @snap_color integration tests (default border color and a
custom --color=scrollbar override, both over the highlighted current line).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore: generate-files & misc

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Loric ANDRE <loric.andre@pm.me>
2026-06-28 18:48:28 +02:00
LoricAndre 5f4798325a
tests: improve coverage on matchers & algos (#1100)
* test(engine,fuzzy_matcher): add unit tests for branch coverage; fix use_cache(false) double-borrow

Add targeted unit tests to exercise every reachable branch in the `engine`
and `fuzzy_matcher` modules, measured with cargo-llvm-cov's branch coverage
on nightly. Tests use realistic inputs and assert concrete behaviour:

- engine: empty/offset/byte-range matching ranges in the fuzzy engine, the
  Frizbee and typo Arinae build paths, AND/OR empty-term filtering, and
  split-engine byte-range char exclusion.
- arinae: typo substitutions and deletions, non-ASCII dispatch, prefilter
  rejection paths, and direct kernel tests for the DP guards / band-skip /
  dead-row pruning that compute_banding makes unreachable through the API.
- clangd/fzy/skim/util: typo-DP substitution, deletion, gap and length-guard
  paths; ASCII/non-ASCII dispatch; single-char and score-only paths; and the
  assert_order failure diagnostics.

Fix a latent double-borrow bug: `use_cache(false)` in the clangd, skim and
fzy matchers called `RefCell::replace` on cache cells whose `RefMut` guards
were still alive, panicking on every match. Drop the guards before clearing
the caches so the option works (and is now covered by tests).

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

* test(fuzzy_matcher): thread guard paths by isolating callees

Cover branches that are reachable only when the inner helper is invoked
directly with inputs the public matchers can never produce:

- clangd `match_bonus` with `Action::Miss` (callers always pass `Match`) —
  asserts the 30-point in-segment-after-miss penalty.
- fzy `internal_to_skim_score(SCORE_MIN)` sentinel mapping; the empty-pattern
  slow-path `n == 0` guard; and `fzy_score` driven with a non-subsequence
  needle so the position backtrace hits the column-0 fallback.

The branches that remain uncovered are now confirmed structurally
unreachable even via direct callee calls: const-generic monomorphization
artifacts, M-cell `!= SCORE_MIN` checks (an M-cell is never exactly the
sentinel after gap accumulation), a match cell at (i>0, j==0) that is always
SCORE_MIN, and short-circuit operands excluded by upstream invariants.

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

* test(fuzzy_matcher/skim): thread arg-reachable guards in skim helpers

build_in_place_bonus's `b.len() > 1` and calculate_score_with_pos's
`op.is_none()` are unreachable through the public matcher (the real caller
never passes an empty choice or an over-wide column range), but they ARE
reachable by calling the private helpers directly with such arguments.
Cover both, leaving only genuinely argument-independent dead branches.

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

* chore: misc checks & fixes

* fix: default bench arg

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* chore: remove magic number

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-06-27 00:16:15 +02:00
Loric ANDRE d14407196b release: v4.9.0 2026-06-26 00:53:37 +02:00
Jason Wang 7d4502201f
fix: refresh preview after mouse selection (#1095)
* fix: refresh preview after mouse selection

* Address mouse preview review feedback

* feat(ci): upload coverage report to pages for easier browsing (#1096)

* feat(ci): upload coverage report to pages for easier browsing

* fix: remove anchors

* fix: release report

* fix: coverage percent

* docs: update README

* chore: only on master

* test: add unit tests for the shell & manpage generators (#1098)

* test: add unit tests for the shell & manpage generators

* chore: propagate key bindings generation errors

* tests: improve coverage to 90% (#1099)

* tests: improve coverage to 90%

* feat: improve coverage

* remove most unix-only tests

* Update src/skim_tests.rs

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

* fixes

* chore: misc

---------

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

* chore: cleanup

---------

Co-authored-by: LoricAndre <57358788+LoricAndre@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Loric ANDRE <loric.andre@pm.me>
2026-06-26 00:36:07 +02:00
LoricAndre 7e2cdf3c8e
tests: improve coverage to 90% (#1099)
* tests: improve coverage to 90%

* feat: improve coverage

* remove most unix-only tests

* Update src/skim_tests.rs

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

* fixes

* chore: misc

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-06-25 19:12:49 +00:00
LoricAndre 8187a12196
test: add unit tests for the shell & manpage generators (#1098)
* test: add unit tests for the shell & manpage generators

* chore: propagate key bindings generation errors
2026-06-24 18:18:15 +00:00
LoricAndre b56eed4125
feat(ci): upload coverage report to pages for easier browsing (#1096)
* feat(ci): upload coverage report to pages for easier browsing

* fix: remove anchors

* fix: release report

* fix: coverage percent

* docs: update README

* chore: only on master
2026-06-24 18:55:33 +02:00
LoricAndre e85cf6b708
chore(ci): use github's coverage (#1094)
* chore(ci): use github's coverage

* fix: perms

* chore: ci

* test(ci): comment perm to check triggers

* test(ci): readd perm

* fix(ci): test with dist config

* fix(ci): generate dist

* fix

* docs: remove codecov

* chore: delete codecov file
2026-06-24 12:51:44 +02:00
dependabot[bot] 7994e44412
chore(deps): bump the cargo-prod group with 4 updates (#1093)
Bumps the cargo-prod group with 4 updates: [log](https://github.com/rust-lang/log), [ratatui](https://github.com/ratatui/ratatui), [ratatui-image](https://github.com/ratatui/ratatui-image) and [ron](https://github.com/ron-rs/ron).


Updates `log` from 0.4.32 to 0.4.33
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.32...0.4.33)

Updates `ratatui` from 0.30.1 to 0.30.2
- [Release notes](https://github.com/ratatui/ratatui/releases)
- [Changelog](https://github.com/ratatui/ratatui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ratatui/ratatui/compare/ratatui-v0.30.1...ratatui-v0.30.2)

Updates `ratatui-image` from 11.0.4 to 11.0.5
- [Release notes](https://github.com/ratatui/ratatui-image/releases)
- [Changelog](https://github.com/ratatui/ratatui-image/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ratatui/ratatui-image/compare/v11.0.4...v11.0.5)

Updates `ron` from 0.12.1 to 0.12.2
- [Release notes](https://github.com/ron-rs/ron/releases)
- [Changelog](https://github.com/ron-rs/ron/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ron-rs/ron/compare/v0.12.1...v0.12.2)

---
updated-dependencies:
- dependency-name: log
  dependency-version: 0.4.33
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: ratatui
  dependency-version: 0.30.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: ratatui-image
  dependency-version: 11.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: ron
  dependency-version: 0.12.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-23 12:57:53 +00:00
Loric ANDRE fbd426f569 release: v4.8.0 2026-06-17 14:31:28 +02:00
Loric ANDRE 00165fbc98 docs: update ARCHITECTURE.md 2026-06-17 14:07:13 +02:00
Loric ANDRE 0de1a2acbb chore: format imports 2026-06-17 13:58:44 +02:00
Loric ANDRE 42fa8e143b chore: add image tests & examples 2026-06-17 13:56:37 +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
dependabot[bot] 1a223219fb
chore(deps): bump the cargo-prod group with 7 updates (#1092)
* chore(deps): bump the cargo-prod group with 7 updates

Bumps the cargo-prod group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [gungraun](https://github.com/gungraun/gungraun) | `0.19.1` | `0.19.2` |
| [log](https://github.com/rust-lang/log) | `0.4.31` | `0.4.32` |
| [memchr](https://github.com/BurntSushi/memchr) | `2.8.1` | `2.8.2` |
| [ratatui](https://github.com/ratatui/ratatui) | `0.30.0` | `0.30.1` |
| [regex](https://github.com/rust-lang/regex) | `1.12.3` | `1.12.4` |
| [which](https://github.com/harryfei/which-rs) | `8.0.2` | `8.0.3` |
| [insta](https://github.com/mitsuhiko/insta) | `1.47.2` | `1.48.0` |


Updates `gungraun` from 0.19.1 to 0.19.2
- [Release notes](https://github.com/gungraun/gungraun/releases)
- [Changelog](https://github.com/gungraun/gungraun/blob/main/CHANGELOG.md)
- [Commits](https://github.com/gungraun/gungraun/compare/v0.19.1...v0.19.2)

Updates `log` from 0.4.31 to 0.4.32
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.31...0.4.32)

Updates `memchr` from 2.8.1 to 2.8.2
- [Commits](https://github.com/BurntSushi/memchr/compare/2.8.1...2.8.2)

Updates `ratatui` from 0.30.0 to 0.30.1
- [Release notes](https://github.com/ratatui/ratatui/releases)
- [Changelog](https://github.com/ratatui/ratatui/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ratatui/ratatui/compare/ratatui-v0.30.0...ratatui-v0.30.1)

Updates `regex` from 1.12.3 to 1.12.4
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.12.3...1.12.4)

Updates `which` from 8.0.2 to 8.0.3
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/8.0.2...8.0.3)

Updates `insta` from 1.47.2 to 1.48.0
- [Release notes](https://github.com/mitsuhiko/insta/releases)
- [Changelog](https://github.com/mitsuhiko/insta/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mitsuhiko/insta/compare/1.47.2...1.48.0)

---
updated-dependencies:
- dependency-name: gungraun
  dependency-version: 0.19.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: log
  dependency-version: 0.4.32
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: memchr
  dependency-version: 2.8.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: ratatui
  dependency-version: 0.30.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: regex
  dependency-version: 1.12.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: which
  dependency-version: 8.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: cargo-prod
- dependency-name: insta
  dependency-version: 1.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: cargo-prod
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: fix failing tests after ratatui update

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Loric ANDRE <loric.andre@pm.me>
2026-06-16 22:40:19 +02:00
LoricAndre b5b11a472f
fix: tmux sigpipe (#1090)
* fix: SIGPIPE when piped command in popup

* chore: export SKIM_DEFAULT_COMMAND when the cli feature is disabled

* fix: exit silently on write error
2026-06-12 10:06:43 +00:00
LoricAndre 6ddf0314e9
perf: optimize --tac pipeline (#1089) 2026-06-12 09:41:04 +00:00
LoricAndre 3f9e5e5687
fix: multiline popup cmd misread (#1088)
* fix: avoid passing cmd through tmux so we don't capture it when multiline

closes #1086

* chore: get default command in SkimOptions::from_env
2026-06-12 09:23:28 +00:00
LoricAndre 91e9cbe512
chore: add msrv checks (#1083)
* chore: add msrv checks

* fix
2026-06-09 13:55:51 +02:00