m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-13 13:53:47 -05:00

Compare commits

..

22 Commits

Author SHA1 Message Date
Junegunn Choi
1f389c4933 Build with Go 1.21 2025-09-11 00:22:16 +09:00
junegunn
a0a334fc8d Deploying to master from @ junegunn/fzf@ae12e94b1f 🚀 2025-09-07 00:02:03 +00:00
Massimo Mund
ae12e94b1f Add sub-word actions (#3997)
Add `backward-subword`, `forward-subword`, `kill-subword`, `backward-kill-subword` actions.
2025-09-05 19:38:22 +09:00
Massimo Mund
9ed971cc90 Add keybindings for CTRL, ALT, SHIFT + UP, DOWN, RIGHT, LEFT, HOME, END, BACKSPACE, DELETE & more (#3996)
* Added tests for `LightRenderer`

* Added common SHIFT, ALT and ALT+SHIFT key sequences

* Added common CTRL key sequences

* Added common CTRL+ALT, CTRL+SHIFT, CTRL+ALT+SHIFT key sequences

* Added proper xterm META modifier handling

according to defc6dd568/input.c (L357-L375)

* Fix `ctrl-backspace` and `ctrl-alt-backspace`

* Fix broken tcell tests on windows by swallowing Resize events

* Added tests for  FullscreenRenderer

* Removed own fork of tcell and updated tcell to 2.9.0

tcell 2.9.0 is needed for `Ctrl-Alt-*` and `Ctrl-Alt-Shift-*` shortcuts in Windows

* Replace conditional checks with switch statements to improve readability

* Replace long conditionals with constant slices to improve readability

* Bind `ctrl-bspace` (`ctrl-h`) to `backward-delete-char` by default

Since we now distinguish between Backspace and Ctrl-Backspace, Ctrl-Backspace should trigger the same action as Backspace by default. In that way nothing changes for the user but you can bind other actions to Ctrl-Backspace when desired.
2025-09-05 14:56:51 +09:00
Junegunn Choi
129cb23078 Require Go 1.23 2025-09-05 14:45:17 +09:00
dependabot[bot]
d22812e917 Bump github.com/gdamore/tcell/v2 from 2.8.1 to 2.9.0 (#4503)
Bumps [github.com/gdamore/tcell/v2](https://github.com/gdamore/tcell) from 2.8.1 to 2.9.0.
- [Release notes](https://github.com/gdamore/tcell/releases)
- [Changelog](https://github.com/gdamore/tcell/blob/main/CHANGESv2.md)
- [Commits](https://github.com/gdamore/tcell/compare/v2.8.1...v2.9.0)

---
updated-dependencies:
- dependency-name: github.com/gdamore/tcell/v2
  dependency-version: 2.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-05 14:39:37 +09:00
Charlie Vieth
10d712824a mod: update charlievieth/fastwalk to v1.0.13 and min Go version to 1.21 (#4508)
This commit updates github.com/charlievieth/fastwalk to v1.0.13 which
addresses fastwalk issue #61. It also updates the minimum supported Go
version to 1.21 (up from 1.20) since that is now the minimum version
supported by fastwalk.
2025-09-04 22:04:52 +09:00
Junegunn Choi
de4059c8fa Update README 2025-09-03 08:18:57 +09:00
Junegunn Choi
416aff86e9 0.65.2 2025-08-31 22:18:44 +09:00
zhedazijingang
59dc7f178f refactor: replace []byte(fmt.Sprintf) with fmt.Appendf (#4507)
Signed-off-by: zhedazijingang <unwrap_or_else@outlook.com>
2025-08-31 22:01:35 +09:00
junegunn
a3c9f8bfee Deploying to master from @ junegunn/fzf@5546c65491 🚀 2025-08-31 00:02:03 +00:00
Junegunn Choi
5546c65491 Fix rendering of items with tabs when using a non-default ellipsis
Fix #4505
2025-08-27 23:31:31 +09:00
junegunn
f2179f015c Deploying to master from @ junegunn/fzf@9a53d84b9c 🚀 2025-08-24 00:02:30 +00:00
Junegunn Choi
9a53d84b9c Update README.md 2025-08-22 22:51:04 +09:00
Junegunn Choi
0a8ff7899c Do not unset FZF_DEFAULT_* variables when using winpty
Fix #4497
Fix #4400
2025-08-22 19:24:01 +09:00
xty
f9d7877d8b [bash 3] Fix CTRL-T and ALT-C to preserve the last yank (#4496) 2025-08-19 23:31:02 +09:00
Peter Sideris
9fe9976591 Fix a typo in man page (#4495) 2025-08-19 23:25:57 +09:00
Chayoung You
de1824f71d [install] Support old uname in macOS (#4492) 2025-08-17 11:54:32 +09:00
dependabot[bot]
19a9296c47 Bump actions/checkout from 4 to 5 (#4485)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-15 21:17:29 +09:00
Ioannis Pinakoulakis
49967f3d45 Use fixed-length array when possible (#4488) 2025-08-15 21:16:41 +09:00
longhutianjie
978b6254c7 chore: remove redundant word in comment (#4490)
Signed-off-by: longhutianjie <keplrnewton@icloud.com>
2025-08-14 13:26:29 +09:00
Junegunn Choi
1afd143810 Fix incorrect truncation of --info-command with --info=inline-right
Fix #4479
2025-08-08 18:51:24 +09:00
31 changed files with 1542 additions and 352 deletions

View File

@@ -27,7 +27,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-depth: 0

View File

@@ -9,6 +9,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: 'Dependency Review'
uses: actions/dependency-review-action@v4

View File

@@ -18,14 +18,14 @@ jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: Setup Ruby
uses: ruby/setup-ruby@v1

View File

@@ -15,14 +15,14 @@ jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: Setup Ruby
uses: ruby/setup-ruby@v1

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Generate Sponsors 💖
uses: JamesIves/github-sponsors-readme-action@v1

View File

@@ -6,5 +6,5 @@ jobs:
name: Spell Check with Typos
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: crate-ci/typos@v1.29.4

View File

@@ -1,2 +1,2 @@
golang 1.20.14
golang 1.21.13
ruby 3.4.1

View File

@@ -6,7 +6,7 @@ Build instructions
### Prerequisites
- Go 1.20 or above
- Go 1.23 or above
### Using Makefile
@@ -41,6 +41,20 @@ make release
> --profile-block /tmp/block.pprof --profile-mutex /tmp/mutex.pprof
> ```
Running tests
-------------
```sh
# Run go unit tests
make test
# Run integration tests (requires to be on tmux)
make itest
# Run a single test case
ruby test/runner.rb --name test_something
```
Third-party libraries used
--------------------------

View File

@@ -1,6 +1,17 @@
CHANGELOG
=========
0.65.2
------
- Bug fixes and improvements
- Fix incorrect truncation of `--info-command` with `--info=inline-right` (#4479)
- [install] Support old uname in macOS (#4492)
- [bash 3] Fix `CTRL-T` and `ALT-C` to preserve the last yank (#4496)
- Do not unset `FZF_DEFAULT_*` variables when using winpty (#4497) (#4400)
- Fix rendering of items with tabs when using a non-default ellipsis (#4505)
- **This is the final release to support Windows 7.**
- Future versions will be built with the latest Go toolchain, which has dropped support for Windows 7.
0.65.1
------
- Fixed incorrect `$FZF_CLICK_HEADER_WORD` and `$FZF_CLICK_FOOTER_WORD` when the header or footer contains ANSI escape sequences and tab characters.

File diff suppressed because one or more lines are too long

8
go.mod
View File

@@ -1,9 +1,9 @@
module github.com/junegunn/fzf
require (
github.com/charlievieth/fastwalk v1.0.12
github.com/gdamore/tcell/v2 v2.8.1
github.com/charlievieth/fastwalk v1.0.13
github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741
github.com/junegunn/tcell/v2 v2.9.1
github.com/mattn/go-isatty v0.0.20
github.com/rivo/uniseg v0.4.7
golang.org/x/sys v0.30.0
@@ -14,7 +14,7 @@ require (
github.com/gdamore/encoding v1.0.1 // 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
golang.org/x/text v0.22.0 // indirect
)
go 1.20
go 1.21.13

44
go.sum
View File

@@ -1,12 +1,11 @@
github.com/charlievieth/fastwalk v1.0.12 h1:pwfxe1LajixViQqo7EFLXU2+mQxb6OaO0CeNdVwRKTg=
github.com/charlievieth/fastwalk v1.0.12/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI=
github.com/charlievieth/fastwalk v1.0.13 h1:rCdesaKpxBft4jdNqKbJtTS23Dfhem3eEPE0jfj//xc=
github.com/charlievieth/fastwalk v1.0.13/go.mod h1:diVcUreiU1aQ4/Wu3NbxxH4/KYdKpLDojrQ1Bb2KgNY=
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/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741 h1:7dYDtfMDfKzjT+DVfIS4iqknSEKtZpEcXtu6vuaasHs=
github.com/junegunn/go-shellwords v0.0.0-20250127100254-2aa3b3277741/go.mod h1:6EILKtGpo5t+KLb85LNZLAF6P9LKp78hJI80PXMcn3c=
github.com/junegunn/tcell/v2 v2.9.1 h1:r5PqSXkPwCMWRCjOu6MY5xdtzpeNAo4W/eZMKEcibYA=
github.com/junegunn/tcell/v2 v2.9.1/go.mod h1:Hjh577pMWP9M119MS7yAK1ygOfQYjmOjdYxbSxlClaw=
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=
@@ -14,35 +13,20 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
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/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=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
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,38 +34,22 @@ 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/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
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/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
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/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/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
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.65.1
version=0.65.2
auto_completion=
key_bindings=
update_config=2
@@ -164,7 +164,7 @@ download() {
}
# Try to download binary executable
archi=$(uname -smo)
archi=$(uname -smo 2>/dev/null || uname -sm)
binary_available=1
binary_error=""
case "$archi" in

View File

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

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 "Aug 2025" "fzf 0.65.1" "fzf\-tmux - open fzf in tmux split pane"
.TH fzf\-tmux 1 "Aug 2025" "fzf 0.65.2" "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 "Aug 2025" "fzf 0.65.1" "fzf - a command-line fuzzy finder"
.TH fzf 1 "Aug 2025" "fzf 0.65.2" "fzf - a command-line fuzzy finder"
.SH NAME
fzf - a command-line fuzzy finder
@@ -1046,7 +1046,7 @@ are not affected by \fB\-\-with\-nth\fR. ANSI color codes are processed even whe
.TP
.BI "\-\-footer\-border" [=STYLE]
Draw border around the header section. \fBline\fR style draws a single
Draw border around the footer section. \fBline\fR style draws a single
separator line between the footer and the list section.
.TP
@@ -1473,12 +1473,22 @@ e.g.
.br
\fIalt\-right\fR
.br
\fIalt\-home\fR
.br
\fIalt\-end\fR
.br
\fIalt\-backspace\fR (\fIalt\-bspace\fR \fIalt\-bs\fR)
.br
\fIalt\-delete\fR
.br
\fIalt\-page\-up\fR
.br
\fIalt\-page\-down\fR
.br
\fIalt\-enter\fR
.br
\fIalt\-space\fR
.br
\fIalt\-backspace\fR (\fIalt\-bspace\fR \fIalt\-bs\fR)
.br
\fItab\fR
.br
\fIshift\-tab\fR (\fIbtab\fR)
@@ -1505,6 +1515,26 @@ e.g.
.br
\fIpage\-down\fR (\fIpgdn\fR)
.br
\fIctrl\-up\fR
.br
\fIctrl\-down\fR
.br
\fIctrl\-left\fR
.br
\fIctrl\-right\fR
.br
\fIctrl\-home\fR
.br
\fIctrl\-end\fR
.br
\fIctrl\-backspace\fR (\fIctrl\-bspace\fR \fIctrl\-bs\fR)
.br
\fIctrl\-delete\fR
.br
\fIctrl\-page\-up\fR
.br
\fIctrl\-page\-down\fR
.br
\fIshift\-up\fR
.br
\fIshift\-down\fR
@@ -1513,8 +1543,16 @@ e.g.
.br
\fIshift\-right\fR
.br
\fIshift\-home\fR
.br
\fIshift\-end\fR
.br
\fIshift\-delete\fR
.br
\fIshift\-page\-up\fR
.br
\fIshift\-page\-down\fR
.br
\fIalt\-shift\-up\fR
.br
\fIalt\-shift\-down\fR
@@ -1523,6 +1561,72 @@ e.g.
.br
\fIalt\-shift\-right\fR
.br
\fIalt\-shift\-home\fR
.br
\fIalt\-shift\-end\fR
.br
\fIalt\-shift\-delete\fR
.br
\fIalt\-shift\-page\-up\fR
.br
\fIalt\-shift\-page\-down\fR
.br
\fIctrl\-alt\-up\fR
.br
\fIctrl\-alt\-down\fR
.br
\fIctrl\-alt\-left\fR
.br
\fIctrl\-alt\-right\fR
.br
\fIctrl\-alt\-home\fR
.br
\fIctrl\-alt\-end\fR
.br
\fIctrl\-alt\-backspace\fR (\fIctrl\-alt\-bspace\fR \fIctrl\-alt\-bs\fR)
.br
\fIctrl\-alt\-delete\fR
.br
\fIctrl\-alt\-page\-up\fR
.br
\fIctrl\-alt\-page\-down\fR
.br
\fIctrl\-shift\-up\fR
.br
\fIctrl\-shift\-down\fR
.br
\fIctrl\-shift\-left\fR
.br
\fIctrl\-shift\-right\fR
.br
\fIctrl\-shift\-home\fR
.br
\fIctrl\-shift\-end\fR
.br
\fIctrl\-shift\-delete\fR
.br
\fIctrl\-shift\-page\-up\fR
.br
\fIctrl\-shift\-page\-down\fR
.br
\fIctrl\-alt\-shift\-up\fR
.br
\fIctrl\-alt\-shift\-down\fR
.br
\fIctrl\-alt\-shift\-left\fR
.br
\fIctrl\-alt\-shift\-right\fR
.br
\fIctrl\-alt\-shift\-home\fR
.br
\fIctrl\-alt\-shift\-end\fR
.br
\fIctrl\-alt\-shift\-delete\fR
.br
\fIctrl\-alt\-shift\-page\-up\fR
.br
\fIctrl\-alt\-shift\-page\-down\fR
.br
\fIleft\-click\fR
.br
\fIright\-click\fR
@@ -1547,6 +1651,8 @@ e.g.
.br
or any single character
Note that some terminal emulators may not support \fIctrl-*\fR bindings.
.SS AVAILABLE EVENTS:
\fIstart\fR
.RS
@@ -1699,9 +1805,11 @@ A key or an event can be bound to one or more of the following actions.
\fBaccept\-non\-empty\fR (same as \fBaccept\fR except that it prevents fzf from exiting without selection)
\fBaccept\-or\-print\-query\fR (same as \fBaccept\fR except that it prints the query when there's no match)
\fBbackward\-char\fR \fIctrl\-b left\fR
\fBbackward\-delete\-char\fR \fIctrl\-h bspace\fR
\fBbackward\-delete\-char\fR \fIctrl\-h ctrl\-bspace bspace\fR
\fBbackward\-delete\-char/eof\fR (same as \fBbackward\-delete\-char\fR except aborts fzf if query is empty)
\fBbackward\-kill\-subword\fR
\fBbackward\-kill\-word\fR \fIalt\-bs\fR
\fBbackward\-subword\fR
\fBbackward\-word\fR \fIalt\-b shift\-left\fR
\fBbecome(...)\fR (replace fzf process with the specified command; see below for the details)
\fBbeginning\-of\-line\fR \fIctrl\-a home\fR
@@ -1741,10 +1849,12 @@ A key or an event can be bound to one or more of the following actions.
\fBexecute\-silent(...)\fR (see below for the details)
\fBfirst\fR (move to the first match; same as \fBpos(1)\fR)
\fBforward\-char\fR \fIctrl\-f right\fR
\fBforward\-subword\fR
\fBforward\-word\fR \fIalt\-f shift\-right\fR
\fBignore\fR
\fBjump\fR (EasyMotion-like 2-keystroke movement)
\fBkill\-line\fR
\fBkill\-subword\fR
\fBkill\-word\fR \fIalt\-d\fR
\fBlast\fR (move to the last match; same as \fBpos(\-1)\fR)
\fBnext\-history\fR (\fIctrl\-n\fR on \fB\-\-history\fR)

View File

@@ -125,7 +125,7 @@ bind -m emacs-standard '"\C-z": vi-editing-mode'
if (( BASH_VERSINFO[0] < 4 )); then
# CTRL-T - Paste the selected file path into the command line
if [[ "${FZF_CTRL_T_COMMAND-x}" != "" ]]; then
bind -m emacs-standard '"\C-t": " \C-b\C-k \C-u`__fzf_select__`\e\C-e\er\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"'
bind -m emacs-standard '"\C-t": " \C-b\C-k \C-u`__fzf_select__`\e\C-e\er\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f\C-y\ey\C-_"'
bind -m vi-command '"\C-t": "\C-z\C-t\C-z"'
bind -m vi-insert '"\C-t": "\C-z\C-t\C-z"'
fi
@@ -150,7 +150,7 @@ fi
# ALT-C - cd into the selected directory
if [[ "${FZF_ALT_C_COMMAND-x}" != "" ]]; then
bind -m emacs-standard '"\ec": " \C-b\C-k \C-u`__fzf_cd__`\e\C-e\er\C-m\C-y\C-h\e \C-y\ey\C-x\C-x\C-d"'
bind -m emacs-standard '"\ec": " \C-b\C-k \C-u`__fzf_cd__`\e\C-e\er\C-m\C-y\C-h\e \C-y\ey\C-x\C-x\C-d\C-y\ey\C-_"'
bind -m vi-command '"\ec": "\C-z\ec\C-z"'
bind -m vi-insert '"\ec": "\C-z\ec\C-z"'
fi

View File

@@ -25,154 +25,158 @@ func _() {
_ = x[actBackwardDeleteChar-14]
_ = x[actBackwardDeleteCharEof-15]
_ = x[actBackwardWord-16]
_ = x[actCancel-17]
_ = x[actChangeBorderLabel-18]
_ = x[actChangeGhost-19]
_ = x[actChangeHeader-20]
_ = x[actChangeFooter-21]
_ = x[actChangeHeaderLabel-22]
_ = x[actChangeFooterLabel-23]
_ = x[actChangeInputLabel-24]
_ = x[actChangeListLabel-25]
_ = x[actChangeMulti-26]
_ = x[actChangeNth-27]
_ = x[actChangePointer-28]
_ = x[actChangePreview-29]
_ = x[actChangePreviewLabel-30]
_ = x[actChangePreviewWindow-31]
_ = x[actChangePrompt-32]
_ = x[actChangeQuery-33]
_ = x[actClearScreen-34]
_ = x[actClearQuery-35]
_ = x[actClearSelection-36]
_ = x[actClose-37]
_ = x[actDeleteChar-38]
_ = x[actDeleteCharEof-39]
_ = x[actEndOfLine-40]
_ = x[actFatal-41]
_ = x[actForwardChar-42]
_ = x[actForwardWord-43]
_ = x[actKillLine-44]
_ = x[actKillWord-45]
_ = x[actUnixLineDiscard-46]
_ = x[actUnixWordRubout-47]
_ = x[actYank-48]
_ = x[actBackwardKillWord-49]
_ = x[actSelectAll-50]
_ = x[actDeselectAll-51]
_ = x[actToggle-52]
_ = x[actToggleSearch-53]
_ = x[actToggleAll-54]
_ = x[actToggleDown-55]
_ = x[actToggleUp-56]
_ = x[actToggleIn-57]
_ = x[actToggleOut-58]
_ = x[actToggleTrack-59]
_ = x[actToggleTrackCurrent-60]
_ = x[actToggleHeader-61]
_ = x[actToggleWrap-62]
_ = x[actToggleMultiLine-63]
_ = x[actToggleHscroll-64]
_ = x[actTrackCurrent-65]
_ = x[actToggleInput-66]
_ = x[actHideInput-67]
_ = x[actShowInput-68]
_ = x[actUntrackCurrent-69]
_ = x[actDown-70]
_ = x[actUp-71]
_ = x[actPageUp-72]
_ = x[actPageDown-73]
_ = x[actPosition-74]
_ = x[actHalfPageUp-75]
_ = x[actHalfPageDown-76]
_ = x[actOffsetUp-77]
_ = x[actOffsetDown-78]
_ = x[actOffsetMiddle-79]
_ = x[actJump-80]
_ = x[actJumpAccept-81]
_ = x[actPrintQuery-82]
_ = x[actRefreshPreview-83]
_ = x[actReplaceQuery-84]
_ = x[actToggleSort-85]
_ = x[actShowPreview-86]
_ = x[actHidePreview-87]
_ = x[actTogglePreview-88]
_ = x[actTogglePreviewWrap-89]
_ = x[actTransform-90]
_ = x[actTransformBorderLabel-91]
_ = x[actTransformGhost-92]
_ = x[actTransformHeader-93]
_ = x[actTransformFooter-94]
_ = x[actTransformHeaderLabel-95]
_ = x[actTransformFooterLabel-96]
_ = x[actTransformInputLabel-97]
_ = x[actTransformListLabel-98]
_ = x[actTransformNth-99]
_ = x[actTransformPointer-100]
_ = x[actTransformPreviewLabel-101]
_ = x[actTransformPrompt-102]
_ = x[actTransformQuery-103]
_ = x[actTransformSearch-104]
_ = x[actTrigger-105]
_ = x[actBgTransform-106]
_ = x[actBgTransformBorderLabel-107]
_ = x[actBgTransformGhost-108]
_ = x[actBgTransformHeader-109]
_ = x[actBgTransformFooter-110]
_ = x[actBgTransformHeaderLabel-111]
_ = x[actBgTransformFooterLabel-112]
_ = x[actBgTransformInputLabel-113]
_ = x[actBgTransformListLabel-114]
_ = x[actBgTransformNth-115]
_ = x[actBgTransformPointer-116]
_ = x[actBgTransformPreviewLabel-117]
_ = x[actBgTransformPrompt-118]
_ = x[actBgTransformQuery-119]
_ = x[actBgTransformSearch-120]
_ = x[actBgCancel-121]
_ = x[actSearch-122]
_ = x[actPreview-123]
_ = x[actPreviewTop-124]
_ = x[actPreviewBottom-125]
_ = x[actPreviewUp-126]
_ = x[actPreviewDown-127]
_ = x[actPreviewPageUp-128]
_ = x[actPreviewPageDown-129]
_ = x[actPreviewHalfPageUp-130]
_ = x[actPreviewHalfPageDown-131]
_ = x[actPrevHistory-132]
_ = x[actPrevSelected-133]
_ = x[actPrint-134]
_ = x[actPut-135]
_ = x[actNextHistory-136]
_ = x[actNextSelected-137]
_ = x[actExecute-138]
_ = x[actExecuteSilent-139]
_ = x[actExecuteMulti-140]
_ = x[actSigStop-141]
_ = x[actFirst-142]
_ = x[actLast-143]
_ = x[actReload-144]
_ = x[actReloadSync-145]
_ = x[actDisableSearch-146]
_ = x[actEnableSearch-147]
_ = x[actSelect-148]
_ = x[actDeselect-149]
_ = x[actUnbind-150]
_ = x[actRebind-151]
_ = x[actToggleBind-152]
_ = x[actBecome-153]
_ = x[actShowHeader-154]
_ = x[actHideHeader-155]
_ = x[actBell-156]
_ = x[actExclude-157]
_ = x[actExcludeMulti-158]
_ = x[actAsync-159]
_ = x[actBackwardSubWord-17]
_ = x[actCancel-18]
_ = x[actChangeBorderLabel-19]
_ = x[actChangeGhost-20]
_ = x[actChangeHeader-21]
_ = x[actChangeFooter-22]
_ = x[actChangeHeaderLabel-23]
_ = x[actChangeFooterLabel-24]
_ = x[actChangeInputLabel-25]
_ = x[actChangeListLabel-26]
_ = x[actChangeMulti-27]
_ = x[actChangeNth-28]
_ = x[actChangePointer-29]
_ = x[actChangePreview-30]
_ = x[actChangePreviewLabel-31]
_ = x[actChangePreviewWindow-32]
_ = x[actChangePrompt-33]
_ = x[actChangeQuery-34]
_ = x[actClearScreen-35]
_ = x[actClearQuery-36]
_ = x[actClearSelection-37]
_ = x[actClose-38]
_ = x[actDeleteChar-39]
_ = x[actDeleteCharEof-40]
_ = x[actEndOfLine-41]
_ = x[actFatal-42]
_ = x[actForwardChar-43]
_ = x[actForwardWord-44]
_ = x[actForwardSubWord-45]
_ = x[actKillLine-46]
_ = x[actKillWord-47]
_ = x[actKillSubWord-48]
_ = x[actUnixLineDiscard-49]
_ = x[actUnixWordRubout-50]
_ = x[actYank-51]
_ = x[actBackwardKillWord-52]
_ = x[actBackwardKillSubWord-53]
_ = x[actSelectAll-54]
_ = x[actDeselectAll-55]
_ = x[actToggle-56]
_ = x[actToggleSearch-57]
_ = x[actToggleAll-58]
_ = x[actToggleDown-59]
_ = x[actToggleUp-60]
_ = x[actToggleIn-61]
_ = x[actToggleOut-62]
_ = x[actToggleTrack-63]
_ = x[actToggleTrackCurrent-64]
_ = x[actToggleHeader-65]
_ = x[actToggleWrap-66]
_ = x[actToggleMultiLine-67]
_ = x[actToggleHscroll-68]
_ = x[actTrackCurrent-69]
_ = x[actToggleInput-70]
_ = x[actHideInput-71]
_ = x[actShowInput-72]
_ = x[actUntrackCurrent-73]
_ = x[actDown-74]
_ = x[actUp-75]
_ = x[actPageUp-76]
_ = x[actPageDown-77]
_ = x[actPosition-78]
_ = x[actHalfPageUp-79]
_ = x[actHalfPageDown-80]
_ = x[actOffsetUp-81]
_ = x[actOffsetDown-82]
_ = x[actOffsetMiddle-83]
_ = x[actJump-84]
_ = x[actJumpAccept-85]
_ = x[actPrintQuery-86]
_ = x[actRefreshPreview-87]
_ = x[actReplaceQuery-88]
_ = x[actToggleSort-89]
_ = x[actShowPreview-90]
_ = x[actHidePreview-91]
_ = x[actTogglePreview-92]
_ = x[actTogglePreviewWrap-93]
_ = x[actTransform-94]
_ = x[actTransformBorderLabel-95]
_ = x[actTransformGhost-96]
_ = x[actTransformHeader-97]
_ = x[actTransformFooter-98]
_ = x[actTransformHeaderLabel-99]
_ = x[actTransformFooterLabel-100]
_ = x[actTransformInputLabel-101]
_ = x[actTransformListLabel-102]
_ = x[actTransformNth-103]
_ = x[actTransformPointer-104]
_ = x[actTransformPreviewLabel-105]
_ = x[actTransformPrompt-106]
_ = x[actTransformQuery-107]
_ = x[actTransformSearch-108]
_ = x[actTrigger-109]
_ = x[actBgTransform-110]
_ = x[actBgTransformBorderLabel-111]
_ = x[actBgTransformGhost-112]
_ = x[actBgTransformHeader-113]
_ = x[actBgTransformFooter-114]
_ = x[actBgTransformHeaderLabel-115]
_ = x[actBgTransformFooterLabel-116]
_ = x[actBgTransformInputLabel-117]
_ = x[actBgTransformListLabel-118]
_ = x[actBgTransformNth-119]
_ = x[actBgTransformPointer-120]
_ = x[actBgTransformPreviewLabel-121]
_ = x[actBgTransformPrompt-122]
_ = x[actBgTransformQuery-123]
_ = x[actBgTransformSearch-124]
_ = x[actBgCancel-125]
_ = x[actSearch-126]
_ = x[actPreview-127]
_ = x[actPreviewTop-128]
_ = x[actPreviewBottom-129]
_ = x[actPreviewUp-130]
_ = x[actPreviewDown-131]
_ = x[actPreviewPageUp-132]
_ = x[actPreviewPageDown-133]
_ = x[actPreviewHalfPageUp-134]
_ = x[actPreviewHalfPageDown-135]
_ = x[actPrevHistory-136]
_ = x[actPrevSelected-137]
_ = x[actPrint-138]
_ = x[actPut-139]
_ = x[actNextHistory-140]
_ = x[actNextSelected-141]
_ = x[actExecute-142]
_ = x[actExecuteSilent-143]
_ = x[actExecuteMulti-144]
_ = x[actSigStop-145]
_ = x[actFirst-146]
_ = x[actLast-147]
_ = x[actReload-148]
_ = x[actReloadSync-149]
_ = x[actDisableSearch-150]
_ = x[actEnableSearch-151]
_ = x[actSelect-152]
_ = x[actDeselect-153]
_ = x[actUnbind-154]
_ = x[actRebind-155]
_ = x[actToggleBind-156]
_ = x[actBecome-157]
_ = x[actShowHeader-158]
_ = x[actHideHeader-159]
_ = x[actBell-160]
_ = x[actExclude-161]
_ = x[actExcludeMulti-162]
_ = x[actAsync-163]
}
const _actionType_name = "actIgnoreactStartactClickactInvalidactBracketedPasteBeginactBracketedPasteEndactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactCancelactChangeBorderLabelactChangeGhostactChangeHeaderactChangeFooteractChangeHeaderLabelactChangeFooterLabelactChangeInputLabelactChangeListLabelactChangeMultiactChangeNthactChangePointeractChangePreviewactChangePreviewLabelactChangePreviewWindowactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactKillLineactKillWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactToggleInputactHideInputactShowInputactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformGhostactTransformHeaderactTransformFooteractTransformHeaderLabelactTransformFooterLabelactTransformInputLabelactTransformListLabelactTransformNthactTransformPointeractTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactTriggeractBgTransformactBgTransformBorderLabelactBgTransformGhostactBgTransformHeaderactBgTransformFooteractBgTransformHeaderLabelactBgTransformFooterLabelactBgTransformInputLabelactBgTransformListLabelactBgTransformNthactBgTransformPointeractBgTransformPreviewLabelactBgTransformPromptactBgTransformQueryactBgTransformSearchactBgCancelactSearchactPreviewactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactToggleBindactBecomeactShowHeaderactHideHeaderactBellactExcludeactExcludeMultiactAsync"
const _actionType_name = "actIgnoreactStartactClickactInvalidactBracketedPasteBeginactBracketedPasteEndactCharactMouseactBeginningOfLineactAbortactAcceptactAcceptNonEmptyactAcceptOrPrintQueryactBackwardCharactBackwardDeleteCharactBackwardDeleteCharEofactBackwardWordactBackwardSubWordactCancelactChangeBorderLabelactChangeGhostactChangeHeaderactChangeFooteractChangeHeaderLabelactChangeFooterLabelactChangeInputLabelactChangeListLabelactChangeMultiactChangeNthactChangePointeractChangePreviewactChangePreviewLabelactChangePreviewWindowactChangePromptactChangeQueryactClearScreenactClearQueryactClearSelectionactCloseactDeleteCharactDeleteCharEofactEndOfLineactFatalactForwardCharactForwardWordactForwardSubWordactKillLineactKillWordactKillSubWordactUnixLineDiscardactUnixWordRuboutactYankactBackwardKillWordactBackwardKillSubWordactSelectAllactDeselectAllactToggleactToggleSearchactToggleAllactToggleDownactToggleUpactToggleInactToggleOutactToggleTrackactToggleTrackCurrentactToggleHeaderactToggleWrapactToggleMultiLineactToggleHscrollactTrackCurrentactToggleInputactHideInputactShowInputactUntrackCurrentactDownactUpactPageUpactPageDownactPositionactHalfPageUpactHalfPageDownactOffsetUpactOffsetDownactOffsetMiddleactJumpactJumpAcceptactPrintQueryactRefreshPreviewactReplaceQueryactToggleSortactShowPreviewactHidePreviewactTogglePreviewactTogglePreviewWrapactTransformactTransformBorderLabelactTransformGhostactTransformHeaderactTransformFooteractTransformHeaderLabelactTransformFooterLabelactTransformInputLabelactTransformListLabelactTransformNthactTransformPointeractTransformPreviewLabelactTransformPromptactTransformQueryactTransformSearchactTriggeractBgTransformactBgTransformBorderLabelactBgTransformGhostactBgTransformHeaderactBgTransformFooteractBgTransformHeaderLabelactBgTransformFooterLabelactBgTransformInputLabelactBgTransformListLabelactBgTransformNthactBgTransformPointeractBgTransformPreviewLabelactBgTransformPromptactBgTransformQueryactBgTransformSearchactBgCancelactSearchactPreviewactPreviewTopactPreviewBottomactPreviewUpactPreviewDownactPreviewPageUpactPreviewPageDownactPreviewHalfPageUpactPreviewHalfPageDownactPrevHistoryactPrevSelectedactPrintactPutactNextHistoryactNextSelectedactExecuteactExecuteSilentactExecuteMultiactSigStopactFirstactLastactReloadactReloadSyncactDisableSearchactEnableSearchactSelectactDeselectactUnbindactRebindactToggleBindactBecomeactShowHeaderactHideHeaderactBellactExcludeactExcludeMultiactAsync"
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 57, 77, 84, 92, 110, 118, 127, 144, 165, 180, 201, 225, 240, 249, 269, 283, 298, 313, 333, 353, 372, 390, 404, 416, 432, 448, 469, 491, 506, 520, 534, 547, 564, 572, 585, 601, 613, 621, 635, 649, 660, 671, 689, 706, 713, 732, 744, 758, 767, 782, 794, 807, 818, 829, 841, 855, 876, 891, 904, 922, 938, 953, 967, 979, 991, 1008, 1015, 1020, 1029, 1040, 1051, 1064, 1079, 1090, 1103, 1118, 1125, 1138, 1151, 1168, 1183, 1196, 1210, 1224, 1240, 1260, 1272, 1295, 1312, 1330, 1348, 1371, 1394, 1416, 1437, 1452, 1471, 1495, 1513, 1530, 1548, 1558, 1572, 1597, 1616, 1636, 1656, 1681, 1706, 1730, 1753, 1770, 1791, 1817, 1837, 1856, 1876, 1887, 1896, 1906, 1919, 1935, 1947, 1961, 1977, 1995, 2015, 2037, 2051, 2066, 2074, 2080, 2094, 2109, 2119, 2135, 2150, 2160, 2168, 2175, 2184, 2197, 2213, 2228, 2237, 2248, 2257, 2266, 2279, 2288, 2301, 2314, 2321, 2331, 2346, 2354}
var _actionType_index = [...]uint16{0, 9, 17, 25, 35, 57, 77, 84, 92, 110, 118, 127, 144, 165, 180, 201, 225, 240, 258, 267, 287, 301, 316, 331, 351, 371, 390, 408, 422, 434, 450, 466, 487, 509, 524, 538, 552, 565, 582, 590, 603, 619, 631, 639, 653, 667, 684, 695, 706, 720, 738, 755, 762, 781, 803, 815, 829, 838, 853, 865, 878, 889, 900, 912, 926, 947, 962, 975, 993, 1009, 1024, 1038, 1050, 1062, 1079, 1086, 1091, 1100, 1111, 1122, 1135, 1150, 1161, 1174, 1189, 1196, 1209, 1222, 1239, 1254, 1267, 1281, 1295, 1311, 1331, 1343, 1366, 1383, 1401, 1419, 1442, 1465, 1487, 1508, 1523, 1542, 1566, 1584, 1601, 1619, 1629, 1643, 1668, 1687, 1707, 1727, 1752, 1777, 1801, 1824, 1841, 1862, 1888, 1908, 1927, 1947, 1958, 1967, 1977, 1990, 2006, 2018, 2032, 2048, 2066, 2086, 2108, 2122, 2137, 2145, 2151, 2165, 2180, 2190, 2206, 2221, 2231, 2239, 2246, 2255, 2268, 2284, 2299, 2308, 2319, 2328, 2337, 2350, 2359, 2372, 2385, 2392, 2402, 2417, 2425}
func (i actionType) String() string {
if i < 0 || i >= actionType(len(_actionType_index)-1) {

View File

@@ -52,7 +52,7 @@ func TestChunkList(t *testing.T) {
// Add more data
for i := 0; i < chunkSize*2; i++ {
cl.Push([]byte(fmt.Sprintf("item %d", i)))
cl.Push(fmt.Appendf(nil, "item %d", i))
}
// Previous snapshot should remain the same
@@ -86,7 +86,7 @@ func TestChunkListTail(t *testing.T) {
})
total := chunkSize*2 + chunkSize/2
for i := 0; i < total; i++ {
cl.Push([]byte(fmt.Sprintf("item %d", i)))
cl.Push(fmt.Appendf(nil, "item %d", i))
}
snapshot, count, changed := cl.Snapshot(0)

View File

@@ -974,8 +974,6 @@ func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Eve
add(tui.Backspace)
case "ctrl-space":
add(tui.CtrlSpace)
case "ctrl-delete":
add(tui.CtrlDelete)
case "ctrl-^", "ctrl-6":
add(tui.CtrlCaret)
case "ctrl-/", "ctrl-_":
@@ -1022,6 +1020,10 @@ func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Eve
list = append(list, evt)
case "alt-bs", "alt-bspace", "alt-backspace":
add(tui.AltBackspace)
case "ctrl-bs", "ctrl-bspace", "ctrl-backspace":
add(tui.CtrlBackspace)
case "ctrl-alt-bs", "ctrl-alt-bspace", "ctrl-alt-backspace":
add(tui.CtrlAltBackspace)
case "alt-up":
add(tui.AltUp)
case "alt-down":
@@ -1030,6 +1032,16 @@ func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Eve
add(tui.AltLeft)
case "alt-right":
add(tui.AltRight)
case "alt-home":
add(tui.AltHome)
case "alt-end":
add(tui.AltEnd)
case "alt-delete":
add(tui.AltDelete)
case "alt-page-up":
add(tui.AltPageUp)
case "alt-page-down":
add(tui.AltPageDown)
case "tab":
add(tui.Tab)
case "btab", "shift-tab":
@@ -1056,6 +1068,88 @@ func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Eve
add(tui.AltShiftLeft)
case "alt-shift-right", "shift-alt-right":
add(tui.AltShiftRight)
case "alt-shift-home", "shift-alt-home":
add(tui.AltShiftHome)
case "alt-shift-end", "shift-alt-end":
add(tui.AltShiftEnd)
case "alt-shift-delete", "shift-alt-delete":
add(tui.AltShiftDelete)
case "alt-shift-page-up", "shift-alt-page-up":
add(tui.AltShiftPageUp)
case "alt-shift-page-down", "shift-alt-page-down":
add(tui.AltShiftPageDown)
case "ctrl-up":
add(tui.CtrlUp)
case "ctrl-down":
add(tui.CtrlDown)
case "ctrl-right":
add(tui.CtrlRight)
case "ctrl-left":
add(tui.CtrlLeft)
case "ctrl-home":
add(tui.CtrlHome)
case "ctrl-end":
add(tui.CtrlEnd)
case "ctrl-delete":
add(tui.CtrlDelete)
case "ctrl-page-up":
add(tui.CtrlPageUp)
case "ctrl-page-down":
add(tui.CtrlPageDown)
case "ctrl-alt-up", "alt-ctrl-up":
add(tui.CtrlAltUp)
case "ctrl-alt-down", "alt-ctrl-down":
add(tui.CtrlAltDown)
case "ctrl-alt-right", "alt-ctrl-right":
add(tui.CtrlAltRight)
case "ctrl-alt-left", "alt-ctrl-left":
add(tui.CtrlAltLeft)
case "ctrl-alt-home", "alt-ctrl-home":
add(tui.CtrlAltHome)
case "ctrl-alt-end", "alt-ctrl-end":
add(tui.CtrlAltEnd)
case "ctrl-alt-delete", "alt-ctrl-delete":
add(tui.CtrlAltDelete)
case "ctrl-alt-page-up", "alt-ctrl-page-up":
add(tui.CtrlAltPageUp)
case "ctrl-alt-page-down", "alt-ctrl-page-down":
add(tui.CtrlAltPageDown)
case "ctrl-shift-up", "shift-ctrl-up":
add(tui.CtrlShiftUp)
case "ctrl-shift-down", "shift-ctrl-down":
add(tui.CtrlShiftDown)
case "ctrl-shift-right", "shift-ctrl-right":
add(tui.CtrlShiftRight)
case "ctrl-shift-left", "shift-ctrl-left":
add(tui.CtrlShiftLeft)
case "ctrl-shift-home", "shift-ctrl-home":
add(tui.CtrlShiftHome)
case "ctrl-shift-end", "shift-ctrl-end":
add(tui.CtrlShiftEnd)
case "ctrl-shift-delete", "shift-ctrl-delete":
add(tui.CtrlShiftDelete)
case "ctrl-shift-page-up", "shift-ctrl-page-up":
add(tui.CtrlShiftPageUp)
case "ctrl-shift-page-down", "shift-ctrl-page-down":
add(tui.CtrlShiftPageDown)
case "ctrl-alt-shift-up":
add(tui.CtrlAltShiftUp)
case "ctrl-alt-shift-down":
add(tui.CtrlAltShiftDown)
case "ctrl-alt-shift-right":
add(tui.CtrlAltShiftRight)
case "ctrl-alt-shift-left":
add(tui.CtrlAltShiftLeft)
case "ctrl-alt-shift-home":
add(tui.CtrlAltShiftHome)
case "ctrl-alt-shift-end":
add(tui.CtrlAltShiftEnd)
case "ctrl-alt-shift-delete":
add(tui.CtrlAltShiftDelete)
case "ctrl-alt-shift-page-up":
add(tui.CtrlAltShiftPageUp)
case "ctrl-alt-shift-page-down":
add(tui.CtrlAltShiftPageDown)
case "shift-up":
add(tui.ShiftUp)
case "shift-down":
@@ -1064,8 +1158,16 @@ func parseKeyChords(str string, message string) (map[tui.Event]string, []tui.Eve
add(tui.ShiftLeft)
case "shift-right":
add(tui.ShiftRight)
case "shift-home":
add(tui.ShiftHome)
case "shift-end":
add(tui.ShiftEnd)
case "shift-delete":
add(tui.ShiftDelete)
case "shift-page-up":
add(tui.ShiftPageUp)
case "shift-page-down":
add(tui.ShiftPageDown)
case "left-click":
add(tui.LeftClick)
case "right-click":
@@ -1561,6 +1663,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA
appendAction(actBackwardDeleteCharEof)
case "backward-word":
appendAction(actBackwardWord)
case "backward-subword":
appendAction(actBackwardSubWord)
case "clear-screen":
appendAction(actClearScreen)
case "delete-char":
@@ -1581,6 +1685,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA
appendAction(actForwardChar)
case "forward-word":
appendAction(actForwardWord)
case "forward-subword":
appendAction(actForwardSubWord)
case "jump":
appendAction(actJump)
case "jump-accept":
@@ -1589,6 +1695,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA
appendAction(actKillLine)
case "kill-word":
appendAction(actKillWord)
case "kill-subword":
appendAction(actKillSubWord)
case "unix-line-discard", "line-discard":
appendAction(actUnixLineDiscard)
case "unix-word-rubout", "word-rubout":
@@ -1597,6 +1705,8 @@ func parseActionList(masked string, original string, prevActions []*action, putA
appendAction(actYank)
case "backward-kill-word":
appendAction(actBackwardKillWord)
case "backward-kill-subword":
appendAction(actBackwardKillSubWord)
case "toggle-down":
appendAction(actToggle, actDown)
case "toggle-up":

View File

@@ -90,11 +90,12 @@ func runProxy(commandPrefix string, cmdBuilder func(temp string, needBash bool)
}
}
// * Write the command to a temporary file and run it with sh to ensure POSIX compliance.
// * Nullify FZF_DEFAULT_* variables as tmux popup may inject them even when undefined.
exports := []string{"FZF_DEFAULT_COMMAND=", "FZF_DEFAULT_OPTS=", "FZF_DEFAULT_OPTS_FILE="}
// Write the command to a temporary file and run it with sh to ensure POSIX compliance.
var exports []string
needBash := false
if withExports {
// Nullify FZF_DEFAULT_* variables as tmux popup may inject them even when undefined.
exports = []string{"FZF_DEFAULT_COMMAND=", "FZF_DEFAULT_OPTS=", "FZF_DEFAULT_OPTS_FILE="}
validIdentifier := regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
for _, pairStr := range os.Environ() {
pair := strings.SplitN(pairStr, "=", 2)

View File

@@ -285,7 +285,7 @@ func (r *Reader) readFiles(roots []string, opts walkerOpts, ignores []string) bo
if strings.HasPrefix(ignore, sep) {
ignoresSuffix = append(ignoresSuffix, ignore)
} else {
// 'foo/bar' should match match
// 'foo/bar' should match
// * 'foo/bar'
// * 'baz/foo/bar'
// * but NOT 'bazfoo/bar'

View File

@@ -128,9 +128,9 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
// No ANSI codes
if len(itemColors) == 0 && len(nthOffsets) == 0 {
var offsets []colorOffset
for _, off := range matchOffsets {
offsets = append(offsets, colorOffset{offset: [2]int32{off[0], off[1]}, color: colMatch, match: true})
offsets := make([]colorOffset, len(matchOffsets))
for i, off := range matchOffsets {
offsets[i] = colorOffset{offset: [2]int32{off[0], off[1]}, color: colMatch, match: true}
}
return offsets
}

View File

@@ -291,6 +291,8 @@ type Terminal struct {
gapLineLen int
wordRubout string
wordNext string
subWordRubout string
subWordNext string
cx int
cy int
offset int
@@ -512,6 +514,7 @@ const (
actBackwardDeleteChar
actBackwardDeleteCharEof
actBackwardWord
actBackwardSubWord
actCancel
actChangeBorderLabel
@@ -541,12 +544,15 @@ const (
actFatal
actForwardChar
actForwardWord
actForwardSubWord
actKillLine
actKillWord
actKillSubWord
actUnixLineDiscard
actUnixWordRubout
actYank
actBackwardKillWord
actBackwardKillSubWord
actSelectAll
actDeselectAll
actToggle
@@ -782,6 +788,7 @@ func defaultKeymap() map[tui.Event][]*action {
add(tui.CtrlF, actForwardChar)
add(tui.CtrlH, actBackwardDeleteChar)
add(tui.Backspace, actBackwardDeleteChar)
add(tui.CtrlBackspace, actBackwardDeleteChar)
add(tui.Tab, actToggleDown)
add(tui.ShiftTab, actToggleUp)
add(tui.CtrlJ, actDown)
@@ -936,6 +943,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
}
wordRubout := "[^\\pL\\pN][\\pL\\pN]"
wordNext := "[\\pL\\pN][^\\pL\\pN]|(.$)"
subWordRubout := "[a-z][A-Z]|[^\\pL\\pN][\\pL\\pN]"
subWordNext := "[a-z][A-Z]|[\\pL\\pN][^\\pL\\pN]|(.$)"
if opts.FileWord {
sep := regexp.QuoteMeta(string(os.PathSeparator))
wordRubout = fmt.Sprintf("%s[^%s]", sep, sep)
@@ -969,6 +978,8 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
markerMultiLine: *opts.MarkerMulti,
wordRubout: wordRubout,
wordNext: wordNext,
subWordRubout: subWordRubout,
subWordNext: subWordNext,
cx: len(input),
cy: 0,
offset: 0,
@@ -1394,7 +1405,7 @@ func (t *Terminal) ansiLabelPrinter(str string, color *tui.ColorPair, fill bool)
if !fill {
ellipsis, ellipsisWidth = util.Truncate(t.ellipsis, limit)
}
if length > limit-ellipsisWidth {
if length > limit {
trimmedRunes, _ := t.trimRight(runes, limit-ellipsisWidth)
window.CPrint(*color, string(trimmedRunes)+string(ellipsis))
} else if fill {
@@ -2617,11 +2628,11 @@ func (t *Terminal) updatePromptOffset() ([]rune, []rune) {
}
maxWidth := util.Max(1, w.Width()-t.promptLen-1)
_, overflow := t.trimLeft(t.input[:t.cx], maxWidth)
_, overflow := t.trimLeft(t.input[:t.cx], maxWidth, 0)
minOffset := int(overflow)
maxOffset := minOffset + (maxWidth-util.Max(0, maxWidth-t.cx))/2
t.xoffset = util.Constrain(t.xoffset, minOffset, maxOffset)
before, _ := t.trimLeft(t.input[t.xoffset:t.cx], maxWidth)
before, _ := t.trimLeft(t.input[t.xoffset:t.cx], maxWidth, 0)
beforeLen := t.displayWidth(before)
after, _ := t.trimRight(t.input[t.cx:], maxWidth-beforeLen)
afterLen := t.displayWidth(after)
@@ -3322,22 +3333,22 @@ func (t *Terminal) displayWidthWithLimit(runes []rune, prefixWidth int, limit in
return width
}
func (t *Terminal) trimLeft(runes []rune, width int) ([]rune, int32) {
func (t *Terminal) trimLeft(runes []rune, width int, ellipsisWidth int) ([]rune, int32) {
width = util.Max(0, width)
var trimmed int32
// Assume that each rune takes at least one column on screen
if len(runes) > width+2 {
diff := len(runes) - width - 2
if len(runes) > width {
diff := len(runes) - width
trimmed = int32(diff)
runes = runes[diff:]
}
currentWidth := t.displayWidth(runes)
for currentWidth > width && len(runes) > 0 {
for currentWidth > width-ellipsisWidth && len(runes) > 0 {
runes = runes[1:]
trimmed++
currentWidth = t.displayWidthWithLimit(runes, 2, width)
currentWidth = t.displayWidthWithLimit(runes, ellipsisWidth, width)
}
return runes, trimmed
}
@@ -3562,7 +3573,7 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
}
if t.hscroll {
if t.keepRight && pos == nil {
trimmed, diff := t.trimLeft(line, maxWidth-ellipsisWidth)
trimmed, diff := t.trimLeft(line, maxWidth, ellipsisWidth)
transformOffsets(diff, false)
line = append(ellipsis, trimmed...)
} else if !t.overflow(line[:maxe], maxWidth-ellipsisWidth) {
@@ -3578,7 +3589,7 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
}
// ..ri..
var diff int32
line, diff = t.trimLeft(line, maxWidth-ellipsisWidth)
line, diff = t.trimLeft(line, maxWidth, ellipsisWidth)
// Transform offsets
transformOffsets(diff, rightTrim)
@@ -6020,6 +6031,11 @@ func (t *Terminal) Loop() error {
if t.cx > 0 {
t.rubout(t.wordRubout)
}
case actBackwardKillSubWord:
beof = len(t.input) == 0
if t.cx > 0 {
t.rubout(t.subWordRubout)
}
case actYank:
suffix := copySlice(t.input[t.cx:])
t.input = append(append(t.input[:t.cx], t.yanked...), suffix...)
@@ -6131,6 +6147,10 @@ func (t *Terminal) Loop() error {
t.cx = findLastMatch(t.wordRubout, string(t.input[:t.cx])) + 1
case actForwardWord:
t.cx += findFirstMatch(t.wordNext, string(t.input[t.cx:])) + 1
case actBackwardSubWord:
t.cx = findLastMatch(t.subWordRubout, string(t.input[:t.cx])) + 1
case actForwardSubWord:
t.cx += findFirstMatch(t.subWordNext, string(t.input[t.cx:])) + 1
case actKillWord:
ncx := t.cx +
findFirstMatch(t.wordNext, string(t.input[t.cx:])) + 1
@@ -6138,6 +6158,13 @@ func (t *Terminal) Loop() error {
t.yanked = copySlice(t.input[t.cx:ncx])
t.input = append(t.input[:t.cx], t.input[ncx:]...)
}
case actKillSubWord:
ncx := t.cx +
findFirstMatch(t.subWordNext, string(t.input[t.cx:])) + 1
if ncx > t.cx {
t.yanked = copySlice(t.input[t.cx:ncx])
t.input = append(t.input[:t.cx], t.input[ncx:]...)
}
case actKillLine:
if t.cx < len(t.input) {
t.yanked = copySlice(t.input[t.cx:])

View File

@@ -37,86 +37,137 @@ func _() {
_ = x[CtrlZ-26]
_ = x[Esc-27]
_ = x[CtrlSpace-28]
_ = x[CtrlDelete-29]
_ = x[CtrlBackSlash-30]
_ = x[CtrlRightBracket-31]
_ = x[CtrlCaret-32]
_ = x[CtrlSlash-33]
_ = x[ShiftTab-34]
_ = x[Backspace-35]
_ = x[Delete-36]
_ = x[PageUp-37]
_ = x[PageDown-38]
_ = x[Up-39]
_ = x[Down-40]
_ = x[Left-41]
_ = x[Right-42]
_ = x[Home-43]
_ = x[End-44]
_ = x[Insert-45]
_ = x[ShiftUp-46]
_ = x[ShiftDown-47]
_ = x[ShiftLeft-48]
_ = x[ShiftRight-49]
_ = x[ShiftDelete-50]
_ = x[F1-51]
_ = x[F2-52]
_ = x[F3-53]
_ = x[F4-54]
_ = x[F5-55]
_ = x[F6-56]
_ = x[F7-57]
_ = x[F8-58]
_ = x[F9-59]
_ = x[F10-60]
_ = x[F11-61]
_ = x[F12-62]
_ = x[AltBackspace-63]
_ = x[AltUp-64]
_ = x[AltDown-65]
_ = x[AltLeft-66]
_ = x[AltRight-67]
_ = x[AltShiftUp-68]
_ = x[AltShiftDown-69]
_ = x[AltShiftLeft-70]
_ = x[AltShiftRight-71]
_ = x[Alt-72]
_ = x[CtrlAlt-73]
_ = x[Invalid-74]
_ = x[Fatal-75]
_ = x[BracketedPasteBegin-76]
_ = x[BracketedPasteEnd-77]
_ = x[Mouse-78]
_ = x[DoubleClick-79]
_ = x[LeftClick-80]
_ = x[RightClick-81]
_ = x[SLeftClick-82]
_ = x[SRightClick-83]
_ = x[ScrollUp-84]
_ = x[ScrollDown-85]
_ = x[SScrollUp-86]
_ = x[SScrollDown-87]
_ = x[PreviewScrollUp-88]
_ = x[PreviewScrollDown-89]
_ = x[Resize-90]
_ = x[Change-91]
_ = x[BackwardEOF-92]
_ = x[Start-93]
_ = x[Load-94]
_ = x[Focus-95]
_ = x[One-96]
_ = x[Zero-97]
_ = x[Result-98]
_ = x[Jump-99]
_ = x[JumpCancel-100]
_ = x[ClickHeader-101]
_ = x[ClickFooter-102]
_ = x[Multi-103]
_ = x[CtrlBackSlash-29]
_ = x[CtrlRightBracket-30]
_ = x[CtrlCaret-31]
_ = x[CtrlSlash-32]
_ = x[ShiftTab-33]
_ = x[Backspace-34]
_ = x[Delete-35]
_ = x[PageUp-36]
_ = x[PageDown-37]
_ = x[Up-38]
_ = x[Down-39]
_ = x[Left-40]
_ = x[Right-41]
_ = x[Home-42]
_ = x[End-43]
_ = x[Insert-44]
_ = x[ShiftUp-45]
_ = x[ShiftDown-46]
_ = x[ShiftLeft-47]
_ = x[ShiftRight-48]
_ = x[ShiftDelete-49]
_ = x[ShiftHome-50]
_ = x[ShiftEnd-51]
_ = x[ShiftPageUp-52]
_ = x[ShiftPageDown-53]
_ = x[F1-54]
_ = x[F2-55]
_ = x[F3-56]
_ = x[F4-57]
_ = x[F5-58]
_ = x[F6-59]
_ = x[F7-60]
_ = x[F8-61]
_ = x[F9-62]
_ = x[F10-63]
_ = x[F11-64]
_ = x[F12-65]
_ = x[AltBackspace-66]
_ = x[AltUp-67]
_ = x[AltDown-68]
_ = x[AltLeft-69]
_ = x[AltRight-70]
_ = x[AltDelete-71]
_ = x[AltHome-72]
_ = x[AltEnd-73]
_ = x[AltPageUp-74]
_ = x[AltPageDown-75]
_ = x[AltShiftUp-76]
_ = x[AltShiftDown-77]
_ = x[AltShiftLeft-78]
_ = x[AltShiftRight-79]
_ = x[AltShiftDelete-80]
_ = x[AltShiftHome-81]
_ = x[AltShiftEnd-82]
_ = x[AltShiftPageUp-83]
_ = x[AltShiftPageDown-84]
_ = x[CtrlUp-85]
_ = x[CtrlDown-86]
_ = x[CtrlLeft-87]
_ = x[CtrlRight-88]
_ = x[CtrlHome-89]
_ = x[CtrlEnd-90]
_ = x[CtrlBackspace-91]
_ = x[CtrlDelete-92]
_ = x[CtrlPageUp-93]
_ = x[CtrlPageDown-94]
_ = x[Alt-95]
_ = x[CtrlAlt-96]
_ = x[CtrlAltUp-97]
_ = x[CtrlAltDown-98]
_ = x[CtrlAltLeft-99]
_ = x[CtrlAltRight-100]
_ = x[CtrlAltHome-101]
_ = x[CtrlAltEnd-102]
_ = x[CtrlAltBackspace-103]
_ = x[CtrlAltDelete-104]
_ = x[CtrlAltPageUp-105]
_ = x[CtrlAltPageDown-106]
_ = x[CtrlShiftUp-107]
_ = x[CtrlShiftDown-108]
_ = x[CtrlShiftLeft-109]
_ = x[CtrlShiftRight-110]
_ = x[CtrlShiftHome-111]
_ = x[CtrlShiftEnd-112]
_ = x[CtrlShiftDelete-113]
_ = x[CtrlShiftPageUp-114]
_ = x[CtrlShiftPageDown-115]
_ = x[CtrlAltShiftUp-116]
_ = x[CtrlAltShiftDown-117]
_ = x[CtrlAltShiftLeft-118]
_ = x[CtrlAltShiftRight-119]
_ = x[CtrlAltShiftHome-120]
_ = x[CtrlAltShiftEnd-121]
_ = x[CtrlAltShiftDelete-122]
_ = x[CtrlAltShiftPageUp-123]
_ = x[CtrlAltShiftPageDown-124]
_ = x[Invalid-125]
_ = x[Fatal-126]
_ = x[BracketedPasteBegin-127]
_ = x[BracketedPasteEnd-128]
_ = x[Mouse-129]
_ = x[DoubleClick-130]
_ = x[LeftClick-131]
_ = x[RightClick-132]
_ = x[SLeftClick-133]
_ = x[SRightClick-134]
_ = x[ScrollUp-135]
_ = x[ScrollDown-136]
_ = x[SScrollUp-137]
_ = x[SScrollDown-138]
_ = x[PreviewScrollUp-139]
_ = x[PreviewScrollDown-140]
_ = x[Resize-141]
_ = x[Change-142]
_ = x[BackwardEOF-143]
_ = x[Start-144]
_ = x[Load-145]
_ = x[Focus-146]
_ = x[One-147]
_ = x[Zero-148]
_ = x[Result-149]
_ = x[Jump-150]
_ = x[JumpCancel-151]
_ = x[ClickHeader-152]
_ = x[ClickFooter-153]
_ = x[Multi-154]
}
const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlDeleteCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltCtrlAltInvalidFatalBracketedPasteBeginBracketedPasteEndMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeaderClickFooterMulti"
const _EventType_name = "RuneCtrlACtrlBCtrlCCtrlDCtrlECtrlFCtrlGCtrlHTabCtrlJCtrlKCtrlLEnterCtrlNCtrlOCtrlPCtrlQCtrlRCtrlSCtrlTCtrlUCtrlVCtrlWCtrlXCtrlYCtrlZEscCtrlSpaceCtrlBackSlashCtrlRightBracketCtrlCaretCtrlSlashShiftTabBackspaceDeletePageUpPageDownUpDownLeftRightHomeEndInsertShiftUpShiftDownShiftLeftShiftRightShiftDeleteShiftHomeShiftEndShiftPageUpShiftPageDownF1F2F3F4F5F6F7F8F9F10F11F12AltBackspaceAltUpAltDownAltLeftAltRightAltDeleteAltHomeAltEndAltPageUpAltPageDownAltShiftUpAltShiftDownAltShiftLeftAltShiftRightAltShiftDeleteAltShiftHomeAltShiftEndAltShiftPageUpAltShiftPageDownCtrlUpCtrlDownCtrlLeftCtrlRightCtrlHomeCtrlEndCtrlBackspaceCtrlDeleteCtrlPageUpCtrlPageDownAltCtrlAltCtrlAltUpCtrlAltDownCtrlAltLeftCtrlAltRightCtrlAltHomeCtrlAltEndCtrlAltBackspaceCtrlAltDeleteCtrlAltPageUpCtrlAltPageDownCtrlShiftUpCtrlShiftDownCtrlShiftLeftCtrlShiftRightCtrlShiftHomeCtrlShiftEndCtrlShiftDeleteCtrlShiftPageUpCtrlShiftPageDownCtrlAltShiftUpCtrlAltShiftDownCtrlAltShiftLeftCtrlAltShiftRightCtrlAltShiftHomeCtrlAltShiftEndCtrlAltShiftDeleteCtrlAltShiftPageUpCtrlAltShiftPageDownInvalidFatalBracketedPasteBeginBracketedPasteEndMouseDoubleClickLeftClickRightClickSLeftClickSRightClickScrollUpScrollDownSScrollUpSScrollDownPreviewScrollUpPreviewScrollDownResizeChangeBackwardEOFStartLoadFocusOneZeroResultJumpJumpCancelClickHeaderClickFooterMulti"
var _EventType_index = [...]uint16{0, 4, 9, 14, 19, 24, 29, 34, 39, 44, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97, 102, 107, 112, 117, 122, 127, 132, 135, 144, 154, 167, 183, 192, 201, 209, 218, 224, 230, 238, 240, 244, 248, 253, 257, 260, 266, 273, 282, 291, 301, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 333, 336, 339, 351, 356, 363, 370, 378, 388, 400, 412, 425, 428, 435, 442, 447, 466, 483, 488, 499, 508, 518, 528, 539, 547, 557, 566, 577, 592, 609, 615, 621, 632, 637, 641, 646, 649, 653, 659, 663, 673, 684, 695, 700}
var _EventType_index = [...]uint16{0, 4, 9, 14, 19, 24, 29, 34, 39, 44, 47, 52, 57, 62, 67, 72, 77, 82, 87, 92, 97, 102, 107, 112, 117, 122, 127, 132, 135, 144, 157, 173, 182, 191, 199, 208, 214, 220, 228, 230, 234, 238, 243, 247, 250, 256, 263, 272, 281, 291, 302, 311, 319, 330, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 364, 367, 370, 382, 387, 394, 401, 409, 418, 425, 431, 440, 451, 461, 473, 485, 498, 512, 524, 535, 549, 565, 571, 579, 587, 596, 604, 611, 624, 634, 644, 656, 659, 666, 675, 686, 697, 709, 720, 730, 746, 759, 772, 787, 798, 811, 824, 838, 851, 863, 878, 893, 910, 924, 940, 956, 973, 989, 1004, 1022, 1040, 1060, 1067, 1072, 1091, 1108, 1113, 1124, 1133, 1143, 1153, 1164, 1172, 1182, 1191, 1202, 1217, 1234, 1240, 1246, 1257, 1262, 1266, 1271, 1274, 1278, 1284, 1288, 1298, 1309, 1320, 1325}
func (i EventType) String() string {
if i < 0 || i >= EventType(len(_EventType_index)-1) {

View File

@@ -335,6 +335,8 @@ func (r *LightRenderer) GetChar() Event {
return Event{CtrlQ, 0, nil}
case 127:
return Event{Backspace, 0, nil}
case 8:
return Event{CtrlBackspace, 0, nil}
case 0:
return Event{CtrlSpace, 0, nil}
case 28:
@@ -381,6 +383,9 @@ func (r *LightRenderer) escSequence(sz *int) Event {
}
*sz = 2
if r.buffer[1] == 8 {
return Event{CtrlAltBackspace, 0, nil}
}
if r.buffer[1] >= 1 && r.buffer[1] <= 'z'-'a'+1 {
return CtrlAltKey(rune(r.buffer[1] + 'a' - 1))
}
@@ -473,22 +478,136 @@ func (r *LightRenderer) escSequence(sz *int) Event {
if r.buffer[3] == '~' {
return Event{Delete, 0, nil}
}
if len(r.buffer) == 7 && r.buffer[6] == '~' && r.buffer[4] == '1' {
switch r.buffer[5] {
case '0':
return Event{AltShiftDelete, 0, nil}
case '1':
return Event{AltDelete, 0, nil}
case '2':
return Event{AltShiftDelete, 0, nil}
case '3':
return Event{CtrlAltDelete, 0, nil}
case '4':
return Event{CtrlAltShiftDelete, 0, nil}
case '5':
return Event{CtrlAltDelete, 0, nil}
case '6':
return Event{CtrlAltShiftDelete, 0, nil}
}
}
if len(r.buffer) == 6 && r.buffer[5] == '~' {
*sz = 6
switch r.buffer[4] {
case '5':
return Event{CtrlDelete, 0, nil}
case '2':
return Event{ShiftDelete, 0, nil}
case '3':
return Event{AltDelete, 0, nil}
case '4':
return Event{AltShiftDelete, 0, nil}
case '5':
return Event{CtrlDelete, 0, nil}
case '6':
return Event{CtrlShiftDelete, 0, nil}
case '7':
return Event{CtrlAltDelete, 0, nil}
case '8':
return Event{CtrlAltShiftDelete, 0, nil}
case '9':
return Event{AltDelete, 0, nil}
}
}
return Event{Invalid, 0, nil}
case '4':
return Event{End, 0, nil}
case '5':
return Event{PageUp, 0, nil}
if r.buffer[3] == '~' {
return Event{PageUp, 0, nil}
}
if len(r.buffer) == 7 && r.buffer[6] == '~' && r.buffer[4] == '1' {
switch r.buffer[5] {
case '0':
return Event{AltShiftPageUp, 0, nil}
case '1':
return Event{AltPageUp, 0, nil}
case '2':
return Event{AltShiftPageUp, 0, nil}
case '3':
return Event{CtrlAltPageUp, 0, nil}
case '4':
return Event{CtrlAltShiftPageUp, 0, nil}
case '5':
return Event{CtrlAltPageUp, 0, nil}
case '6':
return Event{CtrlAltShiftPageUp, 0, nil}
}
}
if len(r.buffer) == 6 && r.buffer[5] == '~' {
*sz = 6
switch r.buffer[4] {
case '2':
return Event{ShiftPageUp, 0, nil}
case '3':
return Event{AltPageUp, 0, nil}
case '4':
return Event{AltShiftPageUp, 0, nil}
case '5':
return Event{CtrlPageUp, 0, nil}
case '6':
return Event{CtrlShiftPageUp, 0, nil}
case '7':
return Event{CtrlAltPageUp, 0, nil}
case '8':
return Event{CtrlAltShiftPageUp, 0, nil}
case '9':
return Event{AltPageUp, 0, nil}
}
}
return Event{Invalid, 0, nil}
case '6':
return Event{PageDown, 0, nil}
if r.buffer[3] == '~' {
return Event{PageDown, 0, nil}
}
if len(r.buffer) == 7 && r.buffer[6] == '~' && r.buffer[4] == '1' {
switch r.buffer[5] {
case '0':
return Event{AltShiftPageDown, 0, nil}
case '1':
return Event{AltPageDown, 0, nil}
case '2':
return Event{AltShiftPageDown, 0, nil}
case '3':
return Event{CtrlAltPageDown, 0, nil}
case '4':
return Event{CtrlAltShiftPageDown, 0, nil}
case '5':
return Event{CtrlAltPageDown, 0, nil}
case '6':
return Event{CtrlAltShiftPageDown, 0, nil}
}
}
if len(r.buffer) == 6 && r.buffer[5] == '~' {
*sz = 6
switch r.buffer[4] {
case '2':
return Event{ShiftPageDown, 0, nil}
case '3':
return Event{AltPageDown, 0, nil}
case '4':
return Event{AltShiftPageDown, 0, nil}
case '5':
return Event{CtrlPageDown, 0, nil}
case '6':
return Event{CtrlShiftPageDown, 0, nil}
case '7':
return Event{CtrlAltPageDown, 0, nil}
case '8':
return Event{CtrlAltShiftPageDown, 0, nil}
case '9':
return Event{AltPageDown, 0, nil}
}
}
return Event{Invalid, 0, nil}
case '7':
return Event{Home, 0, nil}
case '8':
@@ -526,63 +645,172 @@ func (r *LightRenderer) escSequence(sz *int) Event {
}
*sz = 6
switch r.buffer[4] {
case '1', '2', '3', '4', '5':
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
// Kitty iTerm2 WezTerm
// SHIFT-ARROW "\e[1;2D"
// ALT-SHIFT-ARROW "\e[1;4D" "\e[1;10D" "\e[1;4D"
// CTRL-SHIFT-ARROW "\e[1;6D" N/A
// CMD-SHIFT-ARROW "\e[1;10D" N/A N/A ("\e[1;2D")
alt := r.buffer[4] == '3'
ctrl := bytes.IndexByte([]byte{'5', '6', '7', '8'}, r.buffer[4]) >= 0
alt := bytes.IndexByte([]byte{'3', '4', '7', '8'}, r.buffer[4]) >= 0
shift := bytes.IndexByte([]byte{'2', '4', '6', '8'}, r.buffer[4]) >= 0
char := r.buffer[5]
altShift := false
if r.buffer[4] == '1' && r.buffer[5] == '0' {
altShift = true
if len(r.buffer) < 7 {
return Event{Invalid, 0, nil}
}
*sz = 7
char = r.buffer[6]
} else if r.buffer[4] == '4' {
altShift = true
if r.buffer[4] == '9' {
ctrl = false
alt = true
shift = false
if len(r.buffer) < 6 {
return Event{Invalid, 0, nil}
}
*sz = 6
char = r.buffer[5]
} else if r.buffer[4] == '1' && bytes.IndexByte([]byte{'0', '1', '2', '3', '4', '5', '6'}, r.buffer[5]) >= 0 {
ctrl = bytes.IndexByte([]byte{'3', '4', '5', '6'}, r.buffer[5]) >= 0
alt = true
shift = bytes.IndexByte([]byte{'0', '2', '4', '6'}, r.buffer[5]) >= 0
if len(r.buffer) < 7 {
return Event{Invalid, 0, nil}
}
*sz = 7
char = r.buffer[6]
}
ctrlShift := ctrl && shift
ctrlAlt := ctrl && alt
altShift := alt && shift
ctrlAltShift := ctrl && alt && shift
switch char {
case 'A':
if alt {
return Event{AltUp, 0, nil}
if ctrlAltShift {
return Event{CtrlAltShiftUp, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltUp, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftUp, 0, nil}
}
if altShift {
return Event{AltShiftUp, 0, nil}
}
return Event{ShiftUp, 0, nil}
case 'B':
if ctrl {
return Event{CtrlUp, 0, nil}
}
if alt {
return Event{AltDown, 0, nil}
return Event{AltUp, 0, nil}
}
if shift {
return Event{ShiftUp, 0, nil}
}
case 'B':
if ctrlAltShift {
return Event{CtrlAltShiftDown, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltDown, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftDown, 0, nil}
}
if altShift {
return Event{AltShiftDown, 0, nil}
}
return Event{ShiftDown, 0, nil}
case 'C':
if ctrl {
return Event{CtrlDown, 0, nil}
}
if alt {
return Event{AltRight, 0, nil}
return Event{AltDown, 0, nil}
}
if shift {
return Event{ShiftDown, 0, nil}
}
case 'C':
if ctrlAltShift {
return Event{CtrlAltShiftRight, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltRight, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftRight, 0, nil}
}
if altShift {
return Event{AltShiftRight, 0, nil}
}
return Event{ShiftRight, 0, nil}
case 'D':
if ctrl {
return Event{CtrlRight, 0, nil}
}
if shift {
return Event{ShiftRight, 0, nil}
}
if alt {
return Event{AltLeft, 0, nil}
return Event{AltRight, 0, nil}
}
case 'D':
if ctrlAltShift {
return Event{CtrlAltShiftLeft, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltLeft, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftLeft, 0, nil}
}
if altShift {
return Event{AltShiftLeft, 0, nil}
}
return Event{ShiftLeft, 0, nil}
if ctrl {
return Event{CtrlLeft, 0, nil}
}
if alt {
return Event{AltLeft, 0, nil}
}
if shift {
return Event{ShiftLeft, 0, nil}
}
case 'H':
if ctrlAltShift {
return Event{CtrlAltShiftHome, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltHome, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftHome, 0, nil}
}
if altShift {
return Event{AltShiftHome, 0, nil}
}
if ctrl {
return Event{CtrlHome, 0, nil}
}
if alt {
return Event{AltHome, 0, nil}
}
if shift {
return Event{ShiftHome, 0, nil}
}
case 'F':
if ctrlAltShift {
return Event{CtrlAltShiftEnd, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltEnd, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftEnd, 0, nil}
}
if altShift {
return Event{AltShiftEnd, 0, nil}
}
if ctrl {
return Event{CtrlEnd, 0, nil}
}
if alt {
return Event{AltEnd, 0, nil}
}
if shift {
return Event{ShiftEnd, 0, nil}
}
}
} // r.buffer[4]
} // r.buffer[3]

335
src/tui/light_test.go Normal file
View File

@@ -0,0 +1,335 @@
package tui
import (
"fmt"
"os"
"testing"
"unicode"
)
func TestLightRenderer(t *testing.T) {
tty_file, _ := os.Open("")
renderer, _ := NewLightRenderer(
"", tty_file, &ColorTheme{}, true, false, 0, false, true,
func(h int) int { return h })
light_renderer := renderer.(*LightRenderer)
assertCharSequence := func(sequence string, name string) {
bytes := []byte(sequence)
light_renderer.buffer = bytes
event := light_renderer.GetChar()
if event.KeyName() != name {
t.Errorf(
"sequence: %q | %v | '%s' (%s) != %s",
string(bytes), bytes,
event.KeyName(), event.Type.String(), name)
}
}
assertEscSequence := func(sequence string, name string) {
bytes := []byte(sequence)
light_renderer.buffer = bytes
sz := 1
event := light_renderer.escSequence(&sz)
if fmt.Sprintf("!%s", event.Type.String()) == name {
// this is fine
} else if event.KeyName() != name {
t.Errorf(
"sequence: %q | %v | '%s' (%s) != %s",
string(bytes), bytes,
event.KeyName(), event.Type.String(), name)
}
}
// invalid
assertEscSequence("\x1b[<", "!Invalid")
assertEscSequence("\x1b[1;1R", "!Invalid")
assertEscSequence("\x1b[", "!Invalid")
assertEscSequence("\x1b[1", "!Invalid")
assertEscSequence("\x1b[3;3~1", "!Invalid")
assertEscSequence("\x1b[13", "!Invalid")
assertEscSequence("\x1b[1;3", "!Invalid")
assertEscSequence("\x1b[1;10", "!Invalid")
assertEscSequence("\x1b[220~", "!Invalid")
assertEscSequence("\x1b[5;30~", "!Invalid")
assertEscSequence("\x1b[6;30~", "!Invalid")
// general
for r := 'a'; r < 'z'; r++ {
lower_r := fmt.Sprintf("%c", r)
upper_r := fmt.Sprintf("%c", unicode.ToUpper(r))
assertCharSequence(lower_r, lower_r)
assertCharSequence(upper_r, upper_r)
}
assertCharSequence("\x01", "ctrl-a")
assertCharSequence("\x02", "ctrl-b")
assertCharSequence("\x03", "ctrl-c")
assertCharSequence("\x04", "ctrl-d")
assertCharSequence("\x05", "ctrl-e")
assertCharSequence("\x06", "ctrl-f")
assertCharSequence("\x07", "ctrl-g")
// ctrl-h is the same as ctrl-backspace
// ctrl-i is the same as tab
assertCharSequence("\n", "ctrl-j")
assertCharSequence("\x0b", "ctrl-k")
assertCharSequence("\x0c", "ctrl-l")
assertCharSequence("\r", "enter") // enter
assertCharSequence("\x0e", "ctrl-n")
assertCharSequence("\x0f", "ctrl-o")
assertCharSequence("\x10", "ctrl-p")
assertCharSequence("\x11", "ctrl-q")
assertCharSequence("\x12", "ctrl-r")
assertCharSequence("\x13", "ctrl-s")
assertCharSequence("\x14", "ctrl-t")
assertCharSequence("\x15", "ctrl-u")
assertCharSequence("\x16", "ctrl-v")
assertCharSequence("\x17", "ctrl-w")
assertCharSequence("\x18", "ctrl-x")
assertCharSequence("\x19", "ctrl-y")
assertCharSequence("\x1a", "ctrl-z")
assertCharSequence("\x00", "ctrl-space")
assertCharSequence("\x1c", "ctrl-\\")
assertCharSequence("\x1d", "ctrl-]")
assertCharSequence("\x1e", "ctrl-^")
assertCharSequence("\x1f", "ctrl-/")
assertEscSequence("\x1ba", "alt-a")
assertEscSequence("\x1bb", "alt-b")
assertEscSequence("\x1bc", "alt-c")
assertEscSequence("\x1bd", "alt-d")
assertEscSequence("\x1be", "alt-e")
assertEscSequence("\x1bf", "alt-f")
assertEscSequence("\x1bg", "alt-g")
assertEscSequence("\x1bh", "alt-h")
assertEscSequence("\x1bi", "alt-i")
assertEscSequence("\x1bj", "alt-j")
assertEscSequence("\x1bk", "alt-k")
assertEscSequence("\x1bl", "alt-l")
assertEscSequence("\x1bm", "alt-m")
assertEscSequence("\x1bn", "alt-n")
assertEscSequence("\x1bo", "alt-o")
assertEscSequence("\x1bp", "alt-p")
assertEscSequence("\x1bq", "alt-q")
assertEscSequence("\x1br", "alt-r")
assertEscSequence("\x1bs", "alt-s")
assertEscSequence("\x1bt", "alt-t")
assertEscSequence("\x1bu", "alt-u")
assertEscSequence("\x1bv", "alt-v")
assertEscSequence("\x1bw", "alt-w")
assertEscSequence("\x1bx", "alt-x")
assertEscSequence("\x1by", "alt-y")
assertEscSequence("\x1bz", "alt-z")
assertEscSequence("\x1bOP", "f1")
assertEscSequence("\x1bOQ", "f2")
assertEscSequence("\x1bOR", "f3")
assertEscSequence("\x1bOS", "f4")
assertEscSequence("\x1b[15~", "f5")
assertEscSequence("\x1b[17~", "f6")
assertEscSequence("\x1b[18~", "f7")
assertEscSequence("\x1b[19~", "f8")
assertEscSequence("\x1b[20~", "f9")
assertEscSequence("\x1b[21~", "f10")
assertEscSequence("\x1b[23~", "f11")
assertEscSequence("\x1b[24~", "f12")
assertEscSequence("\x1b", "esc")
assertCharSequence("\t", "tab")
assertEscSequence("\x1b[Z", "shift-tab")
assertCharSequence("\x7f", "backspace")
assertEscSequence("\x1b\x7f", "alt-backspace")
assertCharSequence("\b", "ctrl-backspace")
assertEscSequence("\x1b\b", "ctrl-alt-backspace")
assertEscSequence("\x1b[A", "up")
assertEscSequence("\x1b[B", "down")
assertEscSequence("\x1b[C", "right")
assertEscSequence("\x1b[D", "left")
assertEscSequence("\x1b[H", "home")
assertEscSequence("\x1b[F", "end")
assertEscSequence("\x1b[2~", "insert")
assertEscSequence("\x1b[3~", "delete")
assertEscSequence("\x1b[5~", "page-up")
assertEscSequence("\x1b[6~", "page-down")
assertEscSequence("\x1b[7~", "home")
assertEscSequence("\x1b[8~", "end")
assertEscSequence("\x1b[1;2A", "shift-up")
assertEscSequence("\x1b[1;2B", "shift-down")
assertEscSequence("\x1b[1;2C", "shift-right")
assertEscSequence("\x1b[1;2D", "shift-left")
assertEscSequence("\x1b[1;2H", "shift-home")
assertEscSequence("\x1b[1;2F", "shift-end")
assertEscSequence("\x1b[3;2~", "shift-delete")
assertEscSequence("\x1b[5;2~", "shift-page-up")
assertEscSequence("\x1b[6;2~", "shift-page-down")
assertEscSequence("\x1b\x1b", "esc")
assertEscSequence("\x1b\x1b[A", "alt-up")
assertEscSequence("\x1b\x1b[B", "alt-down")
assertEscSequence("\x1b\x1b[C", "alt-right")
assertEscSequence("\x1b\x1b[D", "alt-left")
assertEscSequence("\x1b[1;3A", "alt-up")
assertEscSequence("\x1b[1;3B", "alt-down")
assertEscSequence("\x1b[1;3C", "alt-right")
assertEscSequence("\x1b[1;3D", "alt-left")
assertEscSequence("\x1b[1;3H", "alt-home")
assertEscSequence("\x1b[1;3F", "alt-end")
assertEscSequence("\x1b[3;3~", "alt-delete")
assertEscSequence("\x1b[5;3~", "alt-page-up")
assertEscSequence("\x1b[6;3~", "alt-page-down")
assertEscSequence("\x1b[1;4A", "alt-shift-up")
assertEscSequence("\x1b[1;4B", "alt-shift-down")
assertEscSequence("\x1b[1;4C", "alt-shift-right")
assertEscSequence("\x1b[1;4D", "alt-shift-left")
assertEscSequence("\x1b[1;4H", "alt-shift-home")
assertEscSequence("\x1b[1;4F", "alt-shift-end")
assertEscSequence("\x1b[3;4~", "alt-shift-delete")
assertEscSequence("\x1b[5;4~", "alt-shift-page-up")
assertEscSequence("\x1b[6;4~", "alt-shift-page-down")
assertEscSequence("\x1b[1;5A", "ctrl-up")
assertEscSequence("\x1b[1;5B", "ctrl-down")
assertEscSequence("\x1b[1;5C", "ctrl-right")
assertEscSequence("\x1b[1;5D", "ctrl-left")
assertEscSequence("\x1b[1;5H", "ctrl-home")
assertEscSequence("\x1b[1;5F", "ctrl-end")
assertEscSequence("\x1b[3;5~", "ctrl-delete")
assertEscSequence("\x1b[5;5~", "ctrl-page-up")
assertEscSequence("\x1b[6;5~", "ctrl-page-down")
assertEscSequence("\x1b[1;7A", "ctrl-alt-up")
assertEscSequence("\x1b[1;7B", "ctrl-alt-down")
assertEscSequence("\x1b[1;7C", "ctrl-alt-right")
assertEscSequence("\x1b[1;7D", "ctrl-alt-left")
assertEscSequence("\x1b[1;7H", "ctrl-alt-home")
assertEscSequence("\x1b[1;7F", "ctrl-alt-end")
assertEscSequence("\x1b[3;7~", "ctrl-alt-delete")
assertEscSequence("\x1b[5;7~", "ctrl-alt-page-up")
assertEscSequence("\x1b[6;7~", "ctrl-alt-page-down")
assertEscSequence("\x1b[1;6A", "ctrl-shift-up")
assertEscSequence("\x1b[1;6B", "ctrl-shift-down")
assertEscSequence("\x1b[1;6C", "ctrl-shift-right")
assertEscSequence("\x1b[1;6D", "ctrl-shift-left")
assertEscSequence("\x1b[1;6H", "ctrl-shift-home")
assertEscSequence("\x1b[1;6F", "ctrl-shift-end")
assertEscSequence("\x1b[3;6~", "ctrl-shift-delete")
assertEscSequence("\x1b[5;6~", "ctrl-shift-page-up")
assertEscSequence("\x1b[6;6~", "ctrl-shift-page-down")
assertEscSequence("\x1b[1;8A", "ctrl-alt-shift-up")
assertEscSequence("\x1b[1;8B", "ctrl-alt-shift-down")
assertEscSequence("\x1b[1;8C", "ctrl-alt-shift-right")
assertEscSequence("\x1b[1;8D", "ctrl-alt-shift-left")
assertEscSequence("\x1b[1;8H", "ctrl-alt-shift-home")
assertEscSequence("\x1b[1;8F", "ctrl-alt-shift-end")
assertEscSequence("\x1b[3;8~", "ctrl-alt-shift-delete")
assertEscSequence("\x1b[5;8~", "ctrl-alt-shift-page-up")
assertEscSequence("\x1b[6;8~", "ctrl-alt-shift-page-down")
// xterm meta & mac
assertEscSequence("\x1b[1;9A", "alt-up")
assertEscSequence("\x1b[1;9B", "alt-down")
assertEscSequence("\x1b[1;9C", "alt-right")
assertEscSequence("\x1b[1;9D", "alt-left")
assertEscSequence("\x1b[1;9H", "alt-home")
assertEscSequence("\x1b[1;9F", "alt-end")
assertEscSequence("\x1b[3;9~", "alt-delete")
assertEscSequence("\x1b[5;9~", "alt-page-up")
assertEscSequence("\x1b[6;9~", "alt-page-down")
assertEscSequence("\x1b[1;10A", "alt-shift-up")
assertEscSequence("\x1b[1;10B", "alt-shift-down")
assertEscSequence("\x1b[1;10C", "alt-shift-right")
assertEscSequence("\x1b[1;10D", "alt-shift-left")
assertEscSequence("\x1b[1;10H", "alt-shift-home")
assertEscSequence("\x1b[1;10F", "alt-shift-end")
assertEscSequence("\x1b[3;10~", "alt-shift-delete")
assertEscSequence("\x1b[5;10~", "alt-shift-page-up")
assertEscSequence("\x1b[6;10~", "alt-shift-page-down")
assertEscSequence("\x1b[1;11A", "alt-up")
assertEscSequence("\x1b[1;11B", "alt-down")
assertEscSequence("\x1b[1;11C", "alt-right")
assertEscSequence("\x1b[1;11D", "alt-left")
assertEscSequence("\x1b[1;11H", "alt-home")
assertEscSequence("\x1b[1;11F", "alt-end")
assertEscSequence("\x1b[3;11~", "alt-delete")
assertEscSequence("\x1b[5;11~", "alt-page-up")
assertEscSequence("\x1b[6;11~", "alt-page-down")
assertEscSequence("\x1b[1;12A", "alt-shift-up")
assertEscSequence("\x1b[1;12B", "alt-shift-down")
assertEscSequence("\x1b[1;12C", "alt-shift-right")
assertEscSequence("\x1b[1;12D", "alt-shift-left")
assertEscSequence("\x1b[1;12H", "alt-shift-home")
assertEscSequence("\x1b[1;12F", "alt-shift-end")
assertEscSequence("\x1b[3;12~", "alt-shift-delete")
assertEscSequence("\x1b[5;12~", "alt-shift-page-up")
assertEscSequence("\x1b[6;12~", "alt-shift-page-down")
assertEscSequence("\x1b[1;13A", "ctrl-alt-up")
assertEscSequence("\x1b[1;13B", "ctrl-alt-down")
assertEscSequence("\x1b[1;13C", "ctrl-alt-right")
assertEscSequence("\x1b[1;13D", "ctrl-alt-left")
assertEscSequence("\x1b[1;13H", "ctrl-alt-home")
assertEscSequence("\x1b[1;13F", "ctrl-alt-end")
assertEscSequence("\x1b[3;13~", "ctrl-alt-delete")
assertEscSequence("\x1b[5;13~", "ctrl-alt-page-up")
assertEscSequence("\x1b[6;13~", "ctrl-alt-page-down")
assertEscSequence("\x1b[1;14A", "ctrl-alt-shift-up")
assertEscSequence("\x1b[1;14B", "ctrl-alt-shift-down")
assertEscSequence("\x1b[1;14C", "ctrl-alt-shift-right")
assertEscSequence("\x1b[1;14D", "ctrl-alt-shift-left")
assertEscSequence("\x1b[1;14H", "ctrl-alt-shift-home")
assertEscSequence("\x1b[1;14F", "ctrl-alt-shift-end")
assertEscSequence("\x1b[3;14~", "ctrl-alt-shift-delete")
assertEscSequence("\x1b[5;14~", "ctrl-alt-shift-page-up")
assertEscSequence("\x1b[6;14~", "ctrl-alt-shift-page-down")
assertEscSequence("\x1b[1;15A", "ctrl-alt-up")
assertEscSequence("\x1b[1;15B", "ctrl-alt-down")
assertEscSequence("\x1b[1;15C", "ctrl-alt-right")
assertEscSequence("\x1b[1;15D", "ctrl-alt-left")
assertEscSequence("\x1b[1;15H", "ctrl-alt-home")
assertEscSequence("\x1b[1;15F", "ctrl-alt-end")
assertEscSequence("\x1b[3;15~", "ctrl-alt-delete")
assertEscSequence("\x1b[5;15~", "ctrl-alt-page-up")
assertEscSequence("\x1b[6;15~", "ctrl-alt-page-down")
assertEscSequence("\x1b[1;16A", "ctrl-alt-shift-up")
assertEscSequence("\x1b[1;16B", "ctrl-alt-shift-down")
assertEscSequence("\x1b[1;16C", "ctrl-alt-shift-right")
assertEscSequence("\x1b[1;16D", "ctrl-alt-shift-left")
assertEscSequence("\x1b[1;16H", "ctrl-alt-shift-home")
assertEscSequence("\x1b[1;16F", "ctrl-alt-shift-end")
assertEscSequence("\x1b[3;16~", "ctrl-alt-shift-delete")
assertEscSequence("\x1b[5;16~", "ctrl-alt-shift-page-up")
assertEscSequence("\x1b[6;16~", "ctrl-alt-shift-page-down")
// tmux & emacs
assertEscSequence("\x1bOA", "up")
assertEscSequence("\x1bOB", "down")
assertEscSequence("\x1bOC", "right")
assertEscSequence("\x1bOD", "left")
assertEscSequence("\x1bOH", "home")
assertEscSequence("\x1bOF", "end")
// rrvt
assertEscSequence("\x1b[1~", "home")
assertEscSequence("\x1b[4~", "end")
assertEscSequence("\x1b[11~", "f1")
assertEscSequence("\x1b[12~", "f2")
assertEscSequence("\x1b[13~", "f3")
assertEscSequence("\x1b[14~", "f4")
}

View File

@@ -7,8 +7,8 @@ import (
"regexp"
"time"
"github.com/gdamore/tcell/v2"
"github.com/junegunn/fzf/src/util"
"github.com/junegunn/tcell/v2"
"github.com/rivo/uniseg"
)
@@ -354,6 +354,8 @@ func (r *FullscreenRenderer) GetChar() Event {
shift := (mods & tcell.ModShift) > 0
ctrlAlt := ctrl && alt
altShift := alt && shift
ctrlShift := ctrl && shift
ctrlAltShift := ctrl && alt && shift
keyfn := func(r rune) Event {
if alt {
@@ -380,8 +382,11 @@ func (r *FullscreenRenderer) GetChar() Event {
case tcell.KeyCtrlH:
switch ev.Rune() {
case 0:
if ctrlAlt {
return Event{CtrlAltBackspace, 0, nil}
}
if ctrl {
return Event{Backspace, 0, nil}
return Event{CtrlBackspace, 0, nil}
}
case rune(tcell.KeyCtrlH):
switch {
@@ -442,6 +447,9 @@ func (r *FullscreenRenderer) GetChar() Event {
return Event{CtrlSlash, 0, nil}
// section 3: (Alt)+Backspace2
case tcell.KeyBackspace2:
if ctrl {
return Event{CtrlBackspace, 0, nil}
}
if alt {
return Event{AltBackspace, 0, nil}
}
@@ -449,9 +457,21 @@ func (r *FullscreenRenderer) GetChar() Event {
// section 4: (Alt+Shift)+Key(Up|Down|Left|Right)
case tcell.KeyUp:
if ctrlAltShift {
return Event{CtrlAltShiftUp, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltUp, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftUp, 0, nil}
}
if altShift {
return Event{AltShiftUp, 0, nil}
}
if ctrl {
return Event{CtrlUp, 0, nil}
}
if shift {
return Event{ShiftUp, 0, nil}
}
@@ -460,9 +480,21 @@ func (r *FullscreenRenderer) GetChar() Event {
}
return Event{Up, 0, nil}
case tcell.KeyDown:
if ctrlAltShift {
return Event{CtrlAltShiftDown, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltDown, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftDown, 0, nil}
}
if altShift {
return Event{AltShiftDown, 0, nil}
}
if ctrl {
return Event{CtrlDown, 0, nil}
}
if shift {
return Event{ShiftDown, 0, nil}
}
@@ -471,9 +503,21 @@ func (r *FullscreenRenderer) GetChar() Event {
}
return Event{Down, 0, nil}
case tcell.KeyLeft:
if ctrlAltShift {
return Event{CtrlAltShiftLeft, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltLeft, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftLeft, 0, nil}
}
if altShift {
return Event{AltShiftLeft, 0, nil}
}
if ctrl {
return Event{CtrlLeft, 0, nil}
}
if shift {
return Event{ShiftLeft, 0, nil}
}
@@ -482,9 +526,21 @@ func (r *FullscreenRenderer) GetChar() Event {
}
return Event{Left, 0, nil}
case tcell.KeyRight:
if ctrlAltShift {
return Event{CtrlAltShiftRight, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltRight, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftRight, 0, nil}
}
if altShift {
return Event{AltShiftRight, 0, nil}
}
if ctrl {
return Event{CtrlRight, 0, nil}
}
if shift {
return Event{ShiftRight, 0, nil}
}
@@ -497,20 +553,119 @@ func (r *FullscreenRenderer) GetChar() Event {
case tcell.KeyInsert:
return Event{Insert, 0, nil}
case tcell.KeyHome:
if ctrlAltShift {
return Event{CtrlAltShiftHome, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltHome, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftHome, 0, nil}
}
if altShift {
return Event{AltShiftHome, 0, nil}
}
if ctrl {
return Event{CtrlHome, 0, nil}
}
if shift {
return Event{ShiftHome, 0, nil}
}
if alt {
return Event{AltHome, 0, nil}
}
return Event{Home, 0, nil}
case tcell.KeyDelete:
if ctrlAltShift {
return Event{CtrlAltShiftDelete, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltDelete, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftDelete, 0, nil}
}
if altShift {
return Event{AltShiftDelete, 0, nil}
}
if ctrl {
return Event{CtrlDelete, 0, nil}
}
if alt {
return Event{AltDelete, 0, nil}
}
if shift {
return Event{ShiftDelete, 0, nil}
}
return Event{Delete, 0, nil}
case tcell.KeyEnd:
if ctrlAltShift {
return Event{CtrlAltShiftEnd, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltEnd, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftEnd, 0, nil}
}
if altShift {
return Event{AltShiftEnd, 0, nil}
}
if ctrl {
return Event{CtrlEnd, 0, nil}
}
if shift {
return Event{ShiftEnd, 0, nil}
}
if alt {
return Event{AltEnd, 0, nil}
}
return Event{End, 0, nil}
case tcell.KeyPgUp:
if ctrlAltShift {
return Event{CtrlAltShiftPageUp, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltPageUp, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftPageUp, 0, nil}
}
if altShift {
return Event{AltShiftPageUp, 0, nil}
}
if ctrl {
return Event{CtrlPageUp, 0, nil}
}
if shift {
return Event{ShiftPageUp, 0, nil}
}
if alt {
return Event{AltPageUp, 0, nil}
}
return Event{PageUp, 0, nil}
case tcell.KeyPgDn:
if ctrlAltShift {
return Event{CtrlAltShiftPageDown, 0, nil}
}
if ctrlAlt {
return Event{CtrlAltPageDown, 0, nil}
}
if ctrlShift {
return Event{CtrlShiftPageDown, 0, nil}
}
if altShift {
return Event{AltShiftPageDown, 0, nil}
}
if ctrl {
return Event{CtrlPageDown, 0, nil}
}
if shift {
return Event{ShiftPageDown, 0, nil}
}
if alt {
return Event{AltPageDown, 0, nil}
}
return Event{PageDown, 0, nil}
case tcell.KeyBacktab:
return Event{ShiftTab, 0, nil}

View File

@@ -6,8 +6,8 @@ import (
"os"
"testing"
"github.com/gdamore/tcell/v2"
"github.com/junegunn/fzf/src/util"
"github.com/junegunn/tcell/v2"
)
func assert(t *testing.T, context string, got any, want any) bool {
@@ -107,18 +107,20 @@ func TestGetCharEventKey(t *testing.T) {
{giveKey{tcell.KeyBackspace2, 0, tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // fabricated
{giveKey{tcell.KeyDEL, 0, tcell.ModNone}, wantKey{Backspace, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyDelete, 0, tcell.ModNone}, wantKey{Delete, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModAlt}, wantKey{Delete, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModAlt}, wantKey{AltDelete, 0, nil}},
{giveKey{tcell.KeyBackspace, 0, tcell.ModCtrl}, wantKey{CtrlBackspace, 0, nil}},
{giveKey{tcell.KeyBackspace, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltBackspace, 0, nil}},
{giveKey{tcell.KeyBackspace, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyBS, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyCtrlH, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModNone}, wantKey{Backspace, 0, nil}}, // actual "Backspace" keystroke
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // actual "Alt+Backspace" keystroke
{giveKey{tcell.KeyDEL, rune(tcell.KeyDEL), tcell.ModCtrl}, wantKey{Backspace, 0, nil}}, // actual "Ctrl+Backspace" keystroke
{giveKey{tcell.KeyDEL, rune(tcell.KeyDEL), tcell.ModCtrl}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift}, wantKey{Backspace, 0, nil}}, // actual "Shift+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{Backspace, 0, nil}}, // actual "Ctrl+Alt+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{Backspace, 0, nil}}, // actual "Ctrl+Shift+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltBackspace, 0, nil}}, // actual "Ctrl+Alt+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlBackspace, 0, nil}}, // actual "Ctrl+Shift+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModShift | tcell.ModAlt}, wantKey{AltBackspace, 0, nil}}, // actual "Shift+Alt+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{Backspace, 0, nil}}, // actual "Ctrl+Shift+Alt+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, 0, tcell.ModCtrl | tcell.ModAlt | tcell.ModShift}, wantKey{CtrlAltBackspace, 0, nil}}, // actual "Ctrl+Shift+Alt+Backspace" keystroke
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl}, wantKey{CtrlH, 0, nil}}, // actual "Ctrl+H" keystroke
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAlt, 'h', nil}}, // fabricated "Ctrl+Alt+H" keystroke
{giveKey{tcell.KeyCtrlH, rune(tcell.KeyCtrlH), tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlH, 0, nil}}, // actual "Ctrl+Shift+H" keystroke
@@ -126,9 +128,41 @@ func TestGetCharEventKey(t *testing.T) {
// section 4: (Alt+Shift)+Key(Up|Down|Left|Right)
{giveKey{tcell.KeyUp, 0, tcell.ModNone}, wantKey{Up, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModAlt}, wantKey{AltDown, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModNone}, wantKey{Down, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModNone}, wantKey{Left, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModNone}, wantKey{Right, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModNone}, wantKey{Up, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModNone}, wantKey{Down, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModNone}, wantKey{Right, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModNone}, wantKey{Left, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModCtrl}, wantKey{CtrlUp, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModCtrl}, wantKey{CtrlDown, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModCtrl}, wantKey{CtrlRight, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModCtrl}, wantKey{CtrlLeft, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModShift}, wantKey{ShiftUp, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModShift}, wantKey{ShiftDown, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModShift}, wantKey{ShiftRight, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModShift}, wantKey{ShiftLeft, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModAlt}, wantKey{AltUp, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModAlt}, wantKey{AltDown, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModAlt}, wantKey{AltRight, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModAlt}, wantKey{AltLeft, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftUp, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftDown, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftRight, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftLeft, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltUp, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltDown, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltRight, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltLeft, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftUp, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftDown, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftRight, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftLeft, 0, nil}},
{giveKey{tcell.KeyUp, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftUp, 0, nil}},
{giveKey{tcell.KeyDown, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftDown, 0, nil}},
{giveKey{tcell.KeyRight, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftRight, 0, nil}},
{giveKey{tcell.KeyLeft, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftLeft, 0, nil}},
{giveKey{tcell.KeyUpLeft, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyUpRight, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
{giveKey{tcell.KeyDownLeft, 0, tcell.ModNone}, wantKey{Invalid, 0, nil}}, // fabricated, unhandled
@@ -137,6 +171,46 @@ func TestGetCharEventKey(t *testing.T) {
// section 5: (Insert|Home|Delete|End|PgUp|PgDn|BackTab|F1-F12)
{giveKey{tcell.KeyInsert, 0, tcell.ModNone}, wantKey{Insert, 0, nil}},
{giveKey{tcell.KeyF1, 0, tcell.ModNone}, wantKey{F1, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModNone}, wantKey{Home, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModNone}, wantKey{End, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModNone}, wantKey{Delete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModNone}, wantKey{PageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModNone}, wantKey{PageDown, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModCtrl}, wantKey{CtrlHome, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModCtrl}, wantKey{CtrlEnd, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModCtrl}, wantKey{CtrlDelete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModCtrl}, wantKey{CtrlPageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModCtrl}, wantKey{CtrlPageDown, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModShift}, wantKey{ShiftHome, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModShift}, wantKey{ShiftEnd, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModShift}, wantKey{ShiftDelete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModShift}, wantKey{ShiftPageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModShift}, wantKey{ShiftPageDown, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModAlt}, wantKey{AltHome, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModAlt}, wantKey{AltEnd, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModAlt}, wantKey{AltDelete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModAlt}, wantKey{AltPageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModAlt}, wantKey{AltPageDown, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftHome, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftEnd, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftDelete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftPageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModCtrl | tcell.ModShift}, wantKey{CtrlShiftPageDown, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltHome, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltEnd, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltDelete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltPageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModCtrl | tcell.ModAlt}, wantKey{CtrlAltPageDown, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftHome, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftEnd, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftDelete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftPageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModShift | tcell.ModAlt}, wantKey{AltShiftPageDown, 0, nil}},
{giveKey{tcell.KeyHome, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftHome, 0, nil}},
{giveKey{tcell.KeyEnd, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftEnd, 0, nil}},
{giveKey{tcell.KeyDelete, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftDelete, 0, nil}},
{giveKey{tcell.KeyPgUp, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftPageUp, 0, nil}},
{giveKey{tcell.KeyPgDn, 0, tcell.ModCtrl | tcell.ModShift | tcell.ModAlt}, wantKey{CtrlAltShiftPageDown, 0, nil}},
// section 6: (Ctrl+Alt)+'rune'
{giveKey{tcell.KeyRune, 'a', tcell.ModNone}, wantKey{Rune, 'a', nil}},
{giveKey{tcell.KeyRune, 'a', tcell.ModCtrl}, wantKey{Rune, 'a', nil}}, // fabricated
@@ -198,6 +272,10 @@ func TestGetCharEventKey(t *testing.T) {
initialResizeAsInvalid = false
gotEvent = r.GetChar()
}
if gotEvent.Type == Resize {
t.Logf("Resize swallowed")
gotEvent = r.GetChar()
}
t.Logf("wantEvent = %T{Type: %v, Char: %q (%[3]v)}\n", test.wantKey, test.wantKey.Type, test.wantKey.Char)
t.Logf("gotEvent = %T{Type: %v, Char: %q (%[3]v)}\n", gotEvent, gotEvent.Type, gotEvent.Char)

View File

@@ -44,7 +44,6 @@ const (
CtrlZ
Esc
CtrlSpace
CtrlDelete
// https://apple.stackexchange.com/questions/24261/how-do-i-send-c-that-is-control-slash-to-the-terminal
CtrlBackSlash
@@ -72,6 +71,10 @@ const (
ShiftLeft
ShiftRight
ShiftDelete
ShiftHome
ShiftEnd
ShiftPageUp
ShiftPageDown
F1
F2
@@ -92,15 +95,67 @@ const (
AltDown
AltLeft
AltRight
AltDelete
AltHome
AltEnd
AltPageUp
AltPageDown
AltShiftUp
AltShiftDown
AltShiftLeft
AltShiftRight
AltShiftDelete
AltShiftHome
AltShiftEnd
AltShiftPageUp
AltShiftPageDown
CtrlUp
CtrlDown
CtrlLeft
CtrlRight
CtrlHome
CtrlEnd
CtrlBackspace
CtrlDelete
CtrlPageUp
CtrlPageDown
Alt
CtrlAlt
CtrlAltUp
CtrlAltDown
CtrlAltLeft
CtrlAltRight
CtrlAltHome
CtrlAltEnd
CtrlAltBackspace
CtrlAltDelete
CtrlAltPageUp
CtrlAltPageDown
CtrlShiftUp
CtrlShiftDown
CtrlShiftLeft
CtrlShiftRight
CtrlShiftHome
CtrlShiftEnd
CtrlShiftDelete
CtrlShiftPageUp
CtrlShiftPageDown
CtrlAltShiftUp
CtrlAltShiftDown
CtrlAltShiftLeft
CtrlAltShiftRight
CtrlAltShiftHome
CtrlAltShiftEnd
CtrlAltShiftDelete
CtrlAltShiftPageUp
CtrlAltShiftPageDown
Invalid
Fatal
BracketedPasteBegin

View File

@@ -108,6 +108,40 @@ class TestCore < TestInteractive
assert_equal %w[3 2 5 6 8 7], fzf_output_lines
end
def test_subword_forward
tmux.send_keys "#{FZF} --bind K:kill-subword,F:forward-subword -q 'foo bar foo-bar fooFooBar'", :Enter, :Home
tmux.until { |lines| assert_equal '> foo bar foo-bar fooFooBar', lines.last }
tmux.send_keys 'F', :Delete
tmux.until { |lines| assert_equal '> foobar foo-bar fooFooBar', lines.last }
tmux.send_keys 'K'
tmux.until { |lines| assert_equal '> foo foo-bar fooFooBar', lines.last }
tmux.send_keys 'F', 'K'
tmux.until { |lines| assert_equal '> foo foo fooFooBar', lines.last }
tmux.send_keys 'F', 'F', 'K'
tmux.until { |lines| assert_equal '> foo foo fooFoo', lines.last }
end
def test_subword_backward
tmux.send_keys "#{FZF} --bind K:backward-kill-subword,B:backward-subword -q 'foo bar foo-bar fooBar'", :Enter
tmux.until { |lines| assert_equal '> foo bar foo-bar fooBar', lines.last }
tmux.send_keys 'B', :BSpace
tmux.until { |lines| assert_equal '> foo bar foo-bar foBar', lines.last }
tmux.send_keys 'K'
tmux.until { |lines| assert_equal '> foo bar foo-bar Bar', lines.last }
tmux.send_keys 'B', :BSpace
tmux.until { |lines| assert_equal '> foo bar foobar Bar', lines.last }
tmux.send_keys 'B', 'B', :BSpace
tmux.until { |lines| assert_equal '> foobar foobar Bar', lines.last }
end
def test_multi_max
tmux.send_keys "seq 1 10 | #{FZF} -m 3 --bind A:select-all,T:toggle-all --preview 'echo [{+}]/{}'", :Enter
@@ -1415,6 +1449,11 @@ class TestCore < TestInteractive
tmux.until { assert_match(%r{ --1/10000/10000-- *$}, it[-1]) }
end
def test_info_command_inline_right_no_ansi
tmux.send_keys(%(seq 10000 | #{FZF} --info-command 'echo -e "--$FZF_POS/$FZF_INFO--"' --info inline-right), :Enter)
tmux.until { assert_match(%r{ --1/10000/10000-- *$}, it[-1]) }
end
def test_info_command_and_focus
tmux.send_keys(%(seq 100 | #{FZF} --separator x --info-command 'echo $FZF_POS' --bind focus:clear-query), :Enter)
tmux.until { assert_match(/^ 1 xx/, it[-2]) }