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

Compare commits

...

15 Commits

Author SHA1 Message Date
Junegunn Choi
334a4fa159 0.21.1 2020-04-03 17:33:29 +09:00
Junegunn Choi
21f94ee800 [fzf-tmux] Split zsh variable expansion for old zsh
The following code works in zsh 5.8 but not in 5.4

  ${(Q)${(Z+n+)FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}}}
2020-04-03 13:23:15 +09:00
Junegunn Choi
540bfd7a72 [fzf-tmux] Fall back to plain fzf when split failed 2020-04-03 13:23:15 +09:00
Junegunn Choi
8fbed2b13a [fzf-tmux] Use $PWD instead of #{pane_current_path}
Related: https://github.com/tmux/tmux/issues/1282
2020-04-03 13:23:15 +09:00
Junegunn Choi
aa17510e0a [fzf-tmux] Set default horizontal margin 2020-04-03 13:23:15 +09:00
Junegunn Choi
bf65e8cd12 [fzf-tmux] Add option to start fzf in tmux popup window
Requires latest tmux built from source (e.g. brew install tmux --HEAD)

Examples:

  # 50%/50% width and height on the center of the screen
  fzf-tmux -p

  # 80%/80%
  fzf-tmux -p80%

  # 80%/40%
  fzf-tmux -p80%,40%

  # Separate -w and -h
  fzf-tmux -w80% -h40%

  # 80%/40% at position (0, 0)
  fzf-tmux -w80% -h40% -x0 -y0

You can configure key bindings and fuzzy completion to open in tmux
popup window like so:

  FZF_TMUX_OPTS='-p 80%'
