summaryrefslogtreecommitdiff
path: root/dotfiles/system/.zsh/lib/ftb-tmux-popup
blob: 7e74d3ca46a7ec0dd6f11a41fbbb204c3b45a5fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/hint/zsh
# Show results with tmux popup
# Example usage:
#   zstyle ':fzf-tab:*' fzf-command ftb-tmux-popup
#   zstyle ':fzf-tab:*' popup-pad 0 0
# It can also be used as a standalone tool, like:
#   ls | ftb-tmux-popup
emulate -L zsh -o extended_glob

# import min
autoload -Uz zmathfunc
zmathfunc

: ${tmp_dir:=${TMPPREFIX:-/tmp/zsh}-fzf-tab-$USER}

# fallback to fzf if it is not running in tmux
if (( ! $+TMUX_PANE )); then
  fzf $@
  return
fi

local ret=0

local -a fzf_opts=($@)
fzf_opts=(${${fzf_opts/--height*}/--layout*})

# get position of cursor and size of window
local -a tmp=($(command tmux display-message -p "#{pane_top} #{cursor_y} #{pane_left} #{cursor_x} #{window_height} #{window_width}"))
local cursor_y=$((tmp[1] + tmp[2])) cursor_x=$((tmp[3] + tmp[4])) window_height=$tmp[5] window_width=$tmp[6]

# if not called by fzf-tab
if (( ! $+IN_FZF_TAB )); then
  [[ -d $tmp_dir ]] || mkdir -p $tmp_dir
  cat > $tmp_dir/completions.$$
fi

local text REPLY comp_lines comp_length length popup_pad

zstyle -a ":fzf-tab:$_ftb_curcontext" popup-pad popup_pad || popup_pad=(0 0)

# get the size of content, note we should remove all ANSI color code
comp_lines=$(( ${#${(f)mapfile[$tmp_dir/completions.$$]}} + $popup_pad[2] ))
if (( comp_lines <= 500 )); then
  comp_length=0
  for line in ${(f)mapfile[$tmp_dir/completions.$$]}; do
    length=${(m)#${(S)line//$'\x1b['[0-9]#*m}}
    (( length >= comp_length )) && comp_length=$length
  done
else
  # FIXME: can't get the correct width of CJK characters.
  comp_length=$(command sed 's/\x1b\[[0-9;]*m//g;s/\x00//g' $tmp_dir/completions.$$ | command awk 'length > max_length { max_length = length; } END { print max_length }')
fi
comp_length=$(( comp_length + $popup_pad[1] ))

local popup_height popup_y popup_width popup_x

# calculate the popup height and y position
if (( cursor_y * 2 > window_height )); then
  # show above the cursor
  popup_height=$(( min(comp_lines + 4, cursor_y) ))
  popup_y=$cursor_y
else
  # show below the cursor
  popup_height=$(( min(comp_lines + 4, window_height - cursor_y) ))
  popup_y=$(( cursor_y + popup_height + 1 ))
  fzf_opts+=(--layout=reverse)
fi

# calculate the popup width and x position
popup_width=$(( min(comp_length + 5, window_width) ))
popup_x=$(( cursor_x + popup_width > window_width ? window_width - popup_width : cursor_x ))

echo -E "$commands[fzf] ${(qq)fzf_opts[@]} < $tmp_dir/completions.$$ > $tmp_dir/result-$$" > $tmp_dir/fzf-$$
{
  tmux popup -x $popup_x -y $popup_y \
       -w $popup_width -h $popup_height \
       -d $PWD -E ". $tmp_dir/fzf-$$" || ret=$?
  echo -E "$(<$tmp_dir/result-$$)"
} always {
  command rm $tmp_dir/*-$$
  (( $+IN_FZF_TAB )) || command rm $tmp_dir/completions.$$
}
return $ret