Compare commits

...

7 Commits

Author SHA1 Message Date
Junegunn Choi
091b7eacba 0.48.0 2024-03-14 00:02:53 +09:00
Junegunn Choi
e74b1251c0 Embed shell integration scripts in fzf binary (--bash / --zsh / --fish) (#3675)
This simplifies the distribution, and the users are less likely to have
problems caused by using incompatible scripts and binaries.

    # Set up fzf key bindings and fuzzy completion
    eval "$(fzf --bash)"

    # Set up fzf key bindings and fuzzy completion
    eval "$(fzf --zsh)"

    # Set up fzf key bindings
    fzf --fish | source
2024-03-13 23:59:34 +09:00
Junegunn Choi
d282a1649d Add walker options and replace 'find' with the built-in walker (#3649) 2024-03-13 20:56:31 +09:00
Junegunn Choi
6ce8d49d1b [bash] Fix regression in dynamic completion
Fix #3674
2024-03-13 08:31:31 +09:00
dependabot[bot]
c5b197078a Bump golang.org/x/term from 0.17.0 to 0.18.0 (#3670)
Bumps [golang.org/x/term](https://github.com/golang/term) from 0.17.0 to 0.18.0.
- [Commits](https://github.com/golang/term/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/term
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 08:11:25 +09:00
Junegunn Choi
0494f20d62 Revert "Fix CHANGELOG"
This reverts commit 73aff476dd.
2024-03-10 23:24:59 +09:00
Junegunn Choi
73aff476dd Fix CHANGELOG 2024-03-10 21:52:39 +09:00
19 changed files with 436 additions and 158 deletions

View File

@@ -1,17 +1,62 @@
CHANGELOG CHANGELOG
========= =========
0.48.0
------
- Shell integration scripts are now embedded in the fzf binary. This simplifies the distribution, and the users are less likely to have problems caused by using incompatible scripts and binaries.
- bash
```sh
# Set up fzf key bindings and fuzzy completion
eval "$(fzf --bash)"
```
- zsh
```sh
# Set up fzf key bindings and fuzzy completion
eval "$(fzf --zsh)"
```
- fish
```fish
# Set up fzf key bindings
fzf --fish | source
```
- Added options for customizing the behavior of the built-in walker
| Option | Description | Default |
| --- | --- | --- |
| `--walker=OPTS` | Walker options (`[file][,dir][,follow][,hidden]`) | `file,follow,hidden` |
| `--walker-root=DIR` | Root directory from which to start walker | `.` |
| `--walker-skip=DIRS` | Comma-separated list of directory names to skip | `.git,node_modules` |
- Examples
```sh
# Built-in walker is only used by standalone fzf when $FZF_DEFAULT_COMMAND is not set
unset FZF_DEFAULT_COMMAND
fzf # default: --walker=file,follow,hidden --walker-root=. --walker-skip=.git,node_modules
fzf --walker=file,dir,hidden,follow --walker-skip=.git,node_modules,target
# Walker options in $FZF_DEFAULT_OPTS
export FZF_DEFAULT_OPTS="--walker=file,dir,hidden,follow --walker-skip=.git,node_modules,target"
fzf
# Reading from STDIN; --walker is ignored
seq 100 | fzf --walker=dir
# Reading from $FZF_DEFAULT_COMMAND; --walker is ignored
export FZF_DEFAULT_COMMAND='seq 100'
fzf --walker=dir
```
- Shell integration scripts have been updated to use the built-in walker with these new options and they are now much faster out of the box.
0.47.0 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. - Replaced ["the default find command"][find] with a built-in directory walker 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. This doesn't affect you if you have `$FZF_DEFAULT_COMMAND` set.
- Breaking changes: - Breaking changes:
- Unlike [the previous "find" command][find], the new traversal code will list hidden files, but hidden directories will still be ignored - 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 - No filtering of `devtmpfs` or `proc` types
- Traversal is parallelized, so the order of the entries will be different each time - 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. - You may wonder why fzf implements directory walker anyway when it's a filter program following the [Unix philosophy][unix].
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. But fzf has had [the walker 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. - Built-in walker is 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 - Added `$FZF_DEFAULT_OPTS_FILE` to allow managing default options in a file
- See [#3618](https://github.com/junegunn/fzf/pull/3618) - See [#3618](https://github.com/junegunn/fzf/pull/3618)
- Option precedence from lower to higher - Option precedence from lower to higher
@@ -23,6 +68,7 @@ CHANGELOG
[find]: https://github.com/junegunn/fzf/blob/0.46.1/src/constants.go#L60-L64 [find]: https://github.com/junegunn/fzf/blob/0.46.1/src/constants.go#L60-L64
[walker]: https://github.com/junegunn/fzf/pull/1847 [walker]: https://github.com/junegunn/fzf/pull/1847
[fastwalk]: https://github.com/charlievieth/fastwalk [fastwalk]: https://github.com/charlievieth/fastwalk
[unix]: https://en.wikipedia.org/wiki/Unix_philosophy
0.46.1 0.46.1
------ ------

126
README.md
View File

@@ -56,6 +56,7 @@ Table of Contents
* [Using git](#using-git) * [Using git](#using-git)
* [Using Linux package managers](#using-linux-package-managers) * [Using Linux package managers](#using-linux-package-managers)
* [Windows](#windows) * [Windows](#windows)
* [Setting up shell integration](#setting-up-shell-integration)
* [As Vim plugin](#as-vim-plugin) * [As Vim plugin](#as-vim-plugin)
* [Upgrading fzf](#upgrading-fzf) * [Upgrading fzf](#upgrading-fzf)
* [Building fzf](#building-fzf) * [Building fzf](#building-fzf)
@@ -104,9 +105,9 @@ fzf project consists of the following components:
- `fzf` executable - `fzf` executable
- `fzf-tmux` script for launching fzf in a tmux pane - `fzf-tmux` script for launching fzf in a tmux pane
- Shell extensions - Shell integration
- Key bindings (`CTRL-T`, `CTRL-R`, and `ALT-C`) (bash, zsh, fish) - Key bindings (`CTRL-T`, `CTRL-R`, and `ALT-C`) (bash, zsh, fish)
- Fuzzy auto-completion (bash, zsh) - Fuzzy completion (bash, zsh)
- Vim/Neovim plugin - Vim/Neovim plugin
You can [download fzf executable][bin] alone if you don't need the extra You can [download fzf executable][bin] alone if you don't need the extra
@@ -121,11 +122,12 @@ to install fzf.
```sh ```sh
brew install fzf brew install fzf
# To install useful key bindings and fuzzy completion:
$(brew --prefix)/opt/fzf/install
``` ```
> [!IMPORTANT]
> To set up shell integration (key bindings and fuzzy completion),
> see [the instructions below](#setting-up-shell-integration).
fzf is also available [via MacPorts][portfile]: `sudo port install fzf` fzf is also available [via MacPorts][portfile]: `sudo port install fzf`
[portfile]: https://github.com/macports/macports-ports/blob/master/sysutils/fzf/Portfile [portfile]: https://github.com/macports/macports-ports/blob/master/sysutils/fzf/Portfile
@@ -140,6 +142,9 @@ git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
~/.fzf/install ~/.fzf/install
``` ```
The install script will add lines to your shell configuration file to modify
`$PATH` and set up shell integration.
### Using Linux package managers ### Using Linux package managers
| Package Manager | Linux Distribution | Command | | Package Manager | Linux Distribution | Command |
@@ -158,10 +163,9 @@ git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
| XBPS | Void Linux | `sudo xbps-install -S fzf` | | XBPS | Void Linux | `sudo xbps-install -S fzf` |
| Zypper | openSUSE | `sudo zypper install fzf` | | Zypper | openSUSE | `sudo zypper install fzf` |
> :warning: **Key bindings (CTRL-T / CTRL-R / ALT-C) and fuzzy auto-completion > [!IMPORTANT]
> may not be enabled by default.** > To set up shell integration (key bindings and fuzzy completion),
> > see [the instructions below](#setting-up-shell-integration).
> Refer to the package documentation for more information. (e.g. `apt show fzf`)
[![Packaging status](https://repology.org/badge/vertical-allrepos/fzf.svg)](https://repology.org/project/fzf/versions) [![Packaging status](https://repology.org/badge/vertical-allrepos/fzf.svg)](https://repology.org/project/fzf/versions)
@@ -187,6 +191,31 @@ page][windows-wiki].
[windows-wiki]: https://github.com/junegunn/fzf/wiki/Windows [windows-wiki]: https://github.com/junegunn/fzf/wiki/Windows
### Setting up shell integration
Add the following line to your shell configuration file.
* bash
```sh
# Set up fzf key bindings and fuzzy completion
eval "$(fzf --bash)"
```
* zsh
```sh
# Set up fzf key bindings and fuzzy completion
eval "$(fzf --zsh)"
```
* fish
```fish
# Set up fzf key bindings
fzf --fish | source
```
> [!NOTE]
> `--bash`, `--zsh`, and `--fish` options are only available in
> fzf 0.48.0 or above. If you have an older version of fzf, refer to the
> package documentation for more information. (e.g. `apt show fzf`)
### As Vim plugin ### As Vim plugin
If you use If you use
@@ -231,21 +260,26 @@ find * -type f | fzf > selected
``` ```
Without STDIN pipe, fzf will traverse the file system under the current Without STDIN pipe, fzf will traverse the file system under the current
directory to get the list of files, skipping hidden directories. (You can directory to get the list of files.
override the default behavior with `FZF_DEFAULT_COMMAND`)
```sh ```sh
vim $(fzf) vim $(fzf)
``` ```
> *:bulb: A more robust solution would be to use `xargs` but we've presented > [!NOTE]
> the above as it's easier to grasp* > You can override the default behavior
> * Either by setting `$FZF_DEFAULT_COMMAND` to a command that generates the desired list
> * Or by setting `--walker`, `--walker-root`, and `--walker-skip` options in `$FZF_DEFAULT_OPTS`
> [!WARNING]
> A more robust solution would be to use `xargs` but we've presented
> the above as it's easier to grasp
> ```sh > ```sh
> fzf --print0 | xargs -0 -o vim > fzf --print0 | xargs -0 -o vim
> ``` > ```
> > [!TIP]
> *:bulb: fzf also has the ability to turn itself into a different process.* > fzf also has the ability to turn itself into a different process.
> >
> ```sh > ```sh
> fzf --bind 'enter:become(vim {})' > fzf --bind 'enter:become(vim {})'
@@ -319,13 +353,6 @@ or `py`.
- `FZF_DEFAULT_COMMAND` - `FZF_DEFAULT_COMMAND`
- Default command to use when input is tty - Default command to use when input is tty
- e.g. `export FZF_DEFAULT_COMMAND='fd --type f'` - e.g. `export FZF_DEFAULT_COMMAND='fd --type f'`
- > :warning: This variable is not used by shell extensions due to the
> slight difference in requirements.
>
> (e.g. `CTRL-T` runs `$FZF_CTRL_T_COMMAND` instead, `vim **<tab>` runs
> `_fzf_compgen_path()`, and `cd **<tab>` runs `_fzf_compgen_dir()`)
>
> The available options are described later in this document.
- `FZF_DEFAULT_OPTS` - `FZF_DEFAULT_OPTS`
- Default options - Default options
- e.g. `export FZF_DEFAULT_OPTS="--layout=reverse --inline-info"` - e.g. `export FZF_DEFAULT_OPTS="--layout=reverse --inline-info"`
@@ -334,6 +361,17 @@ or `py`.
point to the location of the file point to the location of the file
- e.g. `export FZF_DEFAULT_OPTS_FILE=~/.fzfrc` - e.g. `export FZF_DEFAULT_OPTS_FILE=~/.fzfrc`
> [!WARNING]
> `FZF_DEFAULT_COMMAND` is not used by shell integration due to the
> slight difference in requirements.
>
> * `CTRL-T` runs `$FZF_CTRL_T_COMMAND` to get a list of files and directories
> * `ALT-C` runs `$FZF_ALT_C_COMMAND` to get a list of directories
> * `vim ~/**<tab>` runs `fzf_compgen_path()` with the prefix (`~/`) as the first argument
> * `cd foo**<tab>` runs `fzf_compgen_dir()` with the prefix (`foo`) as the first argument
>
> The available options are described later in this document.
### Options ### Options
See the man page (`man fzf`) for the full list of options. See the man page (`man fzf`) for the full list of options.
@@ -388,11 +426,14 @@ The install script will setup the following key bindings for bash, zsh, and
fish. fish.
- `CTRL-T` - Paste the selected files and directories onto the command-line - `CTRL-T` - Paste the selected files and directories onto the command-line
- Set `FZF_CTRL_T_COMMAND` to override the default command - The list is generated using `--walker file,dir,follow,hidden` option
- You can override the behavior by setting `FZF_CTRL_T_COMMAND` to a custom command that generates the desired list
- Or you can set `--walker*` options in `FZF_CTRL_T_OPTS`
- Set `FZF_CTRL_T_OPTS` to pass additional options to fzf - Set `FZF_CTRL_T_OPTS` to pass additional options to fzf
```sh ```sh
# Preview file content using bat (https://github.com/sharkdp/bat) # Preview file content using bat (https://github.com/sharkdp/bat)
export FZF_CTRL_T_OPTS=" export FZF_CTRL_T_OPTS="
--walker-skip .git,node_modules,target
--preview 'bat -n --color=always {}' --preview 'bat -n --color=always {}'
--bind 'ctrl-/:change-preview-window(down|hidden|)'" --bind 'ctrl-/:change-preview-window(down|hidden|)'"
``` ```
@@ -411,11 +452,15 @@ fish.
--header 'Press CTRL-Y to copy command into clipboard'" --header 'Press CTRL-Y to copy command into clipboard'"
``` ```
- `ALT-C` - cd into the selected directory - `ALT-C` - cd into the selected directory
- The list is generated using `--walker dir,follow,hidden` option
- Set `FZF_ALT_C_COMMAND` to override the default command - Set `FZF_ALT_C_COMMAND` to override the default command
- Or you can set `--walker-*` options in `FZF_ALT_C_OPTS`
- Set `FZF_ALT_C_OPTS` to pass additional options to fzf - Set `FZF_ALT_C_OPTS` to pass additional options to fzf
```sh ```sh
# Print tree structure in the preview window # Print tree structure in the preview window
export FZF_ALT_C_OPTS="--preview 'tree -C {}'" export FZF_ALT_C_OPTS="
--walker-skip .git,node_modules,target
--preview 'tree -C {}'"
``` ```
If you're on a tmux session, you can start fzf in a tmux split-pane or in If you're on a tmux session, you can start fzf in a tmux split-pane or in
@@ -739,22 +784,21 @@ See the man page (`man fzf`) for the full list of options.
More advanced examples can be found [here](https://github.com/junegunn/fzf/blob/master/ADVANCED.md). More advanced examples can be found [here](https://github.com/junegunn/fzf/blob/master/ADVANCED.md).
---- > [!WARNING]
> Since fzf is a general-purpose text filter rather than a file finder, **it is
Since fzf is a general-purpose text filter rather than a file finder, **it is > not a good idea to add `--preview` option to your `$FZF_DEFAULT_OPTS`**.
not a good idea to add `--preview` option to your `$FZF_DEFAULT_OPTS`**. >
> ```sh
```sh > # *********************
# ********************* > # ** DO NOT DO THIS! **
# ** DO NOT DO THIS! ** > # *********************
# ********************* > export FZF_DEFAULT_OPTS='--preview "bat --style=numbers --color=always --line-range :500 {}"'
export FZF_DEFAULT_OPTS='--preview "bat --style=numbers --color=always --line-range :500 {}"' >
> # bat doesn't work with any input other than the list of files
# bat doesn't work with any input other than the list of files > ps -ef | fzf
ps -ef | fzf > seq 100 | fzf
seq 100 | fzf > history | fzf
history | fzf > ```
```
### Previewing an image ### Previewing an image
@@ -787,7 +831,7 @@ fd --type f --strip-cwd-prefix | fzf
# Setting fd as the default source for fzf # Setting fd as the default source for fzf
export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix' export FZF_DEFAULT_COMMAND='fd --type f --strip-cwd-prefix'
# Now fzf (w/o pipe) will use fd instead of find # Now fzf (w/o pipe) will use the fd command to generate the list
fzf fzf
# To apply the command to CTRL-T as well # To apply the command to CTRL-T as well

View File

@@ -196,8 +196,9 @@ if [[ "$opt" =~ "-E" ]]; then
exit 2 exit 2
fi fi
fi fi
[[ -n "$FZF_DEFAULT_OPTS" ]] && envs="$envs FZF_DEFAULT_OPTS=$(printf %q "$FZF_DEFAULT_OPTS")" envs="$envs FZF_DEFAULT_COMMAND=$(printf %q "$FZF_DEFAULT_COMMAND")"
[[ -n "$FZF_DEFAULT_COMMAND" ]] && envs="$envs FZF_DEFAULT_COMMAND=$(printf %q "$FZF_DEFAULT_COMMAND")" envs="$envs FZF_DEFAULT_OPTS=$(printf %q "$FZF_DEFAULT_OPTS")"
envs="$envs FZF_DEFAULT_OPTS_FILE=$(printf %q "$FZF_DEFAULT_OPTS_FILE")"
[[ -n "$RUNEWIDTH_EASTASIAN" ]] && envs="$envs RUNEWIDTH_EASTASIAN=$(printf %q "$RUNEWIDTH_EASTASIAN")" [[ -n "$RUNEWIDTH_EASTASIAN" ]] && envs="$envs RUNEWIDTH_EASTASIAN=$(printf %q "$RUNEWIDTH_EASTASIAN")"
[[ -n "$BAT_THEME" ]] && envs="$envs BAT_THEME=$(printf %q "$BAT_THEME")" [[ -n "$BAT_THEME" ]] && envs="$envs BAT_THEME=$(printf %q "$BAT_THEME")"
echo "$envs;" > "$argsf" echo "$envs;" > "$argsf"

4
go.mod
View File

@@ -6,8 +6,8 @@ require (
github.com/mattn/go-isatty v0.0.20 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.7 github.com/rivo/uniseg v0.4.7
golang.org/x/sys v0.17.0 golang.org/x/sys v0.18.0
golang.org/x/term v0.17.0 golang.org/x/term v0.18.0
) )
require ( require (

6
go.sum
View File

@@ -35,13 +35,15 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.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.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
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=

36
install
View File

@@ -2,7 +2,7 @@
set -u set -u
version=0.47.0 version=0.48.0
auto_completion= auto_completion=
key_bindings= key_bindings=
update_config=2 update_config=2
@@ -262,6 +262,12 @@ if [[ ! "\$PATH" == *$fzf_base_esc/bin* ]]; then
PATH="\${PATH:+\${PATH}:}$fzf_base/bin" PATH="\${PATH:+\${PATH}:}$fzf_base/bin"
fi fi
EOF
if [[ $auto_completion -eq 1 ]] && [[ $key_bindings -eq 1 ]]; then
echo "eval \"\$(fzf --$shell)\"" >> "$src"
else
cat >> "$src" << EOF
# Auto-completion # Auto-completion
# --------------- # ---------------
$fzf_completion $fzf_completion
@@ -270,6 +276,7 @@ $fzf_completion
# ------------ # ------------
$fzf_key_bindings $fzf_key_bindings
EOF EOF
fi
echo "OK" echo "OK"
done done
@@ -281,18 +288,6 @@ if [[ "$shells" =~ fish ]]; then
or set --universal fish_user_paths \$fish_user_paths "$fzf_base"/bin or set --universal fish_user_paths \$fish_user_paths "$fzf_base"/bin
EOF EOF
[ $? -eq 0 ] && echo "OK" || echo "Failed" [ $? -eq 0 ] && echo "OK" || echo "Failed"
mkdir -p "${fish_dir}/functions"
fish_binding="${fish_dir}/functions/fzf_key_bindings.fish"
if [ $key_bindings -ne 0 ]; then
echo -n "Symlink $fish_binding ... "
ln -sf "$fzf_base/shell/key-bindings.fish" \
"$fish_binding" && echo "OK" || echo "Failed"
else
echo -n "Removing $fish_binding ... "
rm -f "$fish_binding"
echo "OK"
fi
fi fi
append_line() { append_line() {
@@ -355,12 +350,23 @@ done
if [ $key_bindings -eq 1 ] && [[ "$shells" =~ fish ]]; then if [ $key_bindings -eq 1 ] && [[ "$shells" =~ fish ]]; then
bind_file="${fish_dir}/functions/fish_user_key_bindings.fish" bind_file="${fish_dir}/functions/fish_user_key_bindings.fish"
if [ ! -e "$bind_file" ]; then if [ ! -e "$bind_file" ]; then
mkdir -p "${fish_dir}/functions"
create_file "$bind_file" \ create_file "$bind_file" \
'function fish_user_key_bindings' \ 'function fish_user_key_bindings' \
' fzf_key_bindings' \ ' fzf --fish | source' \
'end' 'end'
else else
append_line $update_config "fzf_key_bindings" "$bind_file" echo "Check $bind_file:"
lno=$(\grep -nF "fzf_key_bindings" "$bind_file" | sed 's/:.*//' | tr '\n' ' ')
if [[ -n $lno ]]; then
echo " ** Found 'fzf_key_bindings' in line #$lno"
echo " ** You have to replace the line to 'fzf --fish | source'"
echo
else
echo " - Clear"
echo
append_line $update_config "fzf --fish | source" "$bind_file"
fi
fi fi
fi fi

View File

@@ -1,4 +1,4 @@
$version="0.47.0" $version="0.48.0"
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition $fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition

45
main.go
View File

@@ -1,14 +1,55 @@
package main package main
import ( import (
_ "embed"
"fmt"
"strings"
fzf "github.com/junegunn/fzf/src" fzf "github.com/junegunn/fzf/src"
"github.com/junegunn/fzf/src/protector" "github.com/junegunn/fzf/src/protector"
) )
var version string = "0.47" var version string = "0.48"
var revision string = "devel" var revision string = "devel"
//go:embed shell/key-bindings.bash
var bashKeyBindings []byte
//go:embed shell/completion.bash
var bashCompletion []byte
//go:embed shell/key-bindings.zsh
var zshKeyBindings []byte
//go:embed shell/completion.zsh
var zshCompletion []byte
//go:embed shell/key-bindings.fish
var fishKeyBindings []byte
func printScript(label string, content []byte) {
fmt.Println("### " + label + " ###")
fmt.Println(strings.TrimSpace(string(content)))
fmt.Println("### end: " + label + " ###")
}
func main() { func main() {
protector.Protect() protector.Protect()
fzf.Run(fzf.ParseOptions(), version, revision) options := fzf.ParseOptions()
if options.Bash {
printScript("key-bindings.bash", bashKeyBindings)
printScript("completion.bash", bashCompletion)
return
}
if options.Zsh {
printScript("key-bindings.zsh", zshKeyBindings)
printScript("completion.zsh", zshCompletion)
return
}
if options.Fish {
printScript("key-bindings.fish", fishKeyBindings)
fmt.Println("fzf_key_bindings")
return
}
fzf.Run(options, version, revision)
} }

View File

@@ -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 "Mar 2024" "fzf 0.47.0" "fzf-tmux - open fzf in tmux split pane" .TH fzf-tmux 1 "Mar 2024" "fzf 0.48.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

View File

@@ -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 "Mar 2024" "fzf 0.47.0" "fzf - a command-line fuzzy finder" .TH fzf 1 "Mar 2024" "fzf 0.48.0" "fzf - a command-line fuzzy finder"
.SH NAME .SH NAME
fzf - a command-line fuzzy finder fzf - a command-line fuzzy finder
@@ -33,6 +33,10 @@ fzf [options]
fzf is a general-purpose command-line fuzzy finder. fzf is a general-purpose command-line fuzzy finder.
.SH OPTIONS .SH OPTIONS
.SS Note
.TP
Most long options have the opposite version with \fB--no-\fR prefix.
.SS Search mode .SS Search mode
.TP .TP
.B "-x, --extended" .B "-x, --extended"
@@ -620,7 +624,7 @@ The following example uses https://github.com/junegunn/fzf/blob/master/bin/fzf-p
script to render an image using either of the protocols inside the preview window. script to render an image using either of the protocols inside the preview window.
e.g. e.g.
\fBfzf --preview='fzf-preview.sh {}' \fBfzf --preview='fzf-preview.sh {}'\fR
.RE .RE
@@ -854,8 +858,49 @@ e.g.
.B "--version" .B "--version"
Display version information and exit Display version information and exit
.SS Directory traversal
.TP .TP
Note that most options have the opposite versions with \fB--no-\fR prefix. .B "--walker=[file][,dir][,follow][,hidden]"
Determines the behavior of the built-in directory walker that is used when
\fB$FZF_DEFAULT_COMMAND\fR is not set. The default value is \fBfile,follow,hidden\fR.
* \fBfile\fR: Include files in the search result
.br
* \fBdir\fR: Include directories in the search result
.br
* \fBhidden\fR: Include and follow hidden directories
.br
* \fBfollow\fR: Follow symbolic links
.br
.TP
.B "--walker-root=DIR"
The root directory from which to start the built-in directory walker.
The default value is the current working directory.
.TP
.B "--walker-skip=DIRS"
Comma-separated list of directory names to skip during the directory walk.
The default value is \fB.git,node_modules\fR.
.SS Shell integration
.TP
.B "--bash"
Print script to set up Bash shell integration
e.g. \fBeval "$(fzf --bash)"\fR
.TP
.B "--zsh"
Print script to set up Zsh shell integration
e.g. \fBeval "$(fzf --zsh)"\fR
.TP
.B "--fish"
Print script to set up Fish shell integration
e.g. \fBfzf --fish | source\fR
.SH ENVIRONMENT VARIABLES .SH ENVIRONMENT VARIABLES
.TP .TP

View File

@@ -13,22 +13,19 @@
# To use custom commands instead of find, override _fzf_compgen_{path,dir} # To use custom commands instead of find, override _fzf_compgen_{path,dir}
if ! declare -F _fzf_compgen_path > /dev/null; then #
_fzf_compgen_path() { # _fzf_compgen_path() {
echo "$1" # echo "$1"
command find -L "$1" \ # command find -L "$1" \
-name .git -prune -o -name .hg -prune -o -name .svn -prune -o \( -type d -o -type f -o -type l \) \ # -name .git -prune -o -name .hg -prune -o -name .svn -prune -o \( -type d -o -type f -o -type l \) \
-a -not -path "$1" -print 2> /dev/null | command sed 's@^\./@@' # -a -not -path "$1" -print 2> /dev/null | command sed 's@^\./@@'
} # }
fi #
# _fzf_compgen_dir() {
if ! declare -F _fzf_compgen_dir > /dev/null; then # command find -L "$1" \
_fzf_compgen_dir() { # -name .git -prune -o -name .hg -prune -o -name .svn -prune -o -type d \
command find -L "$1" \ # -a -not -path "$1" -print 2> /dev/null | command sed 's@^\./@@'
-name .git -prune -o -name .hg -prune -o -name .svn -prune -o -type d \ # }
-a -not -path "$1" -print 2> /dev/null | command sed 's@^\./@@'
}
fi
########################################################### ###########################################################
@@ -336,9 +333,18 @@ __fzf_generic_path_completion() {
leftover=${leftover/#\/} leftover=${leftover/#\/}
[[ -z "$dir" ]] && dir='.' [[ -z "$dir" ]] && dir='.'
[[ "$dir" != "/" ]] && dir="${dir/%\//}" [[ "$dir" != "/" ]] && dir="${dir/%\//}"
matches=$(eval "$1 $(printf %q "$dir")" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-} $2" __fzf_comprun "$4" -q "$leftover" | while read -r item; do matches=$(
printf "%q " "${item%$3}$3" unset FZF_DEFAULT_COMMAND
done) export FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-} $2"
if declare -F "$1" > /dev/null; then
eval "$1 $(printf %q "$dir")" | __fzf_comprun "$4" -q "$leftover"
else
[[ $1 =~ dir ]] && walker=dir,follow || walker=file,dir,follow,hidden
__fzf_comprun "$4" -q "$leftover" --walker "$walker" --walker-root="$dir"
fi | while read -r item; do
printf "%q " "${item%$3}$3"
done
)
matches=${matches% } matches=${matches% }
[[ -z "$3" ]] && [[ "${__fzf_nospace_commands-}" = *" ${COMP_WORDS[0]} "* ]] && matches="$matches " [[ -z "$3" ]] && [[ "${__fzf_nospace_commands-}" = *" ${COMP_WORDS[0]} "* ]] && matches="$matches "
if [[ -n "$matches" ]]; then if [[ -n "$matches" ]]; then
@@ -387,6 +393,7 @@ _fzf_complete() {
type -t "$post" > /dev/null 2>&1 || post='command cat' type -t "$post" > /dev/null 2>&1 || post='command cat'
trigger=${FZF_COMPLETION_TRIGGER-'**'} trigger=${FZF_COMPLETION_TRIGGER-'**'}
cmd="${COMP_WORDS[0]}"
cur="${COMP_WORDS[COMP_CWORD]}" cur="${COMP_WORDS[COMP_CWORD]}"
if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then
cur=${cur:0:${#cur}-${#trigger}} cur=${cur:0:${#cur}-${#trigger}}

View File

@@ -77,22 +77,19 @@ fi
{ {
# To use custom commands instead of find, override _fzf_compgen_{path,dir} # To use custom commands instead of find, override _fzf_compgen_{path,dir}
if ! declare -f _fzf_compgen_path > /dev/null; then #
_fzf_compgen_path() { # _fzf_compgen_path() {
echo "$1" # echo "$1"
command find -L "$1" \ # command find -L "$1" \
-name .git -prune -o -name .hg -prune -o -name .svn -prune -o \( -type d -o -type f -o -type l \) \ # -name .git -prune -o -name .hg -prune -o -name .svn -prune -o \( -type d -o -type f -o -type l \) \
-a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@' # -a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
} # }
fi #
# _fzf_compgen_dir() {
if ! declare -f _fzf_compgen_dir > /dev/null; then # command find -L "$1" \
_fzf_compgen_dir() { # -name .git -prune -o -name .hg -prune -o -name .svn -prune -o -type d \
command find -L "$1" \ # -a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
-name .git -prune -o -name .hg -prune -o -name .svn -prune -o -type d \ # }
-a -not -path "$1" -print 2> /dev/null | sed 's@^\./@@'
}
fi
########################################################### ###########################################################
@@ -148,10 +145,19 @@ __fzf_generic_path_completion() {
leftover=${leftover/#\/} leftover=${leftover/#\/}
[ -z "$dir" ] && dir='.' [ -z "$dir" ] && dir='.'
[ "$dir" != "/" ] && dir="${dir/%\//}" [ "$dir" != "/" ] && dir="${dir/%\//}"
matches=$(eval "$compgen $(printf %q "$dir")" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-}" __fzf_comprun "$cmd" ${(Q)${(Z+n+)fzf_opts}} -q "$leftover" | while read item; do matches=$(
item="${item%$suffix}$suffix" unset FZF_DEFAULT_COMMAND
echo -n "${(q)item} " export FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_COMPLETION_OPTS-}"
done) if declare -f "$compgen" > /dev/null; then
eval "$compgen $(printf %q "$dir")" | __fzf_comprun "$cmd" ${(Q)${(Z+n+)fzf_opts}} -q "$leftover"
else
[[ $compgen =~ dir ]] && walker=dir,follow || walker=file,dir,follow,hidden
__fzf_comprun "$cmd" ${(Q)${(Z+n+)fzf_opts}} -q "$leftover" --walker "$walker" --walker-root="$dir" < /dev/tty
fi | while read item; do
item="${item%$suffix}$suffix"
echo -n "${(q)item} "
done
)
matches=${matches% } matches=${matches% }
if [ -n "$matches" ]; then if [ -n "$matches" ]; then
LBUFFER="$lbuf$matches$tail" LBUFFER="$lbuf$matches$tail"

View File

@@ -17,14 +17,9 @@
# Key bindings # Key bindings
# ------------ # ------------
__fzf_select__() { __fzf_select__() {
local cmd opts local opts
cmd="${FZF_CTRL_T_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \ opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse --walker=file,dir,follow,hidden --scheme=path ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-} -m"
-o -type f -print \ FZF_DEFAULT_COMMAND=${FZF_CTRL_T_COMMAND:-} FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) "$@" |
-o -type d -print \
-o -type l -print 2> /dev/null | command cut -b3-"}"
opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse --scheme=path ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-} -m"
eval "$cmd" |
FZF_DEFAULT_OPTS="$opts" $(__fzfcmd) "$@" |
while read -r item; do while read -r item; do
printf '%q ' "$item" # escape special chars printf '%q ' "$item" # escape special chars
done done
@@ -42,11 +37,11 @@ fzf-file-widget() {
} }
__fzf_cd__() { __fzf_cd__() {
local cmd opts dir local opts dir
cmd="${FZF_ALT_C_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \ opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse --walker=dir,follow,hidden --scheme=path ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-} +m"
-o -type d -print 2> /dev/null | command cut -b3-"}" dir=$(
opts="--height ${FZF_TMUX_HEIGHT:-40%} --bind=ctrl-z:ignore --reverse --scheme=path ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-} +m" FZF_DEFAULT_COMMAND=${FZF_ALT_C_COMMAND:-} FZF_DEFAULT_OPTS="$opts" $(__fzfcmd)
dir=$(set +o pipefail; eval "$cmd" | FZF_DEFAULT_OPTS="$opts" $(__fzfcmd)) && printf 'builtin cd -- %q' "$dir" ) && printf 'builtin cd -- %q' "$dir"
} }
if command -v perl > /dev/null; then if command -v perl > /dev/null; then

View File

@@ -25,18 +25,11 @@ function fzf_key_bindings
set -l fzf_query $commandline[2] set -l fzf_query $commandline[2]
set -l prefix $commandline[3] set -l prefix $commandline[3]
# "-path \$dir'*/.*'" matches hidden files/folders inside $dir but not
# $dir itself, even if hidden.
test -n "$FZF_CTRL_T_COMMAND"; or set -l FZF_CTRL_T_COMMAND "
command find -L \$dir -mindepth 1 \\( -path \$dir'*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \
-o -type f -print \
-o -type d -print \
-o -type l -print 2> /dev/null | sed 's@^\./@@'"
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --scheme=path --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --walker=file,dir,follow,hidden --scheme=path --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS"
eval "$FZF_CTRL_T_COMMAND | "(__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r; set result $result $r; end set -lx FZF_DEFAULT_COMMAND "$FZF_CTRL_T_COMMAND"
eval (__fzfcmd)' -m --query "'$fzf_query'"' | while read -l r; set result $result $r; end
end end
if [ -z "$result" ] if [ -z "$result" ]
commandline -f repaint commandline -f repaint
@@ -81,13 +74,11 @@ function fzf_key_bindings
set -l fzf_query $commandline[2] set -l fzf_query $commandline[2]
set -l prefix $commandline[3] set -l prefix $commandline[3]
test -n "$FZF_ALT_C_COMMAND"; or set -l FZF_ALT_C_COMMAND "
command find -L \$dir -mindepth 1 \\( -path \$dir'*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' \\) -prune \
-o -type d -print 2> /dev/null | sed 's@^\./@@'"
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40% test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --scheme=path --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS" set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT --reverse --walker=dir,follow,hidden --scheme=path --bind=ctrl-z:ignore $FZF_DEFAULT_OPTS $FZF_ALT_C_OPTS"
eval "$FZF_ALT_C_COMMAND | "(__fzfcmd)' +m --query "'$fzf_query'"' | read -l result set -lx FZF_DEFAULT_COMMAND "$FZF_ALT_C_COMMAND"
eval (__fzfcmd)' +m --query "'$fzf_query'"' | read -l result
if [ -n "$result" ] if [ -n "$result" ]
cd -- $result cd -- $result

View File

@@ -41,13 +41,9 @@ fi
# CTRL-T - Paste the selected file path(s) into the command line # CTRL-T - Paste the selected file path(s) into the command line
__fsel() { __fsel() {
local cmd="${FZF_CTRL_T_COMMAND:-"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 d -print \
-o -type l -print 2> /dev/null | cut -b3-"}"
setopt localoptions pipefail no_aliases 2> /dev/null setopt localoptions pipefail no_aliases 2> /dev/null
local item local item
eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-}" $(__fzfcmd) -m "$@" | while read item; do FZF_DEFAULT_COMMAND=${FZF_CTRL_T_COMMAND:-} FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --walker=file,dir,follow,hidden --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_CTRL_T_OPTS-}" $(__fzfcmd) -m "$@" < /dev/tty | while read item; do
echo -n "${(q)item} " echo -n "${(q)item} "
done done
local ret=$? local ret=$?
@@ -73,10 +69,8 @@ bindkey -M viins '^T' fzf-file-widget
# ALT-C - cd into the selected directory # ALT-C - cd into the selected directory
fzf-cd-widget() { fzf-cd-widget() {
local cmd="${FZF_ALT_C_COMMAND:-"command find -L . -mindepth 1 \\( -path '*/.*' -o -fstype 'sysfs' -o -fstype 'devfs' -o -fstype 'devtmpfs' -o -fstype 'proc' \\) -prune \
-o -type d -print 2> /dev/null | cut -b3-"}"
setopt localoptions pipefail no_aliases 2> /dev/null setopt localoptions pipefail no_aliases 2> /dev/null
local dir="$(eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-}" $(__fzfcmd) +m)" local dir="$(FZF_DEFAULT_COMMAND=${FZF_ALT_C_COMMAND:-} FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse --walker=dir,follow,hidden --scheme=path --bind=ctrl-z:ignore ${FZF_DEFAULT_OPTS-} ${FZF_ALT_C_OPTS-}" $(__fzfcmd) +m < /dev/tty)"
if [[ -z "$dir" ]]; then if [[ -z "$dir" ]]; then
zle redisplay zle redisplay
return 0 return 0

View File

@@ -117,7 +117,7 @@ func Run(opts *Options, version string, revision string) {
reader = NewReader(func(data []byte) bool { reader = NewReader(func(data []byte) bool {
return chunkList.Push(data) return chunkList.Push(data)
}, eventBox, opts.ReadZero, opts.Filter == nil) }, eventBox, opts.ReadZero, opts.Filter == nil)
go reader.ReadSource() go reader.ReadSource(opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
} }
// Matcher // Matcher
@@ -165,7 +165,7 @@ func Run(opts *Options, version string, revision string) {
} }
return false return false
}, eventBox, opts.ReadZero, false) }, eventBox, opts.ReadZero, false)
reader.ReadSource() reader.ReadSource(opts.WalkerRoot, opts.WalkerOpts, opts.WalkerSkip)
} else { } else {
eventBox.Unwatch(EvtReadNew) eventBox.Unwatch(EvtReadNew)
eventBox.WaitFor(EvtReadFin) eventBox.WaitFor(EvtReadFin)

View File

@@ -124,6 +124,17 @@ const usage = `usage: fzf [options]
(To allow remote process execution, use --listen-unsafe) (To allow remote process execution, use --listen-unsafe)
--version Display version information and exit --version Display version information and exit
Directory traversal (Only used when $FZF_DEFAULT_COMMAND is not set)
--walker=OPTS [file][,dir][,follow][,hidden] (default: file,follow,hidden)
--walker-root=DIR Root directory from which to start walker (default: .)
--walker-skip=DIRS Comma-separated list of directory names to skip
(default: .git,node_modules)
Shell integration
--bash Print script to set up Bash shell integration
--zsh Print script to set up Zsh shell integration
--fish Print script to set up Fish shell integration
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 (e.g. '--layout=reverse --info=inline') FZF_DEFAULT_OPTS Default options (e.g. '--layout=reverse --info=inline')
@@ -274,8 +285,18 @@ func firstLine(s string) string {
return strings.SplitN(s, "\n", 2)[0] return strings.SplitN(s, "\n", 2)[0]
} }
type walkerOpts struct {
file bool
dir bool
hidden bool
follow bool
}
// Options stores the values of command-line options // Options stores the values of command-line options
type Options struct { type Options struct {
Bash bool
Zsh bool
Fish bool
Fuzzy bool Fuzzy bool
FuzzyAlgo algo.Algo FuzzyAlgo algo.Algo
Scheme string Scheme string
@@ -342,15 +363,31 @@ type Options struct {
ListenAddr *listenAddress ListenAddr *listenAddress
Unsafe bool Unsafe bool
ClearOnExit bool ClearOnExit bool
WalkerOpts walkerOpts
WalkerRoot string
WalkerSkip []string
Version bool Version bool
} }
func filterNonEmpty(input []string) []string {
output := make([]string, 0, len(input))
for _, str := range input {
if len(str) > 0 {
output = append(output, str)
}
}
return output
}
func defaultPreviewOpts(command string) previewOpts { func defaultPreviewOpts(command string) previewOpts {
return previewOpts{command, posRight, sizeSpec{50, true}, "", false, false, false, false, tui.DefaultBorderShape, 0, 0, nil} return previewOpts{command, posRight, sizeSpec{50, true}, "", false, false, false, false, tui.DefaultBorderShape, 0, 0, nil}
} }
func defaultOptions() *Options { func defaultOptions() *Options {
return &Options{ return &Options{
Bash: false,
Zsh: false,
Fish: false,
Fuzzy: true, Fuzzy: true,
FuzzyAlgo: algo.FuzzyMatchV2, FuzzyAlgo: algo.FuzzyMatchV2,
Scheme: "default", Scheme: "default",
@@ -413,6 +450,9 @@ func defaultOptions() *Options {
PreviewLabel: labelOpts{}, PreviewLabel: labelOpts{},
Unsafe: false, Unsafe: false,
ClearOnExit: true, ClearOnExit: true,
WalkerOpts: walkerOpts{file: true, hidden: true, follow: true},
WalkerRoot: ".",
WalkerSkip: []string{".git", "node_modules"},
Version: false} Version: false}
} }
@@ -966,6 +1006,30 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) *tui.ColorTheme {
return theme return theme
} }
func parseWalkerOpts(str string) walkerOpts {
opts := walkerOpts{}
for _, str := range strings.Split(strings.ToLower(str), ",") {
switch str {
case "file":
opts.file = true
case "dir":
opts.dir = true
case "hidden":
opts.hidden = true
case "follow":
opts.follow = true
case "":
// Ignored
default:
errorExit("invalid walker option: " + str)
}
}
if !opts.file && !opts.dir {
errorExit("at least one of 'file' or 'dir' should be specified")
}
return opts
}
var ( var (
executeRegexp *regexp.Regexp executeRegexp *regexp.Regexp
splitRegexp *regexp.Regexp splitRegexp *regexp.Regexp
@@ -1602,6 +1666,21 @@ func parseOptions(opts *Options, allArgs []string) {
for i := 0; i < len(allArgs); i++ { for i := 0; i < len(allArgs); i++ {
arg := allArgs[i] arg := allArgs[i]
switch arg { switch arg {
case "--bash":
opts.Bash = true
if opts.Zsh || opts.Fish {
errorExit("cannot specify --bash with --zsh or --fish")
}
case "--zsh":
opts.Zsh = true
if opts.Bash || opts.Fish {
errorExit("cannot specify --zsh with --bash or --fish")
}
case "--fish":
opts.Fish = true
if opts.Bash || opts.Zsh {
errorExit("cannot specify --fish with --bash or --zsh")
}
case "-h", "--help": case "-h", "--help":
help(exitOk) help(exitOk)
case "-x", "--extended": case "-x", "--extended":
@@ -1880,6 +1959,12 @@ func parseOptions(opts *Options, allArgs []string) {
opts.ClearOnExit = true opts.ClearOnExit = true
case "--no-clear": case "--no-clear":
opts.ClearOnExit = false opts.ClearOnExit = false
case "--walker":
opts.WalkerOpts = parseWalkerOpts(nextString(allArgs, &i, "walker options required [file][,dir][,follow][,hidden]"))
case "--walker-root":
opts.WalkerRoot = nextString(allArgs, &i, "directory required")
case "--walker-skip":
opts.WalkerSkip = filterNonEmpty(strings.Split(nextString(allArgs, &i, "directory names to ignore required"), ","))
case "--version": case "--version":
opts.Version = true opts.Version = true
case "--": case "--":
@@ -1977,6 +2062,12 @@ func parseOptions(opts *Options, allArgs []string) {
} }
opts.ListenAddr = &addr opts.ListenAddr = &addr
opts.Unsafe = true opts.Unsafe = true
} else if match, value := optString(arg, "--walker="); match {
opts.WalkerOpts = parseWalkerOpts(value)
} else if match, value := optString(arg, "--walker-root="); match {
opts.WalkerRoot = value
} else if match, value := optString(arg, "--walker-skip="); match {
opts.WalkerSkip = filterNonEmpty(strings.Split(value, ","))
} else if match, value := optString(arg, "--hscroll-off="); match { } else if match, value := optString(arg, "--hscroll-off="); match {
opts.HscrollOff = atoi(value) opts.HscrollOff = atoi(value)
} else if match, value := optString(arg, "--scroll-off="); match { } else if match, value := optString(arg, "--scroll-off="); match {

View File

@@ -93,13 +93,13 @@ func (r *Reader) restart(command string, environ []string) {
} }
// ReadSource reads data from the default command or from standard input // ReadSource reads data from the default command or from standard input
func (r *Reader) ReadSource() { func (r *Reader) ReadSource(root string, opts walkerOpts, ignores []string) {
r.startEventPoller() r.startEventPoller()
var success bool var success bool
if util.IsTty() { if util.IsTty() {
cmd := os.Getenv("FZF_DEFAULT_COMMAND") cmd := os.Getenv("FZF_DEFAULT_COMMAND")
if len(cmd) == 0 { if len(cmd) == 0 {
success = r.readFiles() success = r.readFiles(root, opts, ignores)
} else { } else {
// We can't export FZF_* environment variables to the default command // We can't export FZF_* environment variables to the default command
success = r.readFromCommand(cmd, nil) success = r.readFromCommand(cmd, nil)
@@ -145,9 +145,9 @@ func (r *Reader) readFromStdin() bool {
return true return true
} }
func (r *Reader) readFiles() bool { func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string) bool {
r.killed = false r.killed = false
conf := fastwalk.Config{Follow: true} conf := fastwalk.Config{Follow: opts.follow}
fn := func(path string, de os.DirEntry, err error) error { fn := func(path string, de os.DirEntry, err error) error {
if err != nil { if err != nil {
return nil return nil
@@ -155,10 +155,18 @@ func (r *Reader) readFiles() bool {
path = filepath.Clean(path) path = filepath.Clean(path)
if path != "." { if path != "." {
isDir := de.IsDir() isDir := de.IsDir()
if isDir && filepath.Base(path)[0] == '.' { if isDir {
return filepath.SkipDir base := filepath.Base(path)
if !opts.hidden && base[0] == '.' {
return filepath.SkipDir
}
for _, ignore := range ignores {
if ignore == base {
return filepath.SkipDir
}
}
} }
if !isDir && r.pusher([]byte(path)) { if ((opts.file && !isDir) || (opts.dir && isDir)) && r.pusher([]byte(path)) {
atomic.StoreInt32(&r.event, int32(EvtReadNew)) atomic.StoreInt32(&r.event, int32(EvtReadNew))
} }
} }
@@ -169,7 +177,7 @@ func (r *Reader) readFiles() bool {
} }
return nil return nil
} }
return fastwalk.Walk(&conf, ".", fn) == nil return fastwalk.Walk(&conf, root, fn) == nil
} }
func (r *Reader) readFromCommand(command string, environ []string) bool { func (r *Reader) readFromCommand(command string, environ []string) bool {

View File

@@ -94,6 +94,7 @@ done
bind_file="${fish_dir}/functions/fish_user_key_bindings.fish" bind_file="${fish_dir}/functions/fish_user_key_bindings.fish"
if [ -f "$bind_file" ]; then if [ -f "$bind_file" ]; then
remove_line "$bind_file" "fzf_key_bindings" remove_line "$bind_file" "fzf_key_bindings"
remove_line "$bind_file" "fzf --fish | source"
fi fi
if [ -d "${fish_dir}/functions" ]; then if [ -d "${fish_dir}/functions" ]; then