2020-04-03 13:23:15 +09:00
lacygoill
0f5c6e8f04 [vim] Fix issue with multiple popups (#1927)
Invoking fzf from an existing Vim popup terminal is a special case.
It requires some new code to avoid E994 from being raised and the user
being stuck in a non-closable popup window.

Fix #1916
2020-03-30 02:06:06 +09:00
Roman Perepelitsa
b1b916ce15 [zsh] Ensure that fzf code always parses the same way (#1944)
At the top of each zsh file options are set to their
standard values (those marked with <Z> in `man zshoptions`)
and `aliases` option is disabled.

At the bottom of the file the original options are restored.

Fix #1938
2020-03-30 01:52:48 +09:00
Alexandr
a6a732e1fc Update AtomicBool to use atomic memory operation (#1939) 2020-03-30 01:42:58 +09:00
Junegunn Choi
a5c2f28539 Fix failing test case 2020-03-29 22:06:06 +09:00
Junegunn Choi
18261fe31c [shell] Update CTRL-R to remove duplicate commands
Close #1940
Related: #1363 #749 #270 #49 #88 #492 #600
2020-03-29 21:30:37 +09:00
Chitoku
079046863c [zsh-completion] Fix a bug where _fzf_complete did not iterate through args (#1936) 2020-03-24 08:58:22 +09:00
Junegunn Choi
07b965bba1 Fix ANSI color offsets when --keep-right is used 2020-03-23 19:05:06 +09:00
Junegunn Choi
c39113ee41 [windows] Do not include directories in the list
Fix #1926
2020-03-14 21:43:35 +09:00
Junegunn Choi
14f90502a4 [bash] Restore --nth option in CTRL-R 2020-03-13 09:13:38 +09:00
18 changed files with 344 additions and 142 deletions

View File

@@ -1,6 +1,38 @@
CHANGELOG
=========
0.21.1
------
- Shell extension
- CTRL-R will remove duplicate commands
- fzf-tmux
- Supports tmux popup window (require tmux 3.2 or above)
- ```sh
# 50% width and height
fzf-tmux -p
# 80% width and height
fzf-tmux -p 80%
# 80% width and 40% height
fzf-tmux -p 80%,40%
fzf-tmux -w 80% -h 40%
# Window position
fzf-tmux -w 80% -h 40% -x 0 -y 0
fzf-tmux -w 80% -h 40% -y 1000
# Write ordinary fzf options after --
fzf-tmux -p -- --reverse --info=inline --margin 2,4 --border
```
- On macOS, you can build the latest tmux from the source with
`brew install tmux --HEAD`
- Bug fixes
- Fixed Windows file traversal not to include directories
- Fixed ANSI colors with `--keep-right`
- Fixed _fzf_complete for zsh
- Built with Go 1.14.1
0.21.0
------
- `--height` option is now available on Windows as well (@kelleyma49)

View File

@@ -281,8 +281,10 @@ own as well.
[fzf-tmux](bin/fzf-tmux) is a bash script that opens fzf in a tmux pane.
```sh
# usage: fzf-tmux [-u|-d [HEIGHT[%]]] [-l|-r [WIDTH[%]]] [--] [FZF OPTIONS]
# (-[udlr]: up/down/left/right)
# usage: fzf-tmux [LAYOUT OPTIONS] [--] [FZF OPTIONS]
# See available options
fzf-tmux --help
# select git branches in horizontal split below (15 lines)
git branch | fzf-tmux -d 15
@@ -291,7 +293,7 @@ git branch | fzf-tmux -d 15
cat /usr/share/dict/words | fzf-tmux -l 20% --multi --reverse
```
It will still work even when you're not on tmux, silently ignoring `-[udlr]`
It will still work even when you're not on tmux, silently ignoring `-[pudlr]`
options, so you can invariably use `fzf-tmux` in your scripts.
Alternatively, you can use `--height HEIGHT[%]` option not to start fzf in
@@ -318,9 +320,9 @@ fish.
- Set `FZF_ALT_C_COMMAND` to override the default command
- Set `FZF_ALT_C_OPTS` to pass additional options
If you're on a tmux session, you can start fzf in a split pane by setting
`FZF_TMUX` to 1, and change the height of the pane with `FZF_TMUX_HEIGHT`
(e.g. `20`, `50%`).
If you're on a tmux session, you can start fzf in a tmux split pane or in
a tmux popup window by setting `FZF_TMUX_OPTS` (e.g. `-d 40%`).
See `fzf-tmux --help` for available options.
More tips can be found on [the wiki page](https://github.com/junegunn/fzf/wiki/Configuring-shell-key-bindings).

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# fzf-tmux: starts fzf in a tmux pane
# usage: fzf-tmux [-u|-d [HEIGHT[%]]] [-l|-r [WIDTH[%]]] [--] [FZF OPTIONS]
# usage: fzf-tmux [LAYOUT OPTIONS] [--] [FZF OPTIONS]
fail() {
>&2 echo "$1"
@@ -10,6 +10,7 @@ fail() {
fzf="$(command -v fzf 2> /dev/null)" || fzf="$(dirname "$0")/fzf"
[[ -x "$fzf" ]] || fail 'fzf executable not found'
tmux_args=()
args=()
opt=""
skip=""
@@ -20,15 +21,23 @@ term=""
[[ -n "$COLUMNS" ]] && columns=$COLUMNS || columns=$(tput cols) || columns=$(tmux display-message -p "#{pane_width}")
help() {
>&2 echo 'usage: fzf-tmux [-u|-d [HEIGHT[%]]] [-l|-r [WIDTH[%]]] [--] [FZF OPTIONS]
>&2 echo 'usage: fzf-tmux [LAYOUT OPTIONS] [--] [FZF OPTIONS]
Layout
-u [HEIGHT[%]] Split above (up)
-d [HEIGHT[%]] Split below (down)
-l [WIDTH[%]] Split left
-r [WIDTH[%]] Split right
LAYOUT OPTIONS:
(default layout: -d 50%)
(default: -d 50%)
Popup window (requires tmux 3.2 or above):
-p [WIDTH[%][,HEIGHT[%]]] (default: 50%)
-w WIDTH[%]
-h HEIGHT[%]
-x COL
-y ROW
Split pane:
-u [HEIGHT[%]] Split above (up)
-d [HEIGHT[%]] Split below (down)
-l [WIDTH[%]] Split left
-r [WIDTH[%]] Split right
'
exit
}
@@ -47,8 +56,10 @@ while [[ $# -gt 0 ]]; do
echo "fzf-tmux (with fzf $("$fzf" --version))"
exit
;;
-w*|-h*|-d*|-u*|-r*|-l*)
if [[ "$arg" =~ ^.[lrw] ]]; then
-p*|-w*|-h*|-x*|-y*|-d*|-u*|-r*|-l*)
if [[ "$arg" =~ ^-[pwhxy] ]]; then
[[ "$opt" =~ "-K -E" ]] || opt="-K -E"
elif [[ "$arg" =~ ^.[lr] ]]; then
opt="-h"
if [[ "$arg" =~ ^.l ]]; then
opt="$opt -d"
@@ -66,7 +77,7 @@ while [[ $# -gt 0 ]]; do
if [[ ${#arg} -gt 2 ]]; then
size="${arg:2}"
else
if [[ "$1" =~ ^[0-9]+%?$ ]]; then
if [[ "$1" =~ ^[0-9%,C]+$ ]]; then
size="$1"
shift
else
@@ -74,7 +85,15 @@ while [[ $# -gt 0 ]]; do
fi
fi
if [[ "$size" =~ %$ ]]; then
if [[ "$arg" =~ ^-p ]]; then
if [[ -n "$size" ]]; then
w=${size%%,*}
h=${size##*,}
opt="$opt -w$w -h$h"
fi
elif [[ "$arg" =~ ^-[whxy] ]]; then
opt="$opt ${arg:0:2}$size"
elif [[ "$size" =~ %$ ]]; then
size=${size:0:((${#size}-1))}
if [[ -n "$swap" ]]; then
opt="$opt -p $(( 100 - size ))"
@@ -100,6 +119,8 @@ while [[ $# -gt 0 ]]; do
# "--" can be used to separate fzf-tmux options from fzf options to
# avoid conflicts
skip=1
tmux_args=("${args[@]}")
args=()
continue
;;
*)
@@ -109,13 +130,13 @@ while [[ $# -gt 0 ]]; do
[[ -n "$skip" ]] && args+=("$arg")
done
if [[ -z "$TMUX" || "$opt" =~ ^-h && "$columns" -le 40 || ! "$opt" =~ ^-h && "$lines" -le 15 ]]; then
if [[ -z "$TMUX" ]]; then
"$fzf" "${args[@]}"
exit $?
fi
# --height option is not allowed
args+=("--no-height")
args=("--no-height" "${args[@]}")
# Handle zoomed tmux pane by moving it to a temp window
if tmux list-panes -F '#F' | grep -q Z; then
@@ -159,6 +180,7 @@ trap 'cleanup 1' SIGUSR1
trap 'cleanup' EXIT
envs="env TERM=$TERM "
[[ "$opt" =~ "-K -E" ]] && FZF_DEFAULT_OPTS="--margin 0,1 $FZF_DEFAULT_OPTS"
[[ -n "$FZF_DEFAULT_OPTS" ]] && envs="$envs FZF_DEFAULT_OPTS=$(printf %q "$FZF_DEFAULT_OPTS")"
[[ -n "$FZF_DEFAULT_COMMAND" ]] && envs="$envs FZF_DEFAULT_COMMAND=$(printf %q "$FZF_DEFAULT_COMMAND")"
@@ -181,21 +203,34 @@ close="; trap - EXIT SIGINT SIGTERM $close"
tmux_win_opts=( $(tmux show-window-options remain-on-exit \; show-window-options synchronize-panes | sed '/ off/d; s/^/set-window-option /; s/$/ \\;/') )
if [[ "$opt" =~ "-K -E" ]]; then
cat $fifo2 &
if [[ -n "$term" ]] || [[ -t 0 ]]; then
cat <<< "\"$fzf\" $opts > $fifo2; out=\$? $close; exit \$out" >> $argsf
TMUX=$(echo $TMUX | cut -d , -f 1,2) tmux popup -d "$PWD" "${tmux_args[@]}" $opt -R "$envs bash $argsf" > /dev/null 2>&1
else
mkfifo $fifo1
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; out=\$? $close; exit \$out" >> $argsf
cat <&0 > $fifo1 &
TMUX=$(echo $TMUX | cut -d , -f 1,2) tmux popup -d "$PWD" "${tmux_args[@]}" $opt -R "$envs bash $argsf" > /dev/null 2>&1
fi
exit $?
fi
if [[ -n "$term" ]] || [[ -t 0 ]]; then
cat <<< "\"$fzf\" $opts > $fifo2; echo \$? > $fifo3 $close" >> $argsf
TMUX=$(echo $TMUX | cut -d , -f 1,2) tmux set-window-option synchronize-panes off \;\
set-window-option remain-on-exit off \;\
split-window $opt "$envs bash -c 'cd $(printf %q "$PWD"); exec -a fzf bash $argsf'" $swap \
> /dev/null 2>&1
split-window $opt "${tmux_args[@]}" "$envs bash -c 'cd $(printf %q "$PWD"); exec -a fzf bash $argsf'" $swap \
> /dev/null 2>&1 || { "$fzf" "${args[@]}"; exit $?; }
else
mkfifo $fifo1
cat <<< "\"$fzf\" $opts < $fifo1 > $fifo2; echo \$? > $fifo3 $close" >> $argsf
TMUX=$(echo $TMUX | cut -d , -f 1,2) tmux set-window-option synchronize-panes off \;\
set-window-option remain-on-exit off \;\
split-window $opt "$envs bash -c 'exec -a fzf bash $argsf'" $swap \
> /dev/null 2>&1
split-window $opt "${tmux_args[@]}" "$envs bash -c 'exec -a fzf bash $argsf'" $swap \
> /dev/null 2>&1 || { "$fzf" "${args[@]}"; exit $?; }
cat <&0 > $fifo1 &
fi
cat $fifo2
exit "$(cat $fifo3)"

View File

@@ -2,7 +2,7 @@
set -u
version=0.21.0
version=0.21.1
auto_completion=
key_bindings=
update_config=2

View File

@@ -1,4 +1,4 @@
$version="0.21.0"
$version="0.21.1"
if ([Environment]::Is64BitProcess) {
$binary_arch="amd64"

View File

@@ -21,25 +21,39 @@ 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 2020" "fzf 0.21.0" "fzf-tmux - open fzf in tmux split pane"
.TH fzf-tmux 1 "Apr 2020" "fzf 0.21.1" "fzf-tmux - open fzf in tmux split pane"
.SH NAME
fzf-tmux - open fzf in tmux split pane
.SH SYNOPSIS
.B fzf-tmux [-u|-d [HEIGHT[%]]] [-l|-r [WIDTH[%]]] [--] [FZF OPTIONS]
.B fzf-tmux [LAYOUT OPTIONS] [--] [FZF OPTIONS]
.SH DESCRIPTION
fzf-tmux is a wrapper script for fzf that opens fzf in a tmux split pane. It is
designed to work just like fzf except that it does not take up the whole
screen. You can safely use fzf-tmux instead of fzf in your scripts as the extra
options will be silently ignored if you're not on tmux.
fzf-tmux is a wrapper script for fzf that opens fzf in a tmux split pane or in
a tmux popup window. It is designed to work just like fzf except that it does
not take up the whole screen. You can safely use fzf-tmux instead of fzf in
your scripts as the extra options will be silently ignored if you're not on
tmux.
.SH OPTIONS
.SS Layout
.SH LAYOUT OPTIONS
(default: \fB-d 50%\fR)
(default layout: \fB-d 50%\fR)
.SS Popup window
(requires tmux 3.2 or above)
.TP
.B "-p [WIDTH[%][,HEIGHT[%]]]"
.TP
.B "-w WIDTH[%]"
.TP
.B "-h WIDTH[%]"
.TP
.B "-x COL"
.TP
.B "-y ROW"
.SS Split pane
.TP
.B "-u [height[%]]"
Split above (up)

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 "Mar 2020" "fzf 0.21.0" "fzf - a command-line fuzzy finder"
.TH fzf 1 "Apr 2020" "fzf 0.21.1" "fzf - a command-line fuzzy finder"
.SH NAME
fzf - a command-line fuzzy finder

View File

@@ -651,7 +651,7 @@ function! s:calc_size(max, val, dict)
endfunction
function! s:getpos()
return {'tab': tabpagenr(), 'win': winnr(), 'cnt': winnr('$'), 'tcnt': tabpagenr('$')}
return {'tab': tabpagenr(), 'win': winnr(), 'winid': win_getid(), 'cnt': winnr('$'), 'tcnt': tabpagenr('$')}
endfunction
function! s:split(dict)
@@ -727,8 +727,8 @@ function! s:execute_term(dict, command, temps) abort
" there's no other listed buffer (nvim +'set nobuflisted')
close
endif
execute 'tabnext' self.ppos.tab
execute self.ppos.win.'wincmd w'
silent! execute 'tabnext' self.ppos.tab
silent! execute self.ppos.win.'wincmd w'
endif
if bufexists(self.buf)
@@ -837,7 +837,7 @@ if has('nvim')
else
function! s:create_popup(hl, opts) abort
let is_frame = has_key(a:opts, 'border')
let buf = is_frame ? '' : term_start(&shell, #{hidden: 1})
let buf = is_frame ? '' : term_start(&shell, #{hidden: 1, term_finish: 'close'})
let id = popup_create(buf, #{
\ line: a:opts.row,
\ col: a:opts.col,
@@ -851,7 +851,7 @@ else
call setbufline(winbufnr(id), 1, a:opts.border)
execute 'autocmd BufWipeout * ++once call popup_close('..id..')'
else
execute 'autocmd BufWipeout * ++once bwipeout! '..buf
execute 'autocmd BufWipeout * ++once call term_sendkeys('..buf..', "exit\<CR>")'
endif
return winbufnr(id)
endfunction

View File

@@ -2,10 +2,10 @@
# / __/___ / __/
# / /_/_ / / /_
# / __/ / /_/ __/
# /_/ /___/_/-completion.bash
# /_/ /___/_/ completion.bash
#
# - $FZF_TMUX (default: 0)
# - $FZF_TMUX_HEIGHT (default: '40%')
# - $FZF_TMUX_OPTS (default: empty)
# - $FZF_COMPLETION_TRIGGER (default: '**')
# - $FZF_COMPLETION_OPTS (default: empty)
@@ -37,9 +37,9 @@ bind '"\e[0n": redraw-current-line'
__fzf_comprun() {
if [ "$(type -t _fzf_comprun 2>&1)" = function ]; then
_fzf_comprun "$@"
elif [ -n "$TMUX_PANE" ] && [ "${FZF_TMUX:-0}" != 0 ] && [ ${LINES:-40} -gt 15 ]; then
elif [ -n "$TMUX_PANE" ] && { [ "${FZF_TMUX:-0}" != 0 ] || [ -n "$FZF_TMUX_OPTS" ]; }; then
shift
fzf-tmux -d "${FZF_TMUX_HEIGHT:-40%}" "$@"
fzf-tmux ${FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}} -- "$@"
else
shift
fzf "$@"

View File

@@ -2,14 +2,79 @@
# / __/___ / __/
# / /_/_ / / /_
# / __/ / /_/ __/
# /_/ /___/_/-completion.zsh
# /_/ /___/_/ completion.zsh
#
# - $FZF_TMUX (default: 0)
# - $FZF_TMUX_HEIGHT (default: '40%')
# - $FZF_TMUX_OPTS (default: '-d 40%')
# - $FZF_COMPLETION_TRIGGER (default: '**')
# - $FZF_COMPLETION_OPTS (default: empty)
if [[ $- =~ i ]]; then
# Both branches of the following `if` do the same thing -- define
# __fzf_completion_options such that `eval $__fzf_completion_options` sets
# all options to the same values they currently have. We'll do just that at
# the bottom of the file after changing options to what we prefer.
#
# IMPORTANT: Until we get to the `emulate` line, all words that *can* be quoted
# *must* be quoted in order to prevent alias expansion. In addition, code must
# be written in a way works with any set of zsh options. This is very tricky, so
# careful when you change it.
#
# Start by loading the builtin zsh/parameter module. It provides `options`
# associative array that stores current shell options.
if 'zmodload' 'zsh/parameter' 2>'/dev/null' && (( ${+options} )); then
# This is the fast branch and it gets taken on virtually all Zsh installations.
#
# ${(kv)options[@]} expands to array of keys (option names) and values ("on"
# or "off"). The subsequent expansion# with (j: :) flag joins all elements
# together separated by spaces. __fzf_completion_options ends up with a value
# like this: "options=(shwordsplit off aliases on ...)".
__fzf_completion_options="options=(${(j: :)${(kv)options[@]}})"
else
# This branch is much slower because it forks to get the names of all
# zsh options. It's possible to eliminate this fork but it's not worth the
# trouble because this branch gets taken only on very ancient or broken
# zsh installations.
() {
# That `()` above defines an anonymous function. This is essentially a scope
# for local parameters. We use it to avoid polluting global scope.
'local' '__fzf_opt'
__fzf_completion_options="setopt"
# `set -o` prints one line for every zsh option. Each line contains option
# name, some spaces, and then either "on" or "off". We just want option names.
# Expansion with (@f) flag splits a string into lines. The outer expansion
# removes spaces and everything that follow them on every line. __fzf_opt
# ends up iterating over option names: shwordsplit, aliases, etc.
for __fzf_opt in "${(@)${(@f)$(set -o)}%% *}"; do
if [[ -o "$__fzf_opt" ]]; then
# Option $__fzf_opt is currently on, so remember to set it back on.
__fzf_completion_options+=" -o $__fzf_opt"
else
# Option $__fzf_opt is currently off, so remember to set it back off.
__fzf_completion_options+=" +o $__fzf_opt"
fi
done
# The value of __fzf_completion_options here looks like this:
# "setopt +o shwordsplit -o aliases ..."
}
fi
# Enable the default zsh options (those marked with <Z> in `man zshoptions`)
# but without `aliases`. Aliases in functions are expanded when functions are
# defined, so if we disable aliases here, we'll be sure to have no pesky
# aliases in any of our functions. This way we won't need prefix every
# command with `command` or to quote every word to defend against global
# aliases. Note that `aliases` is not the only option that's important to
# control. There are several others that could wreck havoc if they are set
# to values we don't expect. With the following `emulate` command we
# sidestep this issue entirely.
'emulate' 'zsh' '-o' 'no_aliases'
# This brace is the start of try-always block. The `always` part is like
# `finally` in lesser languages. We use it to *always* restore user options.
{
# Bail out if not interactive shell.
[[ -o interactive ]] || return 0
# To use custom commands instead of find, override _fzf_compgen_{path,dir}
if ! declare -f _fzf_compgen_path > /dev/null; then
@@ -34,9 +99,13 @@ fi
__fzf_comprun() {
if [[ "$(type _fzf_comprun 2>&1)" =~ function ]]; then
_fzf_comprun "$@"
elif [ -n "$TMUX_PANE" ] && [ "${FZF_TMUX:-0}" != 0 ] && [ ${LINES:-40} -gt 15 ]; then
elif [ -n "$TMUX_PANE" ] && { [ "${FZF_TMUX:-0}" != 0 ] || [ -n "$FZF_TMUX_OPTS" ]; }; then
shift
fzf-tmux -d "${FZF_TMUX_HEIGHT:-40%}" "$@"
if [ -n "$FZF_TMUX_OPTS" ]; then
fzf-tmux ${(Q)${(Z+n+)FZF_TMUX_OPTS}} -- "$@"
else
fzf-tmux -d ${FZF_TMUX_HEIGHT:-40%} -- "$@"
fi
else
shift
fzf "$@"
@@ -112,7 +181,7 @@ _fzf_complete() {
local args rest str_arg i sep
args=("$@")
sep=
for i in {0..$#args}; do
for i in {0..${#args[@]}}; do
if [[ "${args[$i]}" = -- ]]; then
sep=$i
break
@@ -241,4 +310,8 @@ fzf-completion() {
zle -N fzf-completion
bindkey '^I' fzf-completion
fi
} always {
# Restore the original options.
eval $__fzf_completion_options
'unset' '__fzf_completion_options'
}

View File

@@ -1,3 +1,16 @@
# ____ ____
# / __/___ / __/
# / /_/_ / / /_
# / __/ / /_/ __/
# /_/ /___/_/ key-bindings.bash
#
# - $FZF_TMUX_OPTS
# - $FZF_CTRL_T_COMMAND
# - $FZF_CTRL_T_OPTS
# - $FZF_CTRL_R_OPTS
# - $FZF_ALT_C_COMMAND
# - $FZF_ALT_C_OPTS
# Key bindings
# ------------
__fzf_select__() {
@@ -5,7 +18,7 @@ __fzf_select__() {
-o -type f -print \
-o -type d -print \
-o -type l -print 2> /dev/null | cut -b3-"}"
eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" fzf -m "$@" | while read -r item; do
eval "$cmd" | FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} --reverse $FZF_DEFAULT_OPTS $FZF_CTRL_T_OPTS" $(__fzfcmd) -m "$@" | while read -r item; do
printf '%q ' "$item"
done
echo
@@ -13,35 +26,15 @@ __fzf_select__() {
if [[ $- =~ i ]]; then
__fzf_use_tmux__() {
[ -n "$TMUX_PANE" ] && [ "${FZF_TMUX:-0}" != 0 ] && [ ${LINES:-40} -gt 15 ]
}
__fzfcmd() {
__fzf_use_tmux__ &&
echo "fzf-tmux -d${FZF_TMUX_HEIGHT:-40%}" || echo "fzf"
}
__fzf_select_tmux__() {
local height
height=${FZF_TMUX_HEIGHT:-40%}
if [[ $height =~ %$ ]]; then
height="-p ${height%\%}"
else
height="-l $height"
fi
tmux split-window $height "cd $(printf %q "$PWD"); FZF_DEFAULT_OPTS=$(printf %q "$FZF_DEFAULT_OPTS") PATH=$(printf %q "$PATH") FZF_CTRL_T_COMMAND=$(printf %q "$FZF_CTRL_T_COMMAND") FZF_CTRL_T_OPTS=$(printf %q "$FZF_CTRL_T_OPTS") bash -c 'source \"${BASH_SOURCE[0]}\"; RESULT=\"\$(__fzf_select__ --no-height)\"; tmux setb -b fzf \"\$RESULT\" \\; pasteb -b fzf -t $TMUX_PANE \\; deleteb -b fzf || tmux send-keys -t $TMUX_PANE \"\$RESULT\"'"
[ -n "$TMUX_PANE" ] && { [ "${FZF_TMUX:-0}" != 0 ] || [ -n "$FZF_TMUX_OPTS" ]; } &&
echo "fzf-tmux ${FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}} -- " || echo "fzf"
}
fzf-file-widget() {
if __fzf_use_tmux__; then
__fzf_select_tmux__
else
local selected="$(__fzf_select__)"
READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
READLINE_POINT=$(( READLINE_POINT + ${#selected} ))
fi
local selected="$(__fzf_select__)"
READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
READLINE_POINT=$(( READLINE_POINT + ${#selected} ))
}
__fzf_cd__() {
@@ -55,8 +48,8 @@ __fzf_history__() {
local output
output=$(
builtin fc -lnr -2147483648 |
last_hist=$(HISTTIMEFORMAT='' builtin history 1) perl -p -l0 -e 'BEGIN { getc; $/ = "\n\t"; $HISTCMD = $ENV{last_hist} + 1 } s/^[ *]//; $_ = $HISTCMD - $. . "\t$_"' |
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m --read0" $(__fzfcmd) --query "$READLINE_LINE"
last_hist=$(HISTTIMEFORMAT='' builtin history 1) perl -n -l0 -e 'BEGIN { getc; $/ = "\n\t"; $HISTCMD = $ENV{last_hist} + 1 } s/^[ *]//; print $HISTCMD - $. . "\t$_" if !$seen{$_}++' |
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS +m --read0" $(__fzfcmd) --query "$READLINE_LINE"
) || return
READLINE_LINE=${output#*$'\t'}
if [ -z "$READLINE_POINT" ]; then
@@ -75,11 +68,7 @@ bind -m emacs-standard '"\C-z": vi-editing-mode'
if [ "${BASH_VERSINFO[0]}" -lt 4 ]; then
# CTRL-T - Paste the selected file path into the command line
if __fzf_use_tmux__; then
bind -m emacs-standard '"\C-t": " \C-b\C-k \C-u`__fzf_select_tmux__`\e\C-e\C-a\C-y\C-h\C-e\e \C-y\ey\C-x\C-x\C-f"'
else
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"'
fi
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 vi-command '"\C-t": "\C-z\C-t\C-z"'
bind -m vi-insert '"\C-t": "\C-z\C-t\C-z"'

View File

@@ -1,3 +1,16 @@
# ____ ____
# / __/___ / __/
# / /_/_ / / /_
# / __/ / /_/ __/
# /_/ /___/_/ key-bindings.fish
#
# - $FZF_TMUX_OPTS
# - $FZF_CTRL_T_COMMAND
# - $FZF_CTRL_T_OPTS
# - $FZF_CTRL_R_OPTS
# - $FZF_ALT_C_COMMAND
# - $FZF_ALT_C_OPTS
# Key bindings
# ------------
function fzf_key_bindings
@@ -84,8 +97,10 @@ function fzf_key_bindings
function __fzfcmd
test -n "$FZF_TMUX"; or set FZF_TMUX 0
test -n "$FZF_TMUX_HEIGHT"; or set FZF_TMUX_HEIGHT 40%
if [ $FZF_TMUX -eq 1 ]
echo "fzf-tmux -d$FZF_TMUX_HEIGHT"
if [ -n "$FZF_TMUX_OPTS" ]
echo "fzf-tmux $FZF_TMUX_OPTS -- "
else if [ $FZF_TMUX -eq 1 ]
echo "fzf-tmux -d$FZF_TMUX_HEIGHT -- "
else
echo "fzf"
end

View File

@@ -1,6 +1,42 @@
# ____ ____
# / __/___ / __/
# / /_/_ / / /_
# / __/ / /_/ __/
# /_/ /___/_/ key-bindings.zsh
#
# - $FZF_TMUX_OPTS
# - $FZF_CTRL_T_COMMAND
# - $FZF_CTRL_T_OPTS
# - $FZF_CTRL_R_OPTS
# - $FZF_ALT_C_COMMAND
# - $FZF_ALT_C_OPTS
# Key bindings
# ------------
if [[ $- == *i* ]]; then
# The code at the top and the bottom of this file is the same as in completion.zsh.
# Refer to that file for explanation.
if 'zmodload' 'zsh/parameter' 2>'/dev/null' && (( ${+options} )); then
__fzf_key_bindings_options="options=(${(j: :)${(kv)options[@]}})"
else
() {
__fzf_key_bindings_options="setopt"
'local' '__fzf_opt'
for __fzf_opt in "${(@)${(@f)$(set -o)}%% *}"; do
if [[ -o "$__fzf_opt" ]]; then
__fzf_key_bindings_options+=" -o $__fzf_opt"
else
__fzf_key_bindings_options+=" +o $__fzf_opt"
fi
done
}
fi
'emulate' 'zsh' '-o' 'no_aliases'
{
[[ -o interactive ]] || return 0
# CTRL-T - Paste the selected file path(s) into the command line
__fsel() {
@@ -17,13 +53,9 @@ __fsel() {
return $ret
}
__fzf_use_tmux__() {
[ -n "$TMUX_PANE" ] && [ "${FZF_TMUX:-0}" != 0 ] && [ ${LINES:-40} -gt 15 ]
}
__fzfcmd() {
__fzf_use_tmux__ &&
echo "fzf-tmux -d${FZF_TMUX_HEIGHT:-40%}" || echo "fzf"
[ -n "$TMUX_PANE" ] && { [ "${FZF_TMUX:-0}" != 0 ] || [ -n "$FZF_TMUX_OPTS" ]; } &&
echo "fzf-tmux ${FZF_TMUX_OPTS:--d${FZF_TMUX_HEIGHT:-40%}} -- " || echo "fzf"
}
fzf-file-widget() {
@@ -68,7 +100,7 @@ bindkey '\ec' fzf-cd-widget
fzf-history-widget() {
local selected num
setopt localoptions noglobsubst noposixbuiltins pipefail no_aliases 2> /dev/null
selected=( $(fc -rl 1 |
selected=( $(fc -rl 1 | perl -ne 'print if !$seen{($_ =~ s/^\s*[0-9]+\s+//r)}++' |
FZF_DEFAULT_OPTS="--height ${FZF_TMUX_HEIGHT:-40%} $FZF_DEFAULT_OPTS -n2..,.. --tiebreak=index --bind=ctrl-r:toggle-sort $FZF_CTRL_R_OPTS --query=${(qqq)LBUFFER} +m" $(__fzfcmd)) )
local ret=$?
if [ -n "$selected" ]; then
@@ -83,4 +115,7 @@ fzf-history-widget() {
zle -N fzf-history-widget
bindkey '^R' fzf-history-widget
fi
} always {
eval $__fzf_key_bindings_options
'unset' '__fzf_key_bindings_options'
}

View File

@@ -10,7 +10,7 @@ import (
const (
// Current version
version = "0.21.0"
version = "0.21.1"
// Core
coordinatorDelayMax time.Duration = 100 * time.Millisecond

View File

@@ -156,10 +156,11 @@ func (r *Reader) readFiles() bool {
fn := func(path string, mode os.FileInfo) error {
path = filepath.Clean(path)
if path != "." {
if mode.Mode().IsDir() && filepath.Base(path)[0] == '.' {
isDir := mode.Mode().IsDir()
if isDir && filepath.Base(path)[0] == '.' {
return filepath.SkipDir
}
if r.pusher([]byte(path)) {
if !isDir && r.pusher([]byte(path)) {
atomic.StoreInt32(&r.event, int32(EvtReadNew))
}
}

View File

@@ -1003,10 +1003,21 @@ func (t *Terminal) printHighlighted(result Result, attr tui.Attr, col1 tui.Color
maxe = util.Constrain(maxe+util.Min(maxWidth/2-2, t.hscrollOff), 0, len(text))
displayWidth := t.displayWidthWithLimit(text, 0, maxWidth)
if displayWidth > maxWidth {
transformOffsets := func(diff int32) {
for idx, offset := range offsets {
b, e := offset.offset[0], offset.offset[1]
b += 2 - diff
e += 2 - diff
b = util.Max32(b, 2)
offsets[idx].offset[0] = b
offsets[idx].offset[1] = util.Max32(b, e)
}
}
if t.hscroll {
if t.keepRight && pos == nil {
text, _ = t.trimLeft(text, maxWidth-2)
text = append([]rune(ellipsis), text...)
trimmed, diff := t.trimLeft(text, maxWidth-2)
transformOffsets(diff)
text = append([]rune(ellipsis), trimmed...)
} else if !t.overflow(text[:maxe], maxWidth-2) {
// Stri..
text, _ = t.trimRight(text, maxWidth-2)
@@ -1021,14 +1032,7 @@ func (t *Terminal) printHighlighted(result Result, attr tui.Attr, col1 tui.Color
text, diff = t.trimLeft(text, maxWidth-2)
// Transform offsets
for idx, offset := range offsets {
b, e := offset.offset[0], offset.offset[1]
b += 2 - diff
e += 2 - diff
b = util.Max32(b, 2)
offsets[idx].offset[0] = b
offsets[idx].offset[1] = util.Max32(b, e)
}
transformOffsets(diff)
text = append([]rune(ellipsis), text...)
}
} else {

View File

@@ -1,32 +1,34 @@
package util
import "sync"
import (
"sync/atomic"
)
func convertBoolToInt32(b bool) int32 {
if b {
return 1
}
return 0
}
// AtomicBool is a boxed-class that provides synchronized access to the
// underlying boolean value
type AtomicBool struct {
mutex sync.Mutex
state bool
state int32 // "1" is true, "0" is false
}
// NewAtomicBool returns a new AtomicBool
func NewAtomicBool(initialState bool) *AtomicBool {
return &AtomicBool{
mutex: sync.Mutex{},
state: initialState}
return &AtomicBool{state: convertBoolToInt32(initialState)}
}
// Get returns the current boolean value synchronously
func (a *AtomicBool) Get() bool {
a.mutex.Lock()
defer a.mutex.Unlock()
return a.state
return atomic.LoadInt32(&a.state) == 1
}
// Set updates the boolean value synchronously
func (a *AtomicBool) Set(newState bool) bool {
a.mutex.Lock()
defer a.mutex.Unlock()
a.state = newState
return a.state
atomic.StoreInt32(&a.state, convertBoolToInt32(newState))
return newState
}

View File

@@ -99,31 +99,27 @@ class Tmux
go(%W[kill-window -t #{win}])
end
def focus
go(%W[select-window -t #{win}])
end
def send_keys(*args)
target =
if args.last.is_a?(Hash)
hash = args.pop
go(%W[select-window -t #{win}])
"#{win}.#{hash[:pane]}"
else
win
end
go(%W[send-keys -t #{target}] + args.map(&:to_s))
go(%W[send-keys -t #{win}] + args.map(&:to_s))
end
def paste(str)
system('tmux', 'setb', str, ';', 'pasteb', '-t', win, ';', 'send-keys', '-t', win, 'Enter')
end
def capture(pane = 0)
go(%W[capture-pane -p -t #{win}.#{pane}]).reverse.drop_while(&:empty?).reverse
def capture
go(%W[capture-pane -p -t #{win}]).reverse.drop_while(&:empty?).reverse
end
def until(refresh = false, pane = 0)
def until(refresh = false)
lines = nil
begin
wait do
lines = capture(pane)
lines = capture
class << lines
def counts
lazy
@@ -1839,15 +1835,18 @@ module TestShell
tmux.send_keys 'echo 1st', :Enter; tmux.prepare
tmux.send_keys 'echo 2nd', :Enter; tmux.prepare
tmux.send_keys 'echo 3d', :Enter; tmux.prepare
tmux.send_keys 'echo 3rd', :Enter; tmux.prepare
3.times { tmux.send_keys 'echo 3rd', :Enter; tmux.prepare }
tmux.send_keys 'echo 4th', :Enter
retries do
tmux.prepare
tmux.send_keys 'C-r'
tmux.until { |lines| lines.match_count.positive? }
end
tmux.send_keys 'e3d'
# Duplicates removed: 3d (1) + 3rd (1) => 2 matches
tmux.until { |lines| lines.match_count == 2 }
tmux.until { |lines| lines[-3].end_with? 'echo 3d' }
tmux.send_keys 'C-r'
tmux.send_keys '3d'
tmux.until { |lines| lines[-3].end_with? 'echo 3rd' }
tmux.send_keys :Enter
tmux.until { |lines| lines[-1] == 'echo 3rd' }
@@ -2038,8 +2037,9 @@ module CompletionTest
# FZF_TMUX=1
new_shell
tmux.send_keys 'unset FZFFOOBR**', :Tab, pane: 0
tmux.until(false, 1) { |lines| lines.match_count == 1 }
tmux.focus
tmux.send_keys 'unset FZFFOOBR**', :Tab
tmux.until { |lines| lines.match_count == 1 }
tmux.send_keys :Enter
tmux.until { |lines| lines[-1].include? 'unset FZFFOOBAR' }
end
@@ -2176,7 +2176,7 @@ unset <%= UNSETS.join(' ') %>
# Old API
_fzf_complete_f() {
_fzf_complete "--multi --prompt \"prompt-f> \"" "$@" < <(
_fzf_complete "+m --multi --prompt \"prompt-f> \"" "$@" < <(
echo foo
echo bar
)
@@ -2184,7 +2184,7 @@ _fzf_complete_f() {
# New API
_fzf_complete_g() {
_fzf_complete --multi --prompt "prompt-g> " -- "$@" < <(
_fzf_complete +m --multi --prompt "prompt-g> " -- "$@" < <(
echo foo
echo bar
)