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

Compare commits

...

19 Commits

Author SHA1 Message Date
Junegunn Choi
b46227dcb6 0.17.5 2018-10-07 01:46:29 +09:00
Paul Frybarger
fd8d371ac7 [zsh] Fix multiline prompt issue with 'zle reset-prompt' (#1397)
Close #867 
Close #1256
2018-10-05 10:56:26 +09:00
Junegunn Choi
0e06e298d4 [man] Document that FZF_DEFAULT_COMMAND should be POSIX-compliant
Close #1379
2018-09-30 22:20:46 +09:00
Junegunn Choi
72df905902 Do not wait for more keystrokes after double escape characters
Close #1393
2018-09-28 10:33:53 +09:00
Junegunn Choi
0d748a0699 Kill running preview process after 500ms when focus has changed
Close #1383
Close #1384
2018-09-28 10:33:52 +09:00
Junegunn Choi
27c40dc6b0 Restore STDIN during execute-silent
This allows users to terminate the process with CTRL-C when it hangs.
2018-09-27 15:54:13 +09:00
Junegunn Choi
8e34e6fbb4 [install] Escape spaces in installation directory
Close #1390
2018-09-27 10:15:22 +09:00
Junegunn Choi
3bc98ed623 Add link to related projects page 2018-09-27 02:52:52 +09:00
Tim Cuthbertson
70a92a858a Don't drop buffered input data in findOffset() (#1392) 2018-09-27 02:35:44 +09:00
Jan Edmund Lazo
49d04374a4 [install] Detect MSYS on Windows (#1391) 2018-09-25 23:03:36 +09:00
Junegunn Choi
8540902a35 Add link to git key bindings gist 2018-09-04 12:24:46 +09:00
Junegunn Choi
8c6fcee3ca [vim] Fix directory switching around sink function
Close #1356

Related:
- #612
- https://github.com/junegunn/fzf.vim/issues/308
2018-08-20 15:31:41 +09:00
Junegunn Choi
13803d0dbb [vim] Clear temporary window-local working directory
Close #1085
Close #1086
Close https://github.com/junegunn/fzf.vim/issues/678
2018-08-10 18:24:18 +09:00
Michael Kelley
423986996a Handle incomplete ESC sequence in typeahead buffer (#1350)
If an ESC char is found while processing characters,
continue to check for characters. This prevents fzf from
prematurely exiting.

Close #1349
2018-08-08 15:43:55 +09:00
Younes Manton
1c9e7b7ea6 Update Makefile to build ppc64le binary (#1326)
* Add ppc64le support to Makefile

* Update crypt libs to fix tty ioctls on ppc64le

The hardcoded tty ioctl commands in the terminal package were not
correct for ppc64le and caused the ioctls to return ENOTTY for
commands like TCGETS and so on. The bug is fixed in later versions.
2018-07-16 18:55:06 +09:00
Jay
6de1ad9d3d [completion] Filter out non-hostnames in SSH config file (#1329)
* Correctly exclude SSH config options with Host

SSH config files have 14 options containing 'Host'.
Previously The zsh and bash completion scripts would include lines
containing these options when doing command-line completion of SSH hosts
with `ssh **`.

This commit fixes that problem by only including lines with 'host '.

* Don't autocomplete SSH hostnames using ?

SSH config files support ? as well as * for wildcards in Host lines.
This commit excludes lines containing ? for zsh/bash command line
completeion using `ssh **`
2018-07-06 11:29:39 +09:00
Oliver Schrenk
5004ae3457 [fish] Use $version instead of $FISH_VERSION (#1100)
$FISH_VERSION is dropped in 2.7, but every version has $version

- https://github.com/fish-shell/fish-shell/issues/4414
- fb8ae04f80

Comment from @faho in #1316:

Unfortunately, $FISH_VERSION was only ever a thing from fish 2.0 to fish 2.7.1.

All fish versions from the very beginning though used a variable called simply "$version" to store their version, so that is the one that should be used.
2018-06-27 19:02:16 +09:00
做梦专业户
e67cc75063 Update Makefile to support armv8l (#1321) 2018-06-27 18:56:02 +09:00
Junegunn Choi
0edbcbdf19 Allow search query longer than the screen width
By implementing horizontal scrolling of the prompt line.
Maximum length is hard-coded to 300-chars.

Close #1312
Fix #1225
2018-06-25 19:07:47 +09:00
21 changed files with 264 additions and 220 deletions

View File

@@ -1,6 +1,14 @@
CHANGELOG CHANGELOG
========= =========
0.17.5
------
- Bug fixes and improvements
- See https://github.com/junegunn/fzf/milestone/13?closed=1
- Search query longer than the screen width is allowed (up to 300 chars)
- Built with Go 1.11.1
0.17.4 0.17.4
------ ------

View File

@@ -1,34 +1,36 @@
ifndef GOOS ifndef GOOS
GOOS := $(word 1, $(subst /, " ", $(word 4, $(shell go version)))) GOOS := $(word 1, $(subst /, " ", $(word 4, $(shell go version))))
endif endif
MAKEFILE := $(realpath $(lastword $(MAKEFILE_LIST))) MAKEFILE := $(realpath $(lastword $(MAKEFILE_LIST)))
ROOT_DIR := $(shell dirname $(MAKEFILE)) ROOT_DIR := $(shell dirname $(MAKEFILE))
GOPATH := $(ROOT_DIR)/gopath GOPATH := $(ROOT_DIR)/gopath
SRC_LINK := $(GOPATH)/src/github.com/junegunn/fzf/src SRC_LINK := $(GOPATH)/src/github.com/junegunn/fzf/src
VENDOR_LINK := $(GOPATH)/src/github.com/junegunn/fzf/vendor VENDOR_LINK := $(GOPATH)/src/github.com/junegunn/fzf/vendor
export GOPATH export GOPATH
GLIDE_YAML := glide.yaml GLIDE_YAML := glide.yaml
GLIDE_LOCK := glide.lock GLIDE_LOCK := glide.lock
SOURCES := $(wildcard *.go src/*.go src/*/*.go) $(SRC_LINK) $(VENDOR_LINK) $(GLIDE_LOCK) $(MAKEFILE) SOURCES := $(wildcard *.go src/*.go src/*/*.go) $(SRC_LINK) $(VENDOR_LINK) $(GLIDE_LOCK) $(MAKEFILE)
REVISION := $(shell git log -n 1 --pretty=format:%h -- $(SOURCES)) REVISION := $(shell git log -n 1 --pretty=format:%h -- $(SOURCES))
BUILD_FLAGS := -a -ldflags "-X main.revision=$(REVISION) -w -extldflags=$(LDFLAGS)" -tags "$(TAGS)" BUILD_FLAGS := -a -ldflags "-X main.revision=$(REVISION) -w -extldflags=$(LDFLAGS)" -tags "$(TAGS)"
BINARY32 := fzf-$(GOOS)_386 BINARY32 := fzf-$(GOOS)_386
BINARY64 := fzf-$(GOOS)_amd64 BINARY64 := fzf-$(GOOS)_amd64
BINARYARM5 := fzf-$(GOOS)_arm5 BINARYARM5 := fzf-$(GOOS)_arm5
BINARYARM6 := fzf-$(GOOS)_arm6 BINARYARM6 := fzf-$(GOOS)_arm6
BINARYARM7 := fzf-$(GOOS)_arm7 BINARYARM7 := fzf-$(GOOS)_arm7
BINARYARM8 := fzf-$(GOOS)_arm8 BINARYARM8 := fzf-$(GOOS)_arm8
VERSION := $(shell awk -F= '/version =/ {print $$2}' src/constants.go | tr -d "\" ") BINARYPPC64LE := fzf-$(GOOS)_ppc64le
RELEASE32 := fzf-$(VERSION)-$(GOOS)_386 VERSION := $(shell awk -F= '/version =/ {print $$2}' src/constants.go | tr -d "\" ")
RELEASE64 := fzf-$(VERSION)-$(GOOS)_amd64 RELEASE32 := fzf-$(VERSION)-$(GOOS)_386
RELEASEARM5 := fzf-$(VERSION)-$(GOOS)_arm5 RELEASE64 := fzf-$(VERSION)-$(GOOS)_amd64
RELEASEARM6 := fzf-$(VERSION)-$(GOOS)_arm6 RELEASEARM5 := fzf-$(VERSION)-$(GOOS)_arm5
RELEASEARM7 := fzf-$(VERSION)-$(GOOS)_arm7 RELEASEARM6 := fzf-$(VERSION)-$(GOOS)_arm6
RELEASEARM8 := fzf-$(VERSION)-$(GOOS)_arm8 RELEASEARM7 := fzf-$(VERSION)-$(GOOS)_arm7
RELEASEARM8 := fzf-$(VERSION)-$(GOOS)_arm8
RELEASEPPC64LE := fzf-$(VERSION)-$(GOOS)_ppc64le
# https://en.wikipedia.org/wiki/Uname # https://en.wikipedia.org/wiki/Uname
UNAME_M := $(shell uname -m) UNAME_M := $(shell uname -m)
@@ -46,6 +48,10 @@ else ifeq ($(UNAME_M),armv6l)
BINARY := $(BINARYARM6) BINARY := $(BINARYARM6)
else ifeq ($(UNAME_M),armv7l) else ifeq ($(UNAME_M),armv7l)
BINARY := $(BINARYARM7) BINARY := $(BINARYARM7)
else ifeq ($(UNAME_M),armv8l)
BINARY := $(BINARYARM8)
else ifeq ($(UNAME_M),ppc64le)
BINARY := $(BINARYPPC64LE)
else else
$(error "Build on $(UNAME_M) is not supported, yet.") $(error "Build on $(UNAME_M) is not supported, yet.")
endif endif
@@ -61,13 +67,14 @@ release: target/$(BINARY32) target/$(BINARY64)
cd target && cp -f $(BINARY64) fzf.exe && zip $(RELEASE64).zip fzf.exe cd target && cp -f $(BINARY64) fzf.exe && zip $(RELEASE64).zip fzf.exe
cd target && rm -f fzf.exe cd target && rm -f fzf.exe
else ifeq ($(GOOS),linux) else ifeq ($(GOOS),linux)
release: target/$(BINARY32) target/$(BINARY64) target/$(BINARYARM5) target/$(BINARYARM6) target/$(BINARYARM7) target/$(BINARYARM8) release: target/$(BINARY32) target/$(BINARY64) target/$(BINARYARM5) target/$(BINARYARM6) target/$(BINARYARM7) target/$(BINARYARM8) target/$(BINARYPPC64LE)
cd target && cp -f $(BINARY32) fzf && tar -czf $(RELEASE32).tgz fzf cd target && cp -f $(BINARY32) fzf && tar -czf $(RELEASE32).tgz fzf
cd target && cp -f $(BINARY64) fzf && tar -czf $(RELEASE64).tgz fzf cd target && cp -f $(BINARY64) fzf && tar -czf $(RELEASE64).tgz fzf
cd target && cp -f $(BINARYARM5) fzf && tar -czf $(RELEASEARM5).tgz fzf cd target && cp -f $(BINARYARM5) fzf && tar -czf $(RELEASEARM5).tgz fzf
cd target && cp -f $(BINARYARM6) fzf && tar -czf $(RELEASEARM6).tgz fzf cd target && cp -f $(BINARYARM6) fzf && tar -czf $(RELEASEARM6).tgz fzf
cd target && cp -f $(BINARYARM7) fzf && tar -czf $(RELEASEARM7).tgz fzf cd target && cp -f $(BINARYARM7) fzf && tar -czf $(RELEASEARM7).tgz fzf
cd target && cp -f $(BINARYARM8) fzf && tar -czf $(RELEASEARM8).tgz fzf cd target && cp -f $(BINARYARM8) fzf && tar -czf $(RELEASEARM8).tgz fzf
cd target && cp -f $(BINARYPPC64LE) fzf && tar -czf $(RELEASEPPC64LE).tgz fzf
cd target && rm -f fzf cd target && rm -f fzf
else else
release: target/$(BINARY32) target/$(BINARY64) release: target/$(BINARY32) target/$(BINARY64)
@@ -125,6 +132,9 @@ target/$(BINARYARM7): $(SOURCES) vendor
target/$(BINARYARM8): $(SOURCES) vendor target/$(BINARYARM8): $(SOURCES) vendor
GOARCH=arm64 go build $(BUILD_FLAGS) -o $@ GOARCH=arm64 go build $(BUILD_FLAGS) -o $@
target/$(BINARYPPC64LE): $(SOURCES) vendor
GOARCH=ppc64le go build $(BUILD_FLAGS) -o $@
bin/fzf: target/$(BINARY) | bin bin/fzf: target/$(BINARY) | bin
cp -f target/$(BINARY) bin/fzf cp -f target/$(BINARY) bin/fzf

View File

@@ -56,6 +56,7 @@ Table of Contents
* [Respecting .gitignore](#respecting-gitignore) * [Respecting .gitignore](#respecting-gitignore)
* [git ls-tree for fast traversal](#git-ls-tree-for-fast-traversal) * [git ls-tree for fast traversal](#git-ls-tree-for-fast-traversal)
* [Fish shell](#fish-shell) * [Fish shell](#fish-shell)
* [Related projects](#related-projects)
* [<a href="LICENSE">License</a>](#license) * [<a href="LICENSE">License</a>](#license)
Installation Installation
@@ -514,7 +515,8 @@ You can customize the size and position of the preview window using
fzf --height 40% --reverse --preview 'file {}' --preview-window down:1 fzf --height 40% --reverse --preview 'file {}' --preview-window down:1
``` ```
For more advanced examples, see [Key bindings for git with fzf][fzf-git]. For more advanced examples, see [Key bindings for git with fzf][fzf-git]
([code](https://gist.github.com/junegunn/8b572b8d4b5eddd8b85e5f4d40f17236)).
[fzf-git]: https://junegunn.kr/2016/07/fzf-git/ [fzf-git]: https://junegunn.kr/2016/07/fzf-git/
@@ -598,6 +600,11 @@ valid directory. Example:
set -g FZF_CTRL_T_COMMAND "command find -L \$dir -type f 2> /dev/null | sed '1d; s#^\./##'" set -g FZF_CTRL_T_COMMAND "command find -L \$dir -type f 2> /dev/null | sed '1d; s#^\./##'"
``` ```
Related projects
----------------
https://github.com/junegunn/fzf/wiki/Related-projects
[License](LICENSE) [License](LICENSE)
------------------ ------------------

94
glide.lock generated
View File

@@ -1,10 +1,6 @@
hash: 92a208bfbaecdf8d1ccaf99a465884c49f9cd91f44f1756d7bbf3290795c781b hash: b617c76661b399f586276767bb93ee67b65dd03cfd1348ecad409e372ea97b3e
updated: 2017-12-03T13:37:23.420874333+09:00 updated: 2018-06-27T18:37:20.189962-07:00
imports: imports:
- name: github.com/bjwbell/gensimd
version: 06eb18285485c0d572cc7f024050fc6cb652ed4c
subpackages:
- simd
- name: github.com/codegangsta/cli - name: github.com/codegangsta/cli
version: c6af8847eb2b7b297d07c3ede98903e95e680ef9 version: c6af8847eb2b7b297d07c3ede98903e95e680ef9
- name: github.com/gdamore/encoding - name: github.com/gdamore/encoding
@@ -25,44 +21,12 @@ imports:
version: 14207d285c6c197daabb5c9793d63e7af9ab2d50 version: 14207d285c6c197daabb5c9793d63e7af9ab2d50
- name: github.com/mattn/go-shellwords - name: github.com/mattn/go-shellwords
version: 02e3cf038dcea8290e44424da473dd12be796a8a version: 02e3cf038dcea8290e44424da473dd12be796a8a
- name: github.com/mengzhuo/intrinsic
version: 34b800838e0bcd9c5b6abd414e3ad03dc1a686b8
subpackages:
- sse2
- name: github.com/mitchellh/go-homedir - name: github.com/mitchellh/go-homedir
version: b8bc1bf767474819792c23f32d8286a45736f1c6 version: b8bc1bf767474819792c23f32d8286a45736f1c6
- name: golang.org/x/crypto - name: golang.org/x/crypto
version: e1a4589e7d3ea14a3352255d04b6f1a418845e5e version: 558b6879de74bc843225cde5686419267ff707ca
subpackages: subpackages:
- acme
- blowfish
- cast5
- chacha20poly1305/internal/chacha20
- curve25519
- ed25519
- ed25519/internal/edwards25519
- hkdf
- nacl/secretbox
- openpgp
- openpgp/armor
- openpgp/elgamal
- openpgp/errors
- openpgp/packet
- openpgp/s2k
- pbkdf2
- pkcs12/internal/rc2
- poly1305
- ripemd160
- salsa20/salsa
- ssh
- ssh/agent
- ssh/terminal - ssh/terminal
- ssh/testdata
- name: golang.org/x/net
version: a8b9294777976932365dabb6640cf1468d95c70f
subpackages:
- context
- context/ctxhttp
- name: golang.org/x/sys - name: golang.org/x/sys
version: b90f89a1e7a9c1f6b918820b3daa7f08488c8594 version: b90f89a1e7a9c1f6b918820b3daa7f08488c8594
subpackages: subpackages:
@@ -70,65 +34,15 @@ imports:
- name: golang.org/x/text - name: golang.org/x/text
version: 4ee4af566555f5fbe026368b75596286a312663a version: 4ee4af566555f5fbe026368b75596286a312663a
subpackages: subpackages:
- cases
- collate
- collate/build
- currency
- encoding - encoding
- encoding/charmap - encoding/charmap
- encoding/ianaindex
- encoding/internal - encoding/internal
- encoding/internal/identifier - encoding/internal/identifier
- encoding/japanese - encoding/japanese
- encoding/korean - encoding/korean
- encoding/simplifiedchinese - encoding/simplifiedchinese
- encoding/traditionalchinese - encoding/traditionalchinese
- encoding/unicode
- encoding/unicode/utf32
- internal
- internal/colltab
- internal/format
- internal/gen
- internal/stringset
- internal/tag
- internal/testtext
- internal/triegen
- internal/ucd
- internal/utf8internal
- language
- language/display
- message
- runes
- secure/bidirule
- transform - transform
- unicode/bidi
- unicode/cldr
- unicode/norm
- unicode/rangetable
- width
- name: golang.org/x/tools
version: 04447353bc504b9a5c02eb227b9ecd252e64ea20
subpackages:
- go/ast/astutil
- go/buildutil
- go/loader
- name: gopkg.in/yaml.v2 - name: gopkg.in/yaml.v2
version: 287cf08546ab5e7e37d55a84f7ed3fd1db036de5 version: 287cf08546ab5e7e37d55a84f7ed3fd1db036de5
testImports: testImports: []
- name: github.com/gopherjs/gopherjs
version: 444abdf920945de5d4a977b572bcc6c674d1e4eb
subpackages:
- js
- name: github.com/jtolds/gls
version: 77f18212c9c7edc9bd6a33d383a7b545ce62f064
- name: github.com/smartystreets/assertions
version: 0b37b35ec7434b77e77a4bb29b79677cced992ea
subpackages:
- internal/go-render/render
- internal/oglematchers
- name: github.com/smartystreets/goconvey
version: e5b2b7c9111590d019a696c7800593f666e1a7f4
subpackages:
- convey
- convey/gotest
- convey/reporting

View File

@@ -11,6 +11,6 @@ import:
subpackages: subpackages:
- encoding - encoding
- package: golang.org/x/crypto - package: golang.org/x/crypto
version: e1a4589e7d3ea14a3352255d04b6f1a418845e5e version: 558b6879de74bc843225cde5686419267ff707ca
subpackages: subpackages:
- ssh/terminal - ssh/terminal

13
install
View File

@@ -2,7 +2,7 @@
set -u set -u
version=0.17.4 version=0.17.5
auto_completion= auto_completion=
key_bindings= key_bindings=
update_config=2 update_config=2
@@ -73,7 +73,8 @@ for opt in "$@"; do
done done
cd "$(dirname "${BASH_SOURCE[0]}")" cd "$(dirname "${BASH_SOURCE[0]}")"
fzf_base="$(pwd)" fzf_base=$(pwd)
fzf_base_esc=$(printf %q "$fzf_base")
ask() { ask() {
while true; do while true; do
@@ -192,6 +193,8 @@ case "$archi" in
CYGWIN*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;; CYGWIN*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;;
MINGW*\ *86) download fzf-$version-windows_${binary_arch:-386}.zip ;; MINGW*\ *86) download fzf-$version-windows_${binary_arch:-386}.zip ;;
MINGW*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;; MINGW*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;;
MSYS*\ *86) download fzf-$version-windows_${binary_arch:-386}.zip ;;
MSYS*\ *64) download fzf-$version-windows_${binary_arch:-amd64}.zip ;;
*) binary_available=0 binary_error=1 ;; *) binary_available=0 binary_error=1 ;;
esac esac
@@ -265,7 +268,7 @@ for shell in $shells; do
cat > "$src" << EOF cat > "$src" << EOF
# Setup fzf # Setup fzf
# --------- # ---------
if [[ ! "\$PATH" == *$fzf_base/bin* ]]; then if [[ ! "\$PATH" == *$fzf_base_esc/bin* ]]; then
export PATH="\$PATH:$fzf_base/bin" export PATH="\$PATH:$fzf_base/bin"
fi fi
@@ -285,8 +288,8 @@ done
if [[ "$shells" =~ fish ]]; then if [[ "$shells" =~ fish ]]; then
echo -n "Update fish_user_paths ... " echo -n "Update fish_user_paths ... "
fish << EOF fish << EOF
echo \$fish_user_paths | \grep $fzf_base/bin > /dev/null echo \$fish_user_paths | \grep "$fzf_base"/bin > /dev/null
or set --universal fish_user_paths \$fish_user_paths $fzf_base/bin or set --universal fish_user_paths \$fish_user_paths "$fzf_base"/bin
EOF EOF
[ $? -eq 0 ] && echo "OK" || echo "Failed" [ $? -eq 0 ] && echo "OK" || echo "Failed"

View File

@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf-tmux 1 "Jun 2018" "fzf 0.17.4" "fzf-tmux - open fzf in tmux split pane" .TH fzf-tmux 1 "Oct 2018" "fzf 0.17.5" "fzf-tmux - open fzf in tmux split pane"
.SH NAME .SH NAME
fzf-tmux - open fzf in tmux split pane fzf-tmux - open fzf in tmux split pane

View File

@@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf 1 "Jun 2018" "fzf 0.17.4" "fzf - a command-line fuzzy finder" .TH fzf 1 "Oct 2018" "fzf 0.17.5" "fzf - a command-line fuzzy finder"
.SH NAME .SH NAME
fzf - a command-line fuzzy finder fzf - a command-line fuzzy finder
@@ -390,7 +390,8 @@ Note that most options have the opposite versions with \fB--no-\fR prefix.
.SH ENVIRONMENT VARIABLES .SH ENVIRONMENT VARIABLES
.TP .TP
.B FZF_DEFAULT_COMMAND .B FZF_DEFAULT_COMMAND
Default command to use when input is tty Default command to use when input is tty. On *nix systems, fzf runs the command
with \fBsh -c\fR, so make sure that it's POSIX-compliant.
.TP .TP
.B FZF_DEFAULT_OPTS .B FZF_DEFAULT_OPTS
Default options. e.g. \fBexport FZF_DEFAULT_OPTS="--extended --cycle"\fR Default options. e.g. \fBexport FZF_DEFAULT_OPTS="--extended --cycle"\fR

View File

@@ -357,7 +357,7 @@ try
throw v:exception throw v:exception
endtry endtry
if has('nvim') && !has_key(dict, 'dir') if !has_key(dict, 'dir')
let dict.dir = s:fzf_getcwd() let dict.dir = s:fzf_getcwd()
endif endif
if has('win32unix') && has_key(dict, 'dir') if has('win32unix') && has_key(dict, 'dir')
@@ -455,15 +455,17 @@ endfunction
function! s:pushd(dict) function! s:pushd(dict)
if s:present(a:dict, 'dir') if s:present(a:dict, 'dir')
let cwd = s:fzf_getcwd() let cwd = s:fzf_getcwd()
if get(a:dict, 'prev_dir', '') ==# cwd let w:fzf_pushd = {
return 1 \ 'command': haslocaldir() ? 'lcd' : (exists(':tcd') && haslocaldir(-1) ? 'tcd' : 'cd'),
endif \ 'origin': cwd
let a:dict.prev_dir = cwd \ }
execute 'lcd' s:escape(a:dict.dir) execute 'lcd' s:escape(a:dict.dir)
let a:dict.dir = s:fzf_getcwd() let cwd = s:fzf_getcwd()
return 1 let w:fzf_pushd.dir = cwd
let a:dict.pushd = w:fzf_pushd
return cwd
endif endif
return 0 return ''
endfunction endfunction
augroup fzf_popd augroup fzf_popd
@@ -472,11 +474,29 @@ augroup fzf_popd
augroup END augroup END
function! s:dopopd() function! s:dopopd()
if !exists('w:fzf_dir') || s:fzf_getcwd() != w:fzf_dir[1] if !exists('w:fzf_pushd')
return return
endif endif
execute 'lcd' s:escape(w:fzf_dir[0])
unlet w:fzf_dir " FIXME: We temporarily change the working directory to 'dir' entry
" of options dictionary (set to the current working directory if not given)
" before running fzf.
"
" e.g. call fzf#run({'dir': '/tmp', 'source': 'ls', 'sink': 'e'})
"
" After processing the sink function, we have to restore the current working
" directory. But doing so may not be desirable if the function changed the
" working directory on purpose.
"
" So how can we tell if we should do it or not? A simple heuristic we use
" here is that we change directory only if the current working directory
" matches 'dir' entry. However, it is possible that the sink function did
" change the directory to 'dir'. In that case, the user will have an
" unexpected result.
if s:fzf_getcwd() ==# w:fzf_pushd.dir
execute w:fzf_pushd.command s:escape(w:fzf_pushd.origin)
endif
unlet w:fzf_pushd
endfunction endfunction
function! s:xterm_launcher() function! s:xterm_launcher()
@@ -534,9 +554,7 @@ function! s:execute(dict, command, use_height, temps) abort
let fzf.dict = a:dict let fzf.dict = a:dict
let fzf.temps = a:temps let fzf.temps = a:temps
function! fzf.on_exit(job_id, exit_status, event) dict function! fzf.on_exit(job_id, exit_status, event) dict
if s:present(self.dict, 'dir') call s:pushd(self.dict)
execute 'lcd' s:escape(self.dict.dir)
endif
let lines = s:collect(self.temps) let lines = s:collect(self.temps)
call s:callback(self.dict, lines) call s:callback(self.dict, lines)
endfunction endfunction
@@ -563,9 +581,10 @@ endfunction
function! s:execute_tmux(dict, command, temps) abort function! s:execute_tmux(dict, command, temps) abort
let command = a:command let command = a:command
if s:pushd(a:dict) let cwd = s:pushd(a:dict)
if len(cwd)
" -c '#{pane_current_path}' is only available on tmux 1.9 or above " -c '#{pane_current_path}' is only available on tmux 1.9 or above
let command = join(['cd', fzf#shellescape(a:dict.dir), '&&', command]) let command = join(['cd', fzf#shellescape(cwd), '&&', command])
endif endif
call system(command) call system(command)
@@ -686,9 +705,7 @@ function! s:execute_term(dict, command, temps) abort
endfunction endfunction
try try
if s:present(a:dict, 'dir') call s:pushd(a:dict)
execute 'lcd' s:escape(a:dict.dir)
endif
if s:is_win if s:is_win
let fzf.temps.batchfile = s:fzf_tempname().'.bat' let fzf.temps.batchfile = s:fzf_tempname().'.bat'
call writefile(s:wrap_cmds(a:command), fzf.temps.batchfile) call writefile(s:wrap_cmds(a:command), fzf.temps.batchfile)
@@ -706,9 +723,7 @@ function! s:execute_term(dict, command, temps) abort
endif endif
endif endif
finally finally
if s:present(a:dict, 'dir') call s:dopopd()
lcd -
endif
endtry endtry
setlocal nospell bufhidden=wipe nobuflisted nonumber setlocal nospell bufhidden=wipe nobuflisted nonumber
setf fzf setf fzf
@@ -727,21 +742,9 @@ function! s:collect(temps) abort
endfunction endfunction
function! s:callback(dict, lines) abort function! s:callback(dict, lines) abort
" Since anything can be done in the sink function, there is no telling that let popd = has_key(a:dict, 'pushd')
" the change of the working directory was made by &autochdir setting.
"
" We use the following heuristic to determine whether to restore CWD:
" - Always restore the current directory when &autochdir is disabled.
" FIXME This makes it impossible to change directory from inside the sink
" function when &autochdir is not used.
" - In case of an error or an interrupt, a:lines will be empty.
" And it will be an array of a single empty string when fzf was finished
" without a match. In these cases, we presume that the change of the
" directory is not expected and should be undone.
let popd = has_key(a:dict, 'prev_dir') &&
\ (!&autochdir || (empty(a:lines) || len(a:lines) == 1 && empty(a:lines[0])))
if popd if popd
let w:fzf_dir = [a:dict.prev_dir, a:dict.dir] let w:fzf_pushd = a:dict.pushd
endif endif
try try
@@ -765,7 +768,7 @@ function! s:callback(dict, lines) abort
" We may have opened a new window or tab " We may have opened a new window or tab
if popd if popd
let w:fzf_dir = [a:dict.prev_dir, a:dict.dir] let w:fzf_pushd = a:dict.pushd
call s:dopopd() call s:dopopd()
endif endif
endfunction endfunction

View File

@@ -241,7 +241,7 @@ _fzf_complete_telnet() {
_fzf_complete_ssh() { _fzf_complete_ssh() {
_fzf_complete '+m' "$@" < <( _fzf_complete '+m' "$@" < <(
cat <(cat ~/.ssh/config /etc/ssh/ssh_config 2> /dev/null | command grep -i '^host' | command grep -v '*' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}') \ cat <(cat ~/.ssh/config /etc/ssh/ssh_config 2> /dev/null | command grep -i '^host ' | command grep -v '[*?]' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}') \
<(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \ <(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
<(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') | <(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
awk '{if (length($2) > 0) {print $2}}' | sort -u awk '{if (length($2) > 0) {print $2}}' | sort -u

View File

@@ -60,8 +60,7 @@ __fzf_generic_path_completion() {
if [ -n "$matches" ]; then if [ -n "$matches" ]; then
LBUFFER="$lbuf$matches$tail" LBUFFER="$lbuf$matches$tail"
fi fi
zle redisplay zle reset-prompt
typeset -f zle-line-init >/dev/null && zle zle-line-init
break break
fi fi
dir=$(dirname "$dir") dir=$(dirname "$dir")
@@ -100,8 +99,7 @@ _fzf_complete() {
if [ -n "$matches" ]; then if [ -n "$matches" ]; then
LBUFFER="$lbuf$matches" LBUFFER="$lbuf$matches"
fi fi
zle redisplay zle reset-prompt
typeset -f zle-line-init >/dev/null && zle zle-line-init
command rm -f "$fifo" command rm -f "$fifo"
} }
@@ -114,7 +112,7 @@ _fzf_complete_telnet() {
_fzf_complete_ssh() { _fzf_complete_ssh() {
_fzf_complete '+m' "$@" < <( _fzf_complete '+m' "$@" < <(
command cat <(cat ~/.ssh/config /etc/ssh/ssh_config 2> /dev/null | command grep -i '^host' | command grep -v '*' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}') \ command cat <(cat ~/.ssh/config /etc/ssh/ssh_config 2> /dev/null | command grep -i '^host ' | command grep -v '[*?]' | awk '{for (i = 2; i <= NF; i++) print $1 " " $i}') \
<(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \ <(command grep -oE '^[[a-z0-9.,:-]+' ~/.ssh/known_hosts | tr ',' '\n' | tr -d '[' | awk '{ print $1 " " $1 }') \
<(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') | <(command grep -v '^\s*\(#\|$\)' /etc/hosts | command grep -Fv '0.0.0.0') |
awk '{if (length($2) > 0) {print $2}}' | sort -u awk '{if (length($2) > 0) {print $2}}' | sort -u
@@ -165,8 +163,7 @@ fzf-completion() {
if [ -n "$matches" ]; then if [ -n "$matches" ]; then
LBUFFER="$LBUFFER$matches" LBUFFER="$LBUFFER$matches"
fi fi
zle redisplay zle reset-prompt
typeset -f zle-line-init >/dev/null && zle zle-line-init
# Trigger sequence given # Trigger sequence given
elif [ ${#tokens} -gt 1 -a "$tail" = "$trigger" ]; then elif [ ${#tokens} -gt 1 -a "$tail" = "$trigger" ]; then
d_cmds=(${=FZF_COMPLETION_DIR_COMMANDS:-cd pushd rmdir}) d_cmds=(${=FZF_COMPLETION_DIR_COMMANDS:-cd pushd rmdir})

View File

@@ -40,8 +40,8 @@ function fzf_key_bindings
begin begin
set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m" set -lx FZF_DEFAULT_OPTS "--height $FZF_TMUX_HEIGHT $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m"
set -l FISH_MAJOR (echo $FISH_VERSION | cut -f1 -d.) set -l FISH_MAJOR (echo $version | cut -f1 -d.)
set -l FISH_MINOR (echo $FISH_VERSION | cut -f2 -d.) set -l FISH_MINOR (echo $version | cut -f2 -d.)
# history's -z flag is needed for multi-line support. # history's -z flag is needed for multi-line support.
# history's -z flag was added in fish 2.4.0, so don't use it for versions # history's -z flag was added in fish 2.4.0, so don't use it for versions

View File

@@ -29,8 +29,7 @@ __fzfcmd() {
fzf-file-widget() { fzf-file-widget() {
LBUFFER="${LBUFFER}$(__fsel)" LBUFFER="${LBUFFER}$(__fsel)"
local ret=$? local ret=$?
zle redisplay zle reset-prompt
typeset -f zle-line-init >/dev/null && zle zle-line-init
return $ret return $ret
} }
zle -N fzf-file-widget zle -N fzf-file-widget
@@ -59,7 +58,6 @@ fzf-cd-widget() {
cd "$dir" cd "$dir"
local ret=$? local ret=$?
zle fzf-redraw-prompt zle fzf-redraw-prompt
typeset -f zle-line-init >/dev/null && zle zle-line-init
return $ret return $ret
} }
zle -N fzf-cd-widget zle -N fzf-cd-widget
@@ -78,8 +76,7 @@ fzf-history-widget() {
zle vi-fetch-history -n $num zle vi-fetch-history -n $num
fi fi
fi fi
zle redisplay zle reset-prompt
typeset -f zle-line-init >/dev/null && zle zle-line-init
return $ret return $ret
} }
zle -N fzf-history-widget zle -N fzf-history-widget

View File

@@ -9,7 +9,7 @@ import (
const ( const (
// Current version // Current version
version = "0.17.4" version = "0.17.5"
// Core // Core
coordinatorDelayMax time.Duration = 100 * time.Millisecond coordinatorDelayMax time.Duration = 100 * time.Millisecond
@@ -22,9 +22,11 @@ const (
readerPollIntervalMax = 50 * time.Millisecond readerPollIntervalMax = 50 * time.Millisecond
// Terminal // Terminal
initialDelay = 20 * time.Millisecond initialDelay = 20 * time.Millisecond
initialDelayTac = 100 * time.Millisecond initialDelayTac = 100 * time.Millisecond
spinnerDuration = 200 * time.Millisecond spinnerDuration = 200 * time.Millisecond
previewCancelWait = 500 * time.Millisecond
maxPatternLength = 300
// Matcher // Matcher
numPartitionsMultiplier = 8 numPartitionsMultiplier = 8
@@ -75,6 +77,7 @@ const (
) )
const ( const (
exitCancel = -1
exitOk = 0 exitOk = 0
exitNoMatch = 1 exitNoMatch = 1
exitError = 2 exitError = 2

View File

@@ -103,7 +103,7 @@ func (r *Reader) readFromStdin() bool {
} }
func (r *Reader) readFromCommand(shell string, cmd string) bool { func (r *Reader) readFromCommand(shell string, cmd string) bool {
listCommand := util.ExecCommandWith(shell, cmd) listCommand := util.ExecCommandWith(shell, cmd, false)
out, err := listCommand.StdoutPipe() out, err := listCommand.StdoutPipe()
if err != nil { if err != nil {
return false return false

View File

@@ -59,6 +59,7 @@ type Terminal struct {
inlineInfo bool inlineInfo bool
prompt string prompt string
promptLen int promptLen int
queryLen [2]int
layout layoutType layout layoutType
fullscreen bool fullscreen bool
hscroll bool hscroll bool
@@ -68,6 +69,7 @@ type Terminal struct {
cx int cx int
cy int cy int
offset int offset int
xoffset int
yanked []rune yanked []rune
input []rune input []rune
multi bool multi bool
@@ -112,6 +114,7 @@ type Terminal struct {
prevLines []itemLine prevLines []itemLine
suppress bool suppress bool
startChan chan bool startChan chan bool
killChan chan int
slab *util.Slab slab *util.Slab
theme *tui.ColorTheme theme *tui.ColorTheme
tui tui.Renderer tui tui.Renderer
@@ -364,6 +367,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
t := Terminal{ t := Terminal{
initDelay: delay, initDelay: delay,
inlineInfo: opts.InlineInfo, inlineInfo: opts.InlineInfo,
queryLen: [2]int{0, 0},
layout: opts.Layout, layout: opts.Layout,
fullscreen: fullscreen, fullscreen: fullscreen,
hscroll: opts.Hscroll, hscroll: opts.Hscroll,
@@ -373,6 +377,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
cx: len(input), cx: len(input),
cy: 0, cy: 0,
offset: 0, offset: 0,
xoffset: 0,
yanked: []rune{}, yanked: []rune{},
input: input, input: input,
multi: opts.Multi, multi: opts.Multi,
@@ -410,6 +415,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox) *Terminal {
slab: util.MakeSlab(slab16Size, slab32Size), slab: util.MakeSlab(slab16Size, slab32Size),
theme: opts.Theme, theme: opts.Theme,
startChan: make(chan bool, 1), startChan: make(chan bool, 1),
killChan: make(chan int),
tui: renderer, tui: renderer,
initFunc: func() { renderer.Init() }} initFunc: func() { renderer.Init() }}
t.prompt, t.promptLen = t.processTabs([]rune(opts.Prompt), 0) t.prompt, t.promptLen = t.processTabs([]rune(opts.Prompt), 0)
@@ -640,7 +646,6 @@ func (t *Terminal) resizeWindows() {
for i := 0; i < t.window.Height(); i++ { for i := 0; i < t.window.Height(); i++ {
t.window.MoveAndClear(i, 0) t.window.MoveAndClear(i, 0)
} }
t.truncateQuery()
} }
func (t *Terminal) move(y int, x int, clear bool) { func (t *Terminal) move(y int, x int, clear bool) {
@@ -668,20 +673,44 @@ func (t *Terminal) move(y int, x int, clear bool) {
} }
} }
func (t *Terminal) truncateQuery() {
t.input, _ = t.trimRight(t.input, maxPatternLength)
t.cx = util.Constrain(t.cx, 0, len(t.input))
}
func (t *Terminal) updatePromptOffset() ([]rune, []rune) {
maxWidth := util.Max(1, t.window.Width()-t.promptLen-1)
_, overflow := t.trimLeft(t.input[:t.cx], maxWidth)
minOffset := int(overflow)
maxOffset := util.Min(util.Min(len(t.input), minOffset+maxWidth), t.cx)
t.xoffset = util.Constrain(t.xoffset, minOffset, maxOffset)
before, _ := t.trimLeft(t.input[t.xoffset:t.cx], maxWidth)
beforeLen := t.displayWidth(before)
after, _ := t.trimRight(t.input[t.cx:], maxWidth-beforeLen)
afterLen := t.displayWidth(after)
t.queryLen = [2]int{beforeLen, afterLen}
return before, after
}
func (t *Terminal) placeCursor() { func (t *Terminal) placeCursor() {
t.move(0, t.promptLen+t.displayWidth(t.input[:t.cx]), false) t.move(0, t.promptLen+t.queryLen[0], false)
} }
func (t *Terminal) printPrompt() { func (t *Terminal) printPrompt() {
t.move(0, 0, true) t.move(0, 0, true)
t.window.CPrint(tui.ColPrompt, t.strong, t.prompt) t.window.CPrint(tui.ColPrompt, t.strong, t.prompt)
t.window.CPrint(tui.ColNormal, t.strong, string(t.input))
before, after := t.updatePromptOffset()
t.window.CPrint(tui.ColNormal, t.strong, string(before))
t.window.CPrint(tui.ColNormal, t.strong, string(after))
} }
func (t *Terminal) printInfo() { func (t *Terminal) printInfo() {
pos := 0 pos := 0
if t.inlineInfo { if t.inlineInfo {
pos = t.promptLen + t.displayWidth(t.input) + 1 pos = t.promptLen + t.queryLen[0] + t.queryLen[1] + 1
if pos+len(" < ") > t.window.Width() { if pos+len(" < ") > t.window.Width() {
return return
} }
@@ -1271,7 +1300,7 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
return return
} }
command := replacePlaceholder(template, t.ansi, t.delimiter, forcePlus, string(t.input), list) command := replacePlaceholder(template, t.ansi, t.delimiter, forcePlus, string(t.input), list)
cmd := util.ExecCommand(command) cmd := util.ExecCommand(command, false)
if !background { if !background {
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
@@ -1282,7 +1311,9 @@ func (t *Terminal) executeCommand(template string, forcePlus bool, background bo
t.redraw() t.redraw()
t.refresh() t.refresh()
} else { } else {
t.tui.Pause(false)
cmd.Run() cmd.Run()
t.tui.Resume(false)
} }
} }
@@ -1334,12 +1365,6 @@ func (t *Terminal) buildPlusList(template string, forcePlus bool) (bool, []*Item
return true, sels return true, sels
} }
func (t *Terminal) truncateQuery() {
maxPatternLength := util.Max(1, t.window.Width()-t.promptLen-1)
t.input, _ = t.trimRight(t.input, maxPatternLength)
t.cx = util.Constrain(t.cx, 0, len(t.input))
}
func (t *Terminal) selectItem(item *Item) { func (t *Terminal) selectItem(item *Item) {
t.selected[item.Index()] = selectedItem{time.Now(), item} t.selected[item.Index()] = selectedItem{time.Now(), item}
t.version++ t.version++
@@ -1358,6 +1383,20 @@ func (t *Terminal) toggleItem(item *Item) {
} }
} }
func (t *Terminal) killPreview(code int) {
select {
case t.killChan <- code:
default:
if code != exitCancel {
os.Exit(code)
}
}
}
func (t *Terminal) cancelPreview() {
t.killPreview(exitCancel)
}
// Loop is called to start Terminal I/O // Loop is called to start Terminal I/O
func (t *Terminal) Loop() { func (t *Terminal) Loop() {
// prof := profile.Start(profile.ProfilePath("/tmp/")) // prof := profile.Start(profile.ProfilePath("/tmp/"))
@@ -1392,10 +1431,10 @@ func (t *Terminal) Loop() {
t.initFunc() t.initFunc()
t.resizeWindows() t.resizeWindows()
t.printPrompt() t.printPrompt()
t.placeCursor()
t.refresh()
t.printInfo() t.printInfo()
t.printHeader() t.printHeader()
t.placeCursor()
t.refresh()
t.mutex.Unlock() t.mutex.Unlock()
go func() { go func() {
timer := time.NewTimer(t.initDelay) timer := time.NewTimer(t.initDelay)
@@ -1435,15 +1474,43 @@ func (t *Terminal) Loop() {
if request[0] != nil { if request[0] != nil {
command := replacePlaceholder(t.preview.command, command := replacePlaceholder(t.preview.command,
t.ansi, t.delimiter, false, string(t.input), request) t.ansi, t.delimiter, false, string(t.input), request)
cmd := util.ExecCommand(command) cmd := util.ExecCommand(command, true)
if t.pwindow != nil { if t.pwindow != nil {
env := os.Environ() env := os.Environ()
env = append(env, fmt.Sprintf("LINES=%d", t.pwindow.Height())) env = append(env, fmt.Sprintf("LINES=%d", t.pwindow.Height()))
env = append(env, fmt.Sprintf("COLUMNS=%d", t.pwindow.Width())) env = append(env, fmt.Sprintf("COLUMNS=%d", t.pwindow.Width()))
cmd.Env = env cmd.Env = env
} }
out, _ := cmd.CombinedOutput() var out bytes.Buffer
t.reqBox.Set(reqPreviewDisplay, string(out)) cmd.Stdout = &out
cmd.Stderr = &out
cmd.Start()
finishChan := make(chan bool, 1)
updateChan := make(chan bool)
go func() {
select {
case code := <-t.killChan:
if code != exitCancel {
util.KillCommand(cmd)
os.Exit(code)
} else {
select {
case <-time.After(previewCancelWait):
util.KillCommand(cmd)
updateChan <- true
case <-finishChan:
updateChan <- false
}
}
case <-finishChan:
updateChan <- false
}
}()
cmd.Wait()
finishChan <- true
if out.Len() > 0 || !<-updateChan {
t.reqBox.Set(reqPreviewDisplay, string(out.Bytes()))
}
} else { } else {
t.reqBox.Set(reqPreviewDisplay, "") t.reqBox.Set(reqPreviewDisplay, "")
} }
@@ -1461,7 +1528,7 @@ func (t *Terminal) Loop() {
t.history.append(string(t.input)) t.history.append(string(t.input))
} }
// prof.Stop() // prof.Stop()
os.Exit(code) t.killPreview(code)
} }
go func() { go func() {
@@ -1488,6 +1555,7 @@ func (t *Terminal) Loop() {
focused = currentFocus focused = currentFocus
if t.isPreviewEnabled() { if t.isPreviewEnabled() {
_, list := t.buildPlusList(t.preview.command, false) _, list := t.buildPlusList(t.preview.command, false)
t.cancelPreview()
t.previewBox.Set(reqPreviewEnqueue, list) t.previewBox.Set(reqPreviewEnqueue, list)
} }
} }
@@ -1529,9 +1597,9 @@ func (t *Terminal) Loop() {
} }
} }
t.placeCursor() t.placeCursor()
t.refresh()
t.mutex.Unlock() t.mutex.Unlock()
}) })
t.refresh()
} }
}() }()
@@ -1597,6 +1665,7 @@ func (t *Terminal) Loop() {
if t.previewer.enabled { if t.previewer.enabled {
valid, list := t.buildPlusList(t.preview.command, false) valid, list := t.buildPlusList(t.preview.command, false)
if valid { if valid {
t.cancelPreview()
t.previewBox.Set(reqPreviewEnqueue, list) t.previewBox.Set(reqPreviewEnqueue, list)
} }
} }
@@ -1852,7 +1921,7 @@ func (t *Terminal) Loop() {
} else if me.Down { } else if me.Down {
if my == 0 && mx >= 0 { if my == 0 && mx >= 0 {
// Prompt // Prompt
t.cx = mx t.cx = mx + t.xoffset
} else if my >= min { } else if my >= min {
// List // List
if t.vset(t.offset+my-min) && t.multi && me.Mod { if t.vset(t.offset+my-min) && t.multi && me.Mod {

View File

@@ -27,7 +27,7 @@ const (
const consoleDevice string = "/dev/tty" const consoleDevice string = "/dev/tty"
var offsetRegexp *regexp.Regexp = regexp.MustCompile("\x1b\\[([0-9]+);([0-9]+)R") var offsetRegexp *regexp.Regexp = regexp.MustCompile("(.*)\x1b\\[([0-9]+);([0-9]+)R")
func openTtyIn() *os.File { func openTtyIn() *os.File {
in, err := os.OpenFile(consoleDevice, syscall.O_RDONLY, 0) in, err := os.OpenFile(consoleDevice, syscall.O_RDONLY, 0)
@@ -154,8 +154,10 @@ func (r *LightRenderer) findOffset() (row int, col int) {
for tries := 0; tries < offsetPollTries; tries++ { for tries := 0; tries < offsetPollTries; tries++ {
bytes = r.getBytesInternal(bytes, tries > 0) bytes = r.getBytesInternal(bytes, tries > 0)
offsets := offsetRegexp.FindSubmatch(bytes) offsets := offsetRegexp.FindSubmatch(bytes)
if len(offsets) > 2 { if len(offsets) > 3 {
return atoi(string(offsets[1]), 0) - 1, atoi(string(offsets[2]), 0) - 1 // add anything we skipped over to the input buffer
r.buffer = append(r.buffer, offsets[1]...)
return atoi(string(offsets[2]), 0) - 1, atoi(string(offsets[3]), 0) - 1
} }
} }
return -1, -1 return -1, -1
@@ -297,6 +299,7 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) []byte {
} }
buffer = append(buffer, byte(c)) buffer = append(buffer, byte(c))
pc := c
for { for {
c, ok = r.getch(true) c, ok = r.getch(true)
if !ok { if !ok {
@@ -306,9 +309,13 @@ func (r *LightRenderer) getBytesInternal(buffer []byte, nonblock bool) []byte {
continue continue
} }
break break
} else if c == ESC && pc != c {
retries = r.escDelay / escPollInterval
} else {
retries = 0
} }
retries = 0
buffer = append(buffer, byte(c)) buffer = append(buffer, byte(c))
pc = c
} }
return buffer return buffer
@@ -374,6 +381,8 @@ func (r *LightRenderer) escSequence(sz *int) Event {
alt = true alt = true
} }
switch r.buffer[1] { switch r.buffer[1] {
case ESC:
return Event{ESC, 0, nil}
case 32: case 32:
return Event{AltSpace, 0, nil} return Event{AltSpace, 0, nil}
case 47: case 47:

View File

@@ -382,12 +382,16 @@ func (r *FullscreenRenderer) GetChar() Event {
return Event{Invalid, 0, nil} return Event{Invalid, 0, nil}
} }
func (r *FullscreenRenderer) Pause(bool) { func (r *FullscreenRenderer) Pause(clear bool) {
_screen.Fini() if clear {
_screen.Fini()
}
} }
func (r *FullscreenRenderer) Resume(bool) { func (r *FullscreenRenderer) Resume(clear bool) {
r.initScreen() if clear {
r.initScreen()
}
} }
func (r *FullscreenRenderer) Close() { func (r *FullscreenRenderer) Close() {

View File

@@ -9,17 +9,26 @@ import (
) )
// ExecCommand executes the given command with $SHELL // ExecCommand executes the given command with $SHELL
func ExecCommand(command string) *exec.Cmd { func ExecCommand(command string, setpgid bool) *exec.Cmd {
shell := os.Getenv("SHELL") shell := os.Getenv("SHELL")
if len(shell) == 0 { if len(shell) == 0 {
shell = "sh" shell = "sh"
} }
return ExecCommandWith(shell, command) return ExecCommandWith(shell, command, setpgid)
} }
// ExecCommandWith executes the given command with the specified shell // ExecCommandWith executes the given command with the specified shell
func ExecCommandWith(shell string, command string) *exec.Cmd { func ExecCommandWith(shell string, command string, setpgid bool) *exec.Cmd {
return exec.Command(shell, "-c", command) cmd := exec.Command(shell, "-c", command)
if setpgid {
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
}
return cmd
}
// KillCommand kills the process for the given command
func KillCommand(cmd *exec.Cmd) error {
return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
} }
// IsWindows returns true on Windows // IsWindows returns true on Windows
@@ -27,7 +36,7 @@ func IsWindows() bool {
return false return false
} }
// SetNonBlock executes syscall.SetNonblock on file descriptor // SetNonblock executes syscall.SetNonblock on file descriptor
func SetNonblock(file *os.File, nonblock bool) { func SetNonblock(file *os.File, nonblock bool) {
syscall.SetNonblock(int(file.Fd()), nonblock) syscall.SetNonblock(int(file.Fd()), nonblock)
} }

View File

@@ -10,13 +10,15 @@ import (
) )
// ExecCommand executes the given command with cmd // ExecCommand executes the given command with cmd
func ExecCommand(command string) *exec.Cmd { func ExecCommand(command string, setpgid bool) *exec.Cmd {
return ExecCommandWith("cmd", command) return ExecCommandWith("cmd", command, setpgid)
} }
// ExecCommandWith executes the given command with cmd. _shell parameter is // ExecCommandWith executes the given command with cmd. _shell parameter is
// ignored on Windows. // ignored on Windows.
func ExecCommandWith(_shell string, command string) *exec.Cmd { // FIXME: setpgid is unused. We set it in the Unix implementation so that we
// can kill preview process with its child processes at once.
func ExecCommandWith(_shell string, command string, setpgid bool) *exec.Cmd {
cmd := exec.Command("cmd") cmd := exec.Command("cmd")
cmd.SysProcAttr = &syscall.SysProcAttr{ cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: false, HideWindow: false,
@@ -26,12 +28,17 @@ func ExecCommandWith(_shell string, command string) *exec.Cmd {
return cmd return cmd
} }
// KillCommand kills the process for the given command
func KillCommand(cmd *exec.Cmd) error {
return cmd.Process.Kill()
}
// IsWindows returns true on Windows // IsWindows returns true on Windows
func IsWindows() bool { func IsWindows() bool {
return true return true
} }
// SetNonBlock executes syscall.SetNonblock on file descriptor // SetNonblock executes syscall.SetNonblock on file descriptor
func SetNonblock(file *os.File, nonblock bool) { func SetNonblock(file *os.File, nonblock bool) {
syscall.SetNonblock(syscall.Handle(file.Fd()), nonblock) syscall.SetNonblock(syscall.Handle(file.Fd()), nonblock)
} }

View File

@@ -8,10 +8,13 @@ Execute (fzf#run with dir option):
let cwd = getcwd() let cwd = getcwd()
let result = fzf#run({ 'source': 'git ls-files', 'options': '--filter=vdr', 'dir': g:dir }) let result = fzf#run({ 'source': 'git ls-files', 'options': '--filter=vdr', 'dir': g:dir })
AssertEqual ['fzf.vader'], result AssertEqual ['fzf.vader'], result
AssertEqual 0, haslocaldir()
AssertEqual getcwd(), cwd AssertEqual getcwd(), cwd
execute 'lcd' fnameescape(cwd)
let result = sort(fzf#run({ 'source': 'git ls-files', 'options': '--filter e', 'dir': g:dir })) let result = sort(fzf#run({ 'source': 'git ls-files', 'options': '--filter e', 'dir': g:dir }))
AssertEqual ['fzf.vader', 'test_go.rb'], result AssertEqual ['fzf.vader', 'test_go.rb'], result
AssertEqual 1, haslocaldir()
AssertEqual getcwd(), cwd AssertEqual getcwd(), cwd
Execute (fzf#run with Funcref command): Execute (fzf#run with Funcref command):
@@ -56,11 +59,11 @@ Execute (Incomplete fzf#run with dir option and autochdir):
" No change in working directory even if &acd is set " No change in working directory even if &acd is set
AssertEqual cwd, getcwd() AssertEqual cwd, getcwd()
Execute (fzf#run with dir option and autochdir): Execute (FIXME: fzf#run with dir option and autochdir):
set acd set acd
let cwd = getcwd()
call fzf#run({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'}) call fzf#run({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
" Working directory changed due to &acd " Working directory changed due to &acd
AssertEqual '/foobar', expand('%')
AssertEqual '/', getcwd() AssertEqual '/', getcwd()
Execute (fzf#run with dir option and autochdir when final cwd is same as dir): Execute (fzf#run with dir option and autochdir when final cwd is same as dir):