Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,15 @@ follows <https://www.conventionalcommits.org/en/v1.0.0/> to track changes.

- Distribute this plugin to nixpkgs ([#42], [NixOS/nixpkgs#428294], thanks
[@szaffarano])
- Support specifying the socket path for the popup server ([#{PRNUM}])
- Support specifying the socket path for the popup server ([#43])

### Fixed

- Support OSX's ancient Bash ([#44])

[#42]: https://github.com/loichyan/tmux-toggle-popup/pull/42
[#43]: https://github.com/loichyan/tmux-toggle-popup/pull/43
[#44]: https://github.com/loichyan/tmux-toggle-popup/pull/44
[NixOS/nixpkgs#428294]: https://github.com/NixOS/nixpkgs/pull/428294
[@szaffarano]: https://github.com/szaffarano

Expand Down
3 changes: 3 additions & 0 deletions osx-env.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FROM bash:3.2.57

RUN apk add --no-cache git tmux
2 changes: 1 addition & 1 deletion src/focus.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

set -e
set -eo pipefail
CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

# shellcheck source=./helpers.sh
Expand Down
56 changes: 52 additions & 4 deletions src/helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ die_badopt() {
# `key=format`, where `format` is a tmux FORMAT to retrieve the intended option,
# and its value is assigned to a variable named `key`.
batch_get_options() {
local vars=() formats=() val=() line
local keys=() formats=() val=() line
while [[ $# -gt 0 ]]; do
vars+=("${1%%=*}")
keys+=("${1%%=*}")
formats+=("${1#*=}")
shift
done
delimiter=${delimiter:-"EOF@$RANDOM"} # generate a random delimiter
set -- "${vars[@]}"
delimiter=${delimiter:-">>>END@$RANDOM"} # generate a random delimiter
set -- "${keys[@]}"
while IFS= read -r line; do
if [[ -z $line ]]; then
:
Expand Down Expand Up @@ -85,3 +85,51 @@ interpolate() {
done
echo "$result"
}

#=== Test utils ===#

failf() {
local source lineno
source=$(basename "${BASH_SOURCE[1]}")
lineno=${BASH_LINENO[1]}
printf "%s:%s: $1" "$source" "$lineno" "${@:2}"
exit 1
}

assert_eq() {
if [[ $1 != "$2" ]]; then
failf "assertion failed: left != right:\n\tleft: %s\n\tright: %s" "$1" "$2"
fi
}

begin_test() {
local source
source=$(basename "${BASH_SOURCE[1]}")
echo -e "[test] ${source%.*}::${1}"
}

# Allocates a temporary file, deleting on exit.
alloctmp() {
local tempath
tempath=$(mktemp)
# shellcheck disable=SC2064
trap "rm '$tempath'" EXIT
echo "$tempath"
}

# Simulates the response of `batch_get_options`. It accepts arguments in the
# same format as `batch_get_options`: each pair contains the variable name and
# its default value. If a variable is set in the execution context, then its
# value will be used.
fake_batch_options() {
local key val
while [[ $# -gt 0 ]]; do
key=${1%%=*}
val=${1#*=}
if [[ -n ${!key} ]]; then
val=${!key}
fi
printf "%s\n$delimiter\n" "$val"
shift
done
}
36 changes: 9 additions & 27 deletions src/helpers_tests.sh
Original file line number Diff line number Diff line change
@@ -1,28 +1,10 @@
#!/usr/bin/env bash

set -euo pipefail
set -eo pipefail
CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

# shellcheck source=../src/helpers.sh
source "$CURRENT_DIR/../src/helpers.sh"

failf() {
local source lineno
source=$(basename "${BASH_SOURCE[1]}")
lineno=${BASH_LINENO[1]}
printf "%s:%s: $1" "$source" "$lineno" "${@:2}"
exit 1
}

assert_eq() {
if [[ $1 != "$2" ]]; then
failf "assertion failed: left != right:\n\tleft: %s\n\tright: %s" "$1" "$2"
fi
}

begin_test() {
echo -e "[test] helpers_tests::$1"
}
source "$CURRENT_DIR/helpers.sh"

#=== test:parse_cmds ===#

Expand All @@ -34,14 +16,14 @@ test_parse_commands() {
failf "expected $# tokens to be parsed, got ${#cmds[@]}:%s" "$(printf "\n\t%s" "${cmds[@]}")"
fi

local -i i=0
local i=0
while [[ $# -gt 0 ]]; do
if [[ $1 != "${cmds[$i]}" ]]; then
git diff <(echo "$1") <(echo "${cmds[i]}")
failf "unexpected token at $((i + 1))"
fi
shift
i+=1
i=$((i + 1))
done
}

Expand Down Expand Up @@ -73,10 +55,10 @@ test_parse_commands \

#=== test:interpolate ===#

declare expected output
declare expected input
test_interpolate() {
output=$(interpolate "${@}" "$format")
assert_eq "$expected" "$output"
input=$(interpolate "${@}" "$format")
assert_eq "$expected" "$input"
}

begin_test "no_interpolate_of_unknown"
Expand All @@ -97,10 +79,10 @@ test_interpolate var1="var1=value1" var2="var2=value2"
#=== test:batch_get_options ===#

# Simulates a tmux response.
declare input delimiter="EOF"
declare delimiter=">>>END" input
declare var1 var2 var3 var4
tmux() {
printf "%s\nEOF\n" "${input[@]}"
printf "%s\n$delimiter\n" "${input[@]}"
}

begin_test "batch_get_options"
Expand Down
12 changes: 7 additions & 5 deletions src/toggle.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash

set -e
set -eo pipefail
CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

# shellcheck source=./helpers.sh
Expand Down Expand Up @@ -45,7 +45,7 @@ usage() {
# - `open_cmds` is used to initialize the popup session
# - `on_cleanup` is used to undo temporary changes on the popup server
# - `popup_id` is set to the name of the target popup session
declare open_cmds on_cleanup popup_id
declare open_cmds=() on_cleanup=() popup_id
prepare_open() {
popup_id=${id:-$(interpolate popup_name="$name" "$id_format")}
popup_id=$(escape_session_name "$popup_id")
Expand Down Expand Up @@ -82,7 +82,7 @@ prepare_open() {
fi
}

declare name id id_format toggle_keys open_args open_dir program display_args
declare name id id_format toggle_keys=() open_args=() open_dir program=() display_args=()
declare on_init before_open after_close toggle_mode socket_name socket_path
declare opened_name caller_id_format caller_path caller_pane_path
declare default_id_format default_shell session_path pane_path
Expand Down Expand Up @@ -148,12 +148,14 @@ main() {

if [[ -n $opened_name ]]; then
if [[ $name == "$opened_name" || $OPTIND -eq 1 || $toggle_mode == "force-close" ]]; then
exec tmux detach >/dev/null
tmux detach >/dev/null
return
elif [[ $toggle_mode == "switch" ]]; then
# Inherit the caller's ID format in switch mode
id_format=${caller_id_format}
prepare_open "switch"
exec tmux "${open_cmds[@]}"
tmux "${open_cmds[@]}"
return
elif [[ $toggle_mode != "force-open" ]]; then
die "illegal toggle mode: $toggle_mode"
fi
Expand Down
114 changes: 114 additions & 0 deletions src/toggle_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env bash
# shellcheck disable=SC2034

set -eo pipefail
CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)

# shellcheck source=../src/helpers.sh
source "$CURRENT_DIR/helpers.sh"

#=== test:tggles ===#

prepare_batch_options() {
fake_batch_options \
t_id_format="pane/path/{popup_name}" \
t_on_init="display 'on-init' ; run '#{@on_init}'" \
t_before_open="display 'before-open' ; run '#{@before_open}'" \
t_after_close="display 'after-close' ; run '#{@after_close}'" \
t_toggle_mode="switch" \
t_socket_name="popup_server1" \
t_socket_path="socket/path/popup_server2" \
t_opened_name="" \
t_caller_id_format="caller/id/format" \
t_caller_path="caller/session/pane" \
t_caller_pane_path="caller/pane/path" \
t_default_id_format="session/path/{popup_name}" \
t_default_shell="/usr/bin/fish" \
t_session_path="working/session/path" \
t_pane_path="working/pane/path"
}

declare delimiter=">>>END" exit_codes f_call_id f_output
tmux() {
# Bump call ID
local call_id
call_id=$(cat "$f_call_id")
echo "$((call_id + 1))" >"$f_call_id"

# The first call is always `batch_get_options`.
# Discard its output since not particular useful.
if [[ $call_id == 0 ]]; then
prepare_batch_options
return
fi

# Appends arguments to output
{
echo ">>>TMUX:BEGIN($call_id)"
printf "%s\n" "$@"
echo "<<<TMUX:END($call_id)"
echo
} >>"$f_output"

# Fake tmux exit code
# shellcheck disable=SC2086
return ${exit_codes[$call_id]}
}

declare test_name
test_toggle() {
f_call_id=$(alloctmp)
f_output=$(alloctmp)
echo 0 >"$f_call_id"
source "$CURRENT_DIR/toggle.sh"

local expected="$CURRENT_DIR/toggle_tests/$test_name.stdout"
if [[ $TEST_OVERWRITE = 1 ]]; then
mkdir -p "$(dirname "$expected")"
cp "$f_output" "$expected"
else
git diff --exit-code "$f_output" "$expected"
fi
}

test_name="open_popup"
exit_codes=(0 0 0)
t_toggle_mode="switch"
t_opened_name=""
begin_test "$test_name"
test_toggle --name="p_open"

test_name="close_popup"
exit_codes=(0 0 0)
t_toggle_mode="switch"
t_opened_name="p_close"
begin_test "$test_name"
test_toggle --name="p_close"

test_name="switch_popup"
exit_codes=(0 0 0)
t_toggle_mode="switch"
t_opened_name="p_switch_1"
begin_test "$test_name"
test_toggle --name="p_switch_2"

test_name="switch_new_popup"
exit_codes=(0 1 0)
t_toggle_mode="switch"
t_opened_name="p_switch_1"
begin_test "$test_name"
test_toggle --name="p_switch_2"

test_name="force_close_popup"
exit_codes=(0 0 0)
t_toggle_mode="force-close"
t_opened_name="p_force_close_1"
begin_test "$test_name"
test_toggle --name="p_force_close_2"

test_name="open_nested_popup"
exit_codes=(0 0 0)
t_toggle_mode="force-open"
t_opened_name="p_open_nested_1"
begin_test "$test_name"
test_toggle --name="p_open_nested_2"
4 changes: 4 additions & 0 deletions src/toggle_tests/close_popup.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
>>>TMUX:BEGIN(1)
detach
<<<TMUX:END(1)

4 changes: 4 additions & 0 deletions src/toggle_tests/force_close_popup.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
>>>TMUX:BEGIN(1)
detach
<<<TMUX:END(1)

25 changes: 25 additions & 0 deletions src/toggle_tests/open_nested_popup.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
>>>TMUX:BEGIN(1)
display
before-open
;
run
#{@before_open}
<<<TMUX:END(1)

>>>TMUX:BEGIN(2)
set
default-shell
/bin/sh
;
popup
tmux set default-shell '/usr/bin/fish'; export TMUX_POPUP_SERVER='popup_server2' SHELL='/usr/bin/fish'; exec tmux -S socket/path/popup_server2 new -As pane/path/p_open_nested_2 \; set @__popup_name p_open_nested_2 \; set @__popup_id_format pane/path/\{popup_name\} \; set @__popup_caller_path working/session/path \; set @__popup_caller_pane_path working/pane/path \; display on-init \; run \#\{@on_init\} >/dev/null
<<<TMUX:END(2)

>>>TMUX:BEGIN(3)
display
after-close
;
run
#{@after_close}
<<<TMUX:END(3)

25 changes: 25 additions & 0 deletions src/toggle_tests/open_popup.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
>>>TMUX:BEGIN(1)
display
before-open
;
run
#{@before_open}
<<<TMUX:END(1)

>>>TMUX:BEGIN(2)
set
default-shell
/bin/sh
;
popup
tmux set default-shell '/usr/bin/fish'; export TMUX_POPUP_SERVER='popup_server2' SHELL='/usr/bin/fish'; exec tmux -S socket/path/popup_server2 new -As pane/path/p_open \; set @__popup_name p_open \; set @__popup_id_format pane/path/\{popup_name\} \; set @__popup_caller_path working/session/path \; set @__popup_caller_pane_path working/pane/path \; display on-init \; run \#\{@on_init\} >/dev/null
<<<TMUX:END(2)

>>>TMUX:BEGIN(3)
display
after-close
;
run
#{@after_close}
<<<TMUX:END(3)

Loading