m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-16 15:23:48 -05:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Junegunn Choi
81366c548b Support zellij floating pane via --popup (new name for --tmux) 2024-12-26 22:06:52 +09:00
39 changed files with 1447 additions and 3068 deletions

View File

@@ -7,4 +7,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: crate-ci/typos@v1.28.4
- uses: crate-ci/typos@v1.28.2

View File

@@ -128,7 +128,7 @@ fzf --height 70% --tmux 70%
You can also specify the position, width, and height of the popup window in
the following format:
* `[center|top|bottom|left|right][,SIZE[%]][,SIZE[%][,border-native]]`
* `[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]`
```sh
# 100% width and 60% height

View File

@@ -1,108 +1,6 @@
CHANGELOG
=========
0.58.0
------
_Release highlights: https://junegunn.github.io/fzf/releases/0.58.0/_
This version introduces three new border types, `--list-border`, `--input-border`, and `--header-border`, offering much greater flexibility for customizing the user interface.
<img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-4-borders.png" />
Also, fzf now offers "style presets" for quick customization, which can be activated using the `--style` option.
| Preset | Screenshot |
| :--- | :--- |
| `default` | <img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-style-default.png"/> |
| `full` | <img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-style-full.png"/> |
| `minimal` | <img src="https://raw.githubusercontent.com/junegunn/i/master/fzf-style-minimal.png"/> |
- Style presets (#4160)
- `--style=full[:BORDER_STYLE]`
- `--style=default`
- `--style=minimal`
- Border and label for the list section (#4148)
- Options
- `--list-border[=STYLE]`
- `--list-label=LABEL`
- `--list-label-pos=COL[:bottom]`
- Colors
- `list-fg`
- `list-bg`
- `list-border`
- `list-label`
- Actions
- `change-list-label`
- `transform-list-label`
- Border and label for the input section (prompt line and info line) (#4154)
- Options
- `--input-border[=STYLE]`
- `--input-label=LABEL`
- `--input-label-pos=COL[:bottom]`
- Colors
- `input-fg` (`query`)
- `input-bg`
- `input-border`
- `input-label`
- Actions
- `change-input-label`
- `transform-input-label`
- Border and label for the header section (#4159)
- Options
- `--header-border[=STYLE]`
- `--header-label=LABEL`
- `--header-label-pos=COL[:bottom]`
- Colors
- `header-fg` (`header`)
- `header-bg`
- `header-border`
- `header-label`
- Actions
- `change-header-label`
- `transform-header-label`
- Added `--preview-border[=STYLE]` as short for `--preview-window=border[-STYLE]`
- Added new preview border style `line` which draws a single separator line between the preview window and the rest of the interface
- fzf will now render a dashed line (`┈┈`) in each `--gap` for better visual separation.
```sh
# All bash/zsh functions, highlighted
declare -f |
perl -0 -pe 's/^}\n/}\0/gm' |
bat --plain --language bash --color always |
fzf --read0 --ansi --layout reverse --multi --highlight-line --gap
```
* You can customize the line using `--gap-line[=STR]`.
- You can specify `border-native` to `--tmux` so that native tmux border is used instead of `--border`. This can be useful if you start a different program from inside the popup.
```sh
fzf --tmux border-native --bind 'enter:execute:less {}'
```
- Added `toggle-multi-line` action
- Added `toggle-hscroll` action
- Added `change-nth` action for dynamically changing the value of the `--nth` option
```sh
# Start with --nth 1, then 2, then 3, then back to the default, 1
echo 'foo foobar foobarbaz' | fzf --bind 'space:change-nth(2|3|)' --nth 1 -q foo
```
- `--nth` parts of each line can now be rendered in a different text style
```sh
# nth in a different style
ls -al | fzf --nth -1 --color nth:italic
ls -al | fzf --nth -1 --color nth:reverse
ls -al | fzf --nth -1 --color nth:reverse:bold
# Dim the other parts
ls -al | fzf --nth -1 --color nth:regular,fg:dim
# With 'change-nth'. The current nth option is exported as $FZF_NTH.
ps -ef | fzf --reverse --header-lines 1 --header-border bottom --input-border \
--color nth:regular,fg:dim \
--bind 'ctrl-n:change-nth(8..|1|2|3|4|5|6|7|)' \
--bind 'result:transform-prompt:echo "${FZF_NTH}> "'
```
- A single-character delimiter is now treated as a plain string delimiter rather than a regular expression delimiter, even if it's a regular expression meta-character.
- This means you can just write `--delimiter '|'` instead of escaping it as `--delimiter '\|'`
- Bug fixes
- Bug fixes and improvements in fish scripts (thanks to @bitraid)
0.57.0
------
- You can now resize the preview window by dragging the border

View File

@@ -1,3 +1,4 @@
SHELL := bash
GO ?= go
GOOS ?= $(shell $(GO) env GOOS)
@@ -13,7 +14,7 @@ endif
ifeq ($(VERSION),)
$(error Not on git repository; cannot determine $$FZF_VERSION)
endif
VERSION_TRIM := $(shell echo $(VERSION) | sed "s/^v//; s/-.*//")
VERSION_TRIM := $(shell sed "s/^v//; s/-.*//" <<< $(VERSION))
VERSION_REGEX := $(subst .,\.,$(VERSION_TRIM))
ifdef FZF_REVISION

File diff suppressed because one or more lines are too long

View File

@@ -9,24 +9,12 @@
# - https://iterm2.com/utilities/imgcat
if [[ $# -ne 1 ]]; then
>&2 echo "usage: $0 FILENAME[:LINENO][:IGNORED]"
>&2 echo "usage: $0 FILENAME"
exit 1
fi
file=${1/#\~\//$HOME/}
center=0
if [[ ! -r $file ]]; then
if [[ $file =~ ^(.+):([0-9]+)\ *$ ]] && [[ -r ${BASH_REMATCH[1]} ]]; then
file=${BASH_REMATCH[1]}
center=${BASH_REMATCH[2]}
elif [[ $file =~ ^(.+):([0-9]+):[0-9]+\ *$ ]] && [[ -r ${BASH_REMATCH[1]} ]]; then
file=${BASH_REMATCH[1]}
center=${BASH_REMATCH[2]}
fi
fi
type=$(file --brief --dereference --mime -- "$file")
type=$(file --dereference --mime -- "$file")
if [[ ! $type =~ image/ ]]; then
if [[ $type =~ =binary ]]; then
@@ -44,7 +32,7 @@ if [[ ! $type =~ image/ ]]; then
exit
fi
${batname} --style="${BAT_STYLE:-numbers}" --color=always --pager=never --highlight-line="${center:-0}" -- "$file"
${batname} --style="${BAT_STYLE:-numbers}" --color=always --pager=never -- "$file"
exit
fi

12
go.mod
View File

@@ -2,19 +2,19 @@ module github.com/junegunn/fzf
require (
github.com/charlievieth/fastwalk v1.0.9
github.com/gdamore/tcell/v2 v2.8.1
github.com/gdamore/tcell/v2 v2.7.4
github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97
github.com/mattn/go-isatty v0.0.20
github.com/rivo/uniseg v0.4.7
golang.org/x/sys v0.29.0
golang.org/x/term v0.28.0
golang.org/x/sys v0.28.0
golang.org/x/term v0.27.0
)
require (
github.com/gdamore/encoding v1.0.1 // indirect
github.com/gdamore/encoding v1.0.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
golang.org/x/text v0.21.0 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
golang.org/x/text v0.14.0 // indirect
)
go 1.20

50
go.sum
View File

@@ -1,18 +1,17 @@
github.com/charlievieth/fastwalk v1.0.9 h1:Odb92AfoReO3oFBfDGT5J+nwgzQPF/gWAw6E6/lkor0=
github.com/charlievieth/fastwalk v1.0.9/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI=
github.com/gdamore/encoding v1.0.1 h1:YzKZckdBL6jVt2Gc+5p82qhrGiqMdG/eNs6Wy0u3Uhw=
github.com/gdamore/encoding v1.0.1/go.mod h1:0Z0cMFinngz9kS1QfMjCP8TY7em3bZYeeklsSDPivEo=
github.com/gdamore/tcell/v2 v2.8.1 h1:KPNxyqclpWpWQlPLx6Xui1pMk8S+7+R37h3g07997NU=
github.com/gdamore/tcell/v2 v2.8.1/go.mod h1:bj8ori1BG3OYMjmb3IklZVWfZUJ1UBQt9JXrOCOhGWw=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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/tcell/v2 v2.7.4 h1:sg6/UnTM9jGpZU+oFYAsDahfchWAFW8Xx2yFinNSAYU=
github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg=
github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97 h1:rqzLixVo1c/GQW6px9j1xQmlvQIn+lf/V6M1UQ7IFzw=
github.com/junegunn/go-shellwords v0.0.0-20240813092932-a62c48c52e97/go.mod h1:6EILKtGpo5t+KLb85LNZLAF6P9LKp78hJI80PXMcn3c=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
@@ -20,29 +19,15 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
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-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -50,36 +35,23 @@ 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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -2,7 +2,7 @@
set -u
version=0.58.0
version=0.57.0
auto_completion=
key_bindings=
update_config=2
@@ -83,7 +83,7 @@ ask() {
check_binary() {
echo -n " - Checking fzf executable ... "
local output
output=$(FZF_DEFAULT_OPTS= "$fzf_base"/bin/fzf --version 2>&1)
output=$("$fzf_base"/bin/fzf --version 2>&1)
if [ $? -ne 0 ]; then
echo "Error: $output"
binary_error="Invalid binary"

View File

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

View File

@@ -11,7 +11,7 @@ import (
"github.com/junegunn/fzf/src/protector"
)
var version = "0.58"
var version = "0.57"
var revision = "devel"
//go:embed shell/key-bindings.bash

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
THE SOFTWARE.
..
.TH fzf\-tmux 1 "Jan 2025" "fzf 0.58.0" "fzf\-tmux - open fzf in tmux split pane"
.TH fzf\-tmux 1 "Dec 2024" "fzf 0.57.0" "fzf\-tmux - open fzf in tmux split pane"
.SH NAME
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
THE SOFTWARE.
..
.TH fzf 1 "Jan 2025" "fzf 0.58.0" "fzf - a command-line fuzzy finder"
.TH fzf 1 "Dec 2024" "fzf 0.57.0" "fzf - a command-line fuzzy finder"
.SH NAME
fzf - a command-line fuzzy finder
@@ -36,15 +36,15 @@ It implements a "fuzzy" matching algorithm, so you can quickly type in patterns
with omitted characters and still get the results you want.
.SH OPTIONS
.SS NOTE
.SS Note
.TP
Most long options have the opposite version with \fB\-\-no\-\fR prefix.
.SS SEARCH
.SS Search mode
.TP
.B "\-x, \-\-extended"
Extended-search mode. Enabled by default. You can disable it with \fB+x\fR or
\fB\-\-no\-extended\fR.
Extended-search mode. Since 0.10.9, this is enabled by default. You can disable
it with \fB+x\fR or \fB\-\-no\-extended\fR.
.TP
.B "\-e, \-\-exact"
Enable exact-match
@@ -55,9 +55,6 @@ Case-insensitive match (default: smart-case match)
.B "+i, \-\-no\-ignore\-case"
Case-sensitive match
.TP
.B "\-\-smart\-case"
Smart-case match (default)
.TP
.B "\-\-literal"
Do not normalize latin script letters for matching.
.TP
@@ -112,28 +109,49 @@ fields.
.BI "\-\-with\-nth=" "N[,..]"
Transform the presentation of each line using field index expressions
.TP
.B "+s, \-\-no\-sort"
Do not sort the result
.TP
.BI "\-d, \-\-delimiter=" "STR"
Field delimiter regex for \fB\-\-nth\fR, \fB\-\-with\-nth\fR, and field index
expressions (default: AWK-style)
.TP
.BI "\-\-disabled"
Do not perform search. With this option, fzf becomes a simple selector
interface rather than a "fuzzy finder". You can later enable the search using
\fBenable\-search\fR or \fBtoggle\-search\fR action.
.SS Search result
.TP
.B "+s, \-\-no\-sort"
Do not sort the result
.TP
.B "\-\-tail=NUM"
Maximum number of items to keep in memory. This is useful when you want to
browse an endless stream of data (e.g. log stream) with fzf while limiting
memory usage.
.RS
e.g.
\fB# Interactive filtering of a log stream
tail \-f *.log | fzf \-\-tail 100000 \-\-tac \-\-no\-sort \-\-exact\fR
.RE
.TP
.BI "\-\-disabled"
Do not perform search. With this option, fzf becomes a simple selector
interface rather than a "fuzzy finder". You can later enable the search using
\fBenable\-search\fR or \fBtoggle\-search\fR action.
.B "\-\-track"
Make fzf track the current selection when the result list is updated.
This can be useful when browsing logs using fzf with sorting disabled. It is
not recommended to use this option with \fB\-\-tac\fR as the resulting behavior
can be confusing. Also, consider using \fBtrack\fR action instead of this
option.
.RS
e.g.
\fBgit log \-\-oneline \-\-graph \-\-color=always | nl |
fzf \-\-ansi \-\-track \-\-no\-sort \-\-layout=reverse\-list\fR
.RE
.TP
.B "\-\-tac"
Reverse the order of the input
.RS
e.g.
\fBhistory | fzf \-\-tac \-\-no\-sort\fR
.RE
.TP
.BI "\-\-tiebreak=" "CRI[,..]"
Comma-separated list of sort criteria to apply when the scores are tied.
@@ -161,146 +179,69 @@ Comma-separated list of sort criteria to apply when the scores are tied.
- Default is \fBlength\fR (or equivalently \fBlength\fR,index)
.br
- If \fBend\fR is found in the list, fzf will scan each line backwards
.SS INPUT/OUTPUT
.SS Interface
.TP
.B "\-\-read0"
Read input delimited by ASCII NUL characters instead of newline characters
.B "\-m, \-\-multi"
Enable multi-select with tab/shift\-tab. It optionally takes an integer argument
which denotes the maximum number of items that can be selected.
.TP
.B "\-\-print0"
Print output delimited by ASCII NUL characters instead of newline characters
.B "+m, \-\-no\-multi"
Disable multi-select
.TP
.B "\-\-ansi"
Enable processing of ANSI color codes
.B "\-\-no\-mouse"
Disable mouse
.TP
.B "\-\-sync"
Synchronous search for multi-staged filtering. If specified, fzf will launch
the finder only after the input stream is complete and the initial filtering
and the associated actions (bound to any of \fBstart\fR, \fBload\fR,
\fBresult\fR, or \fBfocus\fR) are complete.
.RS
e.g. \fB# Avoid rendering both fzf instances at the same time
fzf \-\-multi | fzf \-\-sync
# fzf will not render intermediate states
(sleep 1; seq 1000000; sleep 1) |
fzf \-\-sync \-\-query 5 \-\-listen \-\-bind start:up,load:up,result:up,focus:change\-header:Ready\fR
.RE
.SS GLOBAL STYLE
.BI "\-\-bind=" "KEYBINDS"
Comma-separated list of custom key bindings. See \fBKEY/EVENT BINDINGS\fR for
the details.
.TP
.BI "\-\-style=" "PRESET"
Apply a style preset [default|minimal|full[:BORDER_STYLE]]
.B "\-\-cycle"
Enable cyclic scroll
.TP
.BI "\-\-color=" "[BASE_SCHEME][,COLOR_NAME[:ANSI_COLOR][:ANSI_ATTRIBUTES]]..."
Color configuration. The name of the base color scheme is followed by custom
color mappings.
.RS
.B BASE SCHEME:
(default: \fBdark\fR on 256-color terminal, otherwise \fB16\fR; If \fBNO_COLOR\fR is set, \fBbw\fR)
\fBdark \fRColor scheme for dark 256-color terminal
\fBlight \fRColor scheme for light 256-color terminal
\fB16 \fRColor scheme for 16-color terminal
\fBbw \fRNo colors (equivalent to \fB\-\-no\-color\fR)
.B COLOR NAMES:
\fBfg \fRText
\fBlist\-fg \fRText in the list section
\fBselected\-fg \fRSelected line text
\fBpreview\-fg \fRPreview window text
\fBbg \fRBackground
\fBlist\-bg \fRList section background
\fBselected\-bg \fRSelected line background
\fBpreview\-bg \fRPreview window background
\fBinput\-bg \fRInput window background (\fB\-\-input\-border\fR)
\fBheader\-bg \fRHeader window background (\fB\-\-header\-border\fR)
\fBhl \fRHighlighted substrings
\fBselected\-hl \fRHighlighted substrings in the selected line
\fBcurrent\-fg (fg+) \fRText (current line)
\fBcurrent\-bg (bg+) \fRBackground (current line)
\fBgutter \fRGutter on the left
\fBcurrent\-hl (hl+) \fRHighlighted substrings (current line)
\fBquery (input\-fg) \fRQuery string
\fBdisabled \fRQuery string when search is disabled (\fB\-\-disabled\fR)
\fBinfo \fRInfo line (match counters)
\fBborder \fRBorder around the window (\fB\-\-border\fR and \fB\-\-preview\fR)
\fBlist\-border \fRBorder around the list section (\fB\-\-list\-border\fR)
\fBscrollbar \fRScrollbar
\fBseparator \fRHorizontal separator on info line
\fBgap\-line \fRHorizontal line on each gap
\fBpreview\-border \fRBorder around the preview window (\fB\-\-preview\fR)
\fBpreview\-scrollbar \fRScrollbar
\fBinput\-border \fRBorder around the input window (\fB\-\-input\-border\fR)
\fBheader\-border \fRBorder around the header window (\fB\-\-header\-border\fR)
\fBlabel \fRBorder label (\fB\-\-border\-label\fR, \fB\-\-list\-label\fR, \fB\-\-input\-label\fR, and \fB\-\-preview\-label\fR)
\fBlist\-label \fRBorder label of the list section (\fB\-\-list\-label\fR)
\fBpreview\-label \fRBorder label of the preview window (\fB\-\-preview\-label\fR)
\fBinput\-label \fRBorder label of the input window (\fB\-\-input\-label\fR)
\fBheader\-label \fRBorder label of the header window (\fB\-\-header\-label\fR)
\fBprompt \fRPrompt
\fBpointer \fRPointer to the current line
\fBmarker \fRMulti\-select marker
\fBspinner \fRStreaming input indicator
\fBheader (header\-fg) \fRHeader
\fBnth \fRParts of the line specified by \fB\-\-nth\fR (only supports attributes)
.B ANSI COLORS:
\fB\-1 \fRDefault terminal foreground/background color
\fB \fR(or the original color of the text)
\fB0 ~ 15 \fR16 base colors
\fBblack\fR
\fBred\fR
\fBgreen\fR
\fByellow\fR
\fBblue\fR
\fBmagenta\fR
\fBcyan\fR
\fBwhite\fR
\fBbright\-black\fR (gray | grey)
\fBbright\-red\fR
\fBbright\-green\fR
\fBbright\-yellow\fR
\fBbright\-blue\fR
\fBbright\-magenta\fR
\fBbright\-cyan\fR
\fBbright\-white\fR
\fB16 ~ 255 \fRANSI 256 colors
\fB#rrggbb \fR24-bit colors
.B ANSI ATTRIBUTES: (Only applies to foreground colors)
\fBregular \fRClears previously set attributes; should precede the other ones
\fBbold\fR
\fBunderline\fR
\fBreverse\fR
\fBdim\fR
\fBitalic\fR
\fBstrikethrough\fR
.B EXAMPLES:
\fB# Seoul256 theme with 8-bit colors
# (https://github.com/junegunn/seoul256.vim)
fzf \-\-color='bg:237,bg+:236,info:143,border:240,spinner:108' \\
\-\-color='hl:65,fg:252,header:65,fg+:252' \\
\-\-color='pointer:161,marker:168,prompt:110,hl+:108'
# Seoul256 theme with 24-bit colors
fzf \-\-color='bg:#4B4B4B,bg+:#3F3F3F,info:#BDBB72,border:#6B6B6B,spinner:#98BC99' \\
\-\-color='hl:#719872,fg:#D9D9D9,header:#719872,fg+:#D9D9D9' \\
\-\-color='pointer:#E12672,marker:#E17899,prompt:#98BEDE,hl+:#98BC99'\fR
.RE
.B "\-\-wrap"
Enable line wrap
.TP
.B "\-\-no\-color"
Disable colors
.BI "\-\-wrap\-sign" "=INDICATOR"
Indicator for wrapped lines. The default is '↳ ' or '> ' depending on
\fB\-\-no\-unicode\fR.
.TP
.B "\-\-no\-bold"
Do not use bold text
.B "\-\-no\-multi\-line"
Disable multi-line display of items when using \fB\-\-read0\fR
.TP
.B "\-\-black"
Use black background
.BI "\-\-gap" "[=N]"
Render empty lines between each item
.TP
.B "\-\-keep\-right"
Keep the right end of the line visible when it's too long. Effective only when
the query string is empty.
.TP
.BI "\-\-scroll\-off=" "LINES"
Number of screen lines to keep above or below when scrolling to the top or to
the bottom (default: 3).
.TP
.B "\-\-no\-hscroll"
Disable horizontal scroll
.TP
.BI "\-\-hscroll\-off=" "COLS"
Number of screen columns to keep to the right of the highlighted substring
(default: 10). Setting it to a large value will cause the text to be positioned
on the center of the screen.
.TP
.B "\-\-filepath\-word"
Make word-wise movements and actions respect path separators. The following
actions are affected:
.SS DISPLAY MODE
\fBbackward\-kill\-word\fR
.br
\fBbackward\-word\fR
.br
\fBforward\-word\fR
.br
\fBkill\-word\fR
.TP
.BI "\-\-jump\-labels=" "CHARS"
Label characters for \fBjump\fR mode.
.SS Layout
.TP
.BI "\-\-height=" "[~]HEIGHT[%]"
Display fzf window below the cursor with the given height instead of using
@@ -330,27 +271,24 @@ Adaptive height has the following limitations:
Minimum height when \fB\-\-height\fR is given in percent (default: 10).
Ignored when \fB\-\-height\fR is not specified.
.TP
.BI "\-\-tmux" "[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]][,border-native]]"
Start fzf in a tmux popup (default \fBcenter,50%\fR). Requires tmux 3.3 or
later. This option is ignored if you are not running fzf inside tmux.
.BI "\-\-popup" "[=[center|top|bottom|left|right][,SIZE[%]][,SIZE[%]]]"
Start fzf in a tmux popup or in a zellij floating pane (default
\fBcenter,50%\fR). Requires tmux 3.3+ or zellij. This option is ignored if you
are not running fzf inside tmux or zellij.
e.g.
\fB# Popup in the center with 70% width and height
fzf \-\-tmux 70%
fzf \-\-popup 70%
# Popup on the left with 40% width and 100% height
fzf \-\-tmux right,40%
fzf \-\-popup right,40%
# Popup on the bottom with 100% width and 30% height
fzf \-\-tmux bottom,30%
fzf \-\-popup bottom,30%
# Popup on the top with 80% width and 40% height
fzf \-\-tmux top,80%,40%
fzf \-\-popup top,80%,40%\fR
# Popup with a native tmux border in the center with 80% width and height
fzf \-\-tmux center,80%,border\-native\fR
.SS LAYOUT
.TP
.BI "\-\-layout=" "LAYOUT"
Choose the layout (default: default)
@@ -368,56 +306,7 @@ Choose the layout (default: default)
A synonym for \fB\-\-layout=reverse\fB
.TP
.BI "\-\-margin=" MARGIN
Comma-separated expression for margins around the finder.
.br
.br
.RS
.BR TRBL " Same margin for top, right, bottom, and left"
.br
.BR TB,RL " Vertical, horizontal margin"
.br
.BR T,RL,B " Top, horizontal, bottom margin"
.br
.BR T,R,B,L " Top, right, bottom, left margin"
.br
.br
Each part can be given in absolute number or in percentage relative to the
terminal size with \fB%\fR suffix.
.br
.br
e.g.
\fBfzf \-\-margin 10%
fzf \-\-margin 1,5%\fR
.RE
.TP
.BI "\-\-padding=" PADDING
Comma-separated expression for padding inside the border. Padding is
distinguishable from margin only when \fB\-\-border\fR option is used.
.br
.br
e.g.
\fBfzf \-\-margin 5% \-\-padding 5% \-\-border \-\-preview 'cat {}' \\
\-\-color bg:#222222,preview\-bg:#333333\fR
.br
.RS
.BR TRBL " Same padding for top, right, bottom, and left"
.br
.BR TB,RL " Vertical, horizontal padding"
.br
.BR T,RL,B " Top, horizontal, bottom padding"
.br
.BR T,R,B,L " Top, right, bottom, left padding"
.br
.RE
.TP
.BI "\-\-border" [=STYLE]
.BI "\-\-border" [=BORDER_OPT]
Draw border around the finder
.br
@@ -496,120 +385,65 @@ the label. Label is printed on the top border line by default, add
\fB:bottom\fR to put it on the border line on the bottom. The default value
\fB0 (or \fBcenter\fR) will put the label at the center of the border line.
.SS LIST SECTION
.TP
.BI "\-m, \-\-multi" "[=MAX]"
Enable multi-select with tab/shift\-tab. It optionally takes an integer argument
which denotes the maximum number of items that can be selected.
.TP
.B "+m, \-\-no\-multi"
Disable multi-select
.TP
.B "\-\-highlight\-line"
Highlight the whole current line
.TP
.B "\-\-cycle"
Enable cyclic scroll
.TP
.B "\-\-wrap"
Enable line wrap
.TP
.BI "\-\-wrap\-sign" "=INDICATOR"
Indicator for wrapped lines. The default is '↳ ' or '> ' depending on
\fB\-\-no\-unicode\fR.
.TP
.B "\-\-no\-multi\-line"
Disable multi-line display of items when using \fB\-\-read0\fR
.TP
.B "\-\-track"
Make fzf track the current selection when the result list is updated.
This can be useful when browsing logs using fzf with sorting disabled. It is
not recommended to use this option with \fB\-\-tac\fR as the resulting behavior
can be confusing. Also, consider using \fBtrack\fR action instead of this
option.
.B "\-\-no\-unicode"
Use ASCII characters instead of Unicode drawing characters to draw borders,
the spinner and the horizontal separator.
.TP
.B "\-\-ambidouble"
Set this option if your terminal displays ambiguous width characters (e.g.
box-drawing characters for borders) as 2 columns.
.TP
.BI "\-\-margin=" MARGIN
Comma-separated expression for margins around the finder.
.br
.br
.RS
.BR TRBL " Same margin for top, right, bottom, and left"
.br
.BR TB,RL " Vertical, horizontal margin"
.br
.BR T,RL,B " Top, horizontal, bottom margin"
.br
.BR T,R,B,L " Top, right, bottom, left margin"
.br
.br
Each part can be given in absolute number or in percentage relative to the
terminal size with \fB%\fR suffix.
.br
.br
e.g.
\fBgit log \-\-oneline \-\-graph \-\-color=always | nl |
fzf \-\-ansi \-\-track \-\-no\-sort \-\-layout=reverse\-list\fR
\fBfzf \-\-margin 10%
fzf \-\-margin 1,5%\fR
.RE
.TP
.B "\-\-tac"
Reverse the order of the input
.BI "\-\-padding=" PADDING
Comma-separated expression for padding inside the border. Padding is
distinguishable from margin only when \fB\-\-border\fR option is used.
.br
.RS
.br
e.g.
\fBhistory | fzf \-\-tac \-\-no\-sort\fR
\fBfzf \-\-margin 5% \-\-padding 5% \-\-border \-\-preview 'cat {}' \\
\-\-color bg:#222222,preview\-bg:#333333\fR
.br
.RS
.BR TRBL " Same padding for top, right, bottom, and left"
.br
.BR TB,RL " Vertical, horizontal padding"
.br
.BR T,RL,B " Top, horizontal, bottom padding"
.br
.BR T,R,B,L " Top, right, bottom, left padding"
.br
.RE
.TP
.BI "\-\-gap" "[=N]"
Render empty lines between each item
.TP
.BI "\-\-gap\-line" "[=STR]"
The given string will be repeated to draw a horizontal line on each gap
(default: '┈' or '\-' depending on \fB\-\-no\-unicode\fR).
.TP
.B "\-\-keep\-right"
Keep the right end of the line visible when it's too long. Effective only when
the query string is empty.
.TP
.BI "\-\-scroll\-off=" "LINES"
Number of screen lines to keep above or below when scrolling to the top or to
the bottom (default: 3).
.TP
.B "\-\-no\-hscroll"
Disable horizontal scroll
.TP
.BI "\-\-hscroll\-off=" "COLS"
Number of screen columns to keep to the right of the highlighted substring
(default: 10). Setting it to a large value will cause the text to be positioned
on the center of the screen.
.TP
.BI "\-\-jump\-labels=" "CHARS"
Label characters for \fBjump\fR mode.
.TP
.BI "\-\-pointer=" "STR"
Pointer to the current line (default: '▌' or '>' depending on \fB\-\-no\-unicode\fR)
.TP
.BI "\-\-marker=" "STR"
Multi-select marker (default: '┃' or '>' depending on \fB\-\-no\-unicode\fR)
.TP
.BI "\-\-marker\-multi\-line=" "STR"
Multi-select marker for multi-line entries. 3 elements for top, middle, and bottom.
(default: '╻┃╹' or '.|'' depending on \fB\-\-no\-unicode\fR)
.TP
.BI "\-\-ellipsis=" "STR"
Ellipsis to show when line is truncated (default: '··')
.TP
.BI "\-\-tabstop=" SPACES
Number of spaces for a tab character (default: 8)
.TP
.BI "\-\-scrollbar=" "CHAR1[CHAR2]"
Use the given character to render scrollbar. (default: '│' or ':' depending on
\fB\-\-no\-unicode\fR). The optional \fBCHAR2\fR is used to render scrollbar of
the preview window.
.TP
.B "\-\-no\-scrollbar"
Do not display scrollbar. A synonym for \fB\-\-scrollbar=''\fB
.TP
.BI "\-\-list\-border" [=STYLE]
Draw border around the list section
.TP
.BI "\-\-list\-label" [=LABEL]
Label to print on the list border
.TP
.BI "\-\-list\-label\-pos" [=N[:top|bottom]]
Position of the list label
.SS INPUT SECTION
.TP
.BI "\-\-prompt=" "STR"
Input prompt (default: '> ')
.TP
.BI "\-\-info=" "STYLE"
Determines the display style of the finder info. (e.g. match counter, loading indicator, etc.)
@@ -658,30 +492,160 @@ Do not display horizontal separator on the info line. A synonym for
\fB\-\-separator=''\fB
.TP
.B "\-\-filepath\-word"
Make word-wise movements and actions respect path separators. The following
actions are affected:
\fBbackward\-kill\-word\fR
.br
\fBbackward\-word\fR
.br
\fBforward\-word\fR
.br
\fBkill\-word\fR
.TP
.BI "\-\-input\-border" [=STYLE]
Draw border around the input section
.BI "\-\-scrollbar=" "CHAR1[CHAR2]"
Use the given character to render scrollbar. (default: '│' or ':' depending on
\fB\-\-no\-unicode\fR). The optional \fBCHAR2\fR is used to render scrollbar of
the preview window.
.TP
.BI "\-\-input\-label" [=LABEL]
Label to print on the input border
.B "\-\-no\-scrollbar"
Do not display scrollbar. A synonym for \fB\-\-scrollbar=''\fB
.TP
.BI "\-\-input\-label\-pos" [=N[:top|bottom]]
Position of the input label
.BI "\-\-prompt=" "STR"
Input prompt (default: '> ')
.TP
.BI "\-\-pointer=" "STR"
Pointer to the current line (default: '▌' or '>' depending on \fB\-\-no\-unicode\fR)
.TP
.BI "\-\-marker=" "STR"
Multi-select marker (default: '┃' or '>' depending on \fB\-\-no\-unicode\fR)
.TP
.BI "\-\-marker\-multi\-line=" "STR"
Multi-select marker for multi-line entries. 3 elements for top, middle, and bottom.
(default: '╻┃╹' or '.|'' depending on \fB\-\-no\-unicode\fR)
.TP
.BI "\-\-header=" "STR"
The given string will be printed as the sticky header. The lines are displayed
in the given order from top to bottom regardless of \fB\-\-layout\fR option, and
are not affected by \fB\-\-with\-nth\fR. ANSI color codes are processed even when
\fB\-\-ansi\fR is not set.
.TP
.BI "\-\-header\-lines=" "N"
The first N lines of the input are treated as the sticky header. When
\fB\-\-with\-nth\fR is set, the lines are transformed just like the other
lines that follow.
.TP
.B "\-\-header\-first"
Print header before the prompt line
.TP
.BI "\-\-ellipsis=" "STR"
Ellipsis to show when line is truncated (default: '··')
.SS Display
.TP
.B "\-\-ansi"
Enable processing of ANSI color codes
.TP
.BI "\-\-tabstop=" SPACES
Number of spaces for a tab character (default: 8)
.TP
.BI "\-\-color=" "[BASE_SCHEME][,COLOR_NAME[:ANSI_COLOR][:ANSI_ATTRIBUTES]]..."
Color configuration. The name of the base color scheme is followed by custom
color mappings.
.SS PREVIEW WINDOW
.RS
.B BASE SCHEME:
(default: \fBdark\fR on 256-color terminal, otherwise \fB16\fR; If \fBNO_COLOR\fR is set, \fBbw\fR)
\fBdark \fRColor scheme for dark 256-color terminal
\fBlight \fRColor scheme for light 256-color terminal
\fB16 \fRColor scheme for 16-color terminal
\fBbw \fRNo colors (equivalent to \fB\-\-no\-color\fR)
.B COLOR NAMES:
\fBfg \fRText
\fBselected\-fg \fRSelected line text
\fBpreview\-fg \fRPreview window text
\fBbg \fRBackground
\fBselected\-bg \fRSelected line background
\fBpreview\-bg \fRPreview window background
\fBhl \fRHighlighted substrings
\fBselected\-hl \fRHighlighted substrings in the selected line
\fBcurrent\-fg (fg+) \fRText (current line)
\fBcurrent\-bg (bg+) \fRBackground (current line)
\fBgutter \fRGutter on the left
\fBcurrent\-hl (hl+) \fRHighlighted substrings (current line)
\fBquery \fRQuery string
\fBdisabled \fRQuery string when search is disabled (\fB\-\-disabled\fR)
\fBinfo \fRInfo line (match counters)
\fBborder \fRBorder around the window (\fB\-\-border\fR and \fB\-\-preview\fR)
\fBscrollbar \fRScrollbar
\fBpreview\-border \fRBorder around the preview window (\fB\-\-preview\fR)
\fBpreview\-scrollbar \fRScrollbar
\fBseparator \fRHorizontal separator on info line
\fBlabel \fRBorder label (\fB\-\-border\-label\fR and \fB\-\-preview\-label\fR)
\fBpreview\-label \fRBorder label of the preview window (\fB\-\-preview\-label\fR)
\fBprompt \fRPrompt
\fBpointer \fRPointer to the current line
\fBmarker \fRMulti\-select marker
\fBspinner \fRStreaming input indicator
\fBheader \fRHeader
.B ANSI COLORS:
\fB\-1 \fRDefault terminal foreground/background color
\fB \fR(or the original color of the text)
\fB0 ~ 15 \fR16 base colors
\fBblack\fR
\fBred\fR
\fBgreen\fR
\fByellow\fR
\fBblue\fR
\fBmagenta\fR
\fBcyan\fR
\fBwhite\fR
\fBbright\-black\fR (gray | grey)
\fBbright\-red\fR
\fBbright\-green\fR
\fBbright\-yellow\fR
\fBbright\-blue\fR
\fBbright\-magenta\fR
\fBbright\-cyan\fR
\fBbright\-white\fR
\fB16 ~ 255 \fRANSI 256 colors
\fB#rrggbb \fR24-bit colors
.B ANSI ATTRIBUTES: (Only applies to foreground colors)
\fBregular \fRClears previously set attributes; should precede the other ones
\fBbold\fR
\fBunderline\fR
\fBreverse\fR
\fBdim\fR
\fBitalic\fR
\fBstrikethrough\fR
.B EXAMPLES:
\fB# Seoul256 theme with 8-bit colors
# (https://github.com/junegunn/seoul256.vim)
fzf \-\-color='bg:237,bg+:236,info:143,border:240,spinner:108' \\
\-\-color='hl:65,fg:252,header:65,fg+:252' \\
\-\-color='pointer:161,marker:168,prompt:110,hl+:108'
# Seoul256 theme with 24-bit colors
fzf \-\-color='bg:#4B4B4B,bg+:#3F3F3F,info:#BDBB72,border:#6B6B6B,spinner:#98BC99' \\
\-\-color='hl:#719872,fg:#D9D9D9,header:#719872,fg+:#D9D9D9' \\
\-\-color='pointer:#E12672,marker:#E17899,prompt:#98BEDE,hl+:#98BC99'\fR
.RE
.TP
.B "\-\-highlight\-line"
Highlight the whole current line
.TP
.B "\-\-no\-bold"
Do not use bold text
.TP
.B "\-\-black"
Use black background
.SS History
.TP
.BI "\-\-history=" "HISTORY_FILE"
Load search history from the specified file and update the file on completion.
When enabled, \fBCTRL\-N\fR and \fBCTRL\-P\fR are automatically remapped to
\fBnext\-history\fR and \fBprev\-history\fR.
.TP
.BI "\-\-history\-size=" "N"
Maximum number of entries in the history file (default: 1000). The file is
automatically truncated when the number of the lines exceeds the value.
.SS Preview
.TP
.BI "\-\-preview=" "COMMAND"
Execute the given command for the current line and display the result on the
@@ -761,13 +725,6 @@ e.g.
.RE
.TP
.BI "\-\-preview\-border" [=STYLE]
Short for \fB\-\-preview\-window=border\-STYLE\fR. In addition to the other
styles, \fBline\fR style is also supported for preview border, which draws
a single separator line between the preview window and the rest of the
interface.
.TP
.BI "\-\-preview\-label" [=LABEL]
Label to print on the horizontal border line of the preview window.
@@ -803,7 +760,7 @@ default value 0 (or \fBcenter\fR) will put the label at the center of the
border line.
.TP
.BI "\-\-preview\-window=" "[POSITION][,SIZE[%]][,border\-STYLE][,[no]wrap][,[no]follow][,[no]cycle][,[no]info][,[no]hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)]"
.BI "\-\-preview\-window=" "[POSITION][,SIZE[%]][,border\-BORDER_OPT][,[no]wrap][,[no]follow][,[no]cycle][,[no]info][,[no]hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default][,<SIZE_THRESHOLD(ALTERNATIVE_LAYOUT)]"
.RS
.B POSITION: (default: right)
@@ -846,10 +803,6 @@ e.g. \fBborder\-rounded\fR (border with rounded edges, default),
\fBborder\-sharp\fR (border with sharp edges), \fBborder\-left\fR,
\fBborder\-none\fR, etc.
* In addition to the other border styles, \fBborder\-line\fR style is also
supported, which draws a single separator line between the preview window and
the rest of the interface.
* \fB[:+SCROLL[OFFSETS][/DENOM]]\fR determines the initial scroll offset of the
preview window.
@@ -901,35 +854,7 @@ e.g.
\fBfzf \-\-preview 'cat {}' \-\-preview\-window 'right,border\-left,<30(up,30%,border\-bottom)'\fR
.RE
.SS HEADER
.TP
.BI "\-\-header=" "STR"
The given string will be printed as the sticky header. The lines are displayed
in the given order from top to bottom regardless of \fB\-\-layout\fR option, and
are not affected by \fB\-\-with\-nth\fR. ANSI color codes are processed even when
\fB\-\-ansi\fR is not set.
.TP
.BI "\-\-header\-lines=" "N"
The first N lines of the input are treated as the sticky header. When
\fB\-\-with\-nth\fR is set, the lines are transformed just like the other
lines that follow.
.TP
.B "\-\-header\-first"
Print header before the prompt line
.TP
.BI "\-\-header\-border" [=STYLE]
Draw border around the header section
.TP
.BI "\-\-header\-label" [=LABEL]
Label to print on the header border
.TP
.BI "\-\-header\-label\-pos" [=N[:top|bottom]]
Position of the header label
.SS SCRIPTING
.SS Scripting
.TP
.BI "\-q, \-\-query=" "STR"
Start the finder with the given query
@@ -958,15 +883,24 @@ with the default enter key. If \fB\-\-expect\fR option is specified multiple
times, fzf will expect the union of the keys. \fB\-\-no\-expect\fR will clear the
list.
.RS
e.g.
\fBfzf \-\-expect=ctrl\-v,ctrl\-t,alt\-s \-\-expect=f1,f2,~,@\fR
.RE
This option is not compatible with \fB\-\-bind\fR on the same key and will take
precedence over it. To combine the two, use \fBprint\fR action.
.RS
e.g.
\fBfzf \-\-multi \\
\-\-bind 'enter:print()+accept,ctrl\-y:select\-all+print(ctrl\-y)+accept'\fR
\fBfzf \-\-multi \-\-bind 'enter:print()+accept,ctrl\-y:select\-all+print(ctrl\-y)+accept'\fR
.RE
.TP
.B "\-\-read0"
Read input delimited by ASCII NUL characters instead of newline characters
.TP
.B "\-\-print0"
Print output delimited by ASCII NUL characters instead of newline characters
.TP
.B "\-\-no\-clear"
Do not clear finder interface on exit. If fzf was started in full screen mode,
@@ -982,13 +916,21 @@ e.g.
exit 1
) && seq "$foo" 100 | fzf
.SS KEY/EVENT BINDING
.TP
.BI "\-\-bind=" "BINDINGS"
Comma-separated list of custom key/event bindings. See \fBKEY/EVENT BINDINGS\fR
for the details.
.B "\-\-sync"
Synchronous search for multi-staged filtering. If specified, fzf will launch
the finder only after the input stream is complete and the initial filtering
and the associated actions (bound to any of \fBstart\fR, \fBload\fR,
\fBresult\fR, or \fBfocus\fR) are complete.
.SS ADVANCED
.RS
e.g. \fB# Avoid rendering both fzf instances at the same time
fzf \-\-multi | fzf \-\-sync
# fzf will not render intermediate states
(sleep 1; seq 1000000; sleep 1) |
fzf \-\-sync \-\-query 5 \-\-listen \-\-bind start:up,load:up,result:up,focus:change\-header:Ready\fR
.RE
.TP
.B "\-\-with\-shell=STR"
Shell command and flags to start child processes with. On *nix Systems, the
@@ -996,6 +938,9 @@ default value is \fB$SHELL \-c\fR if \fB$SHELL\fR is set, otherwise \fBsh \-c\fR
On Windows, the default value is \fBcmd /s/c\fR when \fB$SHELL\fR is not
set.
.RS
e.g. \fBgem list | fzf \-\-with\-shell 'ruby \-e' \-\-preview 'pp Gem::Specification.find_by_name({1})'\fR
.RE
.TP
.B "\-\-listen[=[ADDR:]PORT]" "\-\-listen\-unsafe[=[ADDR:]PORT]"
Start HTTP server and listen on the given address. It allows external processes
@@ -1034,8 +979,18 @@ e.g.
# Choose port automatically and export it as $FZF_PORT to the child process
fzf \-\-listen \-\-bind 'start:execute\-silent:echo $FZF_PORT > /tmp/fzf\-port'
\fR
.SS Help
.TP
.B "\-\-version"
Display version information and exit
.TP
.B "\-\-help"
Show help message
.TP
.B "\-\-man"
Show man page
.SS DIRECTORY TRAVERSAL
.SS Directory traversal
.TP
.B "\-\-walker=[file][,dir][,follow][,hidden]"
Determines the behavior of the built-in directory walker that is used when
@@ -1060,22 +1015,7 @@ The default value is the current working directory.
Comma-separated list of directory names to skip during the directory walk.
The default value is \fB.git,node_modules\fR.
.SS HISTORY
.TP
.BI "\-\-history=" "HISTORY_FILE"
Load search history from the specified file and update the file on completion.
When enabled, \fBCTRL\-N\fR and \fBCTRL\-P\fR are automatically remapped to
\fBnext\-history\fR and \fBprev\-history\fR.
.TP
.BI "\-\-history\-size=" "N"
Maximum number of entries in the history file (default: 1000). The file is
automatically truncated when the number of the lines exceeds the value.
.RS
e.g. \fBgem list | fzf \-\-with\-shell 'ruby \-e' \-\-preview 'pp Gem::Specification.find_by_name({1})'\fR
.RE
.SS SHELL INTEGRATION
.SS Shell integration
.TP
.B "\-\-bash"
Print script to set up Bash shell integration
@@ -1094,31 +1034,6 @@ Print script to set up Fish shell integration
e.g. \fBfzf \-\-fish | source\fR
.SS OTHERS
.TP
.B "\-\-no\-mouse"
Disable mouse
.TP
.B "\-\-no\-unicode"
Use ASCII characters instead of Unicode drawing characters to draw borders,
the spinner and the horizontal separator.
.TP
.B "\-\-ambidouble"
Set this option if your terminal displays ambiguous width characters (e.g.
box-drawing characters for borders) as 2 columns.
.SS HELP
.TP
.B "\-\-version"
Display version information and exit
.TP
.B "\-\-help"
Show help message
.TP
.B "\-\-man"
Show man page
.SH ENVIRONMENT VARIABLES
.TP
.B FZF_DEFAULT_COMMAND
@@ -1196,8 +1111,6 @@ fzf exports the following environment variables to its child processes.
.br
.BR FZF_QUERY " Current query string"
.br
.BR FZF_NTH " Current \-\-nth option"
.br
.BR FZF_PROMPT " Prompt string"
.br
.BR FZF_PREVIEW_LABEL " Preview label string"
@@ -1528,12 +1441,8 @@ A key or an event can be bound to one or more of the following actions.
\fBcancel\fR (clear query string if not empty, abort fzf otherwise)
\fBchange\-border\-label(...)\fR (change \fB\-\-border\-label\fR to the given string)
\fBchange\-header(...)\fR (change header to the given string; doesn't affect \fB\-\-header\-lines\fR)
\fBchange\-header\-label(...)\fR (change \fB\-\-header\-label\fR to the given string)
\fBchange\-input\-label(...)\fR (change \fB\-\-input\-label\fR to the given string)
\fBchange\-list\-label(...)\fR (change \fB\-\-list\-label\fR to the given string)
\fBchange\-multi\fR (enable multi-select mode with no limit)
\fBchange\-multi(...)\fR (enable multi-select mode with a limit or disable it with 0)
\fBchange\-nth(...)\fR (change \fB\-\-nth\fR option; rotate through the multiple options separated by '|')
\fBchange\-preview(...)\fR (change \fB\-\-preview\fR option)
\fBchange\-preview\-label(...)\fR (change \fB\-\-preview\-label\fR to the given string)
\fBchange\-preview\-window(...)\fR (change \fB\-\-preview\-window\fR option; rotate through the multiple option sets separated by '|')
@@ -1584,7 +1493,7 @@ A key or an event can be bound to one or more of the following actions.
\fBpreview\-half\-page\-up\fR
\fBpreview\-bottom\fR
\fBpreview\-top\fR
\fBprint(...)\fR (add string to the output queue and print on normal exit)
\fBprint(...)\fR (add string to the output queue and print on exit)
\fBput\fR (put the character to the prompt)
\fBput(...)\fR (put the given string to the prompt)
\fBrefresh\-preview\fR
@@ -1616,9 +1525,6 @@ A key or an event can be bound to one or more of the following actions.
\fBtransform(...)\fR (transform states using the output of an external command)
\fBtransform\-border\-label(...)\fR (transform border label using an external command)
\fBtransform\-header(...)\fR (transform header using an external command)
\fBtransform\-header\-label(...)\fR (transform header label using an external command)
\fBtransform\-input\-label(...)\fR (transform input label using an external command)
\fBtransform\-list\-label(...)\fR (transform list label using an external command)
\fBtransform\-preview\-label(...)\fR (transform preview label using an external command)
\fBtransform\-prompt(...)\fR (transform prompt string using an external command)
\fBtransform\-query(...)\fR (transform query string using an external command)

View File

@@ -31,14 +31,13 @@ function fzf_key_bindings
set -lx dir $commandline[1]
set -l fzf_query $commandline[2]
set -l prefix $commandline[3]
set -l result
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -lx FZF_DEFAULT_OPTS (__fzf_defaults "--reverse --walker=file,dir,follow,hidden --scheme=path --walker-root=$dir" "$FZF_CTRL_T_OPTS")
set -lx FZF_DEFAULT_COMMAND "$FZF_CTRL_T_COMMAND"
set -lx FZF_DEFAULT_OPTS_FILE ''
set result (eval (__fzfcmd) -m --query=$fzf_query)
eval (__fzfcmd) -m --query=$fzf_query | while read -l r; set -a result $r; end
end
if test -z "$result"
commandline -f repaint
@@ -58,25 +57,33 @@ function fzf_key_bindings
function fzf-history-widget -d "Show command history"
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
begin
set -l FISH_MAJOR (string split -- '.' $version)[1]
set -l FISH_MINOR (string split -- '.' $version)[2]
# merge history from other sessions before searching
test -z "$fish_private_mode"; and builtin history merge
set -lx FZF_DEFAULT_OPTS (__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort --wrap-sign '"\t"↳ ' --highlight-line +m $FZF_CTRL_R_OPTS")
set -lx FZF_DEFAULT_OPTS_FILE ''
set -lx FZF_DEFAULT_COMMAND
string match -q -r -- '/fish$' $SHELL; or set -lx SHELL (type -p fish)
if type -q perl
set -a FZF_DEFAULT_OPTS '--tac'
set FZF_DEFAULT_COMMAND 'builtin history -z --reverse | command perl -0 -pe \'s/^/$.\t/g; s/\n/\n\t/gm\''
# history's -z flag is needed for multi-line support.
# history's -z flag was added in fish 2.4.0, so don't use it for versions
# before 2.4.0.
if test "$FISH_MAJOR" -gt 2 -o \( "$FISH_MAJOR" -eq 2 -a "$FISH_MINOR" -ge 4 \)
set -lx FZF_DEFAULT_OPTS (__fzf_defaults "" "-n2..,.. --scheme=history --bind=ctrl-r:toggle-sort --wrap-sign '"\t"↳ ' --highlight-line $FZF_CTRL_R_OPTS +m")
set -lx FZF_DEFAULT_OPTS_FILE ''
if type -q perl
builtin history -z --reverse | command perl -0 -pe 's/^/$.\t/g; s/\n/\n\t/gm' | eval (__fzfcmd) --tac --read0 --print0 -q '(commandline)' | string replace -r '^\d*\t' '' | read -lz result
and commandline -- $result
else
set -l line 0
for i in (builtin history -z --reverse | string split0)
set line (math $line + 1)
string escape -n -- $line\t$i
end | string join0 | string replace -a '\n' '\n\t' | string unescape -n | eval (__fzfcmd) --tac --read0 --print0 -q '(commandline)' | string replace -r '^\d*\t' '' | read -lz result
and commandline -- $result
end
else
set FZF_DEFAULT_COMMAND \
'set -l h (builtin history -z --reverse | string split0);' \
'for i in (seq (count $h) -1 1);' \
'string join0 -- $i\t(string replace -a -- \n \n\t $h[$i] | string collect);' \
'end'
builtin history | eval (__fzfcmd) -q '(commandline)' | read -l result
and commandline -- $result
end
set -l result (eval "$FZF_DEFAULT_COMMAND | $(__fzfcmd) --read0 --print0 -q (commandline) --bind='enter:become:string replace -a -- \n\t \n {2..} | string collect'")
and commandline -- $result
end
commandline -f repaint
end
@@ -92,7 +99,7 @@ function fzf_key_bindings
set -lx FZF_DEFAULT_OPTS (__fzf_defaults "--reverse --walker=dir,follow,hidden --scheme=path --walker-root=$dir" "$FZF_ALT_C_OPTS")
set -lx FZF_DEFAULT_OPTS_FILE ''
set -lx FZF_DEFAULT_COMMAND "$FZF_ALT_C_COMMAND"
set -l result (eval (__fzfcmd) +m --query=$fzf_query)
eval (__fzfcmd) +m --query=$fzf_query | read -l result
if test -n "$result"
cd -- $result
@@ -126,12 +133,14 @@ function fzf_key_bindings
bind \ec fzf-cd-widget
end
bind -M insert \cr fzf-history-widget
if not set -q FZF_CTRL_T_COMMAND; or test -n "$FZF_CTRL_T_COMMAND"
bind -M insert \ct fzf-file-widget
end
if not set -q FZF_ALT_C_COMMAND; or test -n "$FZF_ALT_C_COMMAND"
bind -M insert \ec fzf-cd-widget
if bind -M insert &> /dev/null
bind -M insert \cr fzf-history-widget
if not set -q FZF_CTRL_T_COMMAND; or test -n "$FZF_CTRL_T_COMMAND"
bind -M insert \ct fzf-file-widget
end
if not set -q FZF_ALT_C_COMMAND; or test -n "$FZF_ALT_C_COMMAND"
bind -M insert \ec fzf-cd-widget
end
end
function __fzf_parse_commandline -d 'Parse the current command line token and return split of existing filepath, fzf query, and optional -option= prefix'

View File

@@ -25,116 +25,109 @@ func _() {
_ = x[actBackwardWord-14]
_ = x[actCancel-15]
_ = x[actChangeBorderLabel-16]
_ = x[actChangeListLabel-17]
_ = x[actChangeInputLabel-18]
_ = x[actChangeHeader-19]
_ = x[actChangeHeaderLabel-20]
_ = x[actChangeMulti-21]
_ = x[actChangePreviewLabel-22]
_ = x[actChangePrompt-23]
_ = x[actChangeQuery-24]
_ = x[actChangeNth-25]
_ = x[actClearScreen-26]
_ = x[actClearQuery-27]
_ = x[actClearSelection-28]
_ = x[actClose-29]
_ = x[actDeleteChar-30]
_ = x[actDeleteCharEof-31]
_ = x[actEndOfLine-32]
_ = x[actFatal-33]
_ = x[actForwardChar-34]
_ = x[actForwardWord-35]
_ = x[actKillLine-36]
_ = x[actKillWord-37]
_ = x[actUnixLineDiscard-38]
_ = x[actUnixWordRubout-39]
_ = x[actYank-40]
_ = x[actBackwardKillWord-41]
_ = x[actSelectAll-42]
_ = x[actDeselectAll-43]
_ = x[actToggle-44]
_ = x[actToggleSearch-45]
_ = x[actToggleAll-46]
_ = x[actToggleDown-47]
_ = x[actToggleUp-48]
_ = x[actToggleIn-49]
_ = x[actToggleOut-50]
_ = x[actToggleTrack-51]
_ = x[actToggleTrackCurrent-52]
_ = x[actToggleHeader-53]
_ = x[actToggleWrap-54]
_ = x[actToggleMultiLine-55]
_ = x[actToggleHscroll-56]
_ = x[actTrackCurrent-57]
_ = x[actUntrackCurrent-58]
_ = x[actDown-59]
_ = x[actUp-60]
_ = x[actPageUp-61]
_ = x[actPageDown-62]
_ = x[actPosition-63]
_ = x[actHalfPageUp-64]
_ = x[actHalfPageDown-65]
_ = x[actOffsetUp-66]
_ = x[actOffsetDown-67]
_ = x[actOffsetMiddle-68]
_ = x[actJump-69]
_ = x[actJumpAccept-70]
_ = x[actPrintQuery-71]
_ = x[actRefreshPreview-72]
_ = x[actReplaceQuery-73]
_ = x[actToggleSort-74]
_ = x[actShowPreview-75]
_ = x[actHidePreview-76]
_ = x[actTogglePreview-77]
_ = x[actTogglePreviewWrap-78]
_ = x[actTransform-79]
_ = x[actTransformBorderLabel-80]
_ = x[actTransformListLabel-81]
_ = x[actTransformInputLabel-82]
_ = x[actTransformHeader-83]
_ = x[actTransformHeaderLabel-84]
_ = x[actTransformPreviewLabel-85]
_ = x[actTransformPrompt-86]
_ = x[actTransformQuery-87]
_ = x[actPreview-88]
_ = x[actChangePreview-89]
_ = x[actChangePreviewWindow-90]
_ = x[actPreviewTop-91]
_ = x[actPreviewBottom-92]
_ = x[actPreviewUp-93]
_ = x[actPreviewDown-94]
_ = x[actPreviewPageUp-95]
_ = x[actPreviewPageDown-96]
_ = x[actPreviewHalfPageUp-97]
_ = x[actPreviewHalfPageDown-98]
_ = x[actPrevHistory-99]
_ = x[actPrevSelected-100]
_ = x[actPrint-101]
_ = x[actPut-102]
_ = x[actNextHistory-103]
_ = x[actNextSelected-104]
_ = x[actExecute-105]
_ = x[actExecuteSilent-106]
_ = x[actExecuteMulti-107]
_ = x[actSigStop-108]
_ = x[actFirst-109]
_ = x[actLast-110]
_ = x[actReload-111]
_ = x[actReloadSync-112]
_ = x[actDisableSearch-113]
_ = x[actEnableSearch-114]
_ = x[actSelect-115]
_ = x[actDeselect-116]
_ = x[actUnbind-117]
_ = x[actRebind-118]
_ = x[actBecome-119]
_ = x[actShowHeader-120]
_ = x[actHideHeader-121]
_ = x[actChangeHeader-17]
_ = x[actChangeMulti-18]
_ = x[actChangePreviewLabel-19]
_ = x[actChangePrompt-20]
_ = x[actChangeQuery-21]
_ = x[actClearScreen-22]
_ = x[actClearQuery-23]
_ = x[actClearSelection-24]
_ = x[actClose-25]
_ = x[actDeleteChar-26]
_ = x[actDeleteCharEof-27]
_ = x[actEndOfLine-28]
_ = x[actFatal-29]
_ = x[actForwardChar-30]
_ = x[actForwardWord-31]
_ = x[actKillLine-32]
_ = x[actKillWord-33]
_ = x[actUnixLineDiscard-34]
_ = x[actUnixWordRubout-35]
_ = x[actYank-36]
_ = x[actBackwardKillWord-37]
_ = x[actSelectAll-38]
_ = x[actDeselectAll-39]
_ = x[actToggle-40]
_ = x[actToggleSearch-41]
_ = x[actToggleAll-42]
_ = x[actToggleDown-43]
_ = x[actToggleUp-44]
_ = x[actToggleIn-45]
_ = x[actToggleOut-46]
_ = x[actToggleTrack-47]
_ = x[actToggleTrackCurrent-48]
_ = x[actToggleHeader-49]
_ = x[actToggleWrap-50]
_ = x[actToggleMultiLine-51]
_ = x[actToggleHscroll-52]
_ = x[actTrackCurrent-53]
_ = x[actUntrackCurrent-54]
_ = x[actDown-55]
_ = x[actUp-56]
_ = x[actPageUp-57]
_ = x[actPageDown-58]
_ = x[actPosition-59]
_ = x[actHalfPageUp-60]
_ = x[actHalfPageDown-61]
_ = x[actOffsetUp-62]
_ = x[actOffsetDown-63]
_ = x[actOffsetMiddle-64]
_ = x[actJump-65]
_ = x[actJumpAccept-66]
_ = x[actPrintQuery-67]
_ = x[actRefreshPreview-68]
_ = x[actReplaceQuery-69]
_ = x[actToggleSort-70]
_ = x[actShowPreview-71]
_ = x[actHidePreview-72]
_ = x[actTogglePreview-73]
_ = x[actTogglePreviewWrap-74]
_ = x[actTransform-75]
_ = x[actTransformBorderLabel-76]
_ = x[actTransformHeader-77]
_ = x[actTransformPreviewLabel-78]
_ = x[actTransformPrompt-79]
_ = x[actTransformQuery-80]
_ = x[actPreview-81]
_ = x[actChangePreview-82]
_ = x[actChangePreviewWindow-83]
_ = x[actPreviewTop-84]
_ = x[actPreviewBottom-85]
_ = x[actPreviewUp-86]
_ = x[actPreviewDown-87]
_ = x[actPreviewPageUp-88]
_ = x[actPreviewPageDown-89]
_ = x[actPreviewHalfPageUp-90]
_ = x[actPreviewHalfPageDown-91]
_ = x[actPrevHistory-92]
_ = x[actPrevSelected-93]
_ = x[actPrint-94]
_ = x[actPut-95]
_ = x[actNextHistory-96]
_ = x[actNextSelected-97]
_ = x[actExecute-98]
_ = x[actExecuteSilent-99]
_ = x[actExecuteMulti-100]
_ = x[actSigStop-101]
_ = x[actFirst-102]
_ = x[actLast-103]
_ = x[actReload-104]
_ = x[actReloadSync-105]
_ = x[actDisableSearch-106]
_ = x[actEnableSearch-107]
_ = x[actSelect-108]
_ = x[actDeselect-109]
_ = x[actUnbind-110]
_ = x[actRebind-111]
_ = x[actBecome-112]
_ = x[actShowHeader-113]
_ = x[actHideHeader-114]
}
const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeListLabelactChangeInputLabelactChangeHeaderactChangeHeaderLabelactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactChangeNthactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformListLabelactTransformInputLabelactTransformHeaderactTransformHeaderLabelactTransformPreviewLabelactTransformPromptactTransformQueryactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeader"
const _actionType_name = "actIgnoreactStartactClickactInvalidactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeHeaderactChangeMultiactChangePreviewLabelactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformHeaderactTransformPreviewLabelactTransformPromptactTransformQueryactPreviewactChangePreviewactChangePreviewWindowactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactBecomeactShowHeaderactHideHeader"
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 245, 264, 279, 299, 313, 334, 349, 363, 375, 389, 402, 419, 427, 440, 456, 468, 476, 490, 504, 515, 526, 544, 561, 568, 587, 599, 613, 622, 637, 649, 662, 673, 684, 696, 710, 731, 746, 759, 777, 793, 808, 825, 832, 837, 846, 857, 868, 881, 896, 907, 920, 935, 942, 955, 968, 985, 1000, 1013, 1027, 1041, 1057, 1077, 1089, 1112, 1133, 1155, 1173, 1196, 1220, 1238, 1255, 1265, 1281, 1303, 1316, 1332, 1344, 1358, 1374, 1392, 1412, 1434, 1448, 1463, 1471, 1477, 1491, 1506, 1516, 1532, 1547, 1557, 1565, 1572, 1581, 1594, 1610, 1625, 1634, 1645, 1654, 1663, 1672, 1685, 1698}
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 42, 50, 68, 76, 85, 102, 123, 138, 159, 183, 198, 207, 227, 242, 256, 277, 292, 306, 320, 333, 350, 358, 371, 387, 399, 407, 421, 435, 446, 457, 475, 492, 499, 518, 530, 544, 553, 568, 580, 593, 604, 615, 627, 641, 662, 677, 690, 708, 724, 739, 756, 763, 768, 777, 788, 799, 812, 827, 838, 851, 866, 873, 886, 899, 916, 931, 944, 958, 972, 988, 1008, 1020, 1043, 1061, 1085, 1103, 1120, 1130, 1146, 1168, 1181, 1197, 1209, 1223, 1239, 1257, 1277, 1299, 1313, 1328, 1336, 1342, 1356, 1371, 1381, 1397, 1412, 1422, 1430, 1437, 1446, 1459, 1475, 1490, 1499, 1510, 1519, 1528, 1537, 1550, 1563}
func (i actionType) String() string {
if i < 0 || i >= actionType(len(_actionType_index)-1) {

View File

@@ -401,7 +401,7 @@ func debugV2(T []rune, pattern []rune, F []int32, lastIdx int, H []int16, C []in
if i == 0 {
fmt.Print(" ")
for j := int(f); j <= lastIdx; j++ {
fmt.Print(" " + string(T[j]) + " ")
fmt.Printf(" " + string(T[j]) + " ")
}
fmt.Println()
}

View File

@@ -44,7 +44,7 @@ func (s *ansiState) ToString() string {
}
ret := ""
if s.attr&tui.Bold > 0 || s.attr&tui.BoldForce > 0 {
if s.attr&tui.Bold > 0 {
ret += "1;"
}
if s.attr&tui.Dim > 0 {
@@ -98,11 +98,11 @@ func isPrint(c uint8) bool {
return '\x20' <= c && c <= '\x7e'
}
func matchOperatingSystemCommand(s string, start int) int {
func matchOperatingSystemCommand(s string) int {
// `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)`
// ^ match starting here after the first printable character
// ^ match starting here
//
i := start // prefix matched in nextAnsiEscapeSequence()
i := 5 // prefix matched in nextAnsiEscapeSequence()
for ; i < len(s) && isPrint(s[i]); i++ {
}
if i < len(s) {
@@ -156,7 +156,7 @@ func isCtrlSeqStart(c uint8) bool {
// nextAnsiEscapeSequence returns the ANSI escape sequence and is equivalent to
// calling FindStringIndex() on the below regex (which was originally used):
//
// "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
// "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
func nextAnsiEscapeSequence(s string) (int, int) {
// fast check for ANSI escape sequences
i := 0
@@ -191,20 +191,12 @@ Loop:
}
}
// match: `\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)`
if i+5 < len(s) && s[i+1] == ']' {
j := 2
// \x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)
// ------
for ; i+j < len(s) && isNumeric(s[i+j]); j++ {
}
// match: `\x1b][0-9][;:][[:print:]]+(?:\x1b\\\\|\x07)`
if i+5 < len(s) && s[i+1] == ']' && isNumeric(s[i+2]) &&
(s[i+3] == ';' || s[i+3] == ':') && isPrint(s[i+4]) {
// \x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)
// ---------------
if j > 2 && i+j+1 < len(s) && (s[i+j] == ';' || s[i+j] == ':') && isPrint(s[i+j+1]) {
if k := matchOperatingSystemCommand(s[i:], j+2); k != -1 {
return i, i + k
}
if j := matchOperatingSystemCommand(s[i:]); j != -1 {
return i, i + j
}
}
@@ -318,15 +310,20 @@ func extractColor(str string, state *ansiState, proc func(string, *ansiState) bo
return trimmed, nil, state
}
func parseAnsiCode(s string) (int, string) {
func parseAnsiCode(s string, delimiter byte) (int, byte, string) {
var remaining string
var i int
// Faster than strings.IndexAny(";:")
i = strings.IndexByte(s, ';')
if i < 0 {
i = strings.IndexByte(s, ':')
if delimiter == 0 {
// Faster than strings.IndexAny(";:")
i = strings.IndexByte(s, ';')
if i < 0 {
i = strings.IndexByte(s, ':')
}
} else {
i = strings.IndexByte(s, delimiter)
}
if i >= 0 {
delimiter = s[i]
remaining = s[i+1:]
s = s[:i]
}
@@ -338,14 +335,14 @@ func parseAnsiCode(s string) (int, string) {
for _, ch := range stringBytes(s) {
ch -= '0'
if ch > 9 {
return -1, remaining
return -1, delimiter, remaining
}
code = code*10 + int(ch)
}
return code, remaining
return code, delimiter, remaining
}
return -1, remaining
return -1, delimiter, remaining
}
func interpretCode(ansiCode string, prevState *ansiState) ansiState {
@@ -381,10 +378,11 @@ func interpretCode(ansiCode string, prevState *ansiState) ansiState {
state256 := 0
ptr := &state.fg
var delimiter byte
count := 0
for len(ansiCode) != 0 {
var num int
if num, ansiCode = parseAnsiCode(ansiCode); num != -1 {
if num, delimiter, ansiCode = parseAnsiCode(ansiCode, delimiter); num != -1 {
count++
switch state256 {
case 0:

View File

@@ -335,28 +335,6 @@ func TestExtractColor(t *testing.T) {
assert((*offsets)[0], 0, 6, 2, -1, true)
assert((*offsets)[1], 6, 11, 200, 100, false)
})
state = nil
var color24 tui.Color = (1 << 24) + (180 << 16) + (190 << 8) + 254
src = "\x1b[1mhello \x1b[22;1;38:2:180:190:254mworld"
check(func(offsets *[]ansiOffset, state *ansiState) {
if len(*offsets) != 2 {
t.Fail()
}
if state.fg != color24 || state.attr != 1 {
t.Fail()
}
assert((*offsets)[0], 0, 6, -1, -1, true)
assert((*offsets)[1], 6, 11, color24, -1, true)
})
src = "\x1b]133;A\x1b\\hello \x1b]133;C\x1b\\world"
check(func(offsets *[]ansiOffset, state *ansiState) {
if len(*offsets) != 1 {
t.Fail()
}
assert((*offsets)[0], 0, 11, color24, -1, true)
})
}
func TestAnsiCodeStringConversion(t *testing.T) {
@@ -403,7 +381,7 @@ func TestParseAnsiCode(t *testing.T) {
{"-2", "", -1},
}
for _, x := range tests {
n, s := parseAnsiCode(x.In)
n, _, s := parseAnsiCode(x.In, 0)
if n != x.N || s != x.Exp {
t.Fatalf("%q: got: (%d %q) want: (%d %q)", x.In, n, s, x.N, x.Exp)
}

View File

@@ -39,8 +39,13 @@ func (r revision) compatible(other revision) bool {
// Run starts fzf
func Run(opts *Options) (int, error) {
if opts.Filter == nil {
if opts.Tmux != nil && len(os.Getenv("TMUX")) > 0 && opts.Tmux.index >= opts.Height.index {
return runTmux(os.Args, opts)
if opts.Tmux != nil && opts.Tmux.index >= opts.Height.index {
if len(os.Getenv("TMUX")) > 0 {
return runTmux(os.Args, opts)
}
if len(os.Getenv("ZELLIJ")) > 0 {
return runZellij(os.Args, opts)
}
}
if needWinpty(opts) {
@@ -190,14 +195,11 @@ func Run(opts *Options) (int, error) {
forward = true
}
}
nth := opts.Nth
nthRevision := 0
patternCache := make(map[string]*Pattern)
patternBuilder := func(runes []rune) *Pattern {
return BuildPattern(cache, patternCache,
opts.Fuzzy, opts.FuzzyAlgo, opts.Extended, opts.Case, opts.Normalize, forward, withPos,
opts.Filter == nil, nth, opts.Delimiter, nthRevision, runes)
opts.Filter == nil, opts.Nth, opts.Delimiter, runes)
}
inputRevision := revision{}
snapshotRevision := revision{}
@@ -376,14 +378,6 @@ func Run(opts *Options) (int, error) {
command = val.command
environ = val.environ
changed = val.changed
if val.nth != nil {
// Change nth and clear caches
nth = *val.nth
nthRevision++
patternCache = make(map[string]*Pattern)
cache.Clear()
inputRevision.bumpMinor()
}
if command != nil {
useSnapshot = val.sync
}

View File

@@ -6,17 +6,10 @@ import (
"github.com/junegunn/fzf/src/util"
)
type transformed struct {
// Because nth can be changed dynamically by change-nth action, we need to
// keep the revision number at the time of transformation.
revision int
tokens []Token
}
// Item represents each input line. 56 bytes.
type Item struct {
text util.Chars // 32 = 24 + 1 + 1 + 2 + 4
transformed *transformed // 8
transformed *[]Token // 8
origText *[]byte // 8
colors *[]ansiOffset // 8
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,13 +9,9 @@ import (
)
func TestDelimiterRegex(t *testing.T) {
// Valid regex, but a single character -> string
// Valid regex
delim := delimiterRegexp(".")
if delim.regex != nil || *delim.str != "." {
t.Error(delim)
}
delim = delimiterRegexp("|")
if delim.regex != nil || *delim.str != "|" {
if delim.regex == nil || delim.str != nil {
t.Error(delim)
}
// Broken regex -> string

View File

@@ -60,7 +60,6 @@ type Pattern struct {
cacheKey string
delimiter Delimiter
nth []Range
revision int
procFun map[termType]algo.Algo
cache *ChunkCache
}
@@ -73,7 +72,7 @@ func init() {
// BuildPattern builds Pattern object from the given arguments
func BuildPattern(cache *ChunkCache, patternCache map[string]*Pattern, fuzzy bool, fuzzyAlgo algo.Algo, extended bool, caseMode Case, normalize bool, forward bool,
withPos bool, cacheable bool, nth []Range, delimiter Delimiter, revision int, runes []rune) *Pattern {
withPos bool, cacheable bool, nth []Range, delimiter Delimiter, runes []rune) *Pattern {
var asString string
if extended {
@@ -141,7 +140,6 @@ func BuildPattern(cache *ChunkCache, patternCache map[string]*Pattern, fuzzy boo
sortable: sortable,
cacheable: cacheable,
nth: nth,
revision: revision,
delimiter: delimiter,
cache: cache,
procFun: make(map[termType]algo.Algo)}
@@ -395,15 +393,12 @@ func (p *Pattern) extendedMatch(item *Item, withPos bool, slab *util.Slab) ([]Of
func (p *Pattern) transformInput(item *Item) []Token {
if item.transformed != nil {
transformed := *item.transformed
if transformed.revision == p.revision {
return transformed.tokens
}
return *item.transformed
}
tokens := Tokenize(item.text.ToString(), p.delimiter)
ret := Transform(tokens, p.nth)
item.transformed = &transformed{p.revision, ret}
item.transformed = &ret
return ret
}

View File

@@ -68,7 +68,7 @@ func buildPattern(fuzzy bool, fuzzyAlgo algo.Algo, extended bool, caseMode Case,
withPos bool, cacheable bool, nth []Range, delimiter Delimiter, runes []rune) *Pattern {
return BuildPattern(NewChunkCache(), make(map[string]*Pattern),
fuzzy, fuzzyAlgo, extended, caseMode, normalize, forward,
withPos, cacheable, nth, delimiter, 0, runes)
withPos, cacheable, nth, delimiter, runes)
}
func TestExact(t *testing.T) {
@@ -135,12 +135,12 @@ func TestOrigTextAndTransformed(t *testing.T) {
chunk.items[0] = Item{
text: util.ToChars([]byte("junegunn")),
origText: &origBytes,
transformed: &transformed{pattern.revision, trans}}
transformed: &trans}
pattern.extended = extended
matches := pattern.matchChunk(&chunk, nil, slab) // No cache
if !(matches[0].item.text.ToString() == "junegunn" &&
string(*matches[0].item.origText) == "junegunn.choi" &&
reflect.DeepEqual((*matches[0].item.transformed).tokens, trans)) {
reflect.DeepEqual(*matches[0].item.transformed, trans)) {
t.Error("Invalid match result", matches)
}
@@ -148,7 +148,7 @@ func TestOrigTextAndTransformed(t *testing.T) {
if !(match.item.text.ToString() == "junegunn" &&
string(*match.item.origText) == "junegunn.choi" &&
offsets[0][0] == 0 && offsets[0][1] == 5 &&
reflect.DeepEqual((*match.item.transformed).tokens, trans)) {
reflect.DeepEqual(*match.item.transformed, trans)) {
t.Error("Invalid match result", match, offsets, extended)
}
if !((*pos)[0] == 4 && (*pos)[1] == 0) {

View File

@@ -104,11 +104,11 @@ func minRank() Result {
return Result{item: &minItem, points: [4]uint16{math.MaxUint16, 0, 0, 0}}
}
func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, theme *tui.ColorTheme, colBase tui.ColorPair, colMatch tui.ColorPair, attrNth tui.Attr, current bool) []colorOffset {
func (result *Result) colorOffsets(matchOffsets []Offset, theme *tui.ColorTheme, colBase tui.ColorPair, colMatch tui.ColorPair, current bool) []colorOffset {
itemColors := result.item.Colors()
// No ANSI codes
if len(itemColors) == 0 && len(nthOffsets) == 0 {
if len(itemColors) == 0 {
var offsets []colorOffset
for _, off := range matchOffsets {
offsets = append(offsets, colorOffset{offset: [2]int32{off[0], off[1]}, color: colMatch, match: true})
@@ -118,7 +118,7 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
// Find max column
var maxCol int32
for _, off := range append(matchOffsets, nthOffsets...) {
for _, off := range matchOffsets {
if off[1] > maxCol {
maxCol = off[1]
}
@@ -129,29 +129,20 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
}
}
type cellInfo struct {
index int
color bool
match bool
nth bool
}
cols := make([]cellInfo, maxCol)
cols := make([]int, maxCol)
for colorIndex, ansi := range itemColors {
for i := ansi.offset[0]; i < ansi.offset[1]; i++ {
cols[i] = cellInfo{colorIndex, true, false, false}
cols[i] = colorIndex + 1 // 1-based index of itemColors
}
}
for _, off := range matchOffsets {
for i := off[0]; i < off[1]; i++ {
cols[i].match = true
}
}
for _, off := range nthOffsets {
for i := off[0]; i < off[1]; i++ {
cols[i].nth = true
// Negative of 1-based index of itemColors
// - The extra -1 means highlighted
if cols[i] >= 0 {
cols[i] = cols[i]*-1 - 1
}
}
}
@@ -161,7 +152,7 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
// ------------ ---- -- ----
// ++++++++ ++++++++++
// --++++++++-- --++++++++++---
var curr cellInfo = cellInfo{0, false, false, false}
curr := 0
start := 0
ansiToColorPair := func(ansi ansiOffset, base tui.ColorPair) tui.ColorPair {
fg := ansi.color.fg
@@ -184,17 +175,12 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
}
var colors []colorOffset
add := func(idx int) {
if (curr.color || curr.nth || curr.match) && idx > start {
if curr.match {
var color tui.ColorPair
if curr.nth {
color = colBase.WithAttr(attrNth).Merge(colMatch)
} else {
color = colBase.Merge(colMatch)
}
if curr != 0 && idx > start {
if curr < 0 {
color := colMatch
var url *url
if curr.color && theme.Colored {
ansi := itemColors[curr.index]
if curr < -1 && theme.Colored {
ansi := itemColors[-curr-2]
url = ansi.color.url
origColor := ansiToColorPair(ansi, colMatch)
// hl or hl+ only sets the foreground color, so colMatch is the
@@ -207,32 +193,19 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
// echo -e "\x1b[42mfoo\x1b[mbar" | fzf --ansi --color bg+:1,hl+:-1:underline
if color.Fg().IsDefault() && origColor.HasBg() {
color = origColor
if curr.nth {
color = color.WithAttr(attrNth)
}
} else {
color = origColor.MergeNonDefault(color)
}
}
colors = append(colors, colorOffset{
offset: [2]int32{int32(start), int32(idx)}, color: color, match: true, url: url})
} else if curr.color {
ansi := itemColors[curr.index]
color := ansiToColorPair(ansi, colBase)
if curr.nth {
color = color.WithAttr(attrNth)
}
} else {
ansi := itemColors[curr-1]
colors = append(colors, colorOffset{
offset: [2]int32{int32(start), int32(idx)},
color: color,
color: ansiToColorPair(ansi, colBase),
match: false,
url: ansi.color.url})
} else {
colors = append(colors, colorOffset{
offset: [2]int32{int32(start), int32(idx)},
color: colBase.WithAttr(attrNth),
match: false,
url: nil})
}
}
}

View File

@@ -131,7 +131,7 @@ func TestColorOffset(t *testing.T) {
colBase := tui.NewColorPair(89, 189, tui.AttrUndefined)
colMatch := tui.NewColorPair(99, 199, tui.AttrUndefined)
colors := item.colorOffsets(offsets, nil, tui.Dark256, colBase, colMatch, tui.AttrUndefined, true)
colors := item.colorOffsets(offsets, tui.Dark256, colBase, colMatch, true)
assert := func(idx int, b int32, e int32, c tui.ColorPair) {
o := colors[idx]
if o.offset[0] != b || o.offset[1] != e || o.color != c {
@@ -155,30 +155,20 @@ func TestColorOffset(t *testing.T) {
colRegular := tui.NewColorPair(-1, -1, tui.AttrUndefined)
colUnderline := tui.NewColorPair(-1, -1, tui.Underline)
colors = item.colorOffsets(offsets, tui.Dark256, colRegular, colUnderline, true)
nthOffsets := []Offset{{37, 39}, {42, 45}}
for _, attr := range []tui.Attr{tui.AttrRegular, tui.StrikeThrough} {
colors = item.colorOffsets(offsets, nthOffsets, tui.Dark256, colRegular, colUnderline, attr, true)
// [{[0 5] {1 5 0}} {[5 15] {1 5 8}} {[15 20] {1 5 0}}
// {[22 25] {2 6 1}} {[25 27] {2 6 9}} {[27 30] {-1 -1 8}}
// {[30 32] {3 7 8}} {[32 33] {-1 -1 8}} {[33 35] {4 8 9}}
// {[35 37] {4 8 1}} {[37 39] {4 8 x|1}} {[39 40] {4 8 x|1}}]
assert(0, 0, 5, tui.NewColorPair(1, 5, tui.AttrUndefined))
assert(1, 5, 15, tui.NewColorPair(1, 5, tui.Underline))
assert(2, 15, 20, tui.NewColorPair(1, 5, tui.AttrUndefined))
assert(3, 22, 25, tui.NewColorPair(2, 6, tui.Bold))
assert(4, 25, 27, tui.NewColorPair(2, 6, tui.Bold|tui.Underline))
assert(5, 27, 30, colUnderline)
assert(6, 30, 32, tui.NewColorPair(3, 7, tui.Underline))
assert(7, 32, 33, colUnderline)
assert(8, 33, 35, tui.NewColorPair(4, 8, tui.Bold|tui.Underline))
assert(9, 35, 37, tui.NewColorPair(4, 8, tui.Bold))
expected := tui.Bold | attr
if attr == tui.AttrRegular {
expected = tui.AttrRegular
}
assert(10, 37, 39, tui.NewColorPair(4, 8, expected))
assert(11, 39, 40, tui.NewColorPair(4, 8, tui.Bold))
}
// [{[0 5] {1 5 0}} {[5 15] {1 5 8}} {[15 20] {1 5 0}}
// {[22 25] {2 6 1}} {[25 27] {2 6 9}} {[27 30] {-1 -1 8}}
// {[30 32] {3 7 8}} {[32 33] {-1 -1 8}} {[33 35] {4 8 9}}
// {[35 40] {4 8 1}}]
assert(0, 0, 5, tui.NewColorPair(1, 5, tui.AttrUndefined))
assert(1, 5, 15, tui.NewColorPair(1, 5, tui.Underline))
assert(2, 15, 20, tui.NewColorPair(1, 5, tui.AttrUndefined))
assert(3, 22, 25, tui.NewColorPair(2, 6, tui.Bold))
assert(4, 25, 27, tui.NewColorPair(2, 6, tui.Bold|tui.Underline))
assert(5, 27, 30, colUnderline)
assert(6, 30, 32, tui.NewColorPair(3, 7, tui.Underline))
assert(7, 32, 33, colUnderline)
assert(8, 33, 35, tui.NewColorPair(4, 8, tui.Bold|tui.Underline))
assert(9, 35, 40, tui.NewColorPair(4, 8, tui.Bold))
}

File diff suppressed because it is too large Load Diff

View File

@@ -9,21 +9,16 @@ import (
func runTmux(args []string, opts *Options) (int, error) {
// Prepare arguments
fzf, rest := args[0], args[1:]
args = []string{"--bind=ctrl-z:ignore"}
if !opts.Tmux.border && opts.BorderShape == tui.BorderUndefined {
// We append --border option at the end, because `--style=full:STYLE`
// may have changed the default border style.
rest = append(rest, "--border")
}
if opts.Tmux.border && opts.Margin == defaultMargin() {
args = append(args, "--margin=0,1")
fzf := args[0]
args = append([]string{"--bind=ctrl-z:ignore"}, args[1:]...)
if opts.BorderShape == tui.BorderUndefined {
args = append(args, "--border")
}
argStr := escapeSingleQuote(fzf)
for _, arg := range append(args, rest...) {
for _, arg := range args {
argStr += " " + escapeSingleQuote(arg)
}
argStr += ` --no-tmux --no-height`
argStr += ` --no-popup --no-height`
// Get current directory
dir, err := os.Getwd()
@@ -38,10 +33,7 @@ func runTmux(args []string, opts *Options) (int, error) {
// M Both The mouse position
// W Both The window position on the status line
// S -y The line above or below the status line
tmuxArgs := []string{"display-popup", "-E", "-d", dir}
if !opts.Tmux.border {
tmuxArgs = append(tmuxArgs, "-B")
}
tmuxArgs := []string{"display-popup", "-E", "-B", "-d", dir}
switch opts.Tmux.position {
case posUp:
tmuxArgs = append(tmuxArgs, "-xC", "-y0")

View File

@@ -18,36 +18,6 @@ type Range struct {
end int
}
func (r Range) IsFull() bool {
return r.begin == rangeEllipsis && r.end == rangeEllipsis
}
func RangesToString(ranges []Range) string {
strs := []string{}
for _, r := range ranges {
s := ""
if r.begin == rangeEllipsis && r.end == rangeEllipsis {
s = ".."
} else if r.begin == r.end {
s = strconv.Itoa(r.begin)
} else {
if r.begin != rangeEllipsis {
s += strconv.Itoa(r.begin)
}
if r.begin != -1 {
s += ".."
if r.end != rangeEllipsis {
s += strconv.Itoa(r.end)
}
}
}
strs = append(strs, s)
}
return strings.Join(strs, ",")
}
// Token contains the tokenized part of the strings and its prefix length
type Token struct {
text *util.Chars
@@ -71,7 +41,7 @@ func (d Delimiter) String() string {
}
func newRange(begin int, end int) Range {
if begin == 1 && end != 1 {
if begin == 1 {
begin = rangeEllipsis
}
if end == -1 {
@@ -103,7 +73,7 @@ func ParseRange(str *string) (Range, bool) {
}
begin, err1 := strconv.Atoi(ns[0])
end, err2 := strconv.Atoi(ns[1])
if err1 != nil || err2 != nil || begin == 0 || end == 0 || begin < 0 && end > 0 {
if err1 != nil || err2 != nil || begin == 0 || end == 0 {
return Range{}, false
}
return newRange(begin, end), true

View File

@@ -40,18 +40,6 @@ func TestParseRange(t *testing.T) {
t.Errorf("%v", r)
}
}
{
i := "1..3..5"
if r, ok := ParseRange(&i); ok {
t.Errorf("%v", r)
}
}
{
i := "-3..3"
if r, ok := ParseRange(&i); ok {
t.Errorf("%v", r)
}
}
}
func TestTokenize(t *testing.T) {

View File

@@ -11,11 +11,6 @@ func HasFullscreenRenderer() bool {
var DefaultBorderShape = BorderRounded
func (a Attr) Merge(b Attr) Attr {
if b&AttrRegular > 0 {
// Only keep bold attribute set by the system
return b | (a & BoldForce)
}
return a | b
}
@@ -23,7 +18,6 @@ const (
AttrUndefined = Attr(0)
AttrRegular = Attr(1 << 8)
AttrClear = Attr(1 << 9)
BoldForce = Attr(1 << 10)
Bold = Attr(1)
Dim = Attr(1 << 1)
@@ -36,7 +30,6 @@ const (
)
func (r *FullscreenRenderer) Init() error { return nil }
func (r *FullscreenRenderer) DefaultTheme() *ColorTheme { return nil }
func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {}
func (r *FullscreenRenderer) Pause(bool) {}
func (r *FullscreenRenderer) Resume(bool, bool) {}
@@ -55,6 +48,6 @@ func (r *FullscreenRenderer) MaxY() int { return 0 }
func (r *FullscreenRenderer) RefreshWindows(windows []Window) {}
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window {
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window {
return nil
}

View File

@@ -116,19 +116,19 @@ type LightRenderer struct {
}
type LightWindow struct {
renderer *LightRenderer
colored bool
windowType WindowType
border BorderStyle
top int
left int
width int
height int
posx int
posy int
tabstop int
fg Color
bg Color
renderer *LightRenderer
colored bool
preview bool
border BorderStyle
top int
left int
width int
height int
posx int
posy int
tabstop int
fg Color
bg Color
}
func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) {
@@ -174,6 +174,7 @@ func (r *LightRenderer) Init() error {
return err
}
r.updateTerminalSize()
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
if r.fullscreen {
r.smcup()
@@ -779,40 +780,27 @@ func (r *LightRenderer) MaxY() int {
return r.height
}
func (r *LightRenderer) NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window {
width = util.Max(0, width)
height = util.Max(0, height)
func (r *LightRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window {
w := &LightWindow{
renderer: r,
colored: r.theme.Colored,
windowType: windowType,
border: borderStyle,
top: top,
left: left,
width: width,
height: height,
tabstop: r.tabstop,
fg: colDefault,
bg: colDefault}
switch windowType {
case WindowBase:
w.fg = r.theme.Fg.Color
w.bg = r.theme.Bg.Color
case WindowList:
w.fg = r.theme.ListFg.Color
w.bg = r.theme.ListBg.Color
case WindowInput:
w.fg = r.theme.Input.Color
w.bg = r.theme.InputBg.Color
case WindowHeader:
w.fg = r.theme.Header.Color
w.bg = r.theme.HeaderBg.Color
case WindowPreview:
renderer: r,
colored: r.theme.Colored,
preview: preview,
border: borderStyle,
top: top,
left: left,
width: width,
height: height,
tabstop: r.tabstop,
fg: colDefault,
bg: colDefault}
if preview {
w.fg = r.theme.PreviewFg.Color
w.bg = r.theme.PreviewBg.Color
} else {
w.fg = r.theme.Fg.Color
w.bg = r.theme.Bg.Color
}
if erase && !w.bg.IsDefault() && w.border.shape != BorderNone {
// fzf --color bg:blue --border --padding 1,2
if !w.bg.IsDefault() && w.border.shape != BorderNone {
w.Erase()
}
w.drawBorder(false)
@@ -828,9 +816,6 @@ func (w *LightWindow) DrawHBorder() {
}
func (w *LightWindow) drawBorder(onlyHorizontal bool) {
if w.height == 0 {
return
}
switch w.border.shape {
case BorderRounded, BorderSharp, BorderBold, BorderBlock, BorderThinBlock, BorderDouble:
w.drawBorderAround(onlyHorizontal)
@@ -860,14 +845,7 @@ func (w *LightWindow) drawBorder(onlyHorizontal bool) {
func (w *LightWindow) drawBorderHorizontal(top, bottom bool) {
color := ColBorder
switch w.windowType {
case WindowList:
color = ColListBorder
case WindowInput:
color = ColInputBorder
case WindowHeader:
color = ColHeaderBorder
case WindowPreview:
if w.preview {
color = ColPreviewBorder
}
hw := runeWidth(w.border.top)
@@ -885,14 +863,7 @@ func (w *LightWindow) drawBorderHorizontal(top, bottom bool) {
func (w *LightWindow) drawBorderVertical(left, right bool) {
vw := runeWidth(w.border.left)
color := ColBorder
switch w.windowType {
case WindowList:
color = ColListBorder
case WindowInput:
color = ColInputBorder
case WindowHeader:
color = ColHeaderBorder
case WindowPreview:
if w.preview {
color = ColPreviewBorder
}
for y := 0; y < w.height; y++ {
@@ -912,14 +883,7 @@ func (w *LightWindow) drawBorderVertical(left, right bool) {
func (w *LightWindow) drawBorderAround(onlyHorizontal bool) {
w.Move(0, 0)
color := ColBorder
switch w.windowType {
case WindowList:
color = ColListBorder
case WindowInput:
color = ColInputBorder
case WindowHeader:
color = ColHeaderBorder
case WindowPreview:
if w.preview {
color = ColPreviewBorder
}
hw := runeWidth(w.border.top)
@@ -979,16 +943,9 @@ func (w *LightWindow) Y() int {
return w.posy
}
func (w *LightWindow) EncloseX(x int) bool {
return x >= w.left && x < (w.left+w.width)
}
func (w *LightWindow) EncloseY(y int) bool {
return y >= w.top && y < (w.top+w.height)
}
func (w *LightWindow) Enclose(y int, x int) bool {
return w.EncloseX(x) && w.EncloseY(y)
return x >= w.left && x < (w.left+w.width) &&
y >= w.top && y < (w.top+w.height)
}
func (w *LightWindow) Move(y int, x int) {
@@ -1011,7 +968,7 @@ func attrCodes(attr Attr) []string {
if (attr & AttrClear) > 0 {
return codes
}
if (attr&Bold) > 0 || (attr&BoldForce) > 0 {
if (attr & Bold) > 0 {
codes = append(codes, "1")
}
if (attr & Dim) > 0 {

View File

@@ -18,7 +18,7 @@ func IsLightRendererSupported() bool {
return true
}
func (r *LightRenderer) DefaultTheme() *ColorTheme {
func (r *LightRenderer) defaultTheme() *ColorTheme {
if strings.Contains(os.Getenv("TERM"), "256") {
return Dark256
}

View File

@@ -39,7 +39,7 @@ func IsLightRendererSupported() bool {
return canSetVt100
}
func (r *LightRenderer) DefaultTheme() *ColorTheme {
func (r *LightRenderer) defaultTheme() *ColorTheme {
// the getenv check is borrowed from here: https://github.com/gdamore/tcell/commit/0c473b86d82f68226a142e96cc5a34c5a29b3690#diff-b008fcd5e6934bf31bc3d33bf49f47d8R178:
if !IsLightRendererSupported() || os.Getenv("ConEmuPID") != "" || os.Getenv("TCELL_TRUECOLOR") == "disable" {
return Default16

View File

@@ -40,7 +40,7 @@ type Attr int32
type TcellWindow struct {
color bool
windowType WindowType
preview bool
top int
left int
width int
@@ -97,7 +97,6 @@ const (
AttrUndefined = Attr(0)
AttrRegular = Attr(1 << 7)
AttrClear = Attr(1 << 8)
BoldForce = Attr(1 << 10)
)
func (r *FullscreenRenderer) PassThrough(str string) {
@@ -107,12 +106,8 @@ func (r *FullscreenRenderer) PassThrough(str string) {
func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {}
func (r *FullscreenRenderer) DefaultTheme() *ColorTheme {
s, e := r.getScreen()
if e != nil {
return Default16
}
if s.Colors() >= 256 {
func (r *FullscreenRenderer) defaultTheme() *ColorTheme {
if _screen.Colors() >= 256 {
return Dark256
}
return Default16
@@ -142,11 +137,6 @@ func (c Color) Style() tcell.Color {
}
func (a Attr) Merge(b Attr) Attr {
if b&AttrRegular > 0 {
// Only keep bold attribute set by the system
return b | (a & BoldForce)
}
return a | b
}
@@ -158,19 +148,8 @@ var (
_initialResize bool = true
)
func (r *FullscreenRenderer) getScreen() (tcell.Screen, error) {
if _screen == nil {
s, e := tcell.NewScreen()
if e != nil {
return nil, e
}
_screen = s
}
return _screen, nil
}
func (r *FullscreenRenderer) initScreen() error {
s, e := r.getScreen()
s, e := tcell.NewScreen()
if e != nil {
return e
}
@@ -182,6 +161,7 @@ func (r *FullscreenRenderer) initScreen() error {
} else {
s.DisableMouse()
}
_screen = s
return nil
}
@@ -194,6 +174,7 @@ func (r *FullscreenRenderer) Init() error {
if err := r.initScreen(); err != nil {
return err
}
initTheme(r.theme, r.defaultTheme(), r.forceBlack)
return nil
}
@@ -556,23 +537,14 @@ func (r *FullscreenRenderer) RefreshWindows(windows []Window) {
_screen.Show()
}
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window {
width = util.Max(0, width)
height = util.Max(0, height)
normal := ColBorder
switch windowType {
case WindowList:
normal = ColNormal
case WindowHeader:
normal = ColHeader
case WindowInput:
normal = ColInput
case WindowPreview:
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window {
normal := ColNormal
if preview {
normal = ColPreview
}
w := &TcellWindow{
color: r.theme.Colored,
windowType: windowType,
preview: preview,
top: top,
left: left,
width: width,
@@ -592,7 +564,11 @@ func fill(x, y, w, h int, n ColorPair, r rune) {
}
func (w *TcellWindow) Erase() {
fill(w.left, w.top, w.width-1, w.height-1, w.normal, ' ')
if w.borderStyle.shape.HasLeft() {
fill(w.left-1, w.top, w.width, w.height-1, w.normal, ' ')
} else {
fill(w.left, w.top, w.width-1, w.height-1, w.normal, ' ')
}
w.drawBorder(false)
}
@@ -601,16 +577,9 @@ func (w *TcellWindow) EraseMaybe() bool {
return true
}
func (w *TcellWindow) EncloseX(x int) bool {
return x >= w.left && x < (w.left+w.width)
}
func (w *TcellWindow) EncloseY(y int) bool {
return y >= w.top && y < (w.top+w.height)
}
func (w *TcellWindow) Enclose(y int, x int) bool {
return w.EncloseX(x) && w.EncloseY(y)
return x >= w.left && x < (w.left+w.width) &&
y >= w.top && y < (w.top+w.height)
}
func (w *TcellWindow) Move(y int, x int) {
@@ -700,7 +669,7 @@ func (w *TcellWindow) fillString(text string, pair ColorPair) FillReturn {
}
style = style.
Blink(a&Attr(tcell.AttrBlink) != 0).
Bold(a&Attr(tcell.AttrBold) != 0 || a&BoldForce != 0).
Bold(a&Attr(tcell.AttrBold) != 0).
Dim(a&Attr(tcell.AttrDim) != 0).
Reverse(a&Attr(tcell.AttrReverse) != 0).
Underline(a&Attr(tcell.AttrUnderline) != 0).
@@ -787,9 +756,6 @@ func (w *TcellWindow) DrawHBorder() {
}
func (w *TcellWindow) drawBorder(onlyHorizontal bool) {
if w.height == 0 {
return
}
shape := w.borderStyle.shape
if shape == BorderNone {
return
@@ -802,17 +768,10 @@ func (w *TcellWindow) drawBorder(onlyHorizontal bool) {
var style tcell.Style
if w.color {
switch w.windowType {
case WindowBase:
style = ColBorder.style()
case WindowList:
style = ColListBorder.style()
case WindowHeader:
style = ColHeaderBorder.style()
case WindowInput:
style = ColInputBorder.style()
case WindowPreview:
if w.preview {
style = ColPreviewBorder.style()
} else {
style = ColBorder.style()
}
} else {
style = w.normal.style()

View File

@@ -15,7 +15,7 @@ func TtyIn() (*os.File, error) {
return os.Stdin, nil
}
// TtyOut on Windows returns nil
// TtyIn on Windows returns nil
func TtyOut() (*os.File, error) {
return nil, nil
}

View File

@@ -205,24 +205,10 @@ type ColorAttr struct {
Attr Attr
}
func (a ColorAttr) IsColorDefined() bool {
return a.Color != colUndefined
}
func NewColorAttr() ColorAttr {
return ColorAttr{Color: colUndefined, Attr: AttrUndefined}
}
func (a ColorAttr) Merge(other ColorAttr) ColorAttr {
if other.Color != colUndefined {
a.Color = other.Color
}
if other.Attr != AttrUndefined {
a.Attr = a.Attr.Merge(other.Attr)
}
return a
}
const (
colUndefined Color = -2
colDefault Color = -1
@@ -317,9 +303,6 @@ type ColorTheme struct {
Disabled ColorAttr
Fg ColorAttr
Bg ColorAttr
ListFg ColorAttr
ListBg ColorAttr
Nth ColorAttr
SelectedFg ColorAttr
SelectedBg ColorAttr
SelectedMatch ColorAttr
@@ -328,9 +311,6 @@ type ColorTheme struct {
DarkBg ColorAttr
Gutter ColorAttr
Prompt ColorAttr
InputBg ColorAttr
InputBorder ColorAttr
InputLabel ColorAttr
Match ColorAttr
Current ColorAttr
CurrentMatch ColorAttr
@@ -339,19 +319,13 @@ type ColorTheme struct {
Cursor ColorAttr
Marker ColorAttr
Header ColorAttr
HeaderBg ColorAttr
HeaderBorder ColorAttr
HeaderLabel ColorAttr
Separator ColorAttr
Scrollbar ColorAttr
Border ColorAttr
PreviewBorder ColorAttr
PreviewLabel ColorAttr
PreviewScrollbar ColorAttr
BorderLabel ColorAttr
ListLabel ColorAttr
ListBorder ColorAttr
GapLine ColorAttr
PreviewLabel ColorAttr
}
type Event struct {
@@ -374,7 +348,6 @@ type BorderShape int
const (
BorderUndefined BorderShape = iota
BorderLine
BorderNone
BorderRounded
BorderSharp
@@ -392,7 +365,7 @@ const (
func (s BorderShape) HasLeft() bool {
switch s {
case BorderNone, BorderLine, BorderRight, BorderTop, BorderBottom, BorderHorizontal: // No Left
case BorderNone, BorderRight, BorderTop, BorderBottom, BorderHorizontal: // No Left
return false
}
return true
@@ -400,7 +373,7 @@ func (s BorderShape) HasLeft() bool {
func (s BorderShape) HasRight() bool {
switch s {
case BorderNone, BorderLine, BorderLeft, BorderTop, BorderBottom, BorderHorizontal: // No right
case BorderNone, BorderLeft, BorderTop, BorderBottom, BorderHorizontal: // No right
return false
}
return true
@@ -408,7 +381,7 @@ func (s BorderShape) HasRight() bool {
func (s BorderShape) HasTop() bool {
switch s {
case BorderNone, BorderLine, BorderLeft, BorderRight, BorderBottom, BorderVertical: // No top
case BorderNone, BorderLeft, BorderRight, BorderBottom, BorderVertical: // No top
return false
}
return true
@@ -416,16 +389,12 @@ func (s BorderShape) HasTop() bool {
func (s BorderShape) HasBottom() bool {
switch s {
case BorderNone, BorderLine, BorderLeft, BorderRight, BorderTop, BorderVertical: // No bottom
case BorderNone, BorderLeft, BorderRight, BorderTop, BorderVertical: // No bottom
return false
}
return true
}
func (s BorderShape) Visible() bool {
return s != BorderNone
}
type BorderStyle struct {
shape BorderShape
top rune
@@ -556,18 +525,7 @@ type TermSize struct {
PxHeight int
}
type WindowType int
const (
WindowBase WindowType = iota
WindowList
WindowPreview
WindowInput
WindowHeader
)
type Renderer interface {
DefaultTheme() *ColorTheme
Init() error
Resize(maxHeightFunc func(int) int)
Pause(clear bool)
@@ -588,7 +546,7 @@ type Renderer interface {
Size() TermSize
NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window
NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window
}
type Window interface {
@@ -604,8 +562,6 @@ type Window interface {
X() int
Y() int
EncloseX(x int) bool
EncloseY(y int) bool
Enclose(y int, x int) bool
Move(y int, x int)
@@ -662,11 +618,8 @@ var (
ColSpinner ColorPair
ColInfo ColorPair
ColHeader ColorPair
ColHeaderBorder ColorPair
ColHeaderLabel ColorPair
ColSeparator ColorPair
ColScrollbar ColorPair
ColGapLine ColorPair
ColBorder ColorPair
ColPreview ColorPair
ColPreviewBorder ColorPair
@@ -674,10 +627,6 @@ var (
ColPreviewLabel ColorPair
ColPreviewScrollbar ColorPair
ColPreviewSpinner ColorPair
ColListBorder ColorPair
ColListLabel ColorPair
ColInputBorder ColorPair
ColInputLabel ColorPair
)
func EmptyTheme() *ColorTheme {
@@ -686,8 +635,6 @@ func EmptyTheme() *ColorTheme {
Input: ColorAttr{colUndefined, AttrUndefined},
Fg: ColorAttr{colUndefined, AttrUndefined},
Bg: ColorAttr{colUndefined, AttrUndefined},
ListFg: ColorAttr{colUndefined, AttrUndefined},
ListBg: ColorAttr{colUndefined, AttrUndefined},
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
@@ -703,8 +650,6 @@ func EmptyTheme() *ColorTheme {
Header: ColorAttr{colUndefined, AttrUndefined},
Border: ColorAttr{colUndefined, AttrUndefined},
BorderLabel: ColorAttr{colUndefined, AttrUndefined},
ListLabel: ColorAttr{colUndefined, AttrUndefined},
ListBorder: ColorAttr{colUndefined, AttrUndefined},
Disabled: ColorAttr{colUndefined, AttrUndefined},
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
@@ -714,14 +659,6 @@ func EmptyTheme() *ColorTheme {
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
Separator: ColorAttr{colUndefined, AttrUndefined},
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
InputBg: ColorAttr{colUndefined, AttrUndefined},
InputBorder: ColorAttr{colUndefined, AttrUndefined},
InputLabel: ColorAttr{colUndefined, AttrUndefined},
HeaderBg: ColorAttr{colUndefined, AttrUndefined},
HeaderBorder: ColorAttr{colUndefined, AttrUndefined},
HeaderLabel: ColorAttr{colUndefined, AttrUndefined},
GapLine: ColorAttr{colUndefined, AttrUndefined},
Nth: ColorAttr{colUndefined, AttrUndefined},
}
}
@@ -731,8 +668,6 @@ func NoColorTheme() *ColorTheme {
Input: ColorAttr{colDefault, AttrUndefined},
Fg: ColorAttr{colDefault, AttrUndefined},
Bg: ColorAttr{colDefault, AttrUndefined},
ListFg: ColorAttr{colDefault, AttrUndefined},
ListBg: ColorAttr{colDefault, AttrUndefined},
SelectedFg: ColorAttr{colDefault, AttrUndefined},
SelectedBg: ColorAttr{colDefault, AttrUndefined},
SelectedMatch: ColorAttr{colDefault, AttrUndefined},
@@ -755,18 +690,8 @@ func NoColorTheme() *ColorTheme {
PreviewBorder: ColorAttr{colDefault, AttrUndefined},
PreviewScrollbar: ColorAttr{colDefault, AttrUndefined},
PreviewLabel: ColorAttr{colDefault, AttrUndefined},
ListLabel: ColorAttr{colDefault, AttrUndefined},
ListBorder: ColorAttr{colDefault, AttrUndefined},
Separator: ColorAttr{colDefault, AttrUndefined},
Scrollbar: ColorAttr{colDefault, AttrUndefined},
InputBg: ColorAttr{colDefault, AttrUndefined},
InputBorder: ColorAttr{colDefault, AttrUndefined},
InputLabel: ColorAttr{colDefault, AttrUndefined},
HeaderBg: ColorAttr{colDefault, AttrUndefined},
HeaderBorder: ColorAttr{colDefault, AttrUndefined},
HeaderLabel: ColorAttr{colDefault, AttrUndefined},
GapLine: ColorAttr{colDefault, AttrUndefined},
Nth: ColorAttr{colUndefined, AttrUndefined},
}
}
@@ -776,8 +701,6 @@ func init() {
Input: ColorAttr{colDefault, AttrUndefined},
Fg: ColorAttr{colDefault, AttrUndefined},
Bg: ColorAttr{colDefault, AttrUndefined},
ListFg: ColorAttr{colUndefined, AttrUndefined},
ListBg: ColorAttr{colUndefined, AttrUndefined},
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
@@ -800,23 +723,14 @@ func init() {
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
ListLabel: ColorAttr{colUndefined, AttrUndefined},
ListBorder: ColorAttr{colUndefined, AttrUndefined},
Separator: ColorAttr{colUndefined, AttrUndefined},
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
InputBg: ColorAttr{colUndefined, AttrUndefined},
InputBorder: ColorAttr{colUndefined, AttrUndefined},
InputLabel: ColorAttr{colUndefined, AttrUndefined},
GapLine: ColorAttr{colUndefined, AttrUndefined},
Nth: ColorAttr{colUndefined, AttrUndefined},
}
Dark256 = &ColorTheme{
Colored: true,
Input: ColorAttr{colDefault, AttrUndefined},
Fg: ColorAttr{colDefault, AttrUndefined},
Bg: ColorAttr{colDefault, AttrUndefined},
ListFg: ColorAttr{colUndefined, AttrUndefined},
ListBg: ColorAttr{colUndefined, AttrUndefined},
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
@@ -839,23 +753,14 @@ func init() {
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
ListLabel: ColorAttr{colUndefined, AttrUndefined},
ListBorder: ColorAttr{colUndefined, AttrUndefined},
Separator: ColorAttr{colUndefined, AttrUndefined},
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
InputBg: ColorAttr{colUndefined, AttrUndefined},
InputBorder: ColorAttr{colUndefined, AttrUndefined},
InputLabel: ColorAttr{colUndefined, AttrUndefined},
GapLine: ColorAttr{colUndefined, AttrUndefined},
Nth: ColorAttr{colUndefined, AttrUndefined},
}
Light256 = &ColorTheme{
Colored: true,
Input: ColorAttr{colDefault, AttrUndefined},
Fg: ColorAttr{colDefault, AttrUndefined},
Bg: ColorAttr{colDefault, AttrUndefined},
ListFg: ColorAttr{colUndefined, AttrUndefined},
ListBg: ColorAttr{colUndefined, AttrUndefined},
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
@@ -878,22 +783,12 @@ func init() {
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
ListLabel: ColorAttr{colUndefined, AttrUndefined},
ListBorder: ColorAttr{colUndefined, AttrUndefined},
Separator: ColorAttr{colUndefined, AttrUndefined},
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
InputBg: ColorAttr{colUndefined, AttrUndefined},
InputBorder: ColorAttr{colUndefined, AttrUndefined},
InputLabel: ColorAttr{colUndefined, AttrUndefined},
HeaderBg: ColorAttr{colUndefined, AttrUndefined},
HeaderBorder: ColorAttr{colUndefined, AttrUndefined},
HeaderLabel: ColorAttr{colUndefined, AttrUndefined},
GapLine: ColorAttr{colUndefined, AttrUndefined},
Nth: ColorAttr{colUndefined, AttrUndefined},
}
}
func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInputWindow bool, hasHeaderWindow bool) {
func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) {
if forceBlack {
theme.Bg = ColorAttr{colBlack, AttrUndefined}
}
@@ -914,9 +809,7 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
theme.DarkBg = o(baseTheme.DarkBg, theme.DarkBg)
theme.Prompt = o(baseTheme.Prompt, theme.Prompt)
theme.Match = o(baseTheme.Match, theme.Match)
// Inherit from 'fg', so that we don't have to write 'current-fg:dim'
// e.g. fzf --delimiter / --nth -1 --color fg:dim,nth:regular
theme.Current = theme.Fg.Merge(o(baseTheme.Current, theme.Current))
theme.Current = o(baseTheme.Current, theme.Current)
theme.CurrentMatch = o(baseTheme.CurrentMatch, theme.CurrentMatch)
theme.Spinner = o(baseTheme.Spinner, theme.Spinner)
theme.Info = o(baseTheme.Info, theme.Info)
@@ -926,15 +819,9 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
theme.Border = o(baseTheme.Border, theme.Border)
theme.BorderLabel = o(baseTheme.BorderLabel, theme.BorderLabel)
undefined := NewColorAttr()
scrollbarDefined := theme.Scrollbar != undefined
previewBorderDefined := theme.PreviewBorder != undefined
// These colors are not defined in the base themes
theme.ListFg = o(theme.Fg, theme.ListFg)
theme.ListBg = o(theme.Bg, theme.ListBg)
theme.SelectedFg = o(theme.ListFg, theme.SelectedFg)
theme.SelectedBg = o(theme.ListBg, theme.SelectedBg)
theme.SelectedFg = o(theme.Fg, theme.SelectedFg)
theme.SelectedBg = o(theme.Bg, theme.SelectedBg)
theme.SelectedMatch = o(theme.Match, theme.SelectedMatch)
theme.Disabled = o(theme.Input, theme.Disabled)
theme.Gutter = o(theme.DarkBg, theme.Gutter)
@@ -942,38 +829,9 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
theme.PreviewBg = o(theme.Bg, theme.PreviewBg)
theme.PreviewLabel = o(theme.BorderLabel, theme.PreviewLabel)
theme.PreviewBorder = o(theme.Border, theme.PreviewBorder)
theme.ListLabel = o(theme.BorderLabel, theme.ListLabel)
theme.ListBorder = o(theme.Border, theme.ListBorder)
theme.Separator = o(theme.ListBorder, theme.Separator)
theme.Scrollbar = o(theme.ListBorder, theme.Scrollbar)
theme.GapLine = o(theme.ListBorder, theme.GapLine)
/*
--color list-border:green
--color scrollbar:red
--color scrollbar:red,list-border:green
--color scrollbar:red,preview-border:green
*/
if scrollbarDefined && !previewBorderDefined {
theme.PreviewScrollbar = o(theme.Scrollbar, theme.PreviewScrollbar)
} else {
theme.PreviewScrollbar = o(theme.PreviewBorder, theme.PreviewScrollbar)
}
if hasInputWindow {
theme.InputBg = o(theme.Bg, theme.InputBg)
} else {
// We shouldn't use input-bg if there's no separate input window
// e.g. fzf --color 'list-bg:green,input-bg:red' --no-input-border
theme.InputBg = o(theme.Bg, theme.ListBg)
}
theme.InputBorder = o(theme.Border, theme.InputBorder)
theme.InputLabel = o(theme.BorderLabel, theme.InputLabel)
if hasHeaderWindow {
theme.HeaderBg = o(theme.Bg, theme.HeaderBg)
} else {
theme.HeaderBg = o(theme.Bg, theme.ListBg)
}
theme.HeaderBorder = o(theme.Border, theme.HeaderBorder)
theme.HeaderLabel = o(theme.BorderLabel, theme.HeaderLabel)
theme.Separator = o(theme.Border, theme.Separator)
theme.Scrollbar = o(theme.Border, theme.Scrollbar)
theme.PreviewScrollbar = o(theme.PreviewBorder, theme.PreviewScrollbar)
initPalette(theme)
}
@@ -985,19 +843,19 @@ func initPalette(theme *ColorTheme) {
}
return ColorPair{fg.Color, bg.Color, fg.Attr}
}
blank := theme.ListFg
blank := theme.Fg
blank.Attr = AttrRegular
ColPrompt = pair(theme.Prompt, theme.InputBg)
ColNormal = pair(theme.ListFg, theme.ListBg)
ColPrompt = pair(theme.Prompt, theme.Bg)
ColNormal = pair(theme.Fg, theme.Bg)
ColSelected = pair(theme.SelectedFg, theme.SelectedBg)
ColInput = pair(theme.Input, theme.InputBg)
ColDisabled = pair(theme.Disabled, theme.ListBg)
ColMatch = pair(theme.Match, theme.ListBg)
ColInput = pair(theme.Input, theme.Bg)
ColDisabled = pair(theme.Disabled, theme.Bg)
ColMatch = pair(theme.Match, theme.Bg)
ColSelectedMatch = pair(theme.SelectedMatch, theme.SelectedBg)
ColCursor = pair(theme.Cursor, theme.Gutter)
ColCursorEmpty = pair(blank, theme.Gutter)
if theme.SelectedBg.Color != theme.ListBg.Color {
if theme.SelectedBg.Color != theme.Bg.Color {
ColMarker = pair(theme.Marker, theme.SelectedBg)
} else {
ColMarker = pair(theme.Marker, theme.Gutter)
@@ -1008,11 +866,11 @@ func initPalette(theme *ColorTheme) {
ColCurrentCursorEmpty = pair(blank, theme.DarkBg)
ColCurrentMarker = pair(theme.Marker, theme.DarkBg)
ColCurrentSelectedEmpty = pair(blank, theme.DarkBg)
ColSpinner = pair(theme.Spinner, theme.InputBg)
ColInfo = pair(theme.Info, theme.InputBg)
ColSeparator = pair(theme.Separator, theme.InputBg)
ColScrollbar = pair(theme.Scrollbar, theme.ListBg)
ColGapLine = pair(theme.GapLine, theme.ListBg)
ColSpinner = pair(theme.Spinner, theme.Bg)
ColInfo = pair(theme.Info, theme.Bg)
ColHeader = pair(theme.Header, theme.Bg)
ColSeparator = pair(theme.Separator, theme.Bg)
ColScrollbar = pair(theme.Scrollbar, theme.Bg)
ColBorder = pair(theme.Border, theme.Bg)
ColBorderLabel = pair(theme.BorderLabel, theme.Bg)
ColPreviewLabel = pair(theme.PreviewLabel, theme.PreviewBg)
@@ -1020,13 +878,6 @@ func initPalette(theme *ColorTheme) {
ColPreviewBorder = pair(theme.PreviewBorder, theme.PreviewBg)
ColPreviewScrollbar = pair(theme.PreviewScrollbar, theme.PreviewBg)
ColPreviewSpinner = pair(theme.Spinner, theme.PreviewBg)
ColListLabel = pair(theme.ListLabel, theme.ListBg)
ColListBorder = pair(theme.ListBorder, theme.ListBg)
ColInputBorder = pair(theme.InputBorder, theme.InputBg)
ColInputLabel = pair(theme.InputLabel, theme.InputBg)
ColHeader = pair(theme.Header, theme.HeaderBg)
ColHeaderBorder = pair(theme.HeaderBorder, theme.HeaderBg)
ColHeaderLabel = pair(theme.HeaderLabel, theme.HeaderBg)
}
func runeWidth(r rune) int {

103
src/zellij.go Normal file
View File

@@ -0,0 +1,103 @@
package fzf
import (
"fmt"
"os"
"os/exec"
"strconv"
"github.com/junegunn/fzf/src/tui"
)
func runZellij(args []string, opts *Options) (int, error) {
// Prepare arguments
fzf := args[0]
args = append([]string{"--bind=ctrl-z:ignore"}, args[1:]...)
if opts.BorderShape == tui.BorderUndefined {
args = append(args, "--no-border")
}
argStr := escapeSingleQuote(fzf)
for _, arg := range args {
argStr += " " + escapeSingleQuote(arg)
}
argStr += ` --no-popup --no-height`
// Get current directory
dir, err := os.Getwd()
if err != nil {
dir = "."
}
sh, err := sh(false)
if err != nil {
return ExitError, err
}
fifo, err := fifo("zellij-fifo")
if err != nil {
return ExitError, err
}
zopts := " --width " + opts.Tmux.width.String() + " --height " + opts.Tmux.height.String()
centerX := func() {
// TODO: Handle non-percent values
if opts.Tmux.width.percent {
x := (100.0 - opts.Tmux.width.size) / 2
if x <= 0 {
zopts += " -x0"
} else {
zopts += fmt.Sprintf(" -x%d%%", int(x))
}
} else if cols := os.Getenv("COLUMNS"); len(cols) > 0 {
if w, e := strconv.Atoi(cols); e == nil {
x := (float64(w) - opts.Tmux.width.size) / 2
zopts += fmt.Sprintf(" -x%d", int(x))
}
}
}
centerY := func() {
if opts.Tmux.height.percent {
y := (100.0 - opts.Tmux.height.size) / 2
if y <= 0 {
zopts += " -y0"
} else {
zopts += fmt.Sprintf(" -y%d%%", int(y))
}
} else if lines := os.Getenv("LINES"); len(lines) > 0 {
if h, e := strconv.Atoi(lines); e == nil {
y := (float64(h) - opts.Tmux.height.size) / 2
zopts += fmt.Sprintf(" -y%d", int(y))
}
}
}
switch opts.Tmux.position {
case posUp:
zopts += " -y0"
centerX()
case posDown:
zopts += " -y9999"
centerX()
case posLeft:
zopts += " -x0"
centerY()
case posRight:
zopts += " -x9999"
centerY()
case posCenter:
centerX()
centerY()
}
lines := []string{
"#!/bin/sh",
fmt.Sprintf(`zellij run --name '' --floating --close-on-exit --cwd %s %s -- %s -c "%s $1; echo \$? > %s" || exit $?`, dir, zopts, sh, sh, fifo),
fmt.Sprintf(`exit $(cat %s)`, fifo),
}
temptemp := WriteTemporaryFile(lines, "\n")
defer os.Remove(temptemp)
return runProxy(argStr, func(temp string, needBash bool) (*exec.Cmd, error) {
return exec.Command(sh, temptemp, temp), nil
}, opts, true)
}

View File

@@ -2646,7 +2646,7 @@ class TestGoFZF < TestBase
end
def test_change_preview_window
tmux.send_keys "seq 1000 | #{FZF} --preview 'echo [[{}]]' --no-preview-border --bind '" \
tmux.send_keys "seq 1000 | #{FZF} --preview 'echo [[{}]]' --preview-window border-none --bind '" \
'a:change-preview(echo __{}__),' \
'b:change-preview-window(down)+change-preview(echo =={}==)+change-preview-window(up),' \
'c:change-preview(),d:change-preview-window(hidden),' \
@@ -3423,363 +3423,32 @@ class TestGoFZF < TestBase
>
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 --gap-line xyz --border --reverse), :Enter
tmux.send_keys %(seq 100 | #{FZF} --gap=2 --border --reverse), :Enter
block = <<~BLOCK
>
100/100
> 1
xyzxyzxyzxyzxy
2
xyzxyzxyzxyzxy
3
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_list_border_and_label
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --query 1 --padding 1,2), :Enter
block = <<~BLOCK
11
> 10
3
2
1
19/97
> 1
list
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_input_border_and_label
tmux.send_keys %(seq 100 | #{FZF} --border rounded --input-border bold --input-label input --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2), :Enter
block = <<~BLOCK
11
> 10
3
2
1
input
19/97
> 1
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_input_border_and_label_header_first
tmux.send_keys %(seq 100 | #{FZF} --border rounded --input-border bold --input-label input --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2 --header-first), :Enter
block = <<~BLOCK
11
> 10
input
19/97
> 1
3
2
1
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_list_input_border_and_label
tmux.send_keys %(
seq 100 | #{FZF} --border rounded --list-border double --input-border bold --list-label-pos 2:bottom --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2 \
--bind 'start:transform-input-label(echo INPUT)+transform-list-label(echo LIST)' \
--bind 'space:change-input-label( input )+change-list-label( list )'
).strip, :Enter
block = <<~BLOCK
11
> 10
LIST
3
2
1
INPUT
19/97
> 1
BLOCK
tmux.until { assert_block(block, _1) }
tmux.send_keys :Space
block = <<~BLOCK
11
> 10
list
3
2
1
input
19/97
> 1
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_list_input_border_and_label_header_first
tmux.send_keys %(
seq 100 | #{FZF} --border rounded --list-border double --input-border bold --list-label-pos 2:bottom --input-label-pos 2 --header-lines 3 --query 1 --padding 1,2 \
--bind 'start:transform-input-label(echo INPUT)+transform-list-label(echo LIST)' \
--bind 'space:change-input-label( input )+change-list-label( list )' --header-first
).strip, :Enter
block = <<~BLOCK
11
> 10
LIST
INPUT
19/97
> 1
3
2
1
BLOCK
tmux.until { assert_block(block, _1) }
tmux.send_keys :Space
block = <<~BLOCK
11
> 10
list
input
19/97
> 1
3
2
1
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_header_border_and_label
tmux.send_keys %(seq 100 | #{FZF} --border rounded --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2), :Enter
block = <<~BLOCK
12
11
> 10
3
2
1
header
19/97
> 1
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_header_border_and_label_header_first
tmux.send_keys %(seq 100 | #{FZF} --border rounded --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --header-first), :Enter
block = <<~BLOCK
12
11
> 10
19/97
> 1
3
2
1
header
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_header_border_and_label_with_list_border
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2), :Enter
block = <<~BLOCK
12
11
> 10
list
3
2
1
header
19/97
> 1
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_header_border_and_label_with_list_border_header_first
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --header-first), :Enter
block = <<~BLOCK
12
11
> 10
list
19/97
> 1
3
2
1
header
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_all_borders
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --input-border bold --input-label input --input-label-pos 2:bottom), :Enter
block = <<~BLOCK
12
11
> 10
list
3
2
1
header
19/97
> 1
input
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_all_borders_header_first
tmux.send_keys %(seq 100 | #{FZF} --border rounded --list-border double --list-label list --list-label-pos 2:bottom --header-lines 3 --header-border sharp --header-label header --header-label-pos 2:bottom --query 1 --padding 1,2 --input-border bold --input-label input --input-label-pos 2:bottom --header-first), :Enter
block = <<~BLOCK
12
11
> 10
list
19/97
> 1
input
3
2
1
header
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_style_full_adaptive_height
tmux.send_keys %(seq 1| #{FZF} --style=full --height=~100% --header-lines=1 --info=default), :Enter
block = <<~BLOCK
1
0/0
>
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_style_full_adaptive_height_double
tmux.send_keys %(seq 1| #{FZF} --style=full:double --border --height=~100% --header-lines=1 --info=default), :Enter
block = <<~BLOCK
1
0/0
>
BLOCK
tmux.until { assert_block(block, _1) }
end
def test_change_nth
input = [
*[''] * 1000,
'foo bar bar bar bar',
'foo foo bar bar bar',
'foo foo foo bar bar',
'foo foo foo foo bar',
*[''] * 1000
]
writelines(input)
nths = '1,2..4,-1,-3..,..2'
tmux.send_keys %(#{FZF} -qfoo -n#{nths} --bind 'space:change-nth(2|3|4|5|),result:transform-prompt:echo "[$FZF_NTH] "' < #{tempname}), :Enter
tmux.until do |lines|
assert lines.any_include?("[#{nths}] foo")
assert_equal 4, lines.match_count
end
tmux.send_keys :Space
tmux.until do |lines|
assert lines.any_include?('[2] foo')
assert_equal 3, lines.match_count
end
tmux.send_keys :Space
tmux.until do |lines|
assert lines.any_include?('[3] foo')
assert_equal 2, lines.match_count
end
tmux.send_keys :Space
tmux.until do |lines|
assert lines.any_include?('[4] foo')
assert_equal 1, lines.match_count
end
tmux.send_keys :Space
tmux.until do |lines|
assert lines.any_include?('[5] foo')
assert_equal 0, lines.match_count
end
tmux.send_keys :Space
tmux.until do |lines|
assert lines.any_include?("[#{nths}] foo")
assert_equal 4, lines.match_count
end
end
end
module TestShell