summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/typos.yml2
-rw-r--r--.goreleaser.yml6
-rw-r--r--CHANGELOG.md62
-rw-r--r--Dockerfile4
-rw-r--r--Makefile10
-rw-r--r--README.md3
-rwxr-xr-xbin/fzf-tmux2
-rwxr-xr-xinstall2
-rw-r--r--install.ps12
-rw-r--r--main.go2
-rw-r--r--man/man1/fzf-tmux.12
-rw-r--r--man/man1/fzf.122
-rw-r--r--shell/completion.bash101
-rw-r--r--shell/completion.zsh27
-rw-r--r--shell/key-bindings.bash34
-rw-r--r--shell/key-bindings.fish18
-rw-r--r--shell/key-bindings.zsh30
-rw-r--r--src/actiontype_string.go187
-rw-r--r--src/core.go14
-rw-r--r--src/options.go22
-rw-r--r--src/reader.go9
-rw-r--r--src/reader_test.go3
-rw-r--r--src/server.go2
-rw-r--r--src/terminal.go72
-rw-r--r--src/terminal_test.go10
-rw-r--r--src/terminal_unix.go19
-rw-r--r--src/terminal_windows.go26
-rw-r--r--src/util/util_unix.go56
-rw-r--r--src/util/util_windows.go157
-rwxr-xr-xtest/test_go.rb41
30 files changed, 571 insertions, 376 deletions
diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml
index 752c58c6..91f21864 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.19.0
+ - uses: crate-ci/typos@v1.20.9
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 1ac56108..86e821f0 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -12,6 +12,8 @@ builds:
- darwin
goarch:
- amd64
+ flags:
+ - -trimpath
ldflags:
- "-s -w -X main.version={{ .Version }} -X main.revision={{ .ShortCommit }}"
hooks:
@@ -36,6 +38,8 @@ builds:
- darwin
goarch:
- arm64
+ flags:
+ - -trimpath
ldflags:
- "-s -w -X main.version={{ .Version }} -X main.revision={{ .ShortCommit }}"
hooks:
@@ -71,6 +75,8 @@ builds:
- 5
- 6
- 7
+ flags:
+ - -trimpath
ldflags:
- "-s -w -X main.version={{ .Version }} -X main.revision={{ .ShortCommit }}"
ignore:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3de28297..911f043a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,41 +1,44 @@
CHANGELOG
=========
-0.50.0
+0.51.0
------
-- Search performance optimization. You can observe 50%+ improvement in some scenarios.
+- Added a new environment variable `$FZF_POS` exported to the child processes. It's the vertical position of the cursor in the list starting from 1.
```sh
- $ time wc < $DATA
- 5520118 26862362 897487793
-
- real 0m1.320s
- user 0m1.236s
- sys 0m0.075s
+ # Toggle selection to the top or to the bottom
+ seq 30 | fzf --multi --bind 'load:pos(10)' \
+ --bind 'shift-up:transform:for _ in $(seq $FZF_POS $FZF_MATCH_COUNT); do echo -n +toggle+up; done' \
+ --bind 'shift-down:transform:for _ in $(seq 1 $FZF_POS); do echo -n +toggle+down; done'
+ ```
+- Added `--with-shell` option to start child processes with a custom shell command and flags
+ ```sh
+ gem list | fzf --with-shell 'ruby -e' \
+ --preview 'pp Gem::Specification.find_by_name({1})' \
+ --bind 'ctrl-o:execute-silent:
+ spec = Gem::Specification.find_by_name({1})
+ [spec.homepage, *spec.metadata.filter { _1.end_with?("uri") }.values].uniq.each do
+ system "open", _1
+ end
+ '
+ ```
+- Added `change-multi` action for dynamically changing `--multi` option
+ - `change-multi` - enable multi-select mode with no limit
+ - `change-multi(NUM)` - enable multi-select mode with a limit
+ - `change-multi(0)` - disable multi-select mode
+- `become` action is now supported on Windows
+ - Unlike in *nix, this does not use `execve(2)`. Instead it spawns a new process and waits for it to finish, so the exact behavior may differ.
+- Bug fixes and improvements
- $ time fzf --sync --bind load:abort < $DATA
+0.50.0
+------
+- Search performance optimization. You can observe 50%+ improvement in some scenarios.
+ ```
+ $ rg --line-number --no-heading --smart-case . > $DATA
- real 0m0.479s
- user 0m0.427s
- sys 0m0.176s
+ $ wc < $DATA
+ 5520118 26862362 897487793
$ hyperfine -w 1 -L bin fzf-0.49.0,fzf-7ce6452,fzf-a5447b8,fzf '{bin} --filter "///" < $DATA | head -30'
-
- Benchmark 1: fzf-0.49.0 --filter "///" < $DATA | head -30
- Time (mean ± σ): 2.002 s ± 0.024 s [User: 14.447 s, System: 0.300 s]
- Range (min … max): 1.964 s … 2.042 s 10 runs
-
- Benchmark 2: fzf-7ce6452 --filter "///" < $DATA | head -30
- Time (mean ± σ): 1.627 s ± 0.019 s [User: 10.828 s, System: 0.271 s]
- Range (min … max): 1.596 s … 1.651 s 10 runs
-
- Benchmark 3: fzf-a5447b8 --filter "///" < $DATA | head -30
- Time (mean ± σ): 1.524 s ± 0.025 s [User: 9.818 s, System: 0.269 s]
- Range (min … max): 1.478 s … 1.569 s 10 runs
-
- Benchmark 4: fzf --filter "///" < $DATA | head -30
- Time (mean ± σ): 1.318 s ± 0.025 s [User: 8.005 s, System: 0.262 s]
- Range (min … max): 1.282 s … 1.366 s 10 runs
-
Summary
fzf --filter "///" < $DATA | head -30 ran
1.16 ± 0.03 times faster than fzf-a5447b8 --filter "///" < $DATA | head -30
@@ -60,6 +63,7 @@ CHANGELOG
```sh
fzf --bind 'space:jump,jump:accept,jump-cancel:transform:[[ $FZF_KEY =~ ctrl-c ]] && echo abort'
```
+- fzf can be built with profiling options. See [BUILD.md](BUILD.md) for more information.
- Bug fixes
0.49.0
diff --git a/Dockerfile b/Dockerfile
index aba5f22f..e31f804d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
-FROM --platform=linux/amd64 ubuntu:22.04
+FROM ubuntu:24.04
RUN apt-get update -y && apt install -y git make golang zsh fish ruby tmux
-RUN gem install --no-document -v 5.14.2 minitest
+RUN gem install --no-document -v 5.22.3 minitest
RUN echo '. /usr/share/bash-completion/completions/git' >> ~/.bashrc
RUN echo '. ~/.bashrc' >> ~/.bash_profile
diff --git a/Makefile b/Makefile
index 0416cc35..c38f86de 100644
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ endif
ifeq ($(REVISION),)
$(error Not on git repository; cannot determine $$FZF_REVISION)
endif
-BUILD_FLAGS := -a -ldflags "-s -w -X main.version=$(VERSION) -X main.revision=$(REVISION)" -tags "$(TAGS)"
+BUILD_FLAGS := -a -ldflags "-s -w -X main.version=$(VERSION) -X main.revision=$(REVISION)" -tags "$(TAGS)" -trimpath
BINARY32 := fzf-$(GOOS)_386
BINARY64 := fzf-$(GOOS)_amd64
@@ -174,12 +174,12 @@ bin/fzf: target/$(BINARY) | bin
cp -f target/$(BINARY) bin/fzf
docker:
- docker build -t fzf-arch .
- docker run -it fzf-arch tmux
+ docker build -t fzf-ubuntu .
+ docker run -it fzf-ubuntu tmux
docker-test:
- docker build -t fzf-arch .
- docker run -it fzf-arch
+ docker build -t fzf-ubuntu .
+ docker run -it fzf-ubuntu
update:
$(GO) get -u
diff --git a/README.md b/README.md
index fc581c9d..f23790c3 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/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/comatory"><img src="https://github.com/comatory.png" width="60px" alt="Ondrej Synacek" /></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 O'Leary 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/khuedoan"><img src="https://github.com/khuedoan.png" width="60px" alt="Khue Doan" /></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/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/mauricelam"><img src="https://github.com/mauricelam.png" width="60px" alt="Maurice Lam" /></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="James O'Beirne" /></a><a href="https://github.com/joshuatz"><img src="https://github.com/joshuatz.png" width="60px" alt="Joshua Tzucker" /></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/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/comatory"><img src="https://github.com/comatory.png" width="60px" alt="Ondrej Synacek" /></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 O'Leary 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/khuedoan"><img src="https://github.com/khuedoan.png" width="60px" alt="Khue Doan" /></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/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/warpdotdev"><img src="https://github.com/warpdotdev.png" width="60px" alt="Warp" /></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="James O'Beirne" /></a><a href="https://github.com/joshuatz"><img src="https://github.com/joshuatz.png" width="60px" alt="Joshua Tzucker" /></a><a href="https://github.com/gpopides"><img src="https://github.com/gpopides.png" width="60px" alt="gpopides" /></a><a href="https://github.com/jlebray"><img src="https://github.com/jlebray.png" width="60px" alt="Johan Le Bray" /></a><!-- sponsors -->
Table of Contents
-----------------
@@ -122,6 +122,7 @@ to install fzf.
```sh
brew install fzf
+ # To build fzf from the latest source: brew install --HEAD fzf
```
> [!IMPORTANT]
diff --git a/bin/fzf-tmux b/bin/fzf-tmux
index 1c3c38cc..e66dcda5 100755
--- a/bin/fzf-tmux
+++ b/bin/fzf-tmux
@@ -7,7 +7,7 @@ fail() {
exit 2
}
-fzf="$(command -v fzf 2> /dev/null)" || fzf="$(dirname "$0")/fzf"
+fzf="$(command which fzf)" || fzf="$(dirname "$0")/fzf"
[[ -x "$fzf" ]] || fail 'fzf executable not found'
args=()
diff --git a/install b/install
index 1453ea68..e4529900 100755
--- a/install
+++ b/install
@@ -2,7 +2,7 @@
set -u
-version=0.49.0
+version=0.50.0
auto_completion=
key_bindings=
update_config=2
diff --git a/install.ps1 b/install.ps1
index c4331f8c..deb97490 100644
--- a/install.ps1
+++ b/install.ps1
@@ -1,4 +1,4 @@
-$version="0.49.0"
+$version="0.50.0"
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
diff --git a/main.go b/main.go
index ce68983d..ba1979fa 100644
--- a/main.go
+++ b/main.go
@@ -9,7 +9,7 @@ import (
"github.com/junegunn/fzf/src/protector"
)
-var version string = "0.49"
+var version string = "0.50"
var revision string = "devel"
//go:embed shell/key-bindings.bash
diff --git a/man/man1/fzf-tmux.1 b/man/man1/fzf-tmux.1
index 03a3d729..750a5904 100644
--- a/man/man1/fzf-tmux.1
+++ b/man/man1/fzf-tmux.1
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
..
-.TH fzf-tmux 1 "Apr 2024" "fzf 0.49.0" "fzf-tmux - open fzf in tmux split pane"
+.TH fzf-tmux 1 "Apr 2024" "fzf 0.50.0" "fzf-tmux - open fzf in tmux split pane"
.SH NAME
fzf-tmux - open fzf in tmux split pane
diff --git a/man/man1/fzf.1 b/man/man1/fzf.1
index fc621c3e..8e79c2e4 100644
--- a/man/man1/fzf.1
+++ b/man/man1/fzf.1
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
..
-.TH fzf 1 "Apr 2024" "fzf 0.49.0" "fzf - a command-line fuzzy finder"
+.TH fzf 1 "Apr 2024" "fzf 0.50.0" "fzf - a command-line fuzzy finder"
.SH NAME
fzf - a command-line fuzzy finder
@@ -812,12 +812,22 @@ e.g.
.TP
.B "--sync"
Synchronous search for multi-staged filtering. If specified, fzf will launch
-ncurses finder only after the input stream is complete.
+the finder only after the input stream is complete.
.RS
e.g. \fBfzf --multi | fzf --sync\fR
.RE
.TP
+.B "--with-shell=STR"
+Shell command and flags to start child processes with. On *nix Systems, the
+default value is \fB$SHELL -c\fR if \fB$SHELL\fR is set, otherwise \fBsh -c\fR.
+On Windows, the default value is \fBcmd /v:on/s/c\fR when \fB$SHELL\fR is not
+set.
+
+.RS
+e.g. \fBgem list | fzf --with-shell 'ruby -e' --preview 'pp Gem::Specification.find_by_name({1})'\fR
+.RE
+.TP
.B "--listen[=[ADDR:]PORT]" "--listen-unsafe[=[ADDR:]PORT]"
Start HTTP server and listen on the given address. It allows external processes
to send actions to perform via POST method.
@@ -932,6 +942,8 @@ you need to protect against DNS rebinding and privilege escalation attacks.
.br
.BR 2 " Error"
.br
+.BR 127 " Invalid shell command for \fBbecome\fR action"
+.br
.BR 130 " Interrupted with \fBCTRL-C\fR or \fBESC\fR"
.SH FIELD INDEX EXPRESSION
@@ -972,6 +984,8 @@ fzf exports the following environment variables to its child processes.
.br
.BR FZF_SELECT_COUNT " Number of selected items"
.br
+.BR FZF_POS " Vertical position of the cursor in the list starting from 1"
+.br
.BR FZF_QUERY " Current query string"
.br
.BR FZF_PROMPT " Prompt string"
@@ -1282,6 +1296,8 @@ A key or an event can be bound to one or more of the following actions.
\fBcancel\fR (clear query string if not empty, abort fzf otherwise)
\fBchange-border-label(...)\fR (change \fB--border-label\fR to the given string)
\fBchange-header(...)\fR (change header to the given string; doesn't affect \fB--header-lines\fR)
+ \fBchange-multi\fR (enable multi-select mode with no limit)
+ \fBchange-multi(...)\fR (enable multi-select mode with a limit or disable it with 0)
\fBchange-preview(...)\fR (change \fB--preview\fR option)
\fBchange-preview-label(...)\fR (change \fB--preview-label\fR to the given string)
\fBchange-preview-window(...)\fR (change \fB--preview-window\fR option; rotate through the multiple option sets separated by '|')
@@ -1439,8 +1455,6 @@ call.
\fBfzf --bind "enter:become(vim {})"\fR
-\fBbecome(...)\fR is not supported on Windows.
-
.SS RELOAD INPUT
\fBreload(...)\fR action is used to dynamically update the input list
diff --git a/shell/completion.bash b/shell/completion.bash
index 5786d046..43fa46af 100644
--- a/shell/completion.bash
+++ b/shell/completion.bash
@@ -32,6 +32,14 @@ if [[ $- =~ i ]]; then
# To redraw line after fzf closes (printf '\e[5n')
bind '"\e[0n": redraw-current-line' 2> /dev/null
+__fzf_defaults() {
+ # $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
+ # $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
+ echo "--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore $1"
+ command cat "${FZF_DEFAULT_OPTS_FILE-}" 2> /dev/null
+ echo "${FZF_DEFAULT_OPTS-} $2"
+}
+
__fzf_comprun() {
if [[ "$(type -t _fzf_comprun 2>&1)" = function ]]; then
_fzf_comprun "$@"
@@ -92,128 +100,77 @@ _fzf_opts_completion() {
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="
-h --help
- -x --extended
-e --exact
- --extended-exact
+x --no-extended
- +e --no-exact
-q --query
-f --filter
--literal
- --no-literal
- --algo
--scheme
--expect
- --no-expect
- --enabled --no-phony
- --disabled --phony
+ --disabled
--tiebreak
--bind
--color
- --toggle-sort
-d --delimiter
-n --nth
--with-nth
- -s --sort
+s --no-sort
--track
- --no-track
--tac
- --no-tac
-i
+i
-m --multi
- +m --no-multi
--ansi
- --no-ansi
--no-mouse
+c --no-color
- +2 --no-256
- --black
- --no-black
- --bold
--no-bold
--layout
--reverse
- --no-reverse
--cycle
- --no-cycle
--keep-right
- --no-keep-right
- --hscroll
--no-hscroll
--hscroll-off
--scroll-off
--filepath-word
- --no-filepath-word
--info
- --no-info
- --inline-info
- --no-inline-info
--separator
--no-separator
- --scrollbar
--no-scrollbar
--jump-labels
-1 --select-1
- +1 --no-select-1
-0 --exit-0
- +0 --no-exit-0
--read0
- --no-read0
--print0
- --no-print0
--print-query
- --no-print-query
--prompt
--pointer
--marker
--sync
- --no-sync
- --async
- --no-history
--history
--history-size
- --no-header
- --no-header-lines
--header
--header-lines
--header-first
- --no-header-first
--ellipsis
--preview
- --no-preview
--preview-window
--height
--min-height
- --no-height
- --no-margin
- --no-padding
- --no-border
--border
- --no-border-label
--border-label
--border-label-pos
- --no-preview-label
--preview-label
--preview-label-pos
--no-unicode
- --unicode
--margin
--padding
--tabstop
--listen
- --no-listen
- --clear
--no-clear
--version
--"
case "${prev}" in
- --algo)
- COMPREPLY=( $(compgen -W "v1 v2" -- "$cur") )
- return 0
- ;;
--scheme)
COMPREPLY=( $(compgen -W "default path history" -- "$cur") )
return 0
@@ -335,8 +292,8 @@ __fzf_generic_path_completion() {
[[ -z "$dir" ]] && dir='.'
[[ "$dir" != "/" ]] && dir="${dir/%\//}"
matches=$(
- unset FZF_DEFAULT_COMMAND
- export FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-} $2"
+ export FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-} $2")
+ unset FZF_DEFAULT_COMMAND FZF_DEFAULT_OPTS_FILE
if declare -F "$1" > /dev/null; then
eval "$1 $(printf %q "$dir")" | __fzf_comprun "$4" -q "$leftover"
else
@@ -399,7 +356,10 @@ _fzf_complete() {
if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then
cur=${cur:0:${#cur}-${#trigger}}
- selected=$(FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-} $str_arg" __fzf_comprun "${rest[0]}" "${args[@]}" -q "$cur" | $post | command tr '\n' ' ')
+ selected=$(
+ FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse" "${FZF_COMPLETION_OPTS-} $str_arg") \
+ FZF_DEFAULT_OPTS_FILE='' \
+ __fzf_comprun "${rest[0]}" "${args[@]}" -q "$cur" | $post | command tr '\n' ' ')
selected=${selected% } # Strip trailing space not to repeat "-o nospace"
if [[ -n "$selected" ]]; then
COMPREPLY=("$selected")
@@ -503,8 +463,11 @@ 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
-d_cmds="${FZF_COMPLETION_DIR_COMMANDS:-cd pushd rmdir}"
-a_cmds="
+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.
+a_cmds="${FZF_COMPLETION_PATH_COMMANDS-"
awk bat cat diff diff3
emacs emacsclient ex file ftp g++ gcc gvim head hg hx java
javac ld less more mvim nvim patch perl python ruby
@@ -512,10 +475,11 @@ a_cmds="
basename bunzip2 bzip2 chmod chown curl cp dirname du
find git grep gunzip gzip hg jar
ln ls mv open rm rsync scp
- svn tar unzip zip"
+ svn tar unzip zip"}"
+v_cmds="${FZF_COMPLETION_VAR_COMMANDS-export unset printenv}"
# Preserve existing completion
-__fzf_orig_completion < <(complete -p $d_cmds $a_cmds ssh 2> /dev/null)
+__fzf_orig_completion < <(complete -p $d_cmds $a_cmds $v_cmds unalias kill ssh 2> /dev/null)
if type _comp_load > /dev/null 2>&1; then
# _comp_load was added in bash-completion 2.12 to replace _completion_loader.
@@ -551,10 +515,21 @@ for cmd in $d_cmds; do
__fzf_defc "$cmd" _fzf_dir_completion "-o bashdefault -o nospace -o dirnames"
done
+# Variables
+for cmd in $v_cmds; do
+ __fzf_defc "$cmd" _fzf_var_completion "-o default -o nospace -v"
+done
+
+# Aliases
+__fzf_defc unalias _fzf_alias_completion "-a"
+
+# Processes
+__fzf_defc kill _fzf_proc_completion "-o default -o bashdefault"
+
# ssh
__fzf_defc ssh _fzf_complete_ssh "-o default -o bashdefault"
-unset cmd d_cmds a_cmds
+unset cmd d_cmds a_cmds v_cmds
_fzf_setup_completion() {
local kind fn cmd
@@ -576,10 +551,4 @@ _fzf_setup_completion() {
done
}
-# Environment variables / Aliases / Hosts / Process
-_fzf_setup_completion 'var' export unset printenv
-_fzf_setup_completion 'alias' unalias
-_fzf_setup_completion 'host' telnet
-_fzf_setup_completion 'proc' kill
-
fi
diff --git a/shell/completion.zsh b/shell/completion.zsh
index 7067b06f..ddf5f4bb 100644
--- a/shell/completion.zsh
+++ b/shell/completion.zsh
@@ -9,8 +9,6 @@
# - $FZF_COMPLETION_TRIGGER (default: '**')
# - $FZF_COMPLETION_OPTS (default: empty)
-if [[ -o interactive ]]; then
-
# Both branches of the following `if` do the same thing -- define
# __fzf_completion_options such that `eval $__fzf_completion_options` sets
@@ -75,6 +73,9 @@ fi
# This brace is the start of try-always block. The `always` part is like
# `finally` in lesser languages. We use it to *always* restore user options.
{
+# The 'emulate' command should not be placed inside the interactive if check;
+# placing it there fails to disable alias expansion. See #3731.
+if [[ -o interactive ]]; then
# To use custom commands instead of find, override _fzf_compgen_{path,dir}
#
@@ -93,6 +94,14 @@ fi
###########################################################
+__fzf_defaults() {
+ # $1: Prepend to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
+ # $2: Append to FZF_DEFAULT_OPTS_FILE and FZF_DEFAULT_OPTS
+ echo "--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore $1"
+ command cat "${FZF_DEFAULT_OPTS_FILE-}" 2> /dev/null
+ echo "${FZF_DEFAULT_OPTS-} $2"
+}
+
__fzf_comprun() {
if [[ "$(type _fzf_comprun 2>&1)" =~ function ]]; then
_fzf_comprun "$@"
@@ -146,8 +155,8 @@ __fzf_generic_path_completion() {
[ -z "$dir" ] && dir='.'
[ "$dir" != "/" ] && dir="${dir/%\//}"
matches=$(
- unset FZF_DEFAULT_COMMAND
- export FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-}"
+ export FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-}")
+ unset FZF_DEFAULT_COMMAND FZF_DEFAULT_OPTS_FILE
if declare -f "$compgen" > /dev/null; then
eval "$compgen $(printf %q "$dir")" | __fzf_comprun "$cmd" ${(Q)${(Z+n+)fzf_opts}} -q "$leftover"
else
@@ -217,7 +226,10 @@ _fzf_complete() {
type $post > /dev/null 2>&1 || post=cat
_fzf_feed_fifo "$fifo"
- matches=$(FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-} $str_arg" __fzf_comprun "$cmd" "${args[@]}" -q "${(Q)prefix}" < "$fifo" | $post | tr '\n' ' ')
+ matches=$(
+ FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse" "${FZF_COMPLETION_OPTS-} $str_arg") \
+ FZF_DEFAULT_OPTS_FILE='' \
+ __fzf_comprun "$cmd" "${args[@]}" -q "${(Q)prefix}" < "$fifo" | $post