mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-10 12:23:48 -05:00
Compare commits
1 Commits
v0.56.0
...
leverage-b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38040d43e4 |
2
.github/workflows/typos.yml
vendored
2
.github/workflows/typos.yml
vendored
@@ -7,4 +7,4 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: crate-ci/typos@v1.26.0
|
- uses: crate-ci/typos@v1.24.1
|
||||||
|
|||||||
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,24 +1,6 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
0.56.0
|
|
||||||
------
|
|
||||||
- Added `--gap[=N]` option to display empty lines between items.
|
|
||||||
- This can be useful to visually separate adjacent multi-line items.
|
|
||||||
```sh
|
|
||||||
# All bash functions, highlighted
|
|
||||||
declare -f | perl -0777 -pe 's/^}\n/}\0/gm' |
|
|
||||||
bat --plain --language bash --color always |
|
|
||||||
fzf --read0 --ansi --reverse --multi --highlight-line --gap
|
|
||||||
```
|
|
||||||
- Or just to make the list easier to read. For single-line items, you probably want to set `--color gutter:-1` as well to hide the gutter.
|
|
||||||
```sh
|
|
||||||
fzf --info inline-right --gap --color gutter:-1
|
|
||||||
```
|
|
||||||
- Added `noinfo` option to `--preview-window` to hide the scroll indicator in the preview window
|
|
||||||
- Bug fixes
|
|
||||||
- Thanks to @LangLangBart, @akinomyoga, and @charlievieth for fixing the bugs
|
|
||||||
|
|
||||||
0.55.0
|
0.55.0
|
||||||
------
|
------
|
||||||
_Release highlights: https://junegunn.github.io/fzf/releases/0.55.0/_
|
_Release highlights: https://junegunn.github.io/fzf/releases/0.55.0/_
|
||||||
|
|||||||
6
go.mod
6
go.mod
@@ -1,13 +1,13 @@
|
|||||||
module github.com/junegunn/fzf
|
module github.com/junegunn/fzf
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/charlievieth/fastwalk v1.0.9
|
github.com/charlievieth/fastwalk v1.0.8
|
||||||
github.com/gdamore/tcell/v2 v2.7.4
|
github.com/gdamore/tcell/v2 v2.7.4
|
||||||
github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97
|
github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97
|
||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/rivo/uniseg v0.4.7
|
github.com/rivo/uniseg v0.4.7
|
||||||
golang.org/x/sys v0.26.0
|
golang.org/x/sys v0.25.0
|
||||||
golang.org/x/term v0.25.0
|
golang.org/x/term v0.24.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
12
go.sum
12
go.sum
@@ -1,5 +1,5 @@
|
|||||||
github.com/charlievieth/fastwalk v1.0.9 h1:Odb92AfoReO3oFBfDGT5J+nwgzQPF/gWAw6E6/lkor0=
|
github.com/charlievieth/fastwalk v1.0.8 h1:uaoH6cAKSk73aK7aKXqs0+bL+J3Txzd3NGH8tRXgHko=
|
||||||
github.com/charlievieth/fastwalk v1.0.9/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI=
|
github.com/charlievieth/fastwalk v1.0.8/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI=
|
||||||
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.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
|
github.com/gdamore/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
|
||||||
@@ -36,14 +36,14 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.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/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.25.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/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||||
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.56.0
|
version=0.55.0
|
||||||
auto_completion=
|
auto_completion=
|
||||||
key_bindings=
|
key_bindings=
|
||||||
update_config=2
|
update_config=2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
$version="0.56.0"
|
$version="0.55.0"
|
||||||
|
|
||||||
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||||
|
|
||||||
|
|||||||
2
main.go
2
main.go
@@ -11,7 +11,7 @@ import (
|
|||||||
"github.com/junegunn/fzf/src/protector"
|
"github.com/junegunn/fzf/src/protector"
|
||||||
)
|
)
|
||||||
|
|
||||||
var version = "0.56"
|
var version = "0.55"
|
||||||
var revision = "devel"
|
var revision = "devel"
|
||||||
|
|
||||||
//go:embed shell/key-bindings.bash
|
//go:embed shell/key-bindings.bash
|
||||||
|
|||||||
@@ -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 "Oct 2024" "fzf 0.56.0" "fzf\-tmux - open fzf in tmux split pane"
|
.TH fzf\-tmux 1 "Aug 2024" "fzf 0.55.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 "Oct 2024" "fzf 0.56.0" "fzf - a command-line fuzzy finder"
|
.TH fzf 1 "Sep 2024" "fzf 0.56.0" "fzf - a command-line fuzzy finder"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
fzf - a command-line fuzzy finder
|
fzf - a command-line fuzzy finder
|
||||||
@@ -208,9 +208,6 @@ Indicator for wrapped lines. The default is '↳ ' or '> ' depending on
|
|||||||
.B "\-\-no\-multi\-line"
|
.B "\-\-no\-multi\-line"
|
||||||
Disable multi-line display of items when using \fB\-\-read0\fR
|
Disable multi-line display of items when using \fB\-\-read0\fR
|
||||||
.TP
|
.TP
|
||||||
.BI "\-\-gap" "[=N]"
|
|
||||||
Render empty lines between each item
|
|
||||||
.TP
|
|
||||||
.B "\-\-keep\-right"
|
.B "\-\-keep\-right"
|
||||||
Keep the right end of the line visible when it's too long. Effective only when
|
Keep the right end of the line visible when it's too long. Effective only when
|
||||||
the query string is empty.
|
the query string is empty.
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ _fzf_handle_dynamic_completion() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__fzf_generic_path_completion() {
|
__fzf_generic_path_completion() {
|
||||||
local cur base dir leftover matches trigger cmd
|
local cur base dir leftover matches trigger cmd rest
|
||||||
cmd="${COMP_WORDS[0]}"
|
cmd="${COMP_WORDS[0]}"
|
||||||
if [[ $cmd == \\* ]]; then
|
if [[ $cmd == \\* ]]; then
|
||||||
cmd="${cmd:1}"
|
cmd="${cmd:1}"
|
||||||
@@ -295,6 +295,16 @@ __fzf_generic_path_completion() {
|
|||||||
base=${cur:0:${#cur}-${#trigger}}
|
base=${cur:0:${#cur}-${#trigger}}
|
||||||
eval "base=$base" 2> /dev/null || return
|
eval "base=$base" 2> /dev/null || return
|
||||||
|
|
||||||
|
# Try to leverage existing completion
|
||||||
|
rest=("${@:4}")
|
||||||
|
unset 'rest[${#rest[@]}-2]'
|
||||||
|
COMP_LINE=${COMP_LINE:0:${#COMP_LINE}-${#trigger}}
|
||||||
|
COMP_POINT=$((COMP_POINT-${#trigger}))
|
||||||
|
COMP_WORDS[$COMP_CWORD]=$base
|
||||||
|
_fzf_handle_dynamic_completion "$cmd" "${rest[@]}"
|
||||||
|
[[ $? -ne 0 ]] &&
|
||||||
|
_fzf_handle_dynamic_completion "$cmd" "${rest[@]}"
|
||||||
|
|
||||||
dir=
|
dir=
|
||||||
[[ $base = *"/"* ]] && dir="$base"
|
[[ $base = *"/"* ]] && dir="$base"
|
||||||
while true; do
|
while true; do
|
||||||
@@ -306,7 +316,11 @@ __fzf_generic_path_completion() {
|
|||||||
matches=$(
|
matches=$(
|
||||||
export FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-} $2")
|
export FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse --scheme=path" "${FZF_COMPLETION_OPTS-} $2")
|
||||||
unset FZF_DEFAULT_COMMAND FZF_DEFAULT_OPTS_FILE
|
unset FZF_DEFAULT_COMMAND FZF_DEFAULT_OPTS_FILE
|
||||||
if declare -F "$1" > /dev/null; then
|
if [[ ${#COMPREPLY[@]} -gt 0 ]]; then
|
||||||
|
for h in "${COMPREPLY[@]}"; do
|
||||||
|
echo "$h"
|
||||||
|
done | command sort -u | __fzf_comprun "$4" -q "$leftover"
|
||||||
|
elif declare -F "$1" > /dev/null; then
|
||||||
eval "$1 $(printf %q "$dir")" | __fzf_comprun "$4" -q "$leftover"
|
eval "$1 $(printf %q "$dir")" | __fzf_comprun "$4" -q "$leftover"
|
||||||
else
|
else
|
||||||
if [[ $1 =~ dir ]]; then
|
if [[ $1 =~ dir ]]; then
|
||||||
@@ -374,10 +388,23 @@ _fzf_complete() {
|
|||||||
if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then
|
if [[ "$cur" == *"$trigger" ]] && [[ $cur != *'$('* ]] && [[ $cur != *':='* ]] && [[ $cur != *'`'* ]]; then
|
||||||
cur=${cur:0:${#cur}-${#trigger}}
|
cur=${cur:0:${#cur}-${#trigger}}
|
||||||
|
|
||||||
|
# Try to leverage existing completion
|
||||||
|
COMP_LINE=${COMP_LINE:0:${#COMP_LINE}-${#trigger}}
|
||||||
|
COMP_POINT=$((COMP_POINT-${#trigger}))
|
||||||
|
unset 'rest[${#rest[@]}-2]'
|
||||||
|
_fzf_handle_dynamic_completion "$cmd" "${rest[@]}"
|
||||||
|
[[ $? -ne 0 ]] &&
|
||||||
|
_fzf_handle_dynamic_completion "$cmd" "${rest[@]}"
|
||||||
|
|
||||||
selected=$(
|
selected=$(
|
||||||
|
(if [[ ${#COMPREPLY[@]} -gt 0 ]]; then
|
||||||
|
for h in "${COMPREPLY[@]}"; do
|
||||||
|
echo "$h"
|
||||||
|
done
|
||||||
|
fi; cat) | command sort -u |
|
||||||
FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse" "${FZF_COMPLETION_OPTS-} $str_arg") \
|
FZF_DEFAULT_OPTS=$(__fzf_defaults "--reverse" "${FZF_COMPLETION_OPTS-} $str_arg") \
|
||||||
FZF_DEFAULT_OPTS_FILE='' \
|
FZF_DEFAULT_OPTS_FILE='' \
|
||||||
__fzf_comprun "${rest[0]}" "${args[@]}" -q "$cur" | eval "$post" | command tr '\n' ' ')
|
__fzf_comprun "${rest[0]}" "${args[@]}" -q "$cur" | $post | command tr '\n' ' ')
|
||||||
selected=${selected% } # Strip trailing space not to repeat "-o nospace"
|
selected=${selected% } # Strip trailing space not to repeat "-o nospace"
|
||||||
if [[ -n "$selected" ]]; then
|
if [[ -n "$selected" ]]; then
|
||||||
COMPREPLY=("$selected")
|
COMPREPLY=("$selected")
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ func (m *Matcher) Loop() {
|
|||||||
if !cacheCleared {
|
if !cacheCleared {
|
||||||
if count == prevCount {
|
if count == prevCount {
|
||||||
// Look up mergerCache
|
// Look up mergerCache
|
||||||
if cached, found := m.mergerCache[patternString]; found && cached.final == request.final {
|
if cached, found := m.mergerCache[patternString]; found {
|
||||||
merger = cached
|
merger = cached
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ Usage: fzf [options]
|
|||||||
--wrap Enable line wrap
|
--wrap Enable line wrap
|
||||||
--wrap-sign=STR Indicator for wrapped lines
|
--wrap-sign=STR Indicator for wrapped lines
|
||||||
--no-multi-line Disable multi-line display of items when using --read0
|
--no-multi-line Disable multi-line display of items when using --read0
|
||||||
--gap[=N] Render empty lines between each item
|
|
||||||
--keep-right Keep the right end of the line visible on overflow
|
--keep-right Keep the right end of the line visible on overflow
|
||||||
--scroll-off=LINES Number of screen lines to keep above or below when
|
--scroll-off=LINES Number of screen lines to keep above or below when
|
||||||
scrolling to the top or to the bottom (default: 0)
|
scrolling to the top or to the bottom (default: 0)
|
||||||
@@ -474,7 +473,6 @@ type Options struct {
|
|||||||
Header []string
|
Header []string
|
||||||
HeaderLines int
|
HeaderLines int
|
||||||
HeaderFirst bool
|
HeaderFirst bool
|
||||||
Gap int
|
|
||||||
Ellipsis *string
|
Ellipsis *string
|
||||||
Scrollbar *string
|
Scrollbar *string
|
||||||
Margin [4]sizeSpec
|
Margin [4]sizeSpec
|
||||||
@@ -581,7 +579,6 @@ func defaultOptions() *Options {
|
|||||||
Header: make([]string, 0),
|
Header: make([]string, 0),
|
||||||
HeaderLines: 0,
|
HeaderLines: 0,
|
||||||
HeaderFirst: false,
|
HeaderFirst: false,
|
||||||
Gap: 0,
|
|
||||||
Ellipsis: nil,
|
Ellipsis: nil,
|
||||||
Scrollbar: nil,
|
Scrollbar: nil,
|
||||||
Margin: defaultMargin(),
|
Margin: defaultMargin(),
|
||||||
@@ -2346,12 +2343,6 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
opts.HeaderFirst = true
|
opts.HeaderFirst = true
|
||||||
case "--no-header-first":
|
case "--no-header-first":
|
||||||
opts.HeaderFirst = false
|
opts.HeaderFirst = false
|
||||||
case "--gap":
|
|
||||||
if opts.Gap, err = optionalNumeric(allArgs, &i, 1); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
case "--no-gap":
|
|
||||||
opts.Gap = 0
|
|
||||||
case "--ellipsis":
|
case "--ellipsis":
|
||||||
str, err := nextString(allArgs, &i, "ellipsis string required")
|
str, err := nextString(allArgs, &i, "ellipsis string required")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -2639,10 +2630,6 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
|
|||||||
if opts.HeaderLines, err = atoi(value); err != nil {
|
if opts.HeaderLines, err = atoi(value); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if match, value := optString(arg, "--gap="); match {
|
|
||||||
if opts.Gap, err = atoi(value); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else if match, value := optString(arg, "--ellipsis="); match {
|
} else if match, value := optString(arg, "--ellipsis="); match {
|
||||||
str := firstLine(value)
|
str := firstLine(value)
|
||||||
opts.Ellipsis = &str
|
opts.Ellipsis = &str
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string) bool
|
|||||||
isDir := de.IsDir()
|
isDir := de.IsDir()
|
||||||
if isDir || opts.follow && isSymlinkToDir(path, de) {
|
if isDir || opts.follow && isSymlinkToDir(path, de) {
|
||||||
base := filepath.Base(path)
|
base := filepath.Base(path)
|
||||||
if !opts.hidden && base[0] == '.' && base != ".." {
|
if !opts.hidden && base[0] == '.' {
|
||||||
return filepath.SkipDir
|
return filepath.SkipDir
|
||||||
}
|
}
|
||||||
for _, ignore := range ignores {
|
for _, ignore := range ignores {
|
||||||
|
|||||||
@@ -245,7 +245,6 @@ type Terminal struct {
|
|||||||
hscroll bool
|
hscroll bool
|
||||||
hscrollOff int
|
hscrollOff int
|
||||||
scrollOff int
|
scrollOff int
|
||||||
gap int
|
|
||||||
wordRubout string
|
wordRubout string
|
||||||
wordNext string
|
wordNext string
|
||||||
cx int
|
cx int
|
||||||
@@ -826,7 +825,6 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
|
|||||||
headerVisible: true,
|
headerVisible: true,
|
||||||
headerFirst: opts.HeaderFirst,
|
headerFirst: opts.HeaderFirst,
|
||||||
headerLines: opts.HeaderLines,
|
headerLines: opts.HeaderLines,
|
||||||
gap: opts.Gap,
|
|
||||||
header: []string{},
|
header: []string{},
|
||||||
header0: opts.Header,
|
header0: opts.Header,
|
||||||
ansi: opts.Ansi,
|
ansi: opts.Ansi,
|
||||||
@@ -1138,23 +1136,15 @@ func (t *Terminal) wrapCols() int {
|
|||||||
return util.Max(t.window.Width()-(t.pointerLen+t.markerLen+1), 1)
|
return util.Max(t.window.Width()-(t.pointerLen+t.markerLen+1), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of lines the item takes including the gap
|
|
||||||
func (t *Terminal) numItemLines(item *Item, atMost int) (int, bool) {
|
func (t *Terminal) numItemLines(item *Item, atMost int) (int, bool) {
|
||||||
var numLines int
|
|
||||||
if !t.wrap && !t.multiLine {
|
if !t.wrap && !t.multiLine {
|
||||||
numLines = 1 + t.gap
|
return 1, false
|
||||||
return numLines, numLines > atMost
|
|
||||||
}
|
}
|
||||||
var overflow bool
|
|
||||||
if !t.wrap && t.multiLine {
|
if !t.wrap && t.multiLine {
|
||||||
numLines, overflow = item.text.NumLines(atMost)
|
return item.text.NumLines(atMost)
|
||||||
} else {
|
|
||||||
var lines [][]rune
|
|
||||||
lines, overflow = item.text.Lines(t.multiLine, atMost, t.wrapCols(), t.wrapSignWidth, t.tabstop)
|
|
||||||
numLines = len(lines)
|
|
||||||
}
|
}
|
||||||
numLines += t.gap
|
lines, overflow := item.text.Lines(t.multiLine, atMost, t.wrapCols(), t.wrapSignWidth, t.tabstop)
|
||||||
return numLines, overflow || numLines > atMost
|
return len(lines), overflow
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) itemLines(item *Item, atMost int) ([][]rune, bool) {
|
func (t *Terminal) itemLines(item *Item, atMost int) ([][]rune, bool) {
|
||||||
@@ -2060,21 +2050,6 @@ func (t *Terminal) printHeader() {
|
|||||||
t.wrap = wrap
|
t.wrap = wrap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Terminal) canSpanMultiLines() bool {
|
|
||||||
return t.multiLine || t.wrap || t.gap > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Terminal) renderEmptyLine(line int, barRange [2]int) {
|
|
||||||
t.move(line, 0, true)
|
|
||||||
t.markEmptyLine(line)
|
|
||||||
// If the screen is not filled with the list in non-multi-line mode,
|
|
||||||
// scrollbar is not visible at all. But in multi-line mode, we may need
|
|
||||||
// to redraw the scrollbar character at the end.
|
|
||||||
if t.canSpanMultiLines() {
|
|
||||||
t.prevLines[line].hasBar = t.printBar(line, true, barRange)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Terminal) printList() {
|
func (t *Terminal) printList() {
|
||||||
t.constrain()
|
t.constrain()
|
||||||
barLength, barStart := t.getScrollbar()
|
barLength, barStart := t.getScrollbar()
|
||||||
@@ -2095,7 +2070,14 @@ func (t *Terminal) printList() {
|
|||||||
item := t.merger.Get(itemCount + t.offset)
|
item := t.merger.Get(itemCount + t.offset)
|
||||||
line = t.printItem(item, line, maxy, itemCount, itemCount == t.cy-t.offset, barRange)
|
line = t.printItem(item, line, maxy, itemCount, itemCount == t.cy-t.offset, barRange)
|
||||||
} else if !t.prevLines[line].empty {
|
} else if !t.prevLines[line].empty {
|
||||||
t.renderEmptyLine(line, barRange)
|
t.move(line, 0, true)
|
||||||
|
t.markEmptyLine(line)
|
||||||
|
// If the screen is not filled with the list in non-multi-line mode,
|
||||||
|
// scrollbar is not visible at all. But in multi-line mode, we may need
|
||||||
|
// to redraw the scrollbar character at the end.
|
||||||
|
if t.multiLine || t.wrap {
|
||||||
|
t.prevLines[line].hasBar = t.printBar(line, true, barRange)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2143,6 +2125,9 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
|||||||
prevLine.queryLen == newLine.queryLen &&
|
prevLine.queryLen == newLine.queryLen &&
|
||||||
prevLine.result == newLine.result {
|
prevLine.result == newLine.result {
|
||||||
t.prevLines[line].hasBar = printBar(line, false)
|
t.prevLines[line].hasBar = printBar(line, false)
|
||||||
|
if !t.multiLine && !t.wrap {
|
||||||
|
return line
|
||||||
|
}
|
||||||
return line + numLines - 1
|
return line + numLines - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2229,10 +2214,6 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
|||||||
}
|
}
|
||||||
finalLineNum = t.printHighlighted(result, base, match, false, true, line, maxLine, forceRedraw, preTask, postTask)
|
finalLineNum = t.printHighlighted(result, base, match, false, true, line, maxLine, forceRedraw, preTask, postTask)
|
||||||
}
|
}
|
||||||
for i := 0; i < t.gap && finalLineNum < maxLine; i++ {
|
|
||||||
finalLineNum++
|
|
||||||
t.renderEmptyLine(finalLineNum, barRange)
|
|
||||||
}
|
|
||||||
return finalLineNum
|
return finalLineNum
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2294,7 +2275,7 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
|||||||
allOffsets := result.colorOffsets(charOffsets, t.theme, colBase, colMatch, current)
|
allOffsets := result.colorOffsets(charOffsets, t.theme, colBase, colMatch, current)
|
||||||
|
|
||||||
maxLines := 1
|
maxLines := 1
|
||||||
if t.canSpanMultiLines() {
|
if t.multiLine || t.wrap {
|
||||||
maxLines = maxLineNum - lineNum + 1
|
maxLines = maxLineNum - lineNum + 1
|
||||||
}
|
}
|
||||||
lines, overflow := t.itemLines(item, maxLines)
|
lines, overflow := t.itemLines(item, maxLines)
|
||||||
@@ -2304,7 +2285,7 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
|||||||
topCutoff := false
|
topCutoff := false
|
||||||
skipLines := 0
|
skipLines := 0
|
||||||
wrapped := false
|
wrapped := false
|
||||||
if t.canSpanMultiLines() {
|
if t.multiLine || t.wrap {
|
||||||
// Cut off the upper lines in the 'default' layout
|
// Cut off the upper lines in the 'default' layout
|
||||||
if t.layout == layoutDefault && !current && maxLines == numItemLines && overflow {
|
if t.layout == layoutDefault && !current && maxLines == numItemLines && overflow {
|
||||||
lines, _ = t.itemLines(item, math.MaxInt)
|
lines, _ = t.itemLines(item, math.MaxInt)
|
||||||
@@ -2721,15 +2702,11 @@ Loop:
|
|||||||
url = nil
|
url = nil
|
||||||
t.pwindow.LinkEnd()
|
t.pwindow.LinkEnd()
|
||||||
}
|
}
|
||||||
if ansi != nil {
|
|
||||||
lbg = ansi.lbg
|
|
||||||
} else {
|
|
||||||
lbg = -1
|
|
||||||
}
|
|
||||||
str, width := t.processTabs(trimmed, prefixWidth)
|
str, width := t.processTabs(trimmed, prefixWidth)
|
||||||
if width > prefixWidth {
|
if width > prefixWidth {
|
||||||
prefixWidth = width
|
prefixWidth = width
|
||||||
if t.theme.Colored && ansi != nil && ansi.colored() {
|
if t.theme.Colored && ansi != nil && ansi.colored() {
|
||||||
|
lbg = ansi.lbg
|
||||||
fillRet = t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str)
|
fillRet = t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str)
|
||||||
} else {
|
} else {
|
||||||
fillRet = t.pwindow.CFill(tui.ColPreview.Fg(), tui.ColPreview.Bg(), tui.AttrRegular, str)
|
fillRet = t.pwindow.CFill(tui.ColPreview.Fg(), tui.ColPreview.Bg(), tui.AttrRegular, str)
|
||||||
@@ -2751,7 +2728,7 @@ Loop:
|
|||||||
if unchanged && lineNo == 0 {
|
if unchanged && lineNo == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if t.theme.Colored && lbg >= 0 {
|
if lbg >= 0 {
|
||||||
fillRet = t.pwindow.CFill(-1, lbg, tui.AttrRegular,
|
fillRet = t.pwindow.CFill(-1, lbg, tui.AttrRegular,
|
||||||
strings.Repeat(" ", t.pwindow.Width()-t.pwindow.X())+"\n")
|
strings.Repeat(" ", t.pwindow.Width()-t.pwindow.X())+"\n")
|
||||||
} else {
|
} else {
|
||||||
@@ -4898,7 +4875,7 @@ func (t *Terminal) constrain() {
|
|||||||
for tries := 0; tries < maxLines; tries++ {
|
for tries := 0; tries < maxLines; tries++ {
|
||||||
numItems := maxLines
|
numItems := maxLines
|
||||||
// How many items can be fit on screen including the current item?
|
// How many items can be fit on screen including the current item?
|
||||||
if t.canSpanMultiLines() && t.merger.Length() > 0 {
|
if (t.multiLine || t.wrap) && t.merger.Length() > 0 {
|
||||||
numItemsFound := 0
|
numItemsFound := 0
|
||||||
linesSum := 0
|
linesSum := 0
|
||||||
|
|
||||||
@@ -4953,12 +4930,12 @@ func (t *Terminal) constrain() {
|
|||||||
for {
|
for {
|
||||||
prevOffset := newOffset
|
prevOffset := newOffset
|
||||||
numItems := t.merger.Length()
|
numItems := t.merger.Length()
|
||||||
itemLines := 1 + t.gap
|
itemLines := 1
|
||||||
if t.canSpanMultiLines() && t.cy < numItems {
|
if (t.multiLine || t.wrap) && t.cy < numItems {
|
||||||
itemLines, _ = t.numItemLines(t.merger.Get(t.cy).item, maxLines)
|
itemLines, _ = t.numItemLines(t.merger.Get(t.cy).item, maxLines)
|
||||||
}
|
}
|
||||||
linesBefore := t.cy - newOffset
|
linesBefore := t.cy - newOffset
|
||||||
if t.canSpanMultiLines() {
|
if t.multiLine || t.wrap {
|
||||||
linesBefore = 0
|
linesBefore = 0
|
||||||
for i := newOffset; i < t.cy && i < numItems; i++ {
|
for i := newOffset; i < t.cy && i < numItems; i++ {
|
||||||
lines, _ := t.numItemLines(t.merger.Get(i).item, maxLines-linesBefore-itemLines)
|
lines, _ := t.numItemLines(t.merger.Get(i).item, maxLines-linesBefore-itemLines)
|
||||||
|
|||||||
@@ -3392,40 +3392,6 @@ class TestGoFZF < TestBase
|
|||||||
assert lines[1]&.end_with?('1000││')
|
assert lines[1]&.end_with?('1000││')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_gap
|
|
||||||
tmux.send_keys %(seq 100 | #{FZF} --gap --border --reverse), :Enter
|
|
||||||
block = <<~BLOCK
|
|
||||||
╭─────────────────
|
|
||||||
│ >
|
|
||||||
│ 100/100 ──────
|
|
||||||
│ > 1
|
|
||||||
│
|
|
||||||
│ 2
|
|
||||||
│
|
|
||||||
│ 3
|
|
||||||
│
|
|
||||||
│ 4
|
|
||||||
BLOCK
|
|
||||||
tmux.until { assert_block(block, _1) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_gap_2
|
|
||||||
tmux.send_keys %(seq 100 | #{FZF} --gap=2 --border --reverse), :Enter
|
|
||||||
block = <<~BLOCK
|
|
||||||
╭─────────────────
|
|
||||||
│ >
|
|
||||||
│ 100/100 ──────
|
|
||||||
│ > 1
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│ 2
|
|
||||||
│
|
|
||||||
│
|
|
||||||
│ 3
|
|
||||||
BLOCK
|
|
||||||
tmux.until { assert_block(block, _1) }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module TestShell
|
module TestShell
|
||||||
|
|||||||
Reference in New Issue
Block a user