Repository: junegunn/fzf
Pull request #3956 (2024-08-05 13:48:19)

Bump crate-ci/typos from 1.23.1 to 1.23.6
Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.23.1 to 1.23.6.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/crate-ci/typos/releases">crate-ci/typos's releases</a>.</em></p>
<blockquote>
<h2>v1.23.6</h2>
<h2>[1.23.6] - 2024-07-31</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a href="https://redirect.github.com/crate-ci/typos/issues/1051">July 2024</a> changes</li>
</ul>
<h2>v1.23.5</h2>
<h2>[1.23.5] - 2024-07-25</h2>
<h3>Features</h3>
<ul>
<li><em>(config)</em> Store config in <code>Cargo.toml</code></li>
</ul>
<h2>v1.23.4</h2>
<h2>[1.23.4] - 2024-07-25</h2>
<h3>Fixes</h3>
<ul>
<li>Don't correct <code>countr_one</code> in C++</li>
</ul>
<h2>v1.23.3</h2>
<h2>[1.23.3] - 2024-07-22</h2>
<h3>Fixes</h3>
<ul>
<li>Fix <code>Dockerfile</code></li>
</ul>
<h2>v1.23.2</h2>
<h2>[1.23.2] - 2024-07-10</h2>
<h3>Features</h3>
<ul>
<li>Automatically ignore JWT tokens</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's changelog</a>.</em></p>
<blockquote>
<h2>[1.23.6] - 2024-07-31</h2>
<h3>Fixes</h3>
<ul>
<li>Updated the dictionary with the <a href="https://redirect.github.com/crate-ci/typos/issues/1051">July 2024</a> changes</li>
</ul>
<h2>[1.23.5] - 2024-07-25</h2>
<h3>Features</h3>
<ul>
<li><em>(config)</em> Store config in <code>Cargo.toml</code></li>
</ul>
<h2>[1.23.4] - 2024-07-25</h2>
<h3>Fixes</h3>
<ul>
<li>Don't correct <code>countr_one</code> in C++</li>
</ul>
<h2>[1.23.3] - 2024-07-22</h2>
<h3>Fixes</h3>
<ul>
<li>Fix <code>Dockerfile</code></li>
</ul>
<h2>[1.23.2] - 2024-07-10</h2>
<h3>Features</h3>
<ul>
<li>Automatically ignore JWT tokens</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/crate-ci/typos/commit/935271f0204ebdf61717cf6caac31d8d115f1c14"><code>935271f</code></a> chore: Release</li>
<li><a href="https://github.com/crate-ci/typos/commit/7dbdf8c01c6304e84f7549ec6753946dd2b1af45"><code>7dbdf8c</code></a> chore: Release</li>
<li><a href="https://github.com/crate-ci/typos/commit/be714bc5ef748cae9171f42f58f2f63e014576c8"><code>be714bc</code></a> docs: Update changelog</li>
<li><a href="https://github.com/crate-ci/typos/commit/a87cf89ab1baac02311f5091e1e565dc8d16bb4a"><code>a87cf89</code></a> Merge pull request <a href="https://redirect.github.com/crate-ci/typos/issues/1070">#1070</a> from epage/july</li>
<li><a href="https://github.com/crate-ci/typos/commit/12a33e21f40065016d2a99bfba322beee4604c1b"><code>12a33e2</code></a> fix(dict): July updates</li>
<li><a href="https://github.com/crate-ci/typos/commit/0d9c778a8cc6830f2a2e1d4dd2b98c8d6aa06610"><code>0d9c778</code></a> chore(deps): Update Rust Stable to v1.80 (<a href="https://redirect.github.com/crate-ci/typos/issues/1064">#1064</a>)</li>
<li><a href="https://github.com/crate-ci/typos/commit/ebbe2a1b199238f3153224a5f27001dffa247d4a"><code>ebbe2a1</code></a> Merge pull request <a href="https://redirect.github.com/crate-ci/typos/issues/1066">#1066</a> from epage/template</li>
<li><a href="https://github.com/crate-ci/typos/commit/9dc8c88844ed8d595c374f06f91f8b22c09cc8f5"><code>9dc8c88</code></a> chore(ci): Don't check minimal versions for bins</li>
<li><a href="https://github.com/crate-ci/typos/commit/267121b5d69edcc489eb4c82f15cf302b9abf8d1"><code>267121b</code></a> style: Make clippy happy</li>
<li><a href="https://github.com/crate-ci/typos/commit/063ac6d4b532e7ccb37b02c39a278b0c27d387e6"><code>063ac6d</code></a> chore: Update from _rust/main template</li>
<li>Additional commits viewable in <a href="https://github.com/crate-ci/typos/compare/v1.23.1...v1.23.6">compare view</a></li>
</ul>
</details>
<br />

<details>
<summary>Most Recent Ignore Conditions Applied to This Pull Request</summary>

| Dependency Name | Ignore Conditions |
| --- | --- |
| crate-ci/typos | [< 1.17, > 1.16.4] |
</details>


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.23.1&new-version=1.23.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml
index ef2876c7..082ff80b 100644
--- a/.github/workflows/typos.yml
+++ b/.github/workflows/typos.yml
@@ -7,4 +7,4 @@ jobs:
     runs-on: ubuntu-latest
     steps:
     - uses: actions/checkout@v4
-    - uses: crate-ci/typos@v1.23.1
+    - uses: crate-ci/typos@v1.23.6
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 73cb0331..24a13b4d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,34 @@
 CHANGELOG
 =========
 
+0.55.0
+------
+- [bash] Fuzzy path completion is enabled for all commands
+    - 1. If the default completion is not already set
+    - 2. And if the current bash supports `complete -D` option
+    - However, fuzzy completion for some commands can be "dynamically" disabled by the dynamic completion loader
+    - See the comment in `__fzf_default_completion` function for more information
+- Comments are now allowed in `$FZF_DEFAULT_OPTS` and `$FZF_DEFAULT_OPTS_FILE`
+  ```sh
+  export FZF_DEFAULT_OPTS='
+    # Layout options
+    --layout=reverse
+    --info=inline-right   # Show info on the right side of the prompt line
+    # ...
+  '
+  ```
+- Hyperlinks (OSC 8) are now supported in the preview window and in the main window
+  ```sh
+  printf '<< \e]8;;http://github.com/junegunn/fzf\e\\Link to \e[32mfz\e[0mf\e]8;;\e\\ >>' | fzf --ansi
+
+  fzf --preview "printf '<< \e]8;;http://github.com/junegunn/fzf\e\\Link to \e[32mfz\e[0mf\e]8;;\e\\ >>'"
+  ```
+- [vim] A spec can have `exit` callback that is called with the exit status of fzf
+    - This can be used to clean up temporary resources or restore the original state when fzf is closed without a selection
+- Fixed `--tmux bottom` when the status line is not at the bottom
+- Fixed extra scroll offset in multi-line mode (`--read0` or `--wrap`)
+- Added fallback `ps` command for `kill` completion on Cygwin
+
 0.54.3
 ------
 - Fixed incompatibility of adaptive height specification and 'start:reload'
diff --git a/README-VIM.md b/README-VIM.md
index e727dd1e..3362ea26 100644
--- a/README-VIM.md
+++ b/README-VIM.md
@@ -289,8 +289,9 @@ The following table summarizes the available options.
 | `source`                   | string        | External command to generate input to fzf (e.g. `find .`)             |
 | `source`                   | list          | Vim list as input to fzf                                              |
 | `sink`                     | string        | Vim command to handle the selected item (e.g. `e`, `tabe`)            |
-| `sink`                     | funcref       | Reference to function to process each selected item                   |
+| `sink`                     | funcref       | Function to be called with each selected item                         |
 | `sinklist` (or `sink*`)    | funcref       | Similar to `sink`, but takes the list of output lines at once         |
+| `exit`                     | funcref       | Function to be called with the exit status of fzf (e.g. 0, 1, 2, 130) |
 | `options`                  | string/list   | Options to fzf                                                        |
 | `dir`                      | string        | Working directory                                                     |
 | `up`/`down`/`left`/`right` | number/string | (Layout) Window position and size (e.g. `20`, `50%`)                  |
diff --git a/README.md b/README.md
index 862cfd05..d4e216c6 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,7 @@ I would like to thank all the sponsors of this project who make it possible for
 
 If you'd like to sponsor this project, please visit https://github.com/sponsors/junegunn.
 
-<!-- sponsors --><a href="https://github.com/miyanokomiya"><img src="https://github.com/miyanokomiya.png" width="60px" alt="miyanokomiya" /></a><a href="https://github.com/jonhoo"><img src="https://github.com/jonhoo.png" width="60px" alt="Jon Gjengset" /></a><a href="https://github.com/AceofSpades5757"><img src="https://github.com/AceofSpades5757.png" width="60px" alt="Kyle L. Davis" /></a><a href="https://github.com/Frederick888"><img src="https://github.com/Frederick888.png" width="60px" alt="Frederick Zhang" /></a><a href="https://github.com/moritzdietz"><img src="https://github.com/moritzdietz.png" width="60px" alt="Moritz Dietz" /></a><a href="https://github.com/mikker"><img src="https://github.com/mikker.png" width="60px" alt="Mikkel Malmberg" /></a><a href="https://github.com/pldubouilh"><img src="https://github.com/pldubouilh.png" width="60px" alt="Pierre Dubouilh" /></a><a href="https://github.com/trantor"><img src="https://github.com/trantor.png" width="60px" alt="Fulvio Scapin" /></a><a href="https://github.com/rcorre"><img src="https://github.com/rcorre.png" width="60px" alt="Ryan Roden-Corrent" /></a><a href="https://github.com/blissdev"><img src="https://github.com/blissdev.png" width="60px" alt="Jordan Arentsen" /></a><a href="https://github.com/mislav"><img src="https://github.com/mislav.png" width="60px" alt="Mislav Marohnić" /></a><a href="https://github.com/aexvir"><img src="https://github.com/aexvir.png" width="60px" alt="Alex Viscreanu" /></a><a href="https://github.com/dbalatero"><img src="https://github.com/dbalatero.png" width="60px" alt="David Balatero" /></a><a href="https://github.com/moobar"><img src="https://github.com/moobar.png" width="60px" alt="" /></a><a href="https://github.com/majjoha"><img src="https://github.com/majjoha.png" width="60px" alt="Mathias Jean Johansen" /></a><a href="https://github.com/benelan"><img src="https://github.com/benelan.png" width="60px" alt="Ben Elan" /></a><a href="https://github.com/pawelduda"><img src="https://github.com/pawelduda.png" width="60px" alt="Paweł Duda" /></a><a href="https://github.com/slezica"><img src="https://github.com/slezica.png" width="60px" alt="Santiago Lezica" /></a><a href="https://github.com/pbwn"><img src="https://github.com/pbwn.png" width="60px" alt="" /></a><a href="https://github.com/timgluz"><img src="https://github.com/timgluz.png" width="60px" alt="Timo Sulg" /></a><a href="https://github.com/pyrho"><img src="https://github.com/pyrho.png" width="60px" alt="Damien Rajon" /></a><a href="https://github.com/ArtBIT"><img src="https://github.com/ArtBIT.png" width="60px" alt="ArtBIT" /></a><a href="https://github.com/da-moon"><img src="https://github.com/da-moon.png" width="60px" alt="" /></a><a href="https://github.com/hovissimo"><img src="https://github.com/hovissimo.png" width="60px" alt="Hovis" /></a><a href="https://github.com/dariusjonda"><img src="https://github.com/dariusjonda.png" width="60px" alt="Darius Jonda" /></a><a href="https://github.com/cristiand391"><img src="https://github.com/cristiand391.png" width="60px" alt="Cristian Dominguez" /></a><a href="https://github.com/eliangcs"><img src="https://github.com/eliangcs.png" width="60px" alt="Chang-Hung Liang" /></a><a href="https://github.com/asphaltbuffet"><img src="https://github.com/asphaltbuffet.png" width="60px" alt="Ben Lechlitner" /></a><a href="https://github.com/yash1th"><img src="https://github.com/yash1th.png" width="60px" alt="yash" /></a><a href="https://github.com/looshch"><img src="https://github.com/looshch.png" width="60px" alt="george looshch" /></a><a href="https://github.com/kg8m"><img src="https://github.com/kg8m.png" width="60px" alt="Takumi KAGIYAMA" /></a><a href="https://github.com/polm"><img src="https://github.com/polm.png" width="60px" alt="Paul OLeary McCann" /></a><a href="https://github.com/rbeeger"><img src="https://github.com/rbeeger.png" width="60px" alt="Robert Beeger" /></a><a href="https://github.com/veebch"><img src="https://github.com/veebch.png" width="60px" alt="VEEB Projects" /></a><a href="https://github.com/yowayb"><img src="https://github.com/yowayb.png" width="60px" alt="Yoway Buorn" /></a><a href="https://github.com/scalisi"><img src="https://github.com/scalisi.png" width="60px" alt="Josh Scalisi" /></a><a href="https://github.com/alecbcs"><img src="https://github.com/alecbcs.png" width="60px" alt="Alec Scott" /></a><a href="https://github.com/the-shank"><img src="https://github.com/the-shank.png" width="60px" alt="theshank" /></a><a href="https://github.com/thnxdev"><img src="https://github.com/thnxdev.png" width="60px" alt="thanks.dev" /></a><a href="https://github.com/artursapek"><img src="https://github.com/artursapek.png" width="60px" alt="Artur Sapek" /></a><a href="https://github.com/ramnes"><img src="https://github.com/ramnes.png" width="60px" alt="Guillaume Gelin" /></a><a href="https://github.com/jyc"><img src="https://github.com/jyc.png" width="60px" alt="" /></a><a href="https://github.com/mrcnski"><img src="https://github.com/mrcnski.png" width="60px" alt="Marcin S." /></a><a href="https://github.com/roblevy"><img src="https://github.com/roblevy.png" width="60px" alt="Rob Levy" /></a><a href="https://github.com/glozow"><img src="https://github.com/glozow.png" width="60px" alt="Gloria Zhao" /></a><a href="https://github.com/wjt"><img src="https://github.com/wjt.png" width="60px" alt="Will Thompson" /></a><a href="https://github.com/toupeira"><img src="https://github.com/toupeira.png" width="60px" alt="Markus Koller" /></a><a href="https://github.com/rkpatel33"><img src="https://github.com/rkpatel33.png" width="60px" alt="" /></a><a href="https://github.com/jamesob"><img src="https://github.com/jamesob.png" width="60px" alt="jamesob" /></a><a href="https://github.com/jlebray"><img src="https://github.com/jlebray.png" width="60px" alt="Johan Le Bray" /></a><a href="https://github.com/panosl1"><img src="https://github.com/panosl1.png" width="60px" alt="Panos Lampropoulos" /></a><a href="https://github.com/bespinian"><img src="https://github.com/bespinian.png" width="60px" alt="bespinian" /></a><a href="https://github.com/xordspar0"><img src="https://github.com/xordspar0.png" width="60px" alt="Jordan Christiansen" /></a><a href="https://github.com/scosu"><img src="https://github.com/scosu.png" width="60px" alt="Markus Schneider-Pargmann" /></a><a href="https://github.com/smithbm2316"><img src="https://github.com/smithbm2316.png" width="60px" alt="Ben Smith" /></a><!-- sponsors -->
+<!-- sponsors --><a href="https://github.com/miyanokomiya"><img src="https://github.com/miyanokomiya.png" width="60px" alt="miyanokomiya" /></a><a href="https://github.com/jonhoo"><img src="https://github.com/jonhoo.png" width="60px" alt="Jon Gjengset" /></a><a href="https://github.com/AceofSpades5757"><img src="https://github.com/AceofSpades5757.png" width="60px" alt="Kyle L. Davis" /></a><a href="https://github.com/Frederick888"><img src="https://github.com/Frederick888.png" width="60px" alt="Frederick Zhang" /></a><a href="https://github.com/moritzdietz"><img src="https://github.com/moritzdietz.png" width="60px" alt="Moritz Dietz" /></a><a href="https://github.com/mikker"><img src="https://github.com/mikker.png" width="60px" alt="Mikkel Malmberg" /></a><a href="https://github.com/pldubouilh"><img src="https://github.com/pldubouilh.png" width="60px" alt="Pierre Dubouilh" /></a><a href="https://github.com/trantor"><img src="https://github.com/trantor.png" width="60px" alt="Fulvio Scapin" /></a><a href="https://github.com/rcorre"><img src="https://github.com/rcorre.png" width="60px" alt="Ryan Roden-Corrent" /></a><a href="https://github.com/blissdev"><img src="https://github.com/blissdev.png" width="60px" alt="Jordan Arentsen" /></a><a href="https://github.com/mislav"><img src="https://github.com/mislav.png" width="60px" alt="Mislav Marohnić" /></a><a href="https://github.com/aexvir"><img src="https://github.com/aexvir.png" width="60px" alt="Alex Viscreanu" /></a><a href="https://github.com/dbalatero"><img src="https://github.com/dbalatero.png" width="60px" alt="David Balatero" /></a><a href="https://github.com/moobar"><img src="https://github.com/moobar.png" width="60px" alt="" /></a><a href="https://github.com/majjoha"><img src="https://github.com/majjoha.png" width="60px" alt="Mathias Jean Johansen" /></a><a href="https://github.com/benelan"><img src="https://github.com/benelan.png" width="60px" alt="Ben Elan" /></a><a href="https://github.com/pawelduda"><img src="https://github.com/pawelduda.png" width="60px" alt="Paweł Duda" /></a><a href="https://github.com/slezica"><img src="https://github.com/slezica.png" width="60px" alt="Santiago Lezica" /></a><a href="https://github.com/pbwn"><img src="https://github.com/pbwn.png" width="60px" alt="" /></a><a href="https://github.com/timgluz"><img src="https://github.com/timgluz.png" width="60px" alt="Timo Sulg" /></a><a href="https://github.com/pyrho"><img src="https://github.com/pyrho.png" width="60px" alt="Damien Rajon" /></a><a href="https://github.com/ArtBIT"><img src="https://github.com/ArtBIT.png" width="60px" alt="ArtBIT" /></a><a href="https://github.com/da-moon"><img src="https://github.com/da-moon.png" width="60px" alt="" /></a><a href="https://github.com/jiangyinzuo"><img src="https://github.com/jiangyinzuo.png" width="60px" alt="Yinzuo Jiang" /></a><a href="https://github.com/hovissimo"><img src="https://github.com/hovissimo.png" width="60px" alt="Hovis" /></a><a href="https://github.com/dariusjonda"><img src="https://github.com/dariusjonda.png" width="60px" alt="Darius Jonda" /></a><a href="https://github.com/cristiand391"><img src="https://github.com/cristiand391.png" width="60px" alt="Cristian Dominguez" /></a><a href="https://github.com/eliangcs"><img src="https://github.com/eliangcs.png" width="60px" alt="Chang-Hung Liang" /></a><a href="https://github.com/asphaltbuffet"><img src="https://github.com/asphaltbuffet.png" width="60px" alt="Ben Lechlitner" /></a><a href="https://github.com/yash1th"><img src="https://github.com/yash1th.png" width="60px" alt="yash" /></a><a href="https://github.com/looshch"><img src="https://github.com/looshch.png" width="60px" alt="george looshch" /></a><a href="https://github.com/kg8m"><img src="https://github.com/kg8m.png" width="60px" alt="Takumi KAGIYAMA" /></a><a href="https://github.com/polm"><img src="https://github.com/polm.png" width="60px" alt="Paul OLeary McCann" /></a><a href="https://github.com/rbeeger"><img src="https://github.com/rbeeger.png" width="60px" alt="Robert Beeger" /></a><a href="https://github.com/veebch"><img src="https://github.com/veebch.png" width="60px" alt="VEEB Projects" /></a><a href="https://github.com/yowayb"><img src="https://github.com/yowayb.png" width="60px" alt="Yoway Buorn" /></a><a href="https://github.com/scalisi"><img src="https://github.com/scalisi.png" width="60px" alt="Josh Scalisi" /></a><a href="https://github.com/alecbcs"><img src="https://github.com/alecbcs.png" width="60px" alt="Alec Scott" /></a><a href="https://github.com/the-shank"><img src="https://github.com/the-shank.png" width="60px" alt="theshank" /></a><a href="https://github.com/thnxdev"><img src="https://github.com/thnxdev.png" width="60px" alt="thanks.dev" /></a><a href="https://github.com/artursapek"><img src="https://github.com/artursapek.png" width="60px" alt="Artur Sapek" /></a><a href="https://github.com/ramnes"><img src="https://github.com/ramnes.png" width="60px" alt="Guillaume Gelin" /></a><a href="https://github.com/jyc"><img src="https://github.com/jyc.png" width="60px" alt="" /></a><a href="https://github.com/mrcnski"><img src="https://github.com/mrcnski.png" width="60px" alt="Marcin S." /></a><a href="https://github.com/roblevy"><img src="https://github.com/roblevy.png" width="60px" alt="Rob Levy" /></a><a href="https://github.com/glozow"><img src="https://github.com/glozow.png" width="60px" alt="Gloria Zhao" /></a><a href="https://github.com/wjt"><img src="https://github.com/wjt.png" width="60px" alt="Will Thompson" /></a><a href="https://github.com/toupeira"><img src="https://github.com/toupeira.png" width="60px" alt="Markus Koller" /></a><a href="https://github.com/rkpatel33"><img src="https://github.com/rkpatel33.png" width="60px" alt="" /></a><a href="https://github.com/jamesob"><img src="https://github.com/jamesob.png" width="60px" alt="jamesob" /></a><a href="https://github.com/jlebray"><img src="https://github.com/jlebray.png" width="60px" alt="Johan Le Bray" /></a><a href="https://github.com/panosl1"><img src="https://github.com/panosl1.png" width="60px" alt="Panos Lampropoulos" /></a><a href="https://github.com/bespinian"><img src="https://github.com/bespinian.png" width="60px" alt="bespinian" /></a><a href="https://github.com/scosu"><img src="https://github.com/scosu.png" width="60px" alt="Markus Schneider-Pargmann" /></a><a href="https://github.com/smithbm2316"><img src="https://github.com/smithbm2316.png" width="60px" alt="Ben Smith" /></a><a href="https://github.com/mywang-berk"><img src="https://github.com/mywang-berk.png" width="60px" alt="" /></a><a href="https://github.com/charlieegan3"><img src="https://github.com/charlieegan3.png" width="60px" alt="Charlie Egan" /></a><!-- sponsors -->
 
 Table of Contents
 -----------------
diff --git a/doc/fzf.txt b/doc/fzf.txt
index f946184f..c8de4b92 100644
--- a/doc/fzf.txt
+++ b/doc/fzf.txt
@@ -306,8 +306,9 @@ The following table summarizes the available options.
   `source`                    | string        | External command to generate input to fzf (e.g.  `find .` )
   `source`                    | list          | Vim list as input to fzf
   `sink`                      | string        | Vim command to handle the selected item (e.g.  `e` ,  `tabe` )
-  `sink`                      | funcref       | Reference to function to process each selected item
+  `sink`                      | funcref       | Function to be called with each selected item
   `sinklist`  (or  `sink*` )    | funcref       | Similar to  `sink` , but takes the list of output lines at once
+  `exit`                      | funcref       | Function to be called with the exit status of fzf (e.g. 0, 1, 2, 130)
   `options`                   | string/list   | Options to fzf
   `dir`                       | string        | Working directory
   `up` / `down` / `left` / `right`  | number/string | (Layout) Window position and size (e.g.  `20` ,  `50%` )
diff --git a/go.mod b/go.mod
index 3c549e06..43d81b6d 100644
--- a/go.mod
+++ b/go.mod
@@ -3,11 +3,11 @@ module github.com/junegunn/fzf
 require (
 	github.com/charlievieth/fastwalk v1.0.8
 	github.com/gdamore/tcell/v2 v2.7.4
+	github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97
 	github.com/mattn/go-isatty v0.0.20
-	github.com/mattn/go-shellwords v1.0.12
 	github.com/rivo/uniseg v0.4.7
-	golang.org/x/sys v0.22.0
-	golang.org/x/term v0.22.0
+	golang.org/x/sys v0.24.0
+	golang.org/x/term v0.23.0
 )
 
 require (
diff --git a/go.sum b/go.sum
index 48f60497..7d43f094 100644
--- a/go.sum
+++ b/go.sum
@@ -4,14 +4,14 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdk
 github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
 github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
 github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
+github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97 h1:rqzLixVo1c/GQW6px9j1xQmlvQIn+lf/V6M1UQ7IFzw=
+github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97/go.mod h1:6EILKtGpo5t+KLb85LNZLAF6P9LKp78hJI80PXMcn3c=
 github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
 github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
 github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
-github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
 github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
@@ -36,14 +36,14 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
-golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
+golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
-golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
+golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
+golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
diff --git a/plugin/fzf.vim b/plugin/fzf.vim
index 0a8d570f..0f05c453 100644
--- a/plugin/fzf.vim
+++ b/plugin/fzf.vim
@@ -665,21 +665,17 @@ else
   let s:launcher = function('s:xterm_launcher')
 endif
 
-function! s:exit_handler(code, command, ...)
-  if a:code == 130
-    return 0
-  elseif has('nvim') && a:code == 129
-    " When deleting the terminal buffer while fzf is still running,
-    " Nvim sends SIGHUP.
-    return 0
-  elseif a:code > 1
+function! s:exit_handler(dict, code, command, ...)
+  if has_key(a:dict, 'exit')
+    call a:dict.exit(a:code)
+  endif
+  if a:code == 2
     call s:error('Error running ' . a:command)
     if !empty(a:000)
       sleep
     endif
-    return 0
   endif
-  return 1
+  return a:code
 endfunction
 
 function! s:execute(dict, command, use_height, temps) abort
@@ -731,7 +727,7 @@ function! s:execute(dict, command, use_height, temps) abort
   let exit_status = v:shell_error
   redraw!
   let lines = s:collect(a:temps)
-  return s:exit_handler(exit_status, command) ? lines : []
+  return s:exit_handler(a:dict, exit_status, command) < 2 ? lines : []
 endfunction
 
 function! s:execute_tmux(dict, command, temps) abort
@@ -746,7 +742,7 @@ function! s:execute_tmux(dict, command, temps) abort
   let exit_status = v:shell_error
   redraw!
   let lines = s:collect(a:temps)
-  return s:exit_handler(exit_status, command) ? lines : []
+  return s:exit_handler(a:dict, exit_status, command) < 2 ? lines : []
 endfunction
 
 function! s:calc_size(max, val, dict)
@@ -912,7 +908,7 @@ function! s:execute_term(dict, command, temps) abort
     endif
 
     let lines = s:collect(self.temps)
-    if !s:exit_handler(a:code, self.command, 1)
+    if s:exit_handler(self.dict, a:code, self.command, 1) >= 2
       return
     endif
 
diff --git a/shell/completion.bash b/shell/completion.bash
index a68dac96..abeb2e9a 100644
--- a/shell/completion.bash
+++ b/shell/completion.bash
@@ -289,7 +289,7 @@ __fzf_generic_path_completion() {
   fi
   COMPREPLY=()
   trigger=${FZF_COMPLETION_TRIGGER-'**'}
-  cur="${COMP_WORDS[COMP_CWORD]}"
+  [[ $COMP_CWORD -ge 0 ]] && cur="${COMP_WORDS[COMP_CWORD]}"
   if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then
     base=${cur:0:${#cur}-${#trigger}}
     eval "base=$base" 2> /dev/null || return
@@ -410,7 +410,8 @@ _fzf_complete_kill() {
 _fzf_proc_completion() {
   _fzf_complete -m --header-lines=1 --no-preview --wrap -- "$@" < <(
     command ps -eo user,pid,ppid,start,time,command 2> /dev/null ||
-      command ps -eo user,pid,ppid,time,args # For BusyBox
+      command ps -eo user,pid,ppid,time,args 2> /dev/null || # For BusyBox
+      command ps --everyone --full --windows # For cygwin
   )
 }
 
@@ -480,10 +481,36 @@ complete -o default -F _fzf_opts_completion fzf
 # fzf-tmux specific options (like `-w WIDTH`) are left as a future patch.
 complete -o default -F _fzf_opts_completion fzf-tmux
 
+# Default path completion
+__fzf_default_completion() {
+  __fzf_generic_path_completion _fzf_compgen_path "-m" "" "$@"
+
+  # Dynamic completion loader has updated the completion for the command
+  if [[ $? -eq 124 ]]; then
+    # We trigger _fzf_setup_completion so that fuzzy completion for the command
+    # still works. However, loader can update the completion for multiple
+    # commands at once, and fuzzy completion will no longer work for those
+    # other commands. e.g. pytest -> py.test, pytest-2, pytest-3, etc
+    _fzf_setup_completion path "$1"
+    return 124
+  fi
+}
+
+# Set fuzzy path completion as the default completion for all commands.
+# We can't set up default completion,
+# 1. if it's already set up by another script
+# 2. or if the current version of bash doesn't support -D option
+complete | command grep -q __fzf_default_completion ||
+  complete | command grep -- '-D$' | command grep -qv _comp_complete_load ||
+  complete -D -F __fzf_default_completion -o default -o bashdefault 2> /dev/null
+
 d_cmds="${FZF_COMPLETION_DIR_COMMANDS-cd pushd rmdir}"
 
 # NOTE: $FZF_COMPLETION_PATH_COMMANDS and $FZF_COMPLETION_VAR_COMMANDS are
 # undocumented and subject to change in the future.
+#
+# NOTE: Although we have default completion, we still need to set up completion
+# for each command in case they already have completion set up by another script.
 a_cmds="${FZF_COMPLETION_PATH_COMMANDS-"
   awk bat cat code diff diff3
   emacs emacsclient ex file ftp g++ gcc gvim head hg hx java
diff --git a/shell/completion.zsh b/shell/completion.zsh
index 1ff4a4bc..217404fc 100644
--- a/shell/completion.zsh
+++ b/shell/completion.zsh
@@ -300,7 +300,8 @@ _fzf_complete_unalias() {
 _fzf_complete_kill() {
   _fzf_complete -m --header-lines=1 --no-preview --wrap -- "$@" < <(
     command ps -eo user,pid,ppid,start,time,command 2> /dev/null ||
-      command ps -eo user,pid,ppid,time,args # For BusyBox
+      command ps -eo user,pid,ppid,time,args 2> /dev/null || # For BusyBox
+      command ps --everyone --full --windows # For cygwin
   )
 }
 
diff --git a/src/ansi.go b/src/ansi.go
index 5f7c8be4..638d7eff 100644
--- a/src/ansi.go
+++ b/src/ansi.go
@@ -1,6 +1,7 @@
 package fzf
 
 import (
+	"fmt"
 	"strconv"
 	"strings"
 	"unicode/utf8"
@@ -13,22 +14,28 @@ type ansiOffset struct {
 	color  ansiState
 }
 
+type url struct {
+	uri    string
+	params string
+}
+
 type ansiState struct {
 	fg   tui.Color
 	bg   tui.Color
 	attr tui.Attr
 	lbg  tui.Color
+	url  *url
 }
 
 func (s *ansiState) colored() bool {
-	return s.fg != -1 || s.bg != -1 || s.attr > 0 || s.lbg >= 0
+	return s.fg != -1 || s.bg != -1 || s.attr > 0 || s.lbg >= 0 || s.url != nil
 }
 
 func (s *ansiState) equals(t *ansiState) bool {
 	if t == nil {
 		return !s.colored()
 	}
-	return s.fg == t.fg && s.bg == t.bg && s.attr == t.attr && s.lbg == t.lbg
+	return s.fg == t.fg && s.bg == t.bg && s.attr == t.attr && s.lbg == t.lbg && s.url == t.url
 }
 
 func (s *ansiState) ToString() string {
@@ -60,7 +67,11 @@ func (s *ansiState) ToString() string {
 	}
 	ret += toAnsiString(s.fg, 30) + toAnsiString(s.bg, 40)
 
-	return "\x1b[" + strings.TrimSuffix(ret, ";") + "m"
+	ret = "\x1b[" + strings.TrimSuffix(ret, ";") + "m"
+	if s.url != nil {
+		ret = fmt.Sprintf("\x1b]8;%s;%s\x1b\\%s\x1b]8;;\x1b", s.url.params, s.url.uri, ret)
+	}
+	return ret
 }
 
 func toAnsiString(color tui.Color, offset int) string {
@@ -98,10 +109,19 @@ func matchOperatingSystemCommand(s string) int {
 		if s[i] == '\x07' {
 			return i + 1
 		}
+		// `\x1b]8;PARAMS;URI\x1b\\TITLE\x1b]8;;\x1b`
+		//                   ------
 		if s[i] == '\x1b' && i < len(s)-1 && s[i+1] == '\\' {
 			return i + 2
 		}
 	}
+
+	// `\x1b]8;PARAMS;URI\x1b\\TITLE\x1b]8;;\x1b`
+	//                              ------------
+	if i < len(s) && s[:i+1] == "\x1b]8;;\x1b" {
+		return i + 1
+	}
+
 	return -1
 }
 
@@ -328,13 +348,21 @@ func parseAnsiCode(s string, delimiter byte) (int, byte, string) {
 func interpretCode(ansiCode string, prevState *ansiState) ansiState {
 	var state ansiState
 	if prevState == nil {
-		state = ansiState{-1, -1, 0, -1}
+		state = ansiState{-1, -1, 0, -1, nil}
 	} else {
-		state = ansiState{prevState.fg, prevState.bg, prevState.attr, prevState.lbg}
+		state = ansiState{prevState.fg, prevState.bg, prevState.attr, prevState.lbg, prevState.url}
 	}
 	if ansiCode[0] != '\x1b' || ansiCode[1] != '[' || ansiCode[len(ansiCode)-1] != 'm' {
 		if prevState != nil && strings.HasSuffix(ansiCode, "0K") {
 			state.lbg = prevState.bg
+		} else if ansiCode == "\x1b]8;;\x1b\\" { // End of a hyperlink
+			state.url = nil
+		} else if strings.HasPrefix(ansiCode, "\x1b]8;") && strings.HasSuffix(ansiCode, "\x1b\\") {
+			if paramsEnd := strings.IndexRune(ansiCode[4:], ';'); paramsEnd >= 0 {
+				params := ansiCode[4 : 4+paramsEnd]
+				uri := ansiCode[5+paramsEnd : len(ansiCode)-2]
+				state.url = &url{uri: uri, params: params}
+			}
 		}
 		return state
 	}
diff --git a/src/options.go b/src/options.go
index 1593d6f8..0f903df6 100644
--- a/src/options.go
+++ b/src/options.go
@@ -12,7 +12,7 @@ import (
 	"github.com/junegunn/fzf/src/algo"
 	"github.com/junegunn/fzf/src/tui"
 
-	"github.com/mattn/go-shellwords"
+	"github.com/junegunn/go-shellwords"
 	"github.com/rivo/uniseg"
 )
 
@@ -2915,6 +2915,12 @@ func postProcessOptions(opts *Options) error {
 	return processScheme(opts)
 }
 
+func parseShellWords(str string) ([]string, error) {
+	parser := shellwords.NewParser()
+	parser.ParseComment = true
+	return parser.Parse(str)
+}
+
 // ParseOptions parses command-line options
 func ParseOptions(useDefaults bool, args []string) (*Options, error) {
 	opts := defaultOptions()
@@ -2928,7 +2934,7 @@ func ParseOptions(useDefaults bool, args []string) (*Options, error) {
 				return nil, errors.New("$FZF_DEFAULT_OPTS_FILE: " + err.Error())
 			}
 
-			words, parseErr := shellwords.Parse(string(bytes))
+			words, parseErr := parseShellWords(string(bytes))
 			if parseErr != nil {
 				return nil, errors.New(path + ": " + parseErr.Error())
 			}
@@ -2940,7 +2946,7 @@ func ParseOptions(useDefaults bool, args []string) (*Options, error) {
 		}
 
 		// 2. Options from $FZF_DEFAULT_OPTS string
-		words, parseErr := shellwords.Parse(os.Getenv("FZF_DEFAULT_OPTS"))
+		words, parseErr := parseShellWords(os.Getenv("FZF_DEFAULT_OPTS"))
 		if parseErr != nil {
 			return nil, errors.New("$FZF_DEFAULT_OPTS: " + parseErr.Error())
 		}
diff --git a/src/result.go b/src/result.go
index e1c20801..f10db19b 100644
--- a/src/result.go
+++ b/src/result.go
@@ -16,6 +16,7 @@ type colorOffset struct {
 	offset [2]int32
 	color  tui.ColorPair
 	match  bool
+	url    *url
 }
 
 type Result struct {
@@ -177,8 +178,11 @@ func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme,
 		if curr != 0 && idx > start {
 			if curr < 0 {
 				color := colMatch
+				var url *url
 				if curr < -1 && theme.Colored {
-					origColor := ansiToColorPair(itemColors[-curr-2], colMatch)
+					ansi := itemColors[-curr-2]
+					url = ansi.color.url
+					origColor := ansiToColorPair(ansi, colMatch)
 					// hl or hl+ only sets the foreground color, so colMatch is the
 					// combination of either [hl and bg] or [hl+ and bg+].
 					//
@@ -194,13 +198,14 @@ func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme,
 					}
 				}
 				colors = append(colors, colorOffset{
-					offset: [2]int32{int32(start), int32(idx)}, color: color, match: true})
+					offset: [2]int32{int32(start), int32(idx)}, color: color, match: true, url: url})
 			} else {
 				ansi := itemColors[curr-1]
 				colors = append(colors, colorOffset{
 					offset: [2]int32{int32(start), int32(idx)},
 					color:  ansiToColorPair(ansi, colBase),
-					match:  false})
+					match:  false,
+					url:    ansi.color.url})
 			}
 		}
 	}
diff --git a/src/terminal.go b/src/terminal.go
index bbccf1c6..3993bce9 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -382,6 +382,7 @@ const (
 	reqRedrawPreviewLabel
 	reqClose
 	reqPrintQuery
+	reqPreviewReady
 	reqPreviewEnqueue
 	reqPreviewDisplay
 	reqPreviewRefresh
@@ -1067,7 +1068,7 @@ func (t *Terminal) parsePrompt(prompt string) (func(), int) {
 	//             // unless the part has a non-default ANSI state
 	loc := whiteSuffix.FindStringIndex(trimmed)
 	if loc != nil {
-		blankState := ansiOffset{[2]int32{int32(loc[0]), int32(loc[1])}, ansiState{-1, -1, tui.AttrClear, -1}}
+		blankState := ansiOffset{[2]int32{int32(loc[0]), int32(loc[1])}, ansiState{-1, -1, tui.AttrClear, -1, nil}}
 		if item.colors != nil {
 			lastColor := (*item.colors)[len(*item.colors)-1]
 			if lastColor.offset[1] < int32(loc[1]) {
@@ -2459,15 +2460,24 @@ func (t *Terminal) printColoredString(window tui.Window, text []rune, offsets []
 	var substr string
 	var prefixWidth int
 	maxOffset := int32(len(text))
+	var url *url
 	for _, offset := range offsets {
 		b := util.Constrain32(offset.offset[0], index, maxOffset)
 		e := util.Constrain32(offset.offset[1], index, maxOffset)
+		if url != nil && offset.url == nil {
+			url = nil
+			window.LinkEnd()
+		}
 
 		substr, prefixWidth = t.processTabs(text[index:b], prefixWidth)
 		window.CPrint(colBase, substr)
 
 		if b < e {
 			substr, prefixWidth = t.processTabs(text[b:e], prefixWidth)
+			if url == nil && offset.url != nil {
+				url = offset.url
+				window.LinkBegin(url.uri, url.params)
+			}
 			window.CPrint(offset.color, substr)
 		}
 
@@ -2476,6 +2486,9 @@ func (t *Terminal) printColoredString(window tui.Window, text []rune, offsets []
 			break
 		}
 	}
+	if url != nil {
+		window.LinkEnd()
+	}
 	if index < maxOffset {
 		substr, _ = t.processTabs(text[index:], prefixWidth)
 		window.CPrint(colBase, substr)
@@ -2667,12 +2680,21 @@ Loop:
 
 			var fillRet tui.FillReturn
 			prefixWidth := 0
+			var url *url
 			_, _, ansi = extractColor(line, ansi, func(str string, ansi *ansiState) bool {
 				trimmed := []rune(str)
 				isTrimmed := false
 				if !t.previewOpts.wrap {
 					trimmed, isTrimmed = t.trimRight(trimmed, maxWidth-t.pwindow.X())
 				}
+				if url == nil && ansi != nil && ansi.url != nil {
+					url = ansi.url
+					t.pwindow.LinkBegin(url.uri, url.params)
+				}
+				if url != nil && (ansi == nil || ansi.url == nil) {
+					url = nil
+					t.pwindow.LinkEnd()
+				}
 				str, width := t.processTabs(trimmed, prefixWidth)
 				if width > prefixWidth {
 					prefixWidth = width
@@ -2686,6 +2708,9 @@ Loop:
 				return !isTrimmed &&
 					(fillRet == tui.FillContinue || t.previewOpts.wrap && fillRet == tui.FillNextLine)
 			})
+			if url != nil {
+				t.pwindow.LinkEnd()
+			}
 			t.previewer.scrollable = t.previewer.scrollable || t.pwindow.Y() == height-1 && t.pwindow.X() == t.pwindow.Width()
 			if fillRet == tui.FillNextLine {
 				continue
@@ -2697,10 +2722,14 @@ Loop:
 				break
 			}
 			if lbg >= 0 {
-				t.pwindow.CFill(-1, lbg, tui.AttrRegular,
+				fillRet = t.pwindow.CFill(-1, lbg, tui.AttrRegular,
 					strings.Repeat(" ", t.pwindow.Width()-t.pwindow.X())+"\n")
 			} else {
-				t.pwindow.Fill("\n")
+				fillRet = t.pwindow.Fill("\n")
+			}
+			if fillRet == tui.FillSuspend {
+				t.previewed.filled = true
+				break
 			}
 		}
 		lineNo++
@@ -3469,6 +3498,7 @@ func (t *Terminal) Loop() error {
 		go func() {
 			var version int64
 			stop := false
+			t.previewBox.WaitFor(reqPreviewReady)
 			for {
 				var items []*Item
 				var commandTemplate string
@@ -3497,6 +3527,9 @@ func (t *Terminal) Loop() error {
 				if stop {
 					break
 				}
+				if items == nil {
+					continue
+				}
 				version++
 				// We don't display preview window if no match
 				if items[0] != nil {
@@ -3738,6 +3771,9 @@ func (t *Terminal) Loop() error {
 						t.printHeader()
 					case reqActivate:
 						t.suppress = false
+						if t.hasPreviewer() {
+							t.previewBox.Set(reqPreviewReady, nil)
+						}
 					case reqRedrawBorderLabel:
 						t.printLabel(t.border, t.borderLabel, t.borderLabelOpts, t.borderLabelLen, t.borderShape, true)
 					case reqRedrawPreviewLabel:
diff --git a/src/tui/light.go b/src/tui/light.go
index 3ed24f71..80488bf7 100644
--- a/src/tui/light.go
+++ b/src/tui/light.go
@@ -1030,13 +1030,13 @@ func cleanse(str string) string {
 func (w *LightWindow) CPrint(pair ColorPair, text string) {
 	_, code := w.csiColor(pair.Fg(), pair.Bg(), pair.Attr())
 	w.stderrInternal(cleanse(text), false, code)
-	w.csi("m")
+	w.csi("0m")
 }
 
 func (w *LightWindow) cprint2(fg Color, bg Color, attr Attr, text string) {
 	hasColors, code := w.csiColor(fg, bg, attr)
 	if hasColors {
-		defer w.csi("m")
+		defer w.csi("0m")
 	}
 	w.stderrInternal(cleanse(text), false, code)
 }
@@ -1118,6 +1118,14 @@ func (w *LightWindow) setBg() string {
 	return "\x1b[m"
 }
 
+func (w *LightWindow) LinkBegin(uri string, params string) {
+	w.renderer.queued.WriteString("\x1b]8;" + params + ";" + uri + "\x1b\\")
+}
+
+func (w *LightWindow) LinkEnd() {
+	w.renderer.queued.WriteString("\x1b]8;;\x1b\\")
+}
+
 func (w *LightWindow) Fill(text string) FillReturn {
 	w.Move(w.posy, w.posx)
 	code := w.setBg()
@@ -1133,7 +1141,7 @@ func (w *LightWindow) CFill(fg Color, bg Color, attr Attr, text string) FillRetu
 		bg = w.bg
 	}
 	if hasColors, resetCode := w.csiColor(fg, bg, attr); hasColors {
-		defer w.csi("m")
+		defer w.csi("0m")
 		return w.fill(text, resetCode)
 	}
 	return w.fill(text, w.setBg())
diff --git a/src/tui/tcell.go b/src/tui/tcell.go
index 16ce452d..455dcf13 100644
--- a/src/tui/tcell.go
+++ b/src/tui/tcell.go
@@ -4,6 +4,7 @@ package tui
 
 import (
 	"os"
+	"regexp"
 	"time"
 
 	"github.com/gdamore/tcell/v2"
@@ -49,6 +50,8 @@ type TcellWindow struct {
 	lastY       int
 	moveCursor  bool
 	borderStyle BorderStyle
+	uri         *string
+	params      *string
 }
 
 func (w *TcellWindow) Top() int {
@@ -601,6 +604,16 @@ func (w *TcellWindow) Print(text string) {
 	w.printString(text, w.normal)
 }
 
+func (w *TcellWindow) withUrl(style tcell.Style) tcell.Style {
+	if w.uri != nil {
+		style = style.Url(*w.uri)
+		if md := regexp.MustCompile(`id=([^:]+)`).FindStringSubmatch(*w.params); len(md) > 1 {
+			style = style.UrlId(md[1])
+		}
+	}
+	return style
+}
+
 func (w *TcellWindow) printString(text string, pair ColorPair) {
 	lx := 0
 	a := pair.Attr()
@@ -615,6 +628,7 @@ func (w *TcellWindow) printString(text string, pair ColorPair) {
 			Blink(a&Attr(tcell.AttrBlink) != 0).
 			Dim(a&Attr(tcell.AttrDim) != 0)
 	}
+	style = w.withUrl(style)
 
 	gr := uniseg.NewGraphemes(text)
 	for gr.Next() {
@@ -665,6 +679,7 @@ func (w *TcellWindow) fillString(text string, pair ColorPair) FillReturn {
 		Underline(a&Attr(tcell.AttrUnderline) != 0).
 		StrikeThrough(a&Attr(tcell.AttrStrikeThrough) != 0).
 		Italic(a&Attr(tcell.AttrItalic) != 0)
+	style = w.withUrl(style)
 
 	gr := uniseg.NewGraphemes(text)
 Loop:
@@ -716,6 +731,16 @@ func (w *TcellWindow) Fill(str string) FillReturn {
 	return w.fillString(str, w.normal)
 }
 
+func (w *TcellWindow) LinkBegin(uri string, params string) {
+	w.uri = &uri
+	w.params = &params
+}
+
+func (w *TcellWindow) LinkEnd() {
+	w.uri = nil
+	w.params = nil
+}
+
 func (w *TcellWindow) CFill(fg Color, bg Color, a Attr, str string) FillReturn {
 	if fg == colDefault {
 		fg = w.normal.Fg()
diff --git a/src/tui/tui.go b/src/tui/tui.go
index f3e58f41..240f7ce7 100644
--- a/src/tui/tui.go
+++ b/src/tui/tui.go
@@ -564,6 +564,8 @@ type Window interface {
 	CPrint(color ColorPair, text string)
 	Fill(text string) FillReturn
 	CFill(fg Color, bg Color, attr Attr, text string) FillReturn
+	LinkBegin(uri string, params string)
+	LinkEnd()
 	Erase()
 	EraseMaybe() bool
 }


Test patch:
diff --git a/src/result_test.go b/src/result_test.go
index 2f818a9b..c11e1ab5 100644
--- a/src/result_test.go
+++ b/src/result_test.go
@@ -124,10 +124,10 @@ func TestColorOffset(t *testing.T) {
 	item := Result{
 		item: &Item{
 			colors: &[]ansiOffset{
-				{[2]int32{0, 20}, ansiState{1, 5, 0, -1}},
-				{[2]int32{22, 27}, ansiState{2, 6, tui.Bold, -1}},
-				{[2]int32{30, 32}, ansiState{3, 7, 0, -1}},
-				{[2]int32{33, 40}, ansiState{4, 8, tui.Bold, -1}}}}}
+				{[2]int32{0, 20}, ansiState{1, 5, 0, -1, nil}},
+				{[2]int32{22, 27}, ansiState{2, 6, tui.Bold, -1, nil}},
+				{[2]int32{30, 32}, ansiState{3, 7, 0, -1, nil}},
+				{[2]int32{33, 40}, ansiState{4, 8, tui.Bold, -1, nil}}}}}
 
 	colBase := tui.NewColorPair(89, 189, tui.AttrUndefined)
 	colMatch := tui.NewColorPair(99, 199, tui.AttrUndefined)