diff --git a/playbooks/roles/zsh/tasks/main.yml b/playbooks/roles/zsh/tasks/main.yml index b668957..5cea206 100644 --- a/playbooks/roles/zsh/tasks/main.yml +++ b/playbooks/roles/zsh/tasks/main.yml @@ -47,3 +47,7 @@ src: ~/.dotfiles/bin/ dest: ~/bin +- name: copy contents of zsh/bin + synchronize: + src: ~/.dotfiles/zsh/bin/ + dest: ~/bin diff --git a/zsh/bin/sk-tmux b/zsh/bin/sk-tmux new file mode 100644 index 0000000..824e4e9 --- /dev/null +++ b/zsh/bin/sk-tmux @@ -0,0 +1,239 @@ +#!/usr/bin/env zsh + fail() { + echo >&2 "$1" + return 2 + } + + sk="$(command -v sk 2>/dev/null)" || sk="$(dirname "$0")/sk" + [[ -x "$sk" ]] || fail 'sk executable not found' + + tmux_args=() + args=() + opt="" + skip="" + swap="" + close="" + term="" + [[ -n "$LINES" ]] && lines=$LINES || lines=$(tput lines) || lines=$(tmux display-message -p "#{pane_height}") + [[ -n "$COLUMNS" ]] && columns=$COLUMNS || columns=$(tput cols) || columns=$(tmux display-message -p "#{pane_width}") + + help() { + echo >&2 'usage: sk-tmux [LAYOUT OPTIONS] [--] [sk OPTIONS] + + LAYOUT OPTIONS: + (default layout: -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 +' + return + } + + while [[ $# -gt 0 ]]; do + arg="$1" + shift + [[ -z "$skip" ]] && case "$arg" in + -) + term=1 + ;; + --help) + help + ;; + --version) + echo "sk-tmux (with sk $("$sk" --version))" + return + ;; + -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" + swap="; swap-pane -D ; select-pane -L" + close="; tmux swap-pane -D" + fi + else + opt="" + if [[ "$arg" =~ ^.u ]]; then + opt="$opt -d" + swap="; swap-pane -D ; select-pane -U" + close="; tmux swap-pane -D" + fi + fi + if [[ ${#arg} -gt 2 ]]; then + size="${arg:2}" + else + if [[ "$1" =~ ^[0-9%,]+$ ]] || [[ "$1" =~ ^[A-Z]$ ]]; then + size="$1" + shift + else + continue + fi + fi + + 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))" + else + opt="$opt -p $size" + fi + else + if [[ -n "$swap" ]]; then + if [[ "$arg" =~ ^.l ]]; then + max=$columns + else + max=$lines + fi + size=$((max - size)) + [[ $size -lt 0 ]] && size=0 + opt="$opt -l $size" + else + opt="$opt -l $size" + fi + fi + ;; + --) + # "--" can be used to separate sk-tmux options from sk options to + # avoid conflicts + skip=1 + tmux_args=("${args[@]}") + args=() + continue + ;; + *) + args+=("$arg") + ;; + esac + [[ -n "$skip" ]] && args+=("$arg") + done + + if [[ -z "$TMUX" ]]; then + "$sk" "${args[@]}" + return $? + fi + + # --height option is not allowed + 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 + zoomed=1 + original_window=$(tmux display-message -p "#{window_id}") + tmp_window=$(tmux new-window -d -P -F "#{window_id}" "bash -c 'while :; do for c in \\| / - '\\;' do sleep 0.2; printf \"\\r\$c sk-tmux is running\\r\"; done; done'") + tmux swap-pane -t $tmp_window \; select-window -t $tmp_window + fi + + set -e + + # Clean up named pipes on exit + id=$RANDOM + argsf="${TMPDIR:-/tmp}/sk-argsf" + fifo1="${TMPDIR:-/tmp}/sk-tmp1" + fifo2="${TMPDIR:-/tmp}/sk-tmp2" + fifo3="${TMPDIR:-/tmp}/sk-tmp3" + touch $fifo3 $fifo2 $fifo1 $argsf + # argsf="${TMPDIR:-/tmp}/sk-args-$id" + # fifo1="${TMPDIR:-/tmp}/sk-fifo1-$id" + # fifo2="${TMPDIR:-/tmp}/sk-fifo2-$id" + # fifo3="${TMPDIR:-/tmp}/sk-fifo3-$id" + cleanup() { + \rm -f $argsf $fifo1 $fifo2 $fifo3 + + # Restore tmux window options + if [[ "${#tmux_win_opts[@]}" -gt 0 ]]; then + eval "tmux ${tmux_win_opts[@]}" + fi + + # Remove temp window if we were zoomed + if [[ -n "$zoomed" ]]; then + tmux display-message -p "#{window_id}" >/dev/null + tmux swap-pane -t $original_window \; \ + select-window -t $original_window \; \ + kill-window -t $tmp_window \; \ + resize-pane -Z + fi + + if [ $# -gt 0 ]; then + trap - EXIT + return 130 + fi + } + trap 'cleanup 1' SIGUSR1 + trap 'cleanup' EXIT + + envs="env TERM=$TERM " + [[ "$opt" =~ "-K -E" ]] && sk_DEFAULT_OPTS="--margin 0,1 $sk_DEFAULT_OPTS" + [[ -n "$sk_DEFAULT_OPTS" ]] && envs="$envs sk_DEFAULT_OPTS=$(printf %q "$sk_DEFAULT_OPTS")" + [[ -n "$sk_DEFAULT_COMMAND" ]] && envs="$envs sk_DEFAULT_COMMAND=$(printf %q "$sk_DEFAULT_COMMAND")" + + # Build arguments to sk + opts="" + for arg in "${args[@]}"; do + arg="${arg//\\/\\\\}" + arg="${arg//\"/\\\"}" + arg="${arg//\`/\\\`}" + arg="${arg//$/\\$}" + opts="$opts \"$arg\"" + done + + pppid=$$ + echo -n "trap 'kill -SIGUSR1 -$pppid' EXIT SIGINT SIGTERM;" >$argsf + 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/$/ \\;/')) + + echo $opts + if [[ "$opt" =~ "-K -E" ]]; then + cat $fifo2 & + if [[ -n "$term" ]] || [[ -t 0 ]]; then + cat <<<"\"$sk\" $opts > $fifo2; out=\$? $close; return \$out" >>$argsf + TMUX=$(echo $TMUX | cut -d , -f 2,2) tmux popup -d "$PWD" "${tmux_args[@]}" $opt -R "$envs bash $argsf" >/dev/null 2>&1 + else + mkfifo $fifo1 + cat <<<"\"$sk\" $opts < $fifo1 > $fifo2; out=\$? $close; return \$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 + return $? + fi + + if [[ -n "$term" ]] || [[ -t 0 ]]; then + cat <<<"\"$sk\" $opts > $fifo2; echo \$? > $fifo3 $close" >>$argsf + echo $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 "${tmux_args[@]}" "$envs bash -c 'cd $(printf %q "$PWD"); exec -a sk bash $argsf'" $swap \ + >/dev/null 2>&1 || { + "$sk" "${args[@]}" + return $? + } + else + cat <<<"\"$sk\" $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 "${tmux_args[@]}" "$envs zsh -c 'exec -a sk zsh $argsf'" $swap \ + >/dev/null 2>&1 || { + "$sk" "${args[@]}" + return $? + } + cat <&0 >$fifo1 + fi + cat $fifo2 + return "$(cat $fifo3)" + diff --git a/zsh/funcs/skim.funcs b/zsh/funcs/skim.funcs index b04dedc..32a1d14 100644 --- a/zsh/funcs/skim.funcs +++ b/zsh/funcs/skim.funcs @@ -1,6 +1,5 @@ # Key bindings # ------------ -# copied and modified from https://github.com/junegunn/fzf/blob/master/shell/key-bindings.zsh if [[ $- == *i* ]]; then # CTRL-T - Paste the selected file path(s) into the command line diff --git a/zsh/zshrc b/zsh/zshrc index 5d13bf8..94789cf 100644 --- a/zsh/zshrc +++ b/zsh/zshrc @@ -82,7 +82,7 @@ function nv() { export PATH="$PATH:$HOME/.anyenv/bin" eval "$(anyenv init -)" export PATH="$(yarn global bin):$PATH" -export SKIM_TMUX=1 +# export SKIM_TMUX=1 #THIS MUST BE AT THE END OF THE FILE FOR SDKMAN TO WORK!!! export SDKMAN_DIR="$HOME/.sdkman" @@ -95,6 +95,6 @@ else touch $HOME/.zshsrc fi -for funcfile in $(ls $HOME/.zsh.d); do +for funcfile in $(ls $HOME/.zsh.d/); do source ${HOME}/.zsh.d/${funcfile} done