mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-15 06:43:47 -05:00
Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98ee5e651a | ||
|
|
01871ea383 | ||
|
|
1dbdb9438f | ||
|
|
c70f0eadb8 | ||
|
|
26244ad8c2 | ||
|
|
fa0aa5510d | ||
|
|
eec557b6aa | ||
|
|
0cc27c3cc1 | ||
|
|
507089d7b2 | ||
|
|
a6b3517b75 | ||
|
|
2d6beb7813 | ||
|
|
61bc129e1d | ||
|
|
52210a57f0 | ||
|
|
8061a2f108 | ||
|
|
7444eff6d4 | ||
|
|
f35a9da99a | ||
|
|
c3098e9ab2 | ||
|
|
686f9288fc | ||
|
|
1833670fb9 | ||
|
|
3dd42f5aa2 | ||
|
|
99a7beba57 | ||
|
|
edee2b753c | ||
|
|
545d5770be | ||
|
|
ca747a2b54 | ||
|
|
17da165cfe | ||
|
|
5e6788c679 | ||
|
|
425deadca9 | ||
|
|
2c8e9dd3a5 | ||
|
|
7a72f1a253 | ||
|
|
208e556332 | ||
|
|
c65d11bfb5 | ||
|
|
3b5b52d89a | ||
|
|
a4f6c8f990 | ||
|
|
670c329852 | ||
|
|
f3551c8422 | ||
|
|
90b8187882 | ||
|
|
1a43259989 |
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/depsreview.yaml
vendored
2
.github/workflows/depsreview.yaml
vendored
@@ -9,6 +9,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout Repository'
|
- name: 'Checkout Repository'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: 'Dependency Review'
|
- name: 'Dependency Review'
|
||||||
uses: actions/dependency-review-action@v4
|
uses: actions/dependency-review-action@v4
|
||||||
|
|||||||
2
.github/workflows/linux.yml
vendored
2
.github/workflows/linux.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/macos.yml
vendored
2
.github/workflows/macos.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/sponsors.yml
vendored
2
.github/workflows/sponsors.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout 🛎️
|
- name: Checkout 🛎️
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Generate Sponsors 💖
|
- name: Generate Sponsors 💖
|
||||||
uses: JamesIves/github-sponsors-readme-action@v1
|
uses: JamesIves/github-sponsors-readme-action@v1
|
||||||
|
|||||||
4
.github/workflows/typos.yml
vendored
4
.github/workflows/typos.yml
vendored
@@ -6,5 +6,5 @@ jobs:
|
|||||||
name: Spell Check with Typos
|
name: Spell Check with Typos
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: crate-ci/typos@v1.17.2
|
- uses: crate-ci/typos@v1.19.0
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ pods() {
|
|||||||
- Press enter key on a pod to `kubectl exec` into it
|
- Press enter key on a pod to `kubectl exec` into it
|
||||||
- Press CTRL-O to open the log in your editor
|
- Press CTRL-O to open the log in your editor
|
||||||
- Press CTRL-R to reload the pod list
|
- Press CTRL-R to reload the pod list
|
||||||
- Press CTRL-/ repeatedly to to rotate through a different sets of preview
|
- Press CTRL-/ repeatedly to rotate through a different sets of preview
|
||||||
window options
|
window options
|
||||||
1. `80%,border-bottom`
|
1. `80%,border-bottom`
|
||||||
1. `hidden`
|
1. `hidden`
|
||||||
|
|||||||
2
BUILD.md
2
BUILD.md
@@ -42,6 +42,8 @@ Third-party libraries used
|
|||||||
- Licensed under [MIT](http://mattn.mit-license.org)
|
- Licensed under [MIT](http://mattn.mit-license.org)
|
||||||
- [tcell](https://github.com/gdamore/tcell)
|
- [tcell](https://github.com/gdamore/tcell)
|
||||||
- Licensed under [Apache License 2.0](https://github.com/gdamore/tcell/blob/master/LICENSE)
|
- Licensed under [Apache License 2.0](https://github.com/gdamore/tcell/blob/master/LICENSE)
|
||||||
|
- [fastwalk](https://github.com/charlievieth/fastwalk)
|
||||||
|
- Licensed under [MIT](https://raw.githubusercontent.com/charlievieth/fastwalk/master/LICENSE)
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
|||||||
23
CHANGELOG.md
23
CHANGELOG.md
@@ -1,6 +1,29 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
0.47.0
|
||||||
|
------
|
||||||
|
- Replaced ["the default find command"][find] with a built-in directory traversal to simplify the code and to achieve better performance and consistent behavior across platforms.
|
||||||
|
This doesn't affect you if you have `$FZF_DEFAULT_COMMAND` set.
|
||||||
|
- Breaking changes:
|
||||||
|
- Unlike [the previous "find" command][find], the new traversal code will list hidden files, but hidden directories will still be ignored
|
||||||
|
- No filtering of `devtmpfs` or `proc` types
|
||||||
|
- Traversal is parallelized, so the order of the entries will be different each time
|
||||||
|
- You would wonder why fzf implements directory traversal anyway when it's a filter program following the Unix philosophy.
|
||||||
|
But fzf has had [the traversal code for years][walker] to tackle the performance problem on Windows. And I decided to use the same approach on different platforms as well for the benefits listed above.
|
||||||
|
- Built-in traversal is now done using the excellent [charlievieth/fastwalk][fastwalk] library, which easily outperforms its competitors and supports safely following symlinks.
|
||||||
|
- Added `$FZF_DEFAULT_OPTS_FILE` to allow managing default options in a file
|
||||||
|
- See [#3618](https://github.com/junegunn/fzf/pull/3618)
|
||||||
|
- Option precedence from lower to higher
|
||||||
|
1. Options read from `$FZF_DEFAULT_OPTS_FILE`
|
||||||
|
1. Options from `$FZF_DEFAULT_OPTS`
|
||||||
|
1. Options from command-line arguments
|
||||||
|
- Bug fixes and improvements
|
||||||
|
|
||||||
|
[find]: https://github.com/junegunn/fzf/blob/0.46.1/src/constants.go#L60-L64
|
||||||
|
[walker]: https://github.com/junegunn/fzf/pull/1847
|
||||||
|
[fastwalk]: https://github.com/charlievieth/fastwalk
|
||||||
|
|
||||||
0.46.1
|
0.46.1
|
||||||
------
|
------
|
||||||
- Bug fixes and improvements
|
- Bug fixes and improvements
|
||||||
|
|||||||
@@ -238,19 +238,20 @@ call fzf#run({'sink': 'e'})
|
|||||||
```
|
```
|
||||||
|
|
||||||
We haven't specified the `source`, so this is equivalent to starting fzf on
|
We haven't specified the `source`, so this is equivalent to starting fzf on
|
||||||
command line without standard input pipe; fzf will use find command (or
|
command line without standard input pipe; fzf will traverse the file system
|
||||||
`$FZF_DEFAULT_COMMAND` if defined) to list the files under the current
|
under the current directory to get the list of files. (If
|
||||||
directory. When you select one, it will open it with the sink, `:e` command.
|
`$FZF_DEFAULT_COMMAND` is set, fzf will use the output of the command
|
||||||
If you want to open it in a new tab, you can pass `:tabedit` command instead
|
instead.) When you select one, it will open it with the sink, `:e` command. If
|
||||||
as the sink.
|
you want to open it in a new tab, you can pass `:tabedit` command instead as
|
||||||
|
the sink.
|
||||||
|
|
||||||
```vim
|
```vim
|
||||||
call fzf#run({'sink': 'tabedit'})
|
call fzf#run({'sink': 'tabedit'})
|
||||||
```
|
```
|
||||||
|
|
||||||
Instead of using the default find command, you can use any shell command as
|
You can use any shell command as the source to generate the list. The
|
||||||
the source. The following example will list the files managed by git. It's
|
following example will list the files managed by git. It's equivalent to
|
||||||
equivalent to running `git ls-files | fzf` on shell.
|
running `git ls-files | fzf` on shell.
|
||||||
|
|
||||||
```vim
|
```vim
|
||||||
call fzf#run({'source': 'git ls-files', 'sink': 'e'})
|
call fzf#run({'source': 'git ls-files', 'sink': 'e'})
|
||||||
|
|||||||
@@ -95,9 +95,9 @@ while [[ $# -gt 0 ]]; do
|
|||||||
elif [[ "$size" =~ %$ ]]; then
|
elif [[ "$size" =~ %$ ]]; then
|
||||||
size=${size:0:((${#size}-1))}
|
size=${size:0:((${#size}-1))}
|
||||||
if [[ -n "$swap" ]]; then
|
if [[ -n "$swap" ]]; then
|
||||||
opt="$opt -p $(( 100 - size ))"
|
opt="$opt -l $(( 100 - size ))%"
|
||||||
else
|
else
|
||||||
opt="$opt -p $size"
|
opt="$opt -l $size%"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [[ -n "$swap" ]]; then
|
if [[ -n "$swap" ]]; then
|
||||||
|
|||||||
31
doc/fzf.txt
31
doc/fzf.txt
@@ -1,4 +1,4 @@
|
|||||||
fzf.txt fzf Last change: January 1 2024
|
fzf.txt fzf Last change: February 15 2024
|
||||||
FZF - TABLE OF CONTENTS *fzf* *fzf-toc*
|
FZF - TABLE OF CONTENTS *fzf* *fzf-toc*
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
@@ -264,17 +264,18 @@ entry.
|
|||||||
call fzf#run({'sink': 'e'})
|
call fzf#run({'sink': 'e'})
|
||||||
<
|
<
|
||||||
We haven't specified the `source`, so this is equivalent to starting fzf on
|
We haven't specified the `source`, so this is equivalent to starting fzf on
|
||||||
command line without standard input pipe; fzf will use find command (or
|
command line without standard input pipe; fzf will traverse the file system
|
||||||
`$FZF_DEFAULT_COMMAND` if defined) to list the files under the current
|
under the current directory to get the list of files. (If
|
||||||
directory. When you select one, it will open it with the sink, `:e` command.
|
`$FZF_DEFAULT_COMMAND` is set, fzf will use the output of the command
|
||||||
If you want to open it in a new tab, you can pass `:tabedit` command instead
|
instead.) When you select one, it will open it with the sink, `:e` command. If
|
||||||
as the sink.
|
you want to open it in a new tab, you can pass `:tabedit` command instead as
|
||||||
|
the sink.
|
||||||
>
|
>
|
||||||
call fzf#run({'sink': 'tabedit'})
|
call fzf#run({'sink': 'tabedit'})
|
||||||
<
|
<
|
||||||
Instead of using the default find command, you can use any shell command as
|
You can use any shell command as the source to generate the list. The
|
||||||
the source. The following example will list the files managed by git. It's
|
following example will list the files managed by git. It's equivalent to
|
||||||
equivalent to running `git ls-files | fzf` on shell.
|
running `git ls-files | fzf` on shell.
|
||||||
>
|
>
|
||||||
call fzf#run({'source': 'git ls-files', 'sink': 'e'})
|
call fzf#run({'source': 'git ls-files', 'sink': 'e'})
|
||||||
<
|
<
|
||||||
@@ -417,24 +418,12 @@ TIPS *fzf-tips*
|
|||||||
< fzf inside terminal buffer >________________________________________________~
|
< fzf inside terminal buffer >________________________________________________~
|
||||||
*fzf-inside-terminal-buffer*
|
*fzf-inside-terminal-buffer*
|
||||||
|
|
||||||
The latest versions of Vim and Neovim include builtin terminal emulator
|
|
||||||
(`:terminal`) and fzf will start in a terminal buffer in the following cases:
|
|
||||||
|
|
||||||
- On Neovim
|
|
||||||
- On GVim
|
|
||||||
- On Terminal Vim with a non-default layout
|
|
||||||
- `call fzf#run({'left': '30%'})` or `let g:fzf_layout = {'left': '30%'}`
|
|
||||||
|
|
||||||
On the latest versions of Vim and Neovim, fzf will start in a terminal buffer.
|
On the latest versions of Vim and Neovim, fzf will start in a terminal buffer.
|
||||||
If you find the default ANSI colors to be different, consider configuring the
|
If you find the default ANSI colors to be different, consider configuring the
|
||||||
colors using `g:terminal_ansi_colors` in regular Vim or `g:terminal_color_x`
|
colors using `g:terminal_ansi_colors` in regular Vim or `g:terminal_color_x`
|
||||||
in Neovim.
|
in Neovim.
|
||||||
|
|
||||||
*g:terminal_color_15* *g:terminal_color_14* *g:terminal_color_13*
|
|
||||||
*g:terminal_color_12* *g:terminal_color_11* *g:terminal_color_10* *g:terminal_color_9*
|
|
||||||
*g:terminal_color_8* *g:terminal_color_7* *g:terminal_color_6* *g:terminal_color_5*
|
|
||||||
*g:terminal_color_4* *g:terminal_color_3* *g:terminal_color_2* *g:terminal_color_1*
|
|
||||||
*g:terminal_color_0*
|
|
||||||
>
|
>
|
||||||
" Terminal colors for seoul256 color scheme
|
" Terminal colors for seoul256 color scheme
|
||||||
if has('nvim')
|
if has('nvim')
|
||||||
|
|||||||
13
go.mod
13
go.mod
@@ -1,20 +1,19 @@
|
|||||||
module github.com/junegunn/fzf
|
module github.com/junegunn/fzf
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gdamore/tcell/v2 v2.7.0
|
github.com/charlievieth/fastwalk v1.0.2
|
||||||
github.com/mattn/go-isatty v0.0.17
|
github.com/gdamore/tcell/v2 v2.7.4
|
||||||
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/mattn/go-shellwords v1.0.12
|
github.com/mattn/go-shellwords v1.0.12
|
||||||
github.com/rivo/uniseg v0.4.6
|
github.com/rivo/uniseg v0.4.7
|
||||||
github.com/saracen/walker v0.1.3
|
golang.org/x/sys v0.17.0
|
||||||
golang.org/x/sys v0.16.0
|
golang.org/x/term v0.17.0
|
||||||
golang.org/x/term v0.16.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gdamore/encoding v1.0.0 // indirect
|
github.com/gdamore/encoding v1.0.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
golang.org/x/sync v0.5.0 // indirect
|
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
31
go.sum
31
go.sum
@@ -1,21 +1,21 @@
|
|||||||
|
github.com/charlievieth/fastwalk v1.0.2 h1:KYWo7xszmoldOGrwdNIeznSzhj9mhgk+6DwHunG99bc=
|
||||||
|
github.com/charlievieth/fastwalk v1.0.2/go.mod h1:JSfglY/gmL/rqsUS1NCsJTocB5n6sSl9ApAqif4CUbs=
|
||||||
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
|
||||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||||
github.com/gdamore/tcell/v2 v2.7.0 h1:I5LiGTQuwrysAt1KS9wg1yFfOI3arI3ucFrxtd/xqaA=
|
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
|
||||||
github.com/gdamore/tcell/v2 v2.7.0/go.mod h1:hl/KtAANGBecfIPxk+FzKvThTqI84oplgbPEmVX60b8=
|
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
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/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
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 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
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 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk=
|
||||||
github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
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.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.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/saracen/walker v0.1.3 h1:YtcKKmpRPy6XJTHJ75J2QYXXZYWnZNQxPCVqZSHVV/g=
|
|
||||||
github.com/saracen/walker v0.1.3/go.mod h1:FU+7qU8DeQQgSZDmmThMJi93kPkLFgy0oVAcLxurjIk=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
@@ -26,27 +26,22 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
|
||||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.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-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.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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
|||||||
2
install
2
install
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
set -u
|
set -u
|
||||||
|
|
||||||
version=0.46.1
|
version=0.47.0
|
||||||
auto_completion=
|
auto_completion=
|
||||||
key_bindings=
|
key_bindings=
|
||||||
update_config=2
|
update_config=2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
$version="0.46.1"
|
$version="0.47.0"
|
||||||
|
|
||||||
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/junegunn/fzf/src/protector"
|
"github.com/junegunn/fzf/src/protector"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version string = "0.46"
|
var version string = "0.47"
|
||||||
var revision string = "devel"
|
var revision string = "devel"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|||||||
@@ -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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
..
|
..
|
||||||
.TH fzf-tmux 1 "Feb 2024" "fzf 0.46.1" "fzf-tmux - open fzf in tmux split pane"
|
.TH fzf-tmux 1 "Mar 2024" "fzf 0.47.0" "fzf-tmux - open fzf in tmux split pane"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf-tmux - open fzf in tmux split pane
|
fzf-tmux - open fzf in tmux split pane
|
||||||
|
|||||||
@@ -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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
THE SOFTWARE.
|
THE SOFTWARE.
|
||||||
..
|
..
|
||||||
.TH fzf 1 "Feb 2024" "fzf 0.46.1" "fzf - a command-line fuzzy finder"
|
.TH fzf 1 "Mar 2024" "fzf 0.47.0" "fzf - a command-line fuzzy finder"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf - a command-line fuzzy finder
|
fzf - a command-line fuzzy finder
|
||||||
@@ -865,7 +865,14 @@ with \fB$SHELL -c\fR if \fBSHELL\fR is set, otherwise with \fBsh -c\fR, so in
|
|||||||
this case make sure that the command is POSIX-compliant.
|
this case make sure that the command is POSIX-compliant.
|
||||||
.TP
|
.TP
|
||||||
.B FZF_DEFAULT_OPTS
|
.B FZF_DEFAULT_OPTS
|
||||||
Default options. e.g. \fBexport FZF_DEFAULT_OPTS="--extended --cycle"\fR
|
Default options.
|
||||||
|
.br
|
||||||
|
e.g. \fBexport FZF_DEFAULT_OPTS="--layout=reverse --border --cycle"\fR
|
||||||
|
.TP
|
||||||
|
.B FZF_DEFAULT_OPTS_FILE
|
||||||
|
The location of the file that contains the default options.
|
||||||
|
.br
|
||||||
|
e.g. \fBexport FZF_DEFAULT_OPTS_FILE=~/.fzfrc\fR
|
||||||
.TP
|
.TP
|
||||||
.B FZF_API_KEY
|
.B FZF_API_KEY
|
||||||
Can be used to require an API key when using \fB--listen\fR option. If not set,
|
Can be used to require an API key when using \fB--listen\fR option. If not set,
|
||||||
|
|||||||
@@ -63,6 +63,31 @@ __fzf_orig_completion() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# @param $1 cmd - Command name for which the original completion is searched
|
||||||
|
# @var[out] REPLY - Original function name is returned
|
||||||
|
__fzf_orig_completion_get_orig_func() {
|
||||||
|
local cmd orig_var orig
|
||||||
|
cmd=$1
|
||||||
|
orig_var="_fzf_orig_completion_${cmd//[^A-Za-z0-9_]/_}"
|
||||||
|
orig="${!orig_var-}"
|
||||||
|
REPLY="${orig##*#}"
|
||||||
|
[[ $REPLY ]] && type "$REPLY" &> /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
# @param $1 cmd - Command name for which the original completion is searched
|
||||||
|
# @param $2 func - Fzf's completion function to replace the original function
|
||||||
|
# @var[out] REPLY - Completion setting is returned as a string to "eval"
|
||||||
|
__fzf_orig_completion_instantiate() {
|
||||||
|
local cmd func orig_var orig
|
||||||
|
cmd=$1
|
||||||
|
func=$2
|
||||||
|
orig_var="_fzf_orig_completion_${cmd//[^A-Za-z0-9_]/_}"
|
||||||
|
orig="${!orig_var-}"
|
||||||
|
orig="${orig%#*}"
|
||||||
|
[[ $orig == *' %s '* ]] || return 1
|
||||||
|
printf -v REPLY "$orig" "$func"
|
||||||
|
}
|
||||||
|
|
||||||
_fzf_opts_completion() {
|
_fzf_opts_completion() {
|
||||||
local cur prev opts
|
local cur prev opts
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
@@ -261,15 +286,12 @@ _fzf_opts_completion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_fzf_handle_dynamic_completion() {
|
_fzf_handle_dynamic_completion() {
|
||||||
local cmd orig_var orig ret orig_cmd orig_complete
|
local cmd ret REPLY orig_cmd orig_complete
|
||||||
cmd="$1"
|
cmd="$1"
|
||||||
shift
|
shift
|
||||||
orig_cmd="$1"
|
orig_cmd="$1"
|
||||||
orig_var="_fzf_orig_completion_$cmd"
|
if __fzf_orig_completion_get_orig_func "$cmd"; then
|
||||||
orig="${!orig_var-}"
|
"$REPLY" "$@"
|
||||||
orig="${orig##*#}"
|
|
||||||
if [[ -n "$orig" ]] && type "$orig" > /dev/null 2>&1; then
|
|
||||||
$orig "$@"
|
|
||||||
elif [[ -n "${_fzf_completion_loader-}" ]]; then
|
elif [[ -n "${_fzf_completion_loader-}" ]]; then
|
||||||
orig_complete=$(complete -p "$orig_cmd" 2> /dev/null)
|
orig_complete=$(complete -p "$orig_cmd" 2> /dev/null)
|
||||||
_completion_loader "$@"
|
_completion_loader "$@"
|
||||||
@@ -277,6 +299,12 @@ _fzf_handle_dynamic_completion() {
|
|||||||
# _completion_loader may not have updated completion for the command
|
# _completion_loader may not have updated completion for the command
|
||||||
if [[ "$(complete -p "$orig_cmd" 2> /dev/null)" != "$orig_complete" ]]; then
|
if [[ "$(complete -p "$orig_cmd" 2> /dev/null)" != "$orig_complete" ]]; then
|
||||||
__fzf_orig_completion < <(complete -p "$orig_cmd" 2> /dev/null)
|
__fzf_orig_completion < <(complete -p "$orig_cmd" 2> /dev/null)
|
||||||
|
|
||||||
|
# Update orig_complete by _fzf_orig_completion entry
|
||||||
|
[[ $orig_complete =~ ' -F '(_fzf_[^ ]+)' ' ]] &&
|
||||||
|
__fzf_orig_completion_instantiate "$cmd" "${BASH_REMATCH[1]}" &&
|
||||||
|
orig_complete=$REPLY
|
||||||
|
|
||||||
if [[ "${__fzf_nospace_commands-}" = *" $orig_cmd "* ]]; then
|
if [[ "${__fzf_nospace_commands-}" = *" $orig_cmd "* ]]; then
|
||||||
eval "${orig_complete/ -F / -o nospace -F }"
|
eval "${orig_complete/ -F / -o nospace -F }"
|
||||||
else
|
else
|
||||||
@@ -293,7 +321,6 @@ __fzf_generic_path_completion() {
|
|||||||
if [[ $cmd == \\* ]]; then
|
if [[ $cmd == \\* ]]; then
|
||||||
cmd="${cmd:1}"
|
cmd="${cmd:1}"
|
||||||
fi
|
fi
|
||||||
cmd="${cmd//[^A-Za-z0-9_=]/_}"
|
|
||||||
COMPREPLY=()
|
COMPREPLY=()
|
||||||
trigger=${FZF_COMPLETION_TRIGGER-'**'}
|
trigger=${FZF_COMPLETION_TRIGGER-'**'}
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
@@ -359,7 +386,6 @@ _fzf_complete() {
|
|||||||
post="$(caller 0 | command awk '{print $2}')_post"
|
post="$(caller 0 | command awk '{print $2}')_post"
|
||||||
type -t "$post" > /dev/null 2>&1 || post='command cat'
|
type -t "$post" > /dev/null 2>&1 || post='command cat'
|
||||||
|
|
||||||
cmd="${COMP_WORDS[0]//[^A-Za-z0-9_=]/_}"
|
|
||||||
trigger=${FZF_COMPLETION_TRIGGER-'**'}
|
trigger=${FZF_COMPLETION_TRIGGER-'**'}
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then
|
if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then
|
||||||
@@ -488,15 +514,12 @@ if type _completion_loader > /dev/null 2>&1; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
__fzf_defc() {
|
__fzf_defc() {
|
||||||
local cmd func opts orig_var orig def
|
local cmd func opts REPLY
|
||||||
cmd="$1"
|
cmd="$1"
|
||||||
func="$2"
|
func="$2"
|
||||||
opts="$3"
|
opts="$3"
|
||||||
orig_var="_fzf_orig_completion_${cmd//[^A-Za-z0-9_]/_}"
|
if __fzf_orig_completion_instantiate "$cmd" "$func"; then
|
||||||
orig="${!orig_var-}"
|
eval "$REPLY"
|
||||||
if [[ -n "$orig" ]]; then
|
|
||||||
printf -v def "$orig" "$func"
|
|
||||||
eval "$def"
|
|
||||||
else
|
else
|
||||||
complete -F "$func" $opts "$cmd"
|
complete -F "$func" $opts "$cmd"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -255,24 +255,29 @@ func charClassOf(char rune) charClass {
|
|||||||
|
|
||||||
func bonusFor(prevClass charClass, class charClass) int16 {
|
func bonusFor(prevClass charClass, class charClass) int16 {
|
||||||
if class > charNonWord {
|
if class > charNonWord {
|
||||||
if prevClass == charWhite {
|
switch prevClass {
|
||||||
|
case charWhite:
|
||||||
// Word boundary after whitespace
|
// Word boundary after whitespace
|
||||||
return bonusBoundaryWhite
|
return bonusBoundaryWhite
|
||||||
} else if prevClass == charDelimiter {
|
case charDelimiter:
|
||||||
// Word boundary after a delimiter character
|
// Word boundary after a delimiter character
|
||||||
return bonusBoundaryDelimiter
|
return bonusBoundaryDelimiter
|
||||||
} else if prevClass == charNonWord {
|
case charNonWord:
|
||||||
// Word boundary
|
// Word boundary
|
||||||
return bonusBoundary
|
return bonusBoundary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if prevClass == charLower && class == charUpper ||
|
if prevClass == charLower && class == charUpper ||
|
||||||
prevClass != charNumber && class == charNumber {
|
prevClass != charNumber && class == charNumber {
|
||||||
// camelCase letter123
|
// camelCase letter123
|
||||||
return bonusCamel123
|
return bonusCamel123
|
||||||
} else if class == charNonWord {
|
}
|
||||||
|
|
||||||
|
switch class {
|
||||||
|
case charNonWord, charDelimiter:
|
||||||
return bonusNonWord
|
return bonusNonWord
|
||||||
} else if class == charWhite {
|
case charWhite:
|
||||||
return bonusBoundaryWhite
|
return bonusBoundaryWhite
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package fzf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"os"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/junegunn/fzf/src/util"
|
"github.com/junegunn/fzf/src/util"
|
||||||
@@ -54,16 +53,6 @@ const (
|
|||||||
defaultJumpLabels string = "asdfghjklqwertyuiopzxcvbnm1234567890ASDFGHJKLQWERTYUIOPZXCVBNM`~;:,<.>/?'\"!@#$%^&*()[{]}-_=+"
|
defaultJumpLabels string = "asdfghjklqwertyuiopzxcvbnm1234567890ASDFGHJKLQWERTYUIOPZXCVBNM`~;:,<.>/?'\"!@#$%^&*()[{]}-_=+"
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultCommand string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if !util.IsWindows() {
|
|
||||||
defaultCommand = `set -o pipefail; command find -L . -mindepth 1 \( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \) -prune -o -type f -print -o -type l -print 2> /dev/null | cut -b3-`
|
|
||||||
} else if os.Getenv("TERM") == "cygwin" {
|
|
||||||
defaultCommand = `sh -c "command find -L . -mindepth 1 -path '*/.*' -prune -o -type f -print -o -type l -print 2> /dev/null | cut -b3-"`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fzf events
|
// fzf events
|
||||||
const (
|
const (
|
||||||
EvtReadNew util.EventType = iota
|
EvtReadNew util.EventType = iota
|
||||||
|
|||||||
13
src/core.go
13
src/core.go
@@ -213,6 +213,7 @@ func Run(opts *Options, version string, revision string) {
|
|||||||
reading := true
|
reading := true
|
||||||
ticks := 0
|
ticks := 0
|
||||||
var nextCommand *string
|
var nextCommand *string
|
||||||
|
var nextEnviron []string
|
||||||
eventBox.Watch(EvtReadNew)
|
eventBox.Watch(EvtReadNew)
|
||||||
total := 0
|
total := 0
|
||||||
query := []rune{}
|
query := []rune{}
|
||||||
@@ -232,13 +233,13 @@ func Run(opts *Options, version string, revision string) {
|
|||||||
useSnapshot := false
|
useSnapshot := false
|
||||||
var snapshot []*Chunk
|
var snapshot []*Chunk
|
||||||
var count int
|
var count int
|
||||||
restart := func(command string) {
|
restart := func(command string, environ []string) {
|
||||||
reading = true
|
reading = true
|
||||||
chunkList.Clear()
|
chunkList.Clear()
|
||||||
itemIndex = 0
|
itemIndex = 0
|
||||||
inputRevision++
|
inputRevision++
|
||||||
header = make([]string, 0, opts.HeaderLines)
|
header = make([]string, 0, opts.HeaderLines)
|
||||||
go reader.restart(command)
|
go reader.restart(command, environ)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
delay := true
|
delay := true
|
||||||
@@ -266,8 +267,9 @@ func Run(opts *Options, version string, revision string) {
|
|||||||
os.Exit(value.(int))
|
os.Exit(value.(int))
|
||||||
case EvtReadNew, EvtReadFin:
|
case EvtReadNew, EvtReadFin:
|
||||||
if evt == EvtReadFin && nextCommand != nil {
|
if evt == EvtReadFin && nextCommand != nil {
|
||||||
restart(*nextCommand)
|
restart(*nextCommand, nextEnviron)
|
||||||
nextCommand = nil
|
nextCommand = nil
|
||||||
|
nextEnviron = nil
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
reading = reading && evt == EvtReadNew
|
reading = reading && evt == EvtReadNew
|
||||||
@@ -292,11 +294,13 @@ func Run(opts *Options, version string, revision string) {
|
|||||||
|
|
||||||
case EvtSearchNew:
|
case EvtSearchNew:
|
||||||
var command *string
|
var command *string
|
||||||
|
var environ []string
|
||||||
var changed bool
|
var changed bool
|
||||||
switch val := value.(type) {
|
switch val := value.(type) {
|
||||||
case searchRequest:
|
case searchRequest:
|
||||||
sort = val.sort
|
sort = val.sort
|
||||||
command = val.command
|
command = val.command
|
||||||
|
environ = val.environ
|
||||||
changed = val.changed
|
changed = val.changed
|
||||||
if command != nil {
|
if command != nil {
|
||||||
useSnapshot = val.sync
|
useSnapshot = val.sync
|
||||||
@@ -306,8 +310,9 @@ func Run(opts *Options, version string, revision string) {
|
|||||||
if reading {
|
if reading {
|
||||||
reader.terminate()
|
reader.terminate()
|
||||||
nextCommand = command
|
nextCommand = command
|
||||||
|
nextEnviron = environ
|
||||||
} else {
|
} else {
|
||||||
restart(*command)
|
restart(*command, environ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !changed {
|
if !changed {
|
||||||
|
|||||||
@@ -126,8 +126,8 @@ const usage = `usage: fzf [options]
|
|||||||
|
|
||||||
Environment variables
|
Environment variables
|
||||||
FZF_DEFAULT_COMMAND Default command to use when input is tty
|
FZF_DEFAULT_COMMAND Default command to use when input is tty
|
||||||
FZF_DEFAULT_OPTS Default options
|
FZF_DEFAULT_OPTS Default options (e.g. '--layout=reverse --info=inline')
|
||||||
(e.g. '--layout=reverse --inline-info')
|
FZF_DEFAULT_OPTS_FILE Location of the file to read default options from
|
||||||
FZF_API_KEY X-API-Key header for HTTP server (--listen)
|
FZF_API_KEY X-API-Key header for HTTP server (--listen)
|
||||||
|
|
||||||
`
|
`
|
||||||
@@ -421,8 +421,10 @@ func help(code int) {
|
|||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errorContext = ""
|
||||||
|
|
||||||
func errorExit(msg string) {
|
func errorExit(msg string) {
|
||||||
os.Stderr.WriteString(msg + "\n")
|
os.Stderr.WriteString(errorContext + msg + "\n")
|
||||||
os.Exit(exitError)
|
os.Exit(exitError)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1864,7 +1866,7 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
addr := defaultListenAddr
|
addr := defaultListenAddr
|
||||||
if given {
|
if given {
|
||||||
var err error
|
var err error
|
||||||
err, addr = parseListenAddress(str)
|
addr, err = parseListenAddress(str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorExit(err.Error())
|
errorExit(err.Error())
|
||||||
}
|
}
|
||||||
@@ -1962,14 +1964,14 @@ func parseOptions(opts *Options, allArgs []string) {
|
|||||||
} else if match, value := optString(arg, "--tabstop="); match {
|
} else if match, value := optString(arg, "--tabstop="); match {
|
||||||
opts.Tabstop = atoi(value)
|
opts.Tabstop = atoi(value)
|
||||||
} else if match, value := optString(arg, "--listen="); match {
|
} else if match, value := optString(arg, "--listen="); match {
|
||||||
err, addr := parseListenAddress(value)
|
addr, err := parseListenAddress(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorExit(err.Error())
|
errorExit(err.Error())
|
||||||
}
|
}
|
||||||
opts.ListenAddr = &addr
|
opts.ListenAddr = &addr
|
||||||
opts.Unsafe = false
|
opts.Unsafe = false
|
||||||
} else if match, value := optString(arg, "--listen-unsafe="); match {
|
} else if match, value := optString(arg, "--listen-unsafe="); match {
|
||||||
err, addr := parseListenAddress(value)
|
addr, err := parseListenAddress(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorExit(err.Error())
|
errorExit(err.Error())
|
||||||
}
|
}
|
||||||
@@ -2167,13 +2169,36 @@ func ParseOptions() *Options {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options from Env var
|
// 1. Options from $FZF_DEFAULT_OPTS_FILE
|
||||||
words, _ := shellwords.Parse(os.Getenv("FZF_DEFAULT_OPTS"))
|
if path := os.Getenv("FZF_DEFAULT_OPTS_FILE"); path != "" {
|
||||||
|
bytes, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
errorContext = "$FZF_DEFAULT_OPTS_FILE: "
|
||||||
|
errorExit(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
words, parseErr := shellwords.Parse(string(bytes))
|
||||||
|
if parseErr != nil {
|
||||||
|
errorContext = path + ": "
|
||||||
|
errorExit(parseErr.Error())
|
||||||
|
}
|
||||||
|
if len(words) > 0 {
|
||||||
|
parseOptions(opts, words)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Options from $FZF_DEFAULT_OPTS string
|
||||||
|
words, parseErr := shellwords.Parse(os.Getenv("FZF_DEFAULT_OPTS"))
|
||||||
|
errorContext = "$FZF_DEFAULT_OPTS: "
|
||||||
|
if parseErr != nil {
|
||||||
|
errorExit(parseErr.Error())
|
||||||
|
}
|
||||||
if len(words) > 0 {
|
if len(words) > 0 {
|
||||||
parseOptions(opts, words)
|
parseOptions(opts, words)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options from command-line arguments
|
// 3. Options from command-line arguments
|
||||||
|
errorContext = ""
|
||||||
parseOptions(opts, os.Args[1:])
|
parseOptions(opts, os.Args[1:])
|
||||||
|
|
||||||
postProcessOptions(opts)
|
postProcessOptions(opts)
|
||||||
|
|||||||
@@ -209,11 +209,10 @@ func parseTerms(fuzzy bool, caseMode Case, normalize bool, str string) []termSet
|
|||||||
// Flip exactness
|
// Flip exactness
|
||||||
if fuzzy && !inv {
|
if fuzzy && !inv {
|
||||||
typ = termExact
|
typ = termExact
|
||||||
text = text[1:]
|
|
||||||
} else {
|
} else {
|
||||||
typ = termFuzzy
|
typ = termFuzzy
|
||||||
text = text[1:]
|
|
||||||
}
|
}
|
||||||
|
text = text[1:]
|
||||||
} else if strings.HasPrefix(text, "^") {
|
} else if strings.HasPrefix(text, "^") {
|
||||||
if typ == termSuffix {
|
if typ == termSuffix {
|
||||||
typ = termEqual
|
typ = termEqual
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/charlievieth/fastwalk"
|
||||||
"github.com/junegunn/fzf/src/util"
|
"github.com/junegunn/fzf/src/util"
|
||||||
"github.com/saracen/walker"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reader reads from command or standard input
|
// Reader reads from command or standard input
|
||||||
@@ -77,20 +76,19 @@ func (r *Reader) fin(success bool) {
|
|||||||
|
|
||||||
func (r *Reader) terminate() {
|
func (r *Reader) terminate() {
|
||||||
r.mutex.Lock()
|
r.mutex.Lock()
|
||||||
defer func() { r.mutex.Unlock() }()
|
|
||||||
|
|
||||||
r.killed = true
|
r.killed = true
|
||||||
if r.exec != nil && r.exec.Process != nil {
|
if r.exec != nil && r.exec.Process != nil {
|
||||||
util.KillCommand(r.exec)
|
util.KillCommand(r.exec)
|
||||||
} else if defaultCommand != "" {
|
} else {
|
||||||
os.Stdin.Close()
|
os.Stdin.Close()
|
||||||
}
|
}
|
||||||
|
r.mutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) restart(command string) {
|
func (r *Reader) restart(command string, environ []string) {
|
||||||
r.event = int32(EvtReady)
|
r.event = int32(EvtReady)
|
||||||
r.startEventPoller()
|
r.startEventPoller()
|
||||||
success := r.readFromCommand(nil, command)
|
success := r.readFromCommand(command, environ)
|
||||||
r.fin(success)
|
r.fin(success)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,26 +97,12 @@ func (r *Reader) ReadSource() {
|
|||||||
r.startEventPoller()
|
r.startEventPoller()
|
||||||
var success bool
|
var success bool
|
||||||
if util.IsTty() {
|
if util.IsTty() {
|
||||||
// The default command for *nix requires a shell that supports "pipefail"
|
|
||||||
// https://unix.stackexchange.com/a/654932/62171
|
|
||||||
shell := "bash"
|
|
||||||
currentShell := os.Getenv("SHELL")
|
|
||||||
currentShellName := path.Base(currentShell)
|
|
||||||
for _, shellName := range []string{"bash", "zsh", "ksh", "ash", "hush", "mksh", "yash"} {
|
|
||||||
if currentShellName == shellName {
|
|
||||||
shell = currentShell
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
|
cmd := os.Getenv("FZF_DEFAULT_COMMAND")
|
||||||
if len(cmd) == 0 {
|
if len(cmd) == 0 {
|
||||||
if defaultCommand != "" {
|
|
||||||
success = r.readFromCommand(&shell, defaultCommand)
|
|
||||||
} else {
|
|
||||||
success = r.readFiles()
|
success = r.readFiles()
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
success = r.readFromCommand(nil, cmd)
|
// We can't export FZF_* environment variables to the default command
|
||||||
|
success = r.readFromCommand(cmd, nil)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
success = r.readFromStdin()
|
success = r.readFromStdin()
|
||||||
@@ -163,10 +147,14 @@ func (r *Reader) readFromStdin() bool {
|
|||||||
|
|
||||||
func (r *Reader) readFiles() bool {
|
func (r *Reader) readFiles() bool {
|
||||||
r.killed = false
|
r.killed = false
|
||||||
fn := func(path string, mode os.FileInfo) error {
|
conf := fastwalk.Config{Follow: true}
|
||||||
|
fn := func(path string, de os.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
path = filepath.Clean(path)
|
path = filepath.Clean(path)
|
||||||
if path != "." {
|
if path != "." {
|
||||||
isDir := mode.Mode().IsDir()
|
isDir := de.IsDir()
|
||||||
if isDir && filepath.Base(path)[0] == '.' {
|
if isDir && filepath.Base(path)[0] == '.' {
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
@@ -181,20 +169,16 @@ func (r *Reader) readFiles() bool {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cb := walker.WithErrorCallback(func(pathname string, err error) error {
|
return fastwalk.Walk(&conf, ".", fn) == nil
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return walker.Walk(".", fn, cb) == nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) readFromCommand(shell *string, command string) bool {
|
func (r *Reader) readFromCommand(command string, environ []string) bool {
|
||||||
r.mutex.Lock()
|
r.mutex.Lock()
|
||||||
r.killed = false
|
r.killed = false
|
||||||
r.command = &command
|
r.command = &command
|
||||||
if shell != nil {
|
|
||||||
r.exec = util.ExecCommandWith(*shell, command, true)
|
|
||||||
} else {
|
|
||||||
r.exec = util.ExecCommand(command, true)
|
r.exec = util.ExecCommand(command, true)
|
||||||
|
if environ != nil {
|
||||||
|
r.exec.Env = environ
|
||||||
}
|
}
|
||||||
out, err := r.exec.StdoutPipe()
|
out, err := r.exec.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func TestReadFromCommand(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normal command
|
// Normal command
|
||||||
reader.fin(reader.readFromCommand(nil, `echo abc&&echo def`))
|
reader.fin(reader.readFromCommand(`echo abc&&echo def`, nil))
|
||||||
if len(strs) != 2 || strs[0] != "abc" || strs[1] != "def" {
|
if len(strs) != 2 || strs[0] != "abc" || strs[1] != "def" {
|
||||||
t.Errorf("%s", strs)
|
t.Errorf("%s", strs)
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ func TestReadFromCommand(t *testing.T) {
|
|||||||
reader.startEventPoller()
|
reader.startEventPoller()
|
||||||
|
|
||||||
// Failing command
|
// Failing command
|
||||||
reader.fin(reader.readFromCommand(nil, `no-such-command`))
|
reader.fin(reader.readFromCommand(`no-such-command`, nil))
|
||||||
strs = []string{}
|
strs = []string{}
|
||||||
if len(strs) > 0 {
|
if len(strs) > 0 {
|
||||||
t.Errorf("%s", strs)
|
t.Errorf("%s", strs)
|
||||||
|
|||||||
@@ -53,47 +53,47 @@ func (addr listenAddress) IsLocal() bool {
|
|||||||
|
|
||||||
var defaultListenAddr = listenAddress{"localhost", 0}
|
var defaultListenAddr = listenAddress{"localhost", 0}
|
||||||
|
|
||||||
func parseListenAddress(address string) (error, listenAddress) {
|
func parseListenAddress(address string) (listenAddress, error) {
|
||||||
parts := strings.SplitN(address, ":", 3)
|
parts := strings.SplitN(address, ":", 3)
|
||||||
if len(parts) == 1 {
|
if len(parts) == 1 {
|
||||||
parts = []string{"localhost", parts[0]}
|
parts = []string{"localhost", parts[0]}
|
||||||
}
|
}
|
||||||
if len(parts) != 2 {
|
if len(parts) != 2 {
|
||||||
return fmt.Errorf("invalid listen address: %s", address), defaultListenAddr
|
return defaultListenAddr, fmt.Errorf("invalid listen address: %s", address)
|
||||||
}
|
}
|
||||||
portStr := parts[len(parts)-1]
|
portStr := parts[len(parts)-1]
|
||||||
port, err := strconv.Atoi(portStr)
|
port, err := strconv.Atoi(portStr)
|
||||||
if err != nil || port < 0 || port > 65535 {
|
if err != nil || port < 0 || port > 65535 {
|
||||||
return fmt.Errorf("invalid listen port: %s", portStr), defaultListenAddr
|
return defaultListenAddr, fmt.Errorf("invalid listen port: %s", portStr)
|
||||||
}
|
}
|
||||||
if len(parts[0]) == 0 {
|
if len(parts[0]) == 0 {
|
||||||
parts[0] = "localhost"
|
parts[0] = "localhost"
|
||||||
}
|
}
|
||||||
return nil, listenAddress{parts[0], port}
|
return listenAddress{parts[0], port}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startHttpServer(address listenAddress, actionChannel chan []*action, responseChannel chan string) (error, int) {
|
func startHttpServer(address listenAddress, actionChannel chan []*action, responseChannel chan string) (int, error) {
|
||||||
host := address.host
|
host := address.host
|
||||||
port := address.port
|
port := address.port
|
||||||
apiKey := os.Getenv("FZF_API_KEY")
|
apiKey := os.Getenv("FZF_API_KEY")
|
||||||
if !address.IsLocal() && len(apiKey) == 0 {
|
if !address.IsLocal() && len(apiKey) == 0 {
|
||||||
return fmt.Errorf("FZF_API_KEY is required to allow remote access"), port
|
return port, fmt.Errorf("FZF_API_KEY is required to allow remote access")
|
||||||
}
|
}
|
||||||
addrStr := fmt.Sprintf("%s:%d", host, port)
|
addrStr := fmt.Sprintf("%s:%d", host, port)
|
||||||
listener, err := net.Listen("tcp", addrStr)
|
listener, err := net.Listen("tcp", addrStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to listen on %s", addrStr), port
|
return port, fmt.Errorf("failed to listen on %s", addrStr)
|
||||||
}
|
}
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
addr := listener.Addr().String()
|
addr := listener.Addr().String()
|
||||||
parts := strings.Split(addr, ":")
|
parts := strings.Split(addr, ":")
|
||||||
if len(parts) < 2 {
|
if len(parts) < 2 {
|
||||||
return fmt.Errorf("cannot extract port: %s", addr), port
|
return port, fmt.Errorf("cannot extract port: %s", addr)
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
port, err = strconv.Atoi(parts[len(parts)-1])
|
port, err = strconv.Atoi(parts[len(parts)-1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err, port
|
return port, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ func startHttpServer(address listenAddress, actionChannel chan []*action, respon
|
|||||||
listener.Close()
|
listener.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil, port
|
return port, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we are writing a simplistic HTTP server without using net/http
|
// Here we are writing a simplistic HTTP server without using net/http
|
||||||
@@ -237,18 +237,16 @@ func parseGetParams(query string) getParams {
|
|||||||
parts := strings.SplitN(pair, "=", 2)
|
parts := strings.SplitN(pair, "=", 2)
|
||||||
if len(parts) == 2 {
|
if len(parts) == 2 {
|
||||||
switch parts[0] {
|
switch parts[0] {
|
||||||
case "limit":
|
case "limit", "offset":
|
||||||
val, err := strconv.Atoi(parts[1])
|
if val, err := strconv.Atoi(parts[1]); err == nil {
|
||||||
if err == nil {
|
if parts[0] == "limit" {
|
||||||
params.limit = val
|
params.limit = val
|
||||||
}
|
} else {
|
||||||
case "offset":
|
|
||||||
val, err := strconv.Atoi(parts[1])
|
|
||||||
if err == nil {
|
|
||||||
params.offset = val
|
params.offset = val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func init() {
|
|||||||
// * https://sw.kovidgoyal.net/kitty/graphics-protocol
|
// * https://sw.kovidgoyal.net/kitty/graphics-protocol
|
||||||
// * https://en.wikipedia.org/wiki/Sixel
|
// * https://en.wikipedia.org/wiki/Sixel
|
||||||
// * https://iterm2.com/documentation-images.html
|
// * https://iterm2.com/documentation-images.html
|
||||||
passThroughRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b.*?[^\x1b]\x1b\\|\x1b(_G|P[0-9;]*q).*?\x1b\\\r?|\x1b]1337;.*?\a`)
|
passThroughRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b.*?[^\x1b]\x1b\\|\x1b(_G|P[0-9;]*q).*?\x1b\\\r?|\x1b]1337;.*?(\a|\x1b\\)`)
|
||||||
}
|
}
|
||||||
|
|
||||||
type jumpMode int
|
type jumpMode int
|
||||||
@@ -499,6 +499,7 @@ type searchRequest struct {
|
|||||||
sort bool
|
sort bool
|
||||||
sync bool
|
sync bool
|
||||||
command *string
|
command *string
|
||||||
|
environ []string
|
||||||
changed bool
|
changed bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,7 +829,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
|
|||||||
_, t.hasLoadActions = t.keymap[tui.Load.AsEvent()]
|
_, t.hasLoadActions = t.keymap[tui.Load.AsEvent()]
|
||||||
|
|
||||||
if t.listenAddr != nil {
|
if t.listenAddr != nil {
|
||||||
err, port := startHttpServer(*t.listenAddr, t.serverInputChan, t.serverOutputChan)
|
port, err := startHttpServer(*t.listenAddr, t.serverInputChan, t.serverOutputChan)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorExit(err.Error())
|
errorExit(err.Error())
|
||||||
}
|
}
|
||||||
@@ -3160,7 +3161,7 @@ func (t *Terminal) Loop() {
|
|||||||
}
|
}
|
||||||
t.previewer.lines = result.lines
|
t.previewer.lines = result.lines
|
||||||
t.previewer.spinner = result.spinner
|
t.previewer.spinner = result.spinner
|
||||||
if t.previewer.following.Enabled() {
|
if t.hasPreviewWindow() && t.previewer.following.Enabled() {
|
||||||
t.previewer.offset = util.Max(t.previewer.offset, len(t.previewer.lines)-(t.pwindow.Height()-t.previewOpts.headerLines))
|
t.previewer.offset = util.Max(t.previewer.offset, len(t.previewer.lines)-(t.pwindow.Height()-t.previewOpts.headerLines))
|
||||||
} else if result.offset >= 0 {
|
} else if result.offset >= 0 {
|
||||||
t.previewer.offset = util.Constrain(result.offset, t.previewOpts.headerLines, len(t.previewer.lines)-1)
|
t.previewer.offset = util.Constrain(result.offset, t.previewOpts.headerLines, len(t.previewer.lines)-1)
|
||||||
@@ -3381,6 +3382,9 @@ func (t *Terminal) Loop() {
|
|||||||
// Discard the preview content so that it won't accidentally appear
|
// Discard the preview content so that it won't accidentally appear
|
||||||
// when preview window is re-enabled and previewDelay is triggered
|
// when preview window is re-enabled and previewDelay is triggered
|
||||||
t.previewer.lines = nil
|
t.previewer.lines = nil
|
||||||
|
|
||||||
|
// Also kill the preview process if it's still running
|
||||||
|
t.cancelPreview()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case actTogglePreviewWrap:
|
case actTogglePreviewWrap:
|
||||||
@@ -3987,11 +3991,18 @@ func (t *Terminal) Loop() {
|
|||||||
|
|
||||||
// Full redraw
|
// Full redraw
|
||||||
if !currentPreviewOpts.sameLayout(t.previewOpts) {
|
if !currentPreviewOpts.sameLayout(t.previewOpts) {
|
||||||
wasHidden := t.pwindow == nil
|
// Preview command can be running in the background if the size of
|
||||||
|
// the preview window is 0 but not 'hidden'
|
||||||
|
wasHidden := currentPreviewOpts.hidden
|
||||||
updatePreviewWindow(false)
|
updatePreviewWindow(false)
|
||||||
if wasHidden && t.hasPreviewWindow() {
|
if wasHidden && t.hasPreviewWindow() {
|
||||||
|
// Restart
|
||||||
refreshPreview(t.previewOpts.command)
|
refreshPreview(t.previewOpts.command)
|
||||||
|
} else if t.previewOpts.hidden {
|
||||||
|
// Cancel
|
||||||
|
t.cancelPreview()
|
||||||
} else {
|
} else {
|
||||||
|
// Refresh
|
||||||
req(reqPreviewRefresh)
|
req(reqPreviewRefresh)
|
||||||
}
|
}
|
||||||
} else if !currentPreviewOpts.sameContentLayout(t.previewOpts) {
|
} else if !currentPreviewOpts.sameContentLayout(t.previewOpts) {
|
||||||
@@ -4081,10 +4092,15 @@ func (t *Terminal) Loop() {
|
|||||||
req(reqPrompt)
|
req(reqPrompt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reload := changed || newCommand != nil
|
||||||
|
var reloadRequest *searchRequest
|
||||||
|
if reload {
|
||||||
|
reloadRequest = &searchRequest{sort: t.sort, sync: reloadSync, command: newCommand, environ: t.environ(), changed: changed}
|
||||||
|
}
|
||||||
t.mutex.Unlock() // Must be unlocked before touching reqBox
|
t.mutex.Unlock() // Must be unlocked before touching reqBox
|
||||||
|
|
||||||
if changed || newCommand != nil {
|
if reload {
|
||||||
t.eventBox.Set(EvtSearchNew, searchRequest{sort: t.sort, sync: reloadSync, command: newCommand, changed: changed})
|
t.eventBox.Set(EvtSearchNew, *reloadRequest)
|
||||||
}
|
}
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
t.reqBox.Set(event, nil)
|
t.reqBox.Set(event, nil)
|
||||||
|
|||||||
@@ -808,13 +808,25 @@ func (w *LightWindow) drawBorderHorizontal(top, bottom bool) {
|
|||||||
color = ColPreviewBorder
|
color = ColPreviewBorder
|
||||||
}
|
}
|
||||||
hw := runeWidth(w.border.top)
|
hw := runeWidth(w.border.top)
|
||||||
if top {
|
pad := repeat(' ', w.width/hw)
|
||||||
|
|
||||||
w.Move(0, 0)
|
w.Move(0, 0)
|
||||||
|
if top {
|
||||||
w.CPrint(color, repeat(w.border.top, w.width/hw))
|
w.CPrint(color, repeat(w.border.top, w.width/hw))
|
||||||
|
} else {
|
||||||
|
w.CPrint(color, pad)
|
||||||
}
|
}
|
||||||
if bottom {
|
|
||||||
|
for y := 1; y < w.height-1; y++ {
|
||||||
|
w.Move(y, 0)
|
||||||
|
w.CPrint(color, pad)
|
||||||
|
}
|
||||||
|
|
||||||
w.Move(w.height-1, 0)
|
w.Move(w.height-1, 0)
|
||||||
|
if bottom {
|
||||||
w.CPrint(color, repeat(w.border.bottom, w.width/hw))
|
w.CPrint(color, repeat(w.border.bottom, w.width/hw))
|
||||||
|
} else {
|
||||||
|
w.CPrint(color, pad)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -544,7 +544,7 @@ func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int,
|
|||||||
height: height,
|
height: height,
|
||||||
normal: normal,
|
normal: normal,
|
||||||
borderStyle: borderStyle}
|
borderStyle: borderStyle}
|
||||||
w.drawBorder(false)
|
w.Erase()
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,8 +561,8 @@ func fill(x, y, w, h int, n ColorPair, r rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *TcellWindow) Erase() {
|
func (w *TcellWindow) Erase() {
|
||||||
w.drawBorder(false)
|
|
||||||
fill(w.left-1, w.top, w.width+1, w.height-1, w.normal, ' ')
|
fill(w.left-1, w.top, w.width+1, w.height-1, w.normal, ' ')
|
||||||
|
w.drawBorder(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *TcellWindow) EraseMaybe() bool {
|
func (w *TcellWindow) EraseMaybe() bool {
|
||||||
|
|||||||
@@ -1918,7 +1918,7 @@ class TestGoFZF < TestBase
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_reload
|
def test_reload
|
||||||
tmux.send_keys %(seq 1000 | #{FZF} --bind 'change:reload(seq {q}),a:reload(seq 100),b:reload:seq 200' --header-lines 2 --multi 2), :Enter
|
tmux.send_keys %(seq 1000 | #{FZF} --bind 'change:reload(seq $FZF_QUERY),a:reload(seq 100),b:reload:seq 200' --header-lines 2 --multi 2), :Enter
|
||||||
tmux.until { |lines| assert_equal 998, lines.match_count }
|
tmux.until { |lines| assert_equal 998, lines.match_count }
|
||||||
tmux.send_keys 'a'
|
tmux.send_keys 'a'
|
||||||
tmux.until do |lines|
|
tmux.until do |lines|
|
||||||
@@ -2582,6 +2582,7 @@ class TestGoFZF < TestBase
|
|||||||
def test_change_preview_window_rotate
|
def test_change_preview_window_rotate
|
||||||
tmux.send_keys "seq 100 | #{FZF} --preview-window left,border-none --preview 'echo hello' --bind '" \
|
tmux.send_keys "seq 100 | #{FZF} --preview-window left,border-none --preview 'echo hello' --bind '" \
|
||||||
"a:change-preview-window(right|down|up|hidden|)'", :Enter
|
"a:change-preview-window(right|down|up|hidden|)'", :Enter
|
||||||
|
tmux.until { |lines| assert(lines.any? { _1.include?('100/100') }) }
|
||||||
3.times do
|
3.times do
|
||||||
tmux.until { |lines| lines[0].start_with?('hello') }
|
tmux.until { |lines| lines[0].start_with?('hello') }
|
||||||
tmux.send_keys 'a'
|
tmux.send_keys 'a'
|
||||||
|
|||||||
Reference in New Issue
Block a user