Skip to content

Commit 1cd9aa3

Browse files
authored
fix: supports OSX's ancient Bash (#44)
1 parent 5420270 commit 1cd9aa3

14 files changed

+323
-39
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,15 @@ follows <https://www.conventionalcommits.org/en/v1.0.0/> to track changes.
4141

4242
- Distribute this plugin to nixpkgs ([#42], [NixOS/nixpkgs#428294], thanks
4343
[@szaffarano])
44-
- Support specifying the socket path for the popup server ([#{PRNUM}])
44+
- Support specifying the socket path for the popup server ([#43])
45+
46+
### Fixed
47+
48+
- Support OSX's ancient Bash ([#44])
4549

4650
[#42]: https://github.com/loichyan/tmux-toggle-popup/pull/42
4751
[#43]: https://github.com/loichyan/tmux-toggle-popup/pull/43
52+
[#44]: https://github.com/loichyan/tmux-toggle-popup/pull/44
4853
[NixOS/nixpkgs#428294]: https://github.com/NixOS/nixpkgs/pull/428294
4954
[@szaffarano]: https://github.com/szaffarano
5055

osx-env.dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM bash:3.2.57
2+
3+
RUN apk add --no-cache git tmux

src/focus.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env bash
22

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

66
# shellcheck source=./helpers.sh

src/helpers.sh

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ die_badopt() {
1919
# `key=format`, where `format` is a tmux FORMAT to retrieve the intended option,
2020
# and its value is assigned to a variable named `key`.
2121
batch_get_options() {
22-
local vars=() formats=() val=() line
22+
local keys=() formats=() val=() line
2323
while [[ $# -gt 0 ]]; do
24-
vars+=("${1%%=*}")
24+
keys+=("${1%%=*}")
2525
formats+=("${1#*=}")
2626
shift
2727
done
28-
delimiter=${delimiter:-"EOF@$RANDOM"} # generate a random delimiter
29-
set -- "${vars[@]}"
28+
delimiter=${delimiter:-">>>END@$RANDOM"} # generate a random delimiter
29+
set -- "${keys[@]}"
3030
while IFS= read -r line; do
3131
if [[ -z $line ]]; then
3232
:
@@ -85,3 +85,51 @@ interpolate() {
8585
done
8686
echo "$result"
8787
}
88+
89+
#=== Test utils ===#
90+
91+
failf() {
92+
local source lineno
93+
source=$(basename "${BASH_SOURCE[1]}")
94+
lineno=${BASH_LINENO[1]}
95+
printf "%s:%s: $1" "$source" "$lineno" "${@:2}"
96+
exit 1
97+
}
98+
99+
assert_eq() {
100+
if [[ $1 != "$2" ]]; then
101+
failf "assertion failed: left != right:\n\tleft: %s\n\tright: %s" "$1" "$2"
102+
fi
103+
}
104+
105+
begin_test() {
106+
local source
107+
source=$(basename "${BASH_SOURCE[1]}")
108+
echo -e "[test] ${source%.*}::${1}"
109+
}
110+
111+
# Allocates a temporary file, deleting on exit.
112+
alloctmp() {
113+
local tempath
114+
tempath=$(mktemp)
115+
# shellcheck disable=SC2064
116+
trap "rm '$tempath'" EXIT
117+
echo "$tempath"
118+
}
119+
120+
# Simulates the response of `batch_get_options`. It accepts arguments in the
121+
# same format as `batch_get_options`: each pair contains the variable name and
122+
# its default value. If a variable is set in the execution context, then its
123+
# value will be used.
124+
fake_batch_options() {
125+
local key val
126+
while [[ $# -gt 0 ]]; do
127+
key=${1%%=*}
128+
val=${1#*=}
129+
if [[ -n ${!key} ]]; then
130+
val=${!key}
131+
fi
132+
printf "%s\n$delimiter\n" "$val"
133+
shift
134+
done
135+
}

src/helpers_tests.sh

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,10 @@
11
#!/usr/bin/env bash
22

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

66
# shellcheck source=../src/helpers.sh
7-
source "$CURRENT_DIR/../src/helpers.sh"
8-
9-
failf() {
10-
local source lineno
11-
source=$(basename "${BASH_SOURCE[1]}")
12-
lineno=${BASH_LINENO[1]}
13-
printf "%s:%s: $1" "$source" "$lineno" "${@:2}"
14-
exit 1
15-
}
16-
17-
assert_eq() {
18-
if [[ $1 != "$2" ]]; then
19-
failf "assertion failed: left != right:\n\tleft: %s\n\tright: %s" "$1" "$2"
20-
fi
21-
}
22-
23-
begin_test() {
24-
echo -e "[test] helpers_tests::$1"
25-
}
7+
source "$CURRENT_DIR/helpers.sh"
268

279
#=== test:parse_cmds ===#
2810

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

37-
local -i i=0
19+
local i=0
3820
while [[ $# -gt 0 ]]; do
3921
if [[ $1 != "${cmds[$i]}" ]]; then
4022
git diff <(echo "$1") <(echo "${cmds[i]}")
4123
failf "unexpected token at $((i + 1))"
4224
fi
4325
shift
44-
i+=1
26+
i=$((i + 1))
4527
done
4628
}
4729

@@ -73,10 +55,10 @@ test_parse_commands \
7355

7456
#=== test:interpolate ===#
7557

76-
declare expected output
58+
declare expected input
7759
test_interpolate() {
78-
output=$(interpolate "${@}" "$format")
79-
assert_eq "$expected" "$output"
60+
input=$(interpolate "${@}" "$format")
61+
assert_eq "$expected" "$input"
8062
}
8163

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

9981
# Simulates a tmux response.
100-
declare input delimiter="EOF"
82+
declare delimiter=">>>END" input
10183
declare var1 var2 var3 var4
10284
tmux() {
103-
printf "%s\nEOF\n" "${input[@]}"
85+
printf "%s\n$delimiter\n" "${input[@]}"
10486
}
10587

10688
begin_test "batch_get_options"

src/toggle.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env bash
22

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

66
# shellcheck source=./helpers.sh
@@ -45,7 +45,7 @@ usage() {
4545
# - `open_cmds` is used to initialize the popup session
4646
# - `on_cleanup` is used to undo temporary changes on the popup server
4747
# - `popup_id` is set to the name of the target popup session
48-
declare open_cmds on_cleanup popup_id
48+
declare open_cmds=() on_cleanup=() popup_id
4949
prepare_open() {
5050
popup_id=${id:-$(interpolate popup_name="$name" "$id_format")}
5151
popup_id=$(escape_session_name "$popup_id")
@@ -82,7 +82,7 @@ prepare_open() {
8282
fi
8383
}
8484

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

149149
if [[ -n $opened_name ]]; then
150150
if [[ $name == "$opened_name" || $OPTIND -eq 1 || $toggle_mode == "force-close" ]]; then
151-
exec tmux detach >/dev/null
151+
tmux detach >/dev/null
152+
return
152153
elif [[ $toggle_mode == "switch" ]]; then
153154
# Inherit the caller's ID format in switch mode
154155
id_format=${caller_id_format}
155156
prepare_open "switch"
156-
exec tmux "${open_cmds[@]}"
157+
tmux "${open_cmds[@]}"
158+
return
157159
elif [[ $toggle_mode != "force-open" ]]; then
158160
die "illegal toggle mode: $toggle_mode"
159161
fi

src/toggle_tests.sh

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env bash
2+
# shellcheck disable=SC2034
3+
4+
set -eo pipefail
5+
CURRENT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
6+
7+
# shellcheck source=../src/helpers.sh
8+
source "$CURRENT_DIR/helpers.sh"
9+
10+
#=== test:tggles ===#
11+
12+
prepare_batch_options() {
13+
fake_batch_options \
14+
t_id_format="pane/path/{popup_name}" \
15+
t_on_init="display 'on-init' ; run '#{@on_init}'" \
16+
t_before_open="display 'before-open' ; run '#{@before_open}'" \
17+
t_after_close="display 'after-close' ; run '#{@after_close}'" \
18+
t_toggle_mode="switch" \
19+
t_socket_name="popup_server1" \
20+
t_socket_path="socket/path/popup_server2" \
21+
t_opened_name="" \
22+
t_caller_id_format="caller/id/format" \
23+
t_caller_path="caller/session/pane" \
24+
t_caller_pane_path="caller/pane/path" \
25+
t_default_id_format="session/path/{popup_name}" \
26+
t_default_shell="/usr/bin/fish" \
27+
t_session_path="working/session/path" \
28+
t_pane_path="working/pane/path"
29+
}
30+
31+
declare delimiter=">>>END" exit_codes f_call_id f_output
32+
tmux() {
33+
# Bump call ID
34+
local call_id
35+
call_id=$(cat "$f_call_id")
36+
echo "$((call_id + 1))" >"$f_call_id"
37+
38+
# The first call is always `batch_get_options`.
39+
# Discard its output since not particular useful.
40+
if [[ $call_id == 0 ]]; then
41+
prepare_batch_options
42+
return
43+
fi
44+
45+
# Appends arguments to output
46+
{
47+
echo ">>>TMUX:BEGIN($call_id)"
48+
printf "%s\n" "$@"
49+
echo "<<<TMUX:END($call_id)"
50+
echo
51+
} >>"$f_output"
52+
53+
# Fake tmux exit code
54+
# shellcheck disable=SC2086
55+
return ${exit_codes[$call_id]}
56+
}
57+
58+
declare test_name
59+
test_toggle() {
60+
f_call_id=$(alloctmp)
61+
f_output=$(alloctmp)
62+
echo 0 >"$f_call_id"
63+
source "$CURRENT_DIR/toggle.sh"
64+
65+
local expected="$CURRENT_DIR/toggle_tests/$test_name.stdout"
66+
if [[ $TEST_OVERWRITE = 1 ]]; then
67+
mkdir -p "$(dirname "$expected")"
68+
cp "$f_output" "$expected"
69+
else
70+
git diff --exit-code "$f_output" "$expected"
71+
fi
72+
}
73+
74+
test_name="open_popup"
75+
exit_codes=(0 0 0)
76+
t_toggle_mode="switch"
77+
t_opened_name=""
78+
begin_test "$test_name"
79+
test_toggle --name="p_open"
80+
81+
test_name="close_popup"
82+
exit_codes=(0 0 0)
83+
t_toggle_mode="switch"
84+
t_opened_name="p_close"
85+
begin_test "$test_name"
86+
test_toggle --name="p_close"
87+
88+
test_name="switch_popup"
89+
exit_codes=(0 0 0)
90+
t_toggle_mode="switch"
91+
t_opened_name="p_switch_1"
92+
begin_test "$test_name"
93+
test_toggle --name="p_switch_2"
94+
95+
test_name="switch_new_popup"
96+
exit_codes=(0 1 0)
97+
t_toggle_mode="switch"
98+
t_opened_name="p_switch_1"
99+
begin_test "$test_name"
100+
test_toggle --name="p_switch_2"
101+
102+
test_name="force_close_popup"
103+
exit_codes=(0 0 0)
104+
t_toggle_mode="force-close"
105+
t_opened_name="p_force_close_1"
106+
begin_test "$test_name"
107+
test_toggle --name="p_force_close_2"
108+
109+
test_name="open_nested_popup"
110+
exit_codes=(0 0 0)
111+
t_toggle_mode="force-open"
112+
t_opened_name="p_open_nested_1"
113+
begin_test "$test_name"
114+
test_toggle --name="p_open_nested_2"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
>>>TMUX:BEGIN(1)
2+
detach
3+
<<<TMUX:END(1)
4+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
>>>TMUX:BEGIN(1)
2+
detach
3+
<<<TMUX:END(1)
4+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
>>>TMUX:BEGIN(1)
2+
display
3+
before-open
4+
;
5+
run
6+
#{@before_open}
7+
<<<TMUX:END(1)
8+
9+
>>>TMUX:BEGIN(2)
10+
set
11+
default-shell
12+
/bin/sh
13+
;
14+
popup
15+
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
16+
<<<TMUX:END(2)
17+
18+
>>>TMUX:BEGIN(3)
19+
display
20+
after-close
21+
;
22+
run
23+
#{@after_close}
24+
<<<TMUX:END(3)
25+

0 commit comments

Comments
 (0)