mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-14 22:33:47 -05:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19759ed36e | ||
|
|
1a7ae8e7b9 | ||
|
|
da1f645670 | ||
|
|
3a2015ee26 | ||
|
|
c440418ce6 | ||
|
|
3d37a5ba1d | ||
|
|
15f4cfb6d9 | ||
|
|
be36de2482 | ||
|
|
391237f7df | ||
|
|
977e5effd9 | ||
|
|
8b36a4cb19 | ||
|
|
c8cd94a772 | ||
|
|
764316a53d | ||
|
|
2048fd4042 | ||
|
|
f84b3de24b | ||
|
|
6a1f3ec08b | ||
|
|
2e353aee96 | ||
|
|
8edfd14a37 | ||
|
|
1a191ec6f7 | ||
|
|
e7171e94b4 | ||
|
|
398d937419 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
custom: ["https://paypal.me/junegunn", "https://www.buymeacoffee.com/junegunn"]
|
||||
2
.github/workflows/linux.yml
vendored
2
.github/workflows/linux.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.14, 1.15]
|
||||
go: [1.14, 1.16]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
||||
2
.github/workflows/macos.yml
vendored
2
.github/workflows/macos.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
go: [1.14, 1.15]
|
||||
go: [1.14, 1.16]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
||||
@@ -12,27 +12,20 @@ builds:
|
||||
- darwin
|
||||
goarch:
|
||||
- amd64
|
||||
ldflags:
|
||||
- "-s -w -X main.version={{ .Version }} -X main.revision={{ .ShortCommit }}"
|
||||
|
||||
- id: fzf-macos-arm
|
||||
binary: fzf
|
||||
goos:
|
||||
- darwin
|
||||
goarch:
|
||||
- arm64
|
||||
ldflags:
|
||||
- "-s -w -X main.version={{ .Version }} -X main.revision={{ .ShortCommit }}"
|
||||
hooks:
|
||||
post: |-
|
||||
sh -c '
|
||||
cat > /tmp/fzf-gon.hcl << EOF
|
||||
source = ["./dist/fzf-macos_darwin_{{ .Arch }}/fzf"]
|
||||
bundle_id = "kr.junegunn.fzf"
|
||||
apple_id {
|
||||
username = "junegunn.c@gmail.com"
|
||||
password = "@env:AC_PASSWORD"
|
||||
}
|
||||
sign {
|
||||
application_identity = "Apple Development: junegunn.c@gmail.com"
|
||||
}
|
||||
EOF
|
||||
gon /tmp/fzf-gon.hcl
|
||||
'
|
||||
|
||||
- goos:
|
||||
- id: fzf
|
||||
goos:
|
||||
- linux
|
||||
- windows
|
||||
- freebsd
|
||||
@@ -59,6 +52,8 @@ builds:
|
||||
|
||||
archives:
|
||||
- name_template: "{{ .ProjectName }}-{{ .Version }}-{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
|
||||
builds:
|
||||
- fzf
|
||||
format: tar.gz
|
||||
format_overrides:
|
||||
- goos: windows
|
||||
@@ -66,12 +61,61 @@ archives:
|
||||
files:
|
||||
- non-existent*
|
||||
|
||||
signs:
|
||||
- id: fzf-macos-sign
|
||||
ids: [fzf-macos]
|
||||
artifacts: all
|
||||
cmd: sh
|
||||
args:
|
||||
- "-c"
|
||||
- |-
|
||||
cat > /tmp/fzf-gon-amd64.hcl << EOF
|
||||
source = ["./dist/fzf-macos_darwin_amd64/fzf"]
|
||||
bundle_id = "kr.junegunn.fzf"
|
||||
apple_id {
|
||||
username = "junegunn.c@gmail.com"
|
||||
password = "@env:AC_PASSWORD"
|
||||
}
|
||||
sign {
|
||||
application_identity = "Developer ID Application: Junegunn Choi (Y254DRW44Z)"
|
||||
}
|
||||
zip {
|
||||
output_path = "./dist/fzf-{{ .Version }}-darwin_amd64.zip"
|
||||
}
|
||||
EOF
|
||||
gon /tmp/fzf-gon-amd64.hcl
|
||||
|
||||
- id: fzf-macos-arm-sign
|
||||
ids: [fzf-macos-arm]
|
||||
artifacts: all
|
||||
cmd: sh
|
||||
args:
|
||||
- "-c"
|
||||
- |-
|
||||
cat > /tmp/fzf-gon-arm64.hcl << EOF
|
||||
source = ["./dist/fzf-macos-arm_darwin_arm64/fzf"]
|
||||
bundle_id = "kr.junegunn.fzf"
|
||||
apple_id {
|
||||
username = "junegunn.c@gmail.com"
|
||||
password = "@env:AC_PASSWORD"
|
||||
}
|
||||
sign {
|
||||
application_identity = "Developer ID Application: Junegunn Choi (Y254DRW44Z)"
|
||||
}
|
||||
zip {
|
||||
output_path = "./dist/fzf-{{ .Version }}-darwin_arm64.zip"
|
||||
}
|
||||
EOF
|
||||
gon /tmp/fzf-gon-arm64.hcl
|
||||
|
||||
release:
|
||||
github:
|
||||
owner: junegunn
|
||||
name: fzf
|
||||
prerelease: auto
|
||||
name_template: '{{ .Tag }}'
|
||||
extra_files:
|
||||
- glob: ./dist/fzf-*darwin*.zip
|
||||
|
||||
snapshot:
|
||||
name_template: "{{ .Tag }}-devel"
|
||||
|
||||
21
CHANGELOG.md
21
CHANGELOG.md
@@ -1,6 +1,27 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
0.27.0
|
||||
------
|
||||
- More border options for `--preview-window`
|
||||
```sh
|
||||
fzf --preview 'cat {}' --preview-window border-left
|
||||
fzf --preview 'cat {}' --preview-window border-left --border horizontal
|
||||
fzf --preview 'cat {}' --preview-window top:border-bottom
|
||||
fzf --preview 'cat {}' --preview-window top:border-horizontal
|
||||
```
|
||||
- Automatically set `/dev/tty` as STDIN on execute action
|
||||
```sh
|
||||
# Redirect /dev/tty to suppress "Vim: Warning: Input is not from a terminal"
|
||||
# ls | fzf --bind "enter:execute(vim {} < /dev/tty)"
|
||||
|
||||
# "< /dev/tty" part is no longer needed
|
||||
ls | fzf --bind "enter:execute(vim {})"
|
||||
```
|
||||
- Bug fixes and improvements
|
||||
- Signed and notarized macOS binaries
|
||||
(Huge thanks to [BACKERS.md](https://github.com/junegunn/junegunn/blob/main/BACKERS.md)!)
|
||||
|
||||
0.26.0
|
||||
------
|
||||
- Added support for fixed header in preview window
|
||||
|
||||
@@ -572,8 +572,8 @@ FZF_DEFAULT_COMMAND='find . -type f' \
|
||||
The following example uses fzf as the selector interface for ripgrep. We bound
|
||||
`reload` action to `change` event, so every time you type on fzf, the ripgrep
|
||||
process will restart with the updated query string denoted by the placeholder
|
||||
expression `{q}`. Also, note that we used `--phony` option so that fzf doesn't
|
||||
perform any secondary filtering.
|
||||
expression `{q}`. Also, note that we used `--disabled` option so that fzf
|
||||
doesn't perform any secondary filtering.
|
||||
|
||||
```sh
|
||||
INITIAL_QUERY=""
|
||||
@@ -615,7 +615,7 @@ You can customize the size, position, and border of the preview window using
|
||||
|
||||
```bash
|
||||
fzf --height 40% --layout reverse --info inline --border \
|
||||
--preview 'file {}' --preview-window down:1:noborder \
|
||||
--preview 'file {}' --preview-window up,1,border-horizontal \
|
||||
--color 'fg:#bbccdd,fg+:#ddeeff,bg:#334455,preview-bg:#223344,border:#778899'
|
||||
```
|
||||
|
||||
|
||||
16
go.mod
16
go.mod
@@ -2,14 +2,16 @@ module github.com/junegunn/fzf
|
||||
|
||||
require (
|
||||
github.com/gdamore/tcell v1.4.0
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12
|
||||
github.com/mattn/go-runewidth v0.0.9
|
||||
github.com/mattn/go-shellwords v1.0.10
|
||||
github.com/saracen/walker v0.1.1
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 // indirect
|
||||
golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.12
|
||||
github.com/mattn/go-shellwords v1.0.11
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/saracen/walker v0.1.2
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6
|
||||
golang.org/x/text v0.3.6 // indirect
|
||||
)
|
||||
|
||||
go 1.13
|
||||
|
||||
44
go.sum
44
go.sum
@@ -2,36 +2,32 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdk
|
||||
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
|
||||
github.com/gdamore/tcell v1.4.0 h1:vUnHwJRvcPQa3tzi+0QI4U9JINXYJlOz9yiaiPQ2wMU=
|
||||
github.com/gdamore/tcell v1.4.0/go.mod h1:vxEiSDZdW3L+Uhjii9c3375IlDmR05bzxY404ZVSMo0=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
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.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-shellwords v1.0.10 h1:Y7Xqm8piKOO3v10Thp7Z36h4FYFjt5xB//6XvOrs2Gw=
|
||||
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/saracen/walker v0.1.1 h1:Ou2QIKTWqo0QxhtuHVmtObbmhjMCEUyJ82xp0uV+MGI=
|
||||
github.com/saracen/walker v0.1.1/go.mod h1:0oKYMsKVhSJ+ful4p/XbjvXbMgLEkLITZaxozsl4CGE=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-shellwords v1.0.11 h1:vCoR9VPpsk/TZFW2JwK5I9S0xdrtUq2bph6/YjEPnaw=
|
||||
github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/saracen/walker v0.1.2 h1:/o1TxP82n8thLvmL4GpJXduYaRmJ7qXp8u9dSlV0zmo=
|
||||
github.com/saracen/walker v0.1.2/go.mod h1:0oKYMsKVhSJ+ful4p/XbjvXbMgLEkLITZaxozsl4CGE=
|
||||
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeoexdbeMjttk6Oh1rD10=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1 h1:/DtoiOYKoQCcIFXQjz07RnWNPRCbqmSXSpgEzhC9ZHM=
|
||||
golang.org/x/sys v0.0.0-20201026173827-119d4633e4d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6 h1:EC6+IGYTjPpRfv9a2b/6Puw0W+hLtAhkV1tPsXhutqs=
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
||||
6
install
6
install
@@ -2,7 +2,7 @@
|
||||
|
||||
set -u
|
||||
|
||||
version=0.26.0
|
||||
version=0.27.0
|
||||
auto_completion=
|
||||
key_bindings=
|
||||
update_config=2
|
||||
@@ -168,8 +168,8 @@ archi=$(uname -sm)
|
||||
binary_available=1
|
||||
binary_error=""
|
||||
case "$archi" in
|
||||
# Darwin\ arm64) download fzf-$version-darwin_arm64.tar.gz ;; # TODO
|
||||
Darwin\ x86_64) download fzf-$version-darwin_amd64.tar.gz ;;
|
||||
Darwin\ arm64) download fzf-$version-darwin_arm64.zip ;;
|
||||
Darwin\ x86_64) download fzf-$version-darwin_amd64.zip ;;
|
||||
Linux\ armv5*) download fzf-$version-linux_armv5.tar.gz ;;
|
||||
Linux\ armv6*) download fzf-$version-linux_armv6.tar.gz ;;
|
||||
Linux\ armv7*) download fzf-$version-linux_armv7.tar.gz ;;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$version="0.26.0"
|
||||
$version="0.27.0"
|
||||
|
||||
$fzf_base=Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||
|
||||
|
||||
2
main.go
2
main.go
@@ -5,7 +5,7 @@ import (
|
||||
"github.com/junegunn/fzf/src/protector"
|
||||
)
|
||||
|
||||
var version string = "0.26"
|
||||
var version string = "0.27"
|
||||
var revision string = "devel"
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
..
|
||||
.TH fzf-tmux 1 "Mar 2021" "fzf 0.26.0" "fzf-tmux - open fzf in tmux split pane"
|
||||
.TH fzf-tmux 1 "Apr 2021" "fzf 0.27.0" "fzf-tmux - open fzf in tmux split pane"
|
||||
|
||||
.SH NAME
|
||||
fzf-tmux - open fzf in tmux split pane
|
||||
|
||||
@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
..
|
||||
.TH fzf 1 "Mar 2021" "fzf 0.26.0" "fzf - a command-line fuzzy finder"
|
||||
.TH fzf 1 "Apr 2021" "fzf 0.27.0" "fzf - a command-line fuzzy finder"
|
||||
|
||||
.SH NAME
|
||||
fzf - a command-line fuzzy finder
|
||||
@@ -203,6 +203,8 @@ Draw border around the finder
|
||||
.br
|
||||
.BR right
|
||||
.br
|
||||
.BR none
|
||||
.br
|
||||
|
||||
.TP
|
||||
.B "--no-unicode"
|
||||
@@ -442,7 +444,7 @@ e.g.
|
||||
done'\fR
|
||||
.RE
|
||||
.TP
|
||||
.BI "--preview-window=" "[POSITION][:SIZE[%]][:rounded|sharp|noborder][:[no]wrap][:[no]follow][:[no]cycle][:[no]hidden][:+SCROLL[OFFSETS][/DENOM]][:~HEADER_LINES][:default]"
|
||||
.BI "--preview-window=" "[POSITION][,SIZE[%]][,border-BORDER_OPT][,[no]wrap][,[no]follow][,[no]cycle][,[no]hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default]"
|
||||
|
||||
.RS
|
||||
.B POSITION: (default: right)
|
||||
@@ -477,8 +479,10 @@ e.g.
|
||||
* Cyclic scrolling is enabled with \fB:cycle\fR flag.
|
||||
|
||||
* To change the style of the border of the preview window, specify one of
|
||||
\fBrounded\fR (border with rounded edges, default), \fBsharp\fR (border with
|
||||
sharp edges), or \fBnoborder\fR (no border).
|
||||
the options for \fB--border\fR with \fBborder-\fR prefix.
|
||||
e.g. \fBborder-rounded\fR (border with rounded edges, default),
|
||||
\fBborder-sharp\fR (border with sharp edges), \fBborder-left\fR,
|
||||
\fBborder-none\fR, etc.
|
||||
|
||||
* \fB[:+SCROLL[OFFSETS][/DENOM]]\fR determines the initial scroll offset of the
|
||||
preview window.
|
||||
@@ -497,8 +501,8 @@ are always visible.
|
||||
.RS
|
||||
e.g.
|
||||
\fB# Non-default scroll window positions and sizes
|
||||
fzf --preview="head {}" --preview-window=up:30%
|
||||
fzf --preview="file {}" --preview-window=down:1
|
||||
fzf --preview="head {}" --preview-window=up,30%
|
||||
fzf --preview="file {}" --preview-window=down,1
|
||||
|
||||
# Initial scroll offset is set to the line number of each line of
|
||||
# git grep output *minus* 5 lines (-5)
|
||||
@@ -516,7 +520,7 @@ e.g.
|
||||
git grep --line-number '' |
|
||||
fzf --delimiter : \\
|
||||
--preview 'bat --style=full --color=always --highlight-line {2} {1}' \\
|
||||
--preview-window '~3:+{2}+3/2'
|
||||
--preview-window '~3,+{2}+3/2'
|
||||
|
||||
# Display top 3 lines as the fixed header
|
||||
fzf --preview 'bat --style=full --color=always {}' --preview-window '~3'\fR
|
||||
|
||||
@@ -154,46 +154,79 @@ function! fzf#install()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:version_requirement(val, min)
|
||||
let val = split(a:val, '\.')
|
||||
let min = split(a:min, '\.')
|
||||
for idx in range(0, len(min) - 1)
|
||||
let v = get(val, idx, 0)
|
||||
if v < min[idx] | return 0
|
||||
elseif v > min[idx] | return 1
|
||||
let s:versions = {}
|
||||
function s:get_version(bin)
|
||||
if has_key(s:versions, a:bin)
|
||||
return s:versions[a:bin]
|
||||
end
|
||||
let command = a:bin . ' --version'
|
||||
let output = systemlist(command)
|
||||
if v:shell_error || empty(output)
|
||||
return ''
|
||||
endif
|
||||
let ver = matchstr(output[-1], '[0-9.]\+')
|
||||
let s:versions[a:bin] = ver
|
||||
return ver
|
||||
endfunction
|
||||
|
||||
function! s:compare_versions(a, b)
|
||||
let a = split(a:a, '\.')
|
||||
let b = split(a:b, '\.')
|
||||
for idx in range(0, max([len(a), len(b)]) - 1)
|
||||
let v1 = str2nr(get(a, idx, 0))
|
||||
let v2 = str2nr(get(b, idx, 0))
|
||||
if v1 < v2 | return -1
|
||||
elseif v1 > v2 | return 1
|
||||
endif
|
||||
endfor
|
||||
return 1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:compare_binary_versions(a, b)
|
||||
return s:compare_versions(s:get_version(a:a), s:get_version(a:b))
|
||||
endfunction
|
||||
|
||||
let s:checked = {}
|
||||
function! fzf#exec(...)
|
||||
if !exists('s:exec')
|
||||
if executable(s:fzf_go)
|
||||
let s:exec = s:fzf_go
|
||||
elseif executable('fzf')
|
||||
let s:exec = 'fzf'
|
||||
elseif input('fzf executable not found. Download binary? (y/n) ') =~? '^y'
|
||||
redraw
|
||||
call fzf#install()
|
||||
return fzf#exec()
|
||||
else
|
||||
redraw
|
||||
throw 'fzf executable not found'
|
||||
let binaries = []
|
||||
if executable('fzf')
|
||||
call add(binaries, 'fzf')
|
||||
endif
|
||||
if executable(s:fzf_go)
|
||||
call add(binaries, s:fzf_go)
|
||||
endif
|
||||
|
||||
if empty(binaries)
|
||||
if input('fzf executable not found. Download binary? (y/n) ') =~? '^y'
|
||||
redraw
|
||||
call fzf#install()
|
||||
return fzf#exec()
|
||||
else
|
||||
redraw
|
||||
throw 'fzf executable not found'
|
||||
endif
|
||||
elseif len(binaries) > 1
|
||||
call sort(binaries, 's:compare_binary_versions')
|
||||
endif
|
||||
|
||||
let s:exec = binaries[-1]
|
||||
endif
|
||||
|
||||
if a:0 && !has_key(s:checked, a:1)
|
||||
let command = s:exec . ' --version'
|
||||
let output = systemlist(command)
|
||||
if v:shell_error || empty(output)
|
||||
throw printf('Failed to run "%s": %s', command, output)
|
||||
endif
|
||||
let fzf_version = matchstr(output[-1], '[0-9.]\+')
|
||||
if s:version_requirement(fzf_version, a:1)
|
||||
let fzf_version = s:get_version(s:exec)
|
||||
if empty(fzf_version)
|
||||
let message = printf('Failed to run "%s --version"', s:exec)
|
||||
unlet s:exec
|
||||
throw message
|
||||
end
|
||||
|
||||
if s:compare_versions(fzf_version, a:1) >= 0
|
||||
let s:checked[a:1] = 1
|
||||
return s:exec
|
||||
elseif a:0 < 2 && input(printf('You need fzf %s or above. Found: %s. Download binary? (y/n) ', a:1, fzf_version)) =~? '^y'
|
||||
let s:versions = {}
|
||||
unlet s:exec
|
||||
redraw
|
||||
call fzf#install()
|
||||
return fzf#exec(a:1, 1)
|
||||
@@ -852,9 +885,6 @@ function! s:execute_term(dict, command, temps) abort
|
||||
let term_opts.curwin = 1
|
||||
endif
|
||||
let fzf.buf = term_start([&shell, &shellcmdflag, command], term_opts)
|
||||
if exists('&termwinkey')
|
||||
call setbufvar(fzf.buf, '&termwinkey', '<c-z>')
|
||||
endif
|
||||
if is_popup && exists('#TerminalWinOpen')
|
||||
doautocmd <nomodeline> TerminalWinOpen
|
||||
endif
|
||||
@@ -863,6 +893,9 @@ function! s:execute_term(dict, command, temps) abort
|
||||
endif
|
||||
endif
|
||||
tnoremap <buffer> <c-z> <nop>
|
||||
if exists('&termwinkey') && (empty(&termwinkey) || &termwinkey =~? '<c-w>')
|
||||
tnoremap <buffer> <c-w> <c-w>.
|
||||
endif
|
||||
finally
|
||||
call s:dopopd()
|
||||
endtry
|
||||
|
||||
10
src/ansi.go
10
src/ansi.go
@@ -103,11 +103,11 @@ func matchOperatingSystemCommand(s string) int {
|
||||
}
|
||||
|
||||
func matchControlSequence(s string) int {
|
||||
// `\x1b[\\[()][0-9;]*[a-zA-Z@]`
|
||||
// ^ match starting here
|
||||
// `\x1b[\\[()][0-9;?]*[a-zA-Z@]`
|
||||
// ^ match starting here
|
||||
//
|
||||
i := 2 // prefix matched in nextAnsiEscapeSequence()
|
||||
for ; i < len(s) && (isNumeric(s[i]) || s[i] == ';'); i++ {
|
||||
for ; i < len(s) && (isNumeric(s[i]) || s[i] == ';' || s[i] == '?'); i++ {
|
||||
}
|
||||
if i < len(s) {
|
||||
c := s[i]
|
||||
@@ -125,7 +125,7 @@ func isCtrlSeqStart(c uint8) bool {
|
||||
// nextAnsiEscapeSequence returns the ANSI escape sequence and is equivalent to
|
||||
// calling FindStringIndex() on the below regex (which was originally used):
|
||||
//
|
||||
// "(?:\x1b[\\[()][0-9;]*[a-zA-Z@]|\x1b][0-9];[[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
|
||||
// "(?:\x1b[\\[()][0-9;?]*[a-zA-Z@]|\x1b][0-9];[[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
|
||||
//
|
||||
func nextAnsiEscapeSequence(s string) (int, int) {
|
||||
// fast check for ANSI escape sequences
|
||||
@@ -154,7 +154,7 @@ Loop:
|
||||
return i - n, i + 1
|
||||
}
|
||||
case '\x1b':
|
||||
// match: `\x1b[\\[()][0-9;]*[a-zA-Z@]`
|
||||
// match: `\x1b[\\[()][0-9;?]*[a-zA-Z@]`
|
||||
if i+2 < len(s) && isCtrlSeqStart(s[i+1]) {
|
||||
if j := matchControlSequence(s[i:]); j != -1 {
|
||||
return i, i + j
|
||||
|
||||
@@ -58,7 +58,7 @@ const usage = `usage: fzf [options]
|
||||
--layout=LAYOUT Choose layout: [default|reverse|reverse-list]
|
||||
--border[=STYLE] Draw border around the finder
|
||||
[rounded|sharp|horizontal|vertical|
|
||||
top|bottom|left|right] (default: rounded)
|
||||
top|bottom|left|right|none] (default: rounded)
|
||||
--margin=MARGIN Screen margin (TRBL | TB,RL | T,RL,B | T,R,B,L)
|
||||
--padding=PADDING Padding inside border (TRBL | TB,RL | T,RL,B | T,R,B,L)
|
||||
--info=STYLE Finder info style [default|inline|hidden]
|
||||
@@ -81,11 +81,11 @@ const usage = `usage: fzf [options]
|
||||
Preview
|
||||
--preview=COMMAND Command to preview highlighted line ({})
|
||||
--preview-window=OPT Preview window layout (default: right:50%)
|
||||
[up|down|left|right][:SIZE[%]]
|
||||
[:[no]wrap][:[no]cycle][:[no]follow][:[no]hidden]
|
||||
[:rounded|sharp|noborder]
|
||||
[:+SCROLL[OFFSETS][/DENOM]][:~HEADER_LINES]
|
||||
[:default]
|
||||
[up|down|left|right][,SIZE[%]]
|
||||
[,[no]wrap][,[no]cycle][,[no]follow][,[no]hidden]
|
||||
[,border-BORDER_OPT]
|
||||
[,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES]
|
||||
[,default]
|
||||
|
||||
Scripting
|
||||
-q, --query=STR Start the finder with the given query
|
||||
@@ -436,11 +436,13 @@ func parseBorder(str string, optional bool) tui.BorderShape {
|
||||
return tui.BorderLeft
|
||||
case "right":
|
||||
return tui.BorderRight
|
||||
case "none":
|
||||
return tui.BorderNone
|
||||
default:
|
||||
if optional && str == "" {
|
||||
return tui.BorderRounded
|
||||
}
|
||||
errorExit("invalid border style (expected: rounded|sharp|horizontal|vertical|top|bottom|left|right)")
|
||||
errorExit("invalid border style (expected: rounded|sharp|horizontal|vertical|top|bottom|left|right|none)")
|
||||
}
|
||||
return tui.BorderNone
|
||||
}
|
||||
@@ -1076,10 +1078,11 @@ func parseInfoStyle(str string) infoStyle {
|
||||
}
|
||||
|
||||
func parsePreviewWindow(opts *previewOpts, input string) {
|
||||
tokens := strings.Split(input, ":")
|
||||
delimRegex := regexp.MustCompile("[:,]") // : for backward compatibility
|
||||
sizeRegex := regexp.MustCompile("^[0-9]+%?$")
|
||||
offsetRegex := regexp.MustCompile(`^(\+{-?[0-9]+})?([+-][0-9]+)*(-?/[1-9][0-9]*)?$`)
|
||||
headerRegex := regexp.MustCompile("^~(0|[1-9][0-9]*)$")
|
||||
tokens := delimRegex.Split(input, -1)
|
||||
for _, token := range tokens {
|
||||
switch token {
|
||||
case "":
|
||||
@@ -1105,12 +1108,24 @@ func parsePreviewWindow(opts *previewOpts, input string) {
|
||||
opts.position = posLeft
|
||||
case "right":
|
||||
opts.position = posRight
|
||||
case "rounded", "border":
|
||||
case "rounded", "border", "border-rounded":
|
||||
opts.border = tui.BorderRounded
|
||||
case "sharp":
|
||||
case "sharp", "border-sharp":
|
||||
opts.border = tui.BorderSharp
|
||||
case "noborder":
|
||||
case "noborder", "border-none":
|
||||
opts.border = tui.BorderNone
|
||||
case "border-horizontal":
|
||||
opts.border = tui.BorderHorizontal
|
||||
case "border-vertical":
|
||||
opts.border = tui.BorderVertical
|
||||
case "border-top":
|
||||
opts.border = tui.BorderTop
|
||||
case "border-bottom":
|
||||
opts.border = tui.BorderBottom
|
||||
case "border-left":
|
||||
opts.border = tui.BorderLeft
|
||||
case "border-right":
|
||||
opts.border = tui.BorderRight
|
||||
case "follow":
|
||||
opts.follow = true
|
||||
case "nofollow":
|
||||
@@ -1368,7 +1383,7 @@ func parseOptions(opts *Options, allArgs []string) {
|
||||
opts.Preview.command = ""
|
||||
case "--preview-window":
|
||||
parsePreviewWindow(&opts.Preview,
|
||||
nextString(allArgs, &i, "preview window layout required: [up|down|left|right][:SIZE[%]][:rounded|sharp|noborder][:wrap][:cycle][:hidden][:+SCROLL[OFFSETS][/DENOM]][:~HEADER_LINES][:default]"))
|
||||
nextString(allArgs, &i, "preview window layout required: [up|down|left|right][,SIZE[%]][,border-BORDER_OPT][,wrap][,cycle][,hidden][,+SCROLL[OFFSETS][/DENOM]][,~HEADER_LINES][,default]"))
|
||||
case "--height":
|
||||
opts.Height = parseHeight(nextString(allArgs, &i, "height required: HEIGHT[%]"))
|
||||
case "--min-height":
|
||||
|
||||
@@ -384,7 +384,7 @@ func TestPreviewOpts(t *testing.T) {
|
||||
opts.Preview.size.size == 50) {
|
||||
t.Error()
|
||||
}
|
||||
opts = optsFor("--preview", "cat {}", "--preview-window=left:15:hidden:wrap:+{1}-/2")
|
||||
opts = optsFor("--preview", "cat {}", "--preview-window=left:15,hidden,wrap:+{1}-/2")
|
||||
if !(opts.Preview.command == "cat {}" &&
|
||||
opts.Preview.hidden == true &&
|
||||
opts.Preview.wrap == true &&
|
||||
@@ -394,7 +394,7 @@ func TestPreviewOpts(t *testing.T) {
|
||||
opts.Preview.size.size == 15) {
|
||||
t.Error(opts.Preview)
|
||||
}
|
||||
opts = optsFor("--preview-window=up:15:wrap:hidden:+{1}+3-1-2/2", "--preview-window=down", "--preview-window=cycle")
|
||||
opts = optsFor("--preview-window=up,15,wrap,hidden,+{1}+3-1-2/2", "--preview-window=down", "--preview-window=cycle")
|
||||
if !(opts.Preview.command == "" &&
|
||||
opts.Preview.hidden == true &&
|
||||
opts.Preview.wrap == true &&
|
||||
|
||||
@@ -831,16 +831,33 @@ func (t *Terminal) resizeWindows() {
|
||||
createPreviewWindow := func(y int, x int, w int, h int) {
|
||||
pwidth := w
|
||||
pheight := h
|
||||
if t.previewOpts.border != tui.BorderNone {
|
||||
previewBorder := tui.MakeBorderStyle(t.previewOpts.border, t.unicode)
|
||||
t.pborder = t.tui.NewWindow(y, x, w, h, true, previewBorder)
|
||||
var previewBorder tui.BorderStyle
|
||||
if t.previewOpts.border == tui.BorderNone {
|
||||
previewBorder = tui.MakeTransparentBorder()
|
||||
} else {
|
||||
previewBorder = tui.MakeBorderStyle(t.previewOpts.border, t.unicode)
|
||||
}
|
||||
t.pborder = t.tui.NewWindow(y, x, w, h, true, previewBorder)
|
||||
switch t.previewOpts.border {
|
||||
case tui.BorderSharp, tui.BorderRounded:
|
||||
pwidth -= 4
|
||||
pheight -= 2
|
||||
x += 2
|
||||
y += 1
|
||||
} else {
|
||||
previewBorder := tui.MakeTransparentBorder()
|
||||
t.pborder = t.tui.NewWindow(y, x, w, h, true, previewBorder)
|
||||
case tui.BorderLeft:
|
||||
pwidth -= 2
|
||||
x += 2
|
||||
case tui.BorderRight:
|
||||
pwidth -= 2
|
||||
case tui.BorderTop:
|
||||
pheight -= 1
|
||||
y += 1
|
||||
case tui.BorderBottom:
|
||||
pheight -= 1
|
||||
case tui.BorderHorizontal:
|
||||
pheight -= 2
|
||||
y += 1
|
||||
case tui.BorderVertical:
|
||||
pwidth -= 4
|
||||
x += 2
|
||||
}
|
||||
@@ -848,9 +865,13 @@ func (t *Terminal) resizeWindows() {
|
||||
}
|
||||
verticalPad := 2
|
||||
minPreviewHeight := 3
|
||||
if t.previewOpts.border == tui.BorderNone {
|
||||
switch t.previewOpts.border {
|
||||
case tui.BorderNone, tui.BorderVertical, tui.BorderLeft, tui.BorderRight:
|
||||
verticalPad = 0
|
||||
minPreviewHeight = 1
|
||||
case tui.BorderTop, tui.BorderBottom:
|
||||
verticalPad = 1
|
||||
minPreviewHeight = 2
|
||||
}
|
||||
switch t.previewOpts.position {
|
||||
case posUp:
|
||||
@@ -1722,24 +1743,22 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
|
||||
}
|
||||
command := t.replacePlaceholder(template, forcePlus, string(t.input), list)
|
||||
cmd := util.ExecCommand(command, false)
|
||||
t.executing.Set(true)
|
||||
if !background {
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdin = tui.TtyIn()
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
t.tui.Pause(true)
|
||||
t.executing.Set(true)
|
||||
cmd.Run()
|
||||
t.executing.Set(false)
|
||||
t.tui.Resume(true, false)
|
||||
t.redraw()
|
||||
t.refresh()
|
||||
} else {
|
||||
t.tui.Pause(false)
|
||||
t.executing.Set(true)
|
||||
cmd.Run()
|
||||
t.executing.Set(false)
|
||||
t.tui.Resume(false, false)
|
||||
}
|
||||
t.executing.Set(false)
|
||||
cleanTemporaryFiles()
|
||||
}
|
||||
|
||||
@@ -1970,6 +1989,7 @@ func (t *Terminal) Loop() {
|
||||
}()
|
||||
|
||||
// Goroutine 2 periodically requests rendering
|
||||
rendered := util.NewAtomicBool(false)
|
||||
go func(version int64) {
|
||||
lines := []string{}
|
||||
spinner := makeSpinner(t.unicode)
|
||||
@@ -1984,6 +2004,7 @@ func (t *Terminal) Loop() {
|
||||
if spinnerIndex >= 0 {
|
||||
spin := spinner[spinnerIndex%len(spinner)]
|
||||
t.reqBox.Set(reqPreviewDisplay, previewResult{version, lines, offset, spin})
|
||||
rendered.Set(true)
|
||||
offset = -1
|
||||
}
|
||||
spinnerIndex++
|
||||
@@ -2003,6 +2024,7 @@ func (t *Terminal) Loop() {
|
||||
}
|
||||
if err != nil {
|
||||
t.reqBox.Set(reqPreviewDisplay, previewResult{version, lines, offset, ""})
|
||||
rendered.Set(true)
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
@@ -2024,7 +2046,13 @@ func (t *Terminal) Loop() {
|
||||
util.KillCommand(cmd)
|
||||
t.eventBox.Set(EvtQuit, code)
|
||||
} else {
|
||||
timer := time.NewTimer(previewCancelWait)
|
||||
// We can immediately kill a long-running preview program
|
||||
// once we started rendering its partial output
|
||||
delay := previewCancelWait
|
||||
if rendered.Get() {
|
||||
delay = 0
|
||||
}
|
||||
timer := time.NewTimer(delay)
|
||||
select {
|
||||
case <-timer.C:
|
||||
util.KillCommand(cmd)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
"github.com/junegunn/fzf/src/util"
|
||||
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -74,7 +74,7 @@ type LightRenderer struct {
|
||||
clickY []int
|
||||
ttyin *os.File
|
||||
buffer []byte
|
||||
origState *terminal.State
|
||||
origState *term.State
|
||||
width int
|
||||
height int
|
||||
yoffset int
|
||||
@@ -693,13 +693,17 @@ func (w *LightWindow) drawBorder() {
|
||||
}
|
||||
|
||||
func (w *LightWindow) drawBorderHorizontal(top, bottom bool) {
|
||||
color := ColBorder
|
||||
if w.preview {
|
||||
color = ColPreviewBorder
|
||||
}
|
||||
if top {
|
||||
w.Move(0, 0)
|
||||
w.CPrint(ColBorder, repeat(w.border.horizontal, w.width))
|
||||
w.CPrint(color, repeat(w.border.horizontal, w.width))
|
||||
}
|
||||
if bottom {
|
||||
w.Move(w.height-1, 0)
|
||||
w.CPrint(ColBorder, repeat(w.border.horizontal, w.width))
|
||||
w.CPrint(color, repeat(w.border.horizontal, w.width))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,14 +712,18 @@ func (w *LightWindow) drawBorderVertical(left, right bool) {
|
||||
if !left || !right {
|
||||
width++
|
||||
}
|
||||
color := ColBorder
|
||||
if w.preview {
|
||||
color = ColPreviewBorder
|
||||
}
|
||||
for y := 0; y < w.height; y++ {
|
||||
w.Move(y, 0)
|
||||
if left {
|
||||
w.CPrint(ColBorder, string(w.border.vertical))
|
||||
w.CPrint(color, string(w.border.vertical))
|
||||
}
|
||||
w.CPrint(ColBorder, repeat(' ', width))
|
||||
w.CPrint(color, repeat(' ', width))
|
||||
if right {
|
||||
w.CPrint(ColBorder, string(w.border.vertical))
|
||||
w.CPrint(color, string(w.border.vertical))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/junegunn/fzf/src/util"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
func IsLightRendererSupported() bool {
|
||||
@@ -34,12 +34,12 @@ func (r *LightRenderer) fd() int {
|
||||
|
||||
func (r *LightRenderer) initPlatform() error {
|
||||
fd := r.fd()
|
||||
origState, err := terminal.GetState(fd)
|
||||
origState, err := term.GetState(fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.origState = origState
|
||||
terminal.MakeRaw(fd)
|
||||
term.MakeRaw(fd)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -63,15 +63,15 @@ func openTtyIn() *os.File {
|
||||
}
|
||||
|
||||
func (r *LightRenderer) setupTerminal() {
|
||||
terminal.MakeRaw(r.fd())
|
||||
term.MakeRaw(r.fd())
|
||||
}
|
||||
|
||||
func (r *LightRenderer) restoreTerminal() {
|
||||
terminal.Restore(r.fd(), r.origState)
|
||||
term.Restore(r.fd(), r.origState)
|
||||
}
|
||||
|
||||
func (r *LightRenderer) updateTerminalSize() {
|
||||
width, height, err := terminal.GetSize(r.fd())
|
||||
width, height, err := term.GetSize(r.fd())
|
||||
|
||||
if err == nil {
|
||||
r.width = width
|
||||
|
||||
@@ -5,11 +5,16 @@ package tui
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/junegunn/fzf/src/util"
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
const (
|
||||
timeoutInterval = 10
|
||||
)
|
||||
|
||||
var (
|
||||
consoleFlagsInput = uint32(windows.ENABLE_VIRTUAL_TERMINAL_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_EXTENDED_FLAGS)
|
||||
consoleFlagsOutput = uint32(windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING | windows.ENABLE_PROCESSED_OUTPUT | windows.DISABLE_NEWLINE_AUTO_RETURN)
|
||||
@@ -60,7 +65,7 @@ func (r *LightRenderer) initPlatform() error {
|
||||
|
||||
// channel for non-blocking reads. Buffer to make sure
|
||||
// we get the ESC sets:
|
||||
r.ttyinChannel = make(chan byte, 12)
|
||||
r.ttyinChannel = make(chan byte, 1024)
|
||||
|
||||
// the following allows for non-blocking IO.
|
||||
// syscall.SetNonblock() is a NOOP under Windows.
|
||||
@@ -68,9 +73,6 @@ func (r *LightRenderer) initPlatform() error {
|
||||
fd := int(r.inHandle)
|
||||
b := make([]byte, 1)
|
||||
for {
|
||||
// HACK: if run from PSReadline, something resets ConsoleMode to remove ENABLE_VIRTUAL_TERMINAL_INPUT.
|
||||
_ = windows.SetConsoleMode(windows.Handle(r.inHandle), consoleFlagsInput)
|
||||
|
||||
_, err := util.Read(fd, b)
|
||||
if err == nil {
|
||||
r.ttyinChannel <- b[0]
|
||||
@@ -130,7 +132,7 @@ func (r *LightRenderer) getch(nonblock bool) (int, bool) {
|
||||
select {
|
||||
case bc := <-r.ttyinChannel:
|
||||
return int(bc), true
|
||||
default:
|
||||
case <-time.After(timeoutInterval * time.Millisecond):
|
||||
return 0, false
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -4,6 +4,7 @@ package tui
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
@@ -29,3 +30,18 @@ func ttyname() string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// TtyIn returns terminal device to be used as STDIN, falls back to os.Stdin
|
||||
func TtyIn() *os.File {
|
||||
in, err := os.OpenFile(consoleDevice, syscall.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
tty := ttyname()
|
||||
if len(tty) > 0 {
|
||||
if in, err := os.OpenFile(tty, syscall.O_RDONLY, 0); err == nil {
|
||||
return in
|
||||
}
|
||||
}
|
||||
return os.Stdin
|
||||
}
|
||||
return in
|
||||
}
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
package tui
|
||||
|
||||
import "os"
|
||||
|
||||
func ttyname() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// TtyIn on Windows returns os.Stdin
|
||||
func TtyIn() *os.File {
|
||||
return os.Stdin
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user