这是indexloc提供的服务,不要输入任何密码
Skip to content

Reuse #199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jan 9, 2024
Merged

Reuse #199

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
360 changes: 180 additions & 180 deletions .github/workflows/test.yml

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ OPTIONS:
mh main-horizontal
mv main-vertical
-n <number> Set the maximum number of <argument> taken for each pane.
-r Create or reuse the existing panes.
-s Speedy mode: Run command without opening an interactive shell.
-ss Speedy mode AND close a pane automatically at the same time as process exiting.
-S <socket-path> Set a full alternative path to the server socket.
Expand Down Expand Up @@ -326,6 +327,17 @@ When the tmux is already open and `xpanes` is executed on the existing tmux sess
- In addition, it separates the window into multiple panes.
- Finally, the window will be active.

You can use the -x option to create the panes in the current window.

You can use the -r option to create panes in the current window, or reuse the
existing ones. It is useful if you want to rerun the same xpanes command over
and over, e.g.:

xpanes -r -B 'ssh `host`' -c '`program> {}`' server client

will open 2 new panes. When the host reboots, you can rerun the same command
and the existing panes will be reused.

### [Pipe mode] Inside of tmux session & Accepting standard input

When `xpanes` accepts standard input (i.e, `xpanes` follows another command and pipe `|`) under **Normal mode2** , `xpanes`'s behavior is going to be the special one called "Pipe mode".
Expand Down
126 changes: 84 additions & 42 deletions bin/xpanes
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ XP_MAX_PANE_ARGS=""
XP_OPT_SET_TITLE=0
XP_OPT_CHANGE_BORDER=0
XP_OPT_EXTRA=0
XP_OPT_REUSE=0
XP_OPT_SPEEDY=0
XP_OPT_SPEEDY_AWAIT=0
XP_OPT_USE_PRESET_LAYOUT=0
Expand Down Expand Up @@ -199,6 +200,7 @@ OPTIONS:
mh main-horizontal
mv main-vertical
-n <number> Set the maximum number of <argument> taken for each pane.
-r Reuse the existing panes, or create then in the current active window.
-s Speedy mode: Run command without opening an interactive shell.
-ss Speedy mode AND close a pane automatically at the same time as process exiting.
-S <socket-path> Set a full alternative path to the server socket.
Expand Down Expand Up @@ -1438,7 +1440,11 @@ xpns_pre_execution() {
local _args4args=""

if [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
xpns_log "error" "'-x' must be used within the running tmux session."
xpns_log "error" "'-x' must be used on the running tmux session."
exit ${XP_EINVAL}
fi
if [[ ${XP_OPT_REUSE} -eq 1 ]]; then
xpns_log "error" "'-r' must be used on the running tmux session."
exit ${XP_EINVAL}
fi

Expand Down Expand Up @@ -1571,14 +1577,29 @@ xpns_execution() {
xpns_suppress_allow_rename "${_def_allow_rename-}"
XP_CMD_UTILITY="$(xpns_get_joined_begin_commands "${XP_CMD_UTILITY}")"

if [[ ${XP_OPT_REUSE} -eq 1 ]]; then
_window_name="$( ${TMUX_XPANES_EXEC} display -p -F "#{window_id}")"
_pane_count="$( ${TMUX_XPANES_EXEC} list-panes | grep -c .)"
_pane_base_index=$(($(${TMUX_XPANES_EXEC} display -p -F "#{pane_index}") + 1))
_pane_active_pane_id=$(${TMUX_XPANES_EXEC} display -p -F "#{pane_id}")

# Reusing the panes: if there's only 1 pane, behave like -x otherwise
# make sure there are enough panes of higher index than the current one.
# This allows to run -r to create the panes and then repeatedly to reuse
# those panes.
if [[ $((_pane_count - _pane_base_index)) -lt ${#XP_ARGS[@]} ]]; then
xpns_log "error" "Not enough panes ($((_pane_count - 1))) after this one to run the ${#XP_ARGS[@]} commands."
exit ${XP_EINVAL}
fi
fi
if [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
# Reuse existing window name
# tmux 1.6 does not support -F option
_window_name="$( ${TMUX_XPANES_EXEC} display -p -F "#{window_id}")"
_pane_count="$( ${TMUX_XPANES_EXEC} list-panes | grep -c .)"
_pane_base_index=$((_pane_base_index + _pane_count - 1))
_pane_active_pane_id=$(${TMUX_XPANES_EXEC} display -p -F "#{pane_id}")
else
elif [[ ${XP_OPT_REUSE} -eq 0 ]]; then
_window_name=$(
xpns_generate_window_name \
"${XP_EMPTY_STR}" \
Expand All @@ -1590,43 +1611,45 @@ xpns_execution() {
## --------------------
# Prepare window and panes
## --------------------
if [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
xpns_prepare_extra_panes \
"${_window_name}" \
"${_pane_base_index}" \
"${XP_OPT_LOG_STORE}" \
"${XP_OPT_SET_TITLE}" \
"${XP_OPT_SPEEDY}" \
"${XP_OPT_SPEEDY_AWAIT}" \
"${XP_OPT_INTERVAL}" \
"${XP_REPSTR}" \
"${XP_CMD_UTILITY}" \
"${XP_ARGS[@]}"
elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 1 ]]; then
xpns_prepare_preset_layout_window \
"${_window_name}" \
"${_pane_base_index}" \
"${XP_OPT_LOG_STORE}" \
"${XP_OPT_SET_TITLE}" \
"${XP_OPT_ATTACH}" \
"${XP_OPT_SPEEDY}" \
"${XP_OPT_SPEEDY_AWAIT}" \
"${XP_OPT_INTERVAL}" \
"${XP_REPSTR}" \
"${XP_CMD_UTILITY}" \
"${XP_ARGS[@]}"
elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 0 ]]; then
xpns_prepare_window \
"${_window_name}" \
"${XP_OPT_LOG_STORE}" \
"${XP_OPT_SET_TITLE}" \
"${XP_OPT_ATTACH}" \
"${XP_OPT_SPEEDY}" \
"${XP_OPT_SPEEDY_AWAIT}" \
"${XP_OPT_INTERVAL}" \
"${XP_REPSTR}" \
"${XP_CMD_UTILITY}" \
"${XP_ARGS[@]}"
if [[ ${XP_OPT_REUSE} -eq 0 ]]; then
if [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
xpns_prepare_extra_panes \
"${_window_name}" \
"${_pane_base_index}" \
"${XP_OPT_LOG_STORE}" \
"${XP_OPT_SET_TITLE}" \
"${XP_OPT_SPEEDY}" \
"${XP_OPT_SPEEDY_AWAIT}" \
"${XP_OPT_INTERVAL}" \
"${XP_REPSTR}" \
"${XP_CMD_UTILITY}" \
"${XP_ARGS[@]}"
elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 1 ]]; then
xpns_prepare_preset_layout_window \
"${_window_name}" \
"${_pane_base_index}" \
"${XP_OPT_LOG_STORE}" \
"${XP_OPT_SET_TITLE}" \
"${XP_OPT_ATTACH}" \
"${XP_OPT_SPEEDY}" \
"${XP_OPT_SPEEDY_AWAIT}" \
"${XP_OPT_INTERVAL}" \
"${XP_REPSTR}" \
"${XP_CMD_UTILITY}" \
"${XP_ARGS[@]}"
elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 0 ]]; then
xpns_prepare_window \
"${_window_name}" \
"${XP_OPT_LOG_STORE}" \
"${XP_OPT_SET_TITLE}" \
"${XP_OPT_ATTACH}" \
"${XP_OPT_SPEEDY}" \
"${XP_OPT_SPEEDY_AWAIT}" \
"${XP_OPT_INTERVAL}" \
"${XP_REPSTR}" \
"${XP_CMD_UTILITY}" \
"${XP_ARGS[@]}"
fi
fi

## With -ss option, it is possible to close all the panes as of here.
Expand Down Expand Up @@ -1698,7 +1721,7 @@ xpns_execution() {

## With -l <layout>, panes are organized.
## As well as -x, they are re-organized.
if [[ $XP_OPT_USE_PRESET_LAYOUT -eq 1 ]] || [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
if [[ (${XP_OPT_USE_PRESET_LAYOUT} -eq 1 || ${XP_OPT_EXTRA} -eq 1) && ${XP_OPT_REUSE} -eq 0 ]]; then
xpns_organize_panes \
"${_window_name}" \
"${_last_args_idx}"
Expand All @@ -1723,8 +1746,8 @@ xpns_execution() {
pane-border-status "${TMUX_XPANES_PANE_BORDER_STATUS}"
fi

# In case of -x, this statement is skipped to keep the original window name
if [[ ${XP_OPT_EXTRA} -eq 0 ]]; then
# In case of -x or -r, this statement is skipped to keep the original window name
if [[ ${XP_OPT_EXTRA} -eq 0 ]] && [[ ${XP_OPT_REUSE} -eq 0 ]]; then
# Restore original window name.
${TMUX_XPANES_EXEC} \
rename-window -t "${_window_name}" \
Expand Down Expand Up @@ -1987,6 +2010,7 @@ xpns_parse_options() {
exit 0
;;
-x)
# If you modify those, make similar changes to -r
XP_OPTIONS+=("$opt")
XP_OPT_EXTRA=1
XP_OPT_USE_PRESET_LAYOUT=1 ## Layout presets must be used with -x
Expand All @@ -2013,6 +2037,24 @@ xpns_parse_options() {
sleep 1
fi
;;
-r)
XP_OPTIONS+=("$opt")
# Reusing the panes: if there's only 1 pane, behave like -x
# This allows to run -r to create the panes and then repeatedly to reuse
# those panes.
_pane_count="$( ${TMUX_XPANES_EXEC} list-panes | grep -c .)"
if [[ ${_pane_count} -eq 1 ]]; then
XP_OPT_EXTRA=1
XP_OPT_USE_PRESET_LAYOUT=1 ## Layout presets must be used with -x
if ! xpns_warning_before_extra; then
exit ${XP_EINTENT}
fi
else
XP_OPT_REUSE=1
XP_OPT_EXTRA=0
XP_OPT_IS_SYNC=0
fi
;;
-s)
XP_OPTIONS+=("$opt")
XP_OPT_SPEEDY=1
Expand Down
1 change: 1 addition & 0 deletions completion/zsh/_xpanes
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ _xpanes () {
"($opts_omit -s -ss --ssh)-s[Speedy mode: Run command without opening an interactive shell.]" \
"($opts_omit -ss -s)-ss[Speedy mode AND close a pane automatically at the same time as process exiting.]" \
"($opts_omit -n)-n[Set the maximum number of <argument> taken for each pane.]:num:" \
"($opts_omit -r)-r[Reuse the existing panes, or create then in the current active window.]" \
"($opts_omit -S)-S[Specify a full alternative path to the server socket.]:filename:_files" \
"($opts_omit -t)-t[Display each argument on the each pane's border as their title.]" \
"($opts_omit -x --stay)-x[Create extra panes in the current active window.]" \
Expand Down
3 changes: 3 additions & 0 deletions man/man.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ OPTIONS
`-n` <*number*>
Set the maximum number of <*argument*> taken for each pane.

`-r`
Reuse the existing panes, or create then in the current active window.

`-S` <*socket-path*>
Set a full alternative path to the server socket.

Expand Down
3 changes: 3 additions & 0 deletions man/xpanes.1
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ Speedy mode AND close a pane automatically at the same time as process exiting.
\fB\fC\-n\fR <\fInumber\fP>
Set the maximum number of <\fIargument\fP> taken for each pane.
.TP
\fB\fC\-r\fR
Reuse the existing panes, or create then in the current active window.
.TP
\fB\fC\-S\fR <\fIsocket\-path\fP>
Set a full alternative path to the server socket.
.TP
Expand Down
9 changes: 9 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ $ git submodule update

4. Run `bash ./update_yaml.sh`

## How to run specific test

Execute `test_generator.sh <number>` and execute the generated result as a script.
For the test case 85, run like below.

```bash
$ bash test_generator.sh 85 > test_85.sh
$ bash ./test_85.sh
```
80 changes: 79 additions & 1 deletion test/cases_all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2813,7 +2813,7 @@ test_x_option_abort() {

_cmd="${EXEC} -S $_socket_file -x AAAA AAAA BBBB CCCC"
eval "${_cmd}"
# Run -a option with Normal mode1
# Run -x option with Normal mode1
assertEquals 4 $?

: "In TMUX session" && {
Expand Down Expand Up @@ -4621,6 +4621,84 @@ test_b_x_log_option () {
return 0
}

# @case: 85
# @skip:
test_r_option_error () {
local _socket_file="${SHUNIT_TMPDIR}/.xpanes-shunit"
local _cmd="${EXEC} -d -S $_socket_file -r AAA BBB CCC"
echo $'\n'" $ $_cmd"$'\n'
eval "$_cmd"
assertEquals 4 $?
close_tmux_session "$_socket_file"
return 0
}

# @case: 86
# @skip:
test_r_option_same_as_x() {
local _socket_file="${SHUNIT_TMPDIR}/.xpanes-shunit"
local _cmd
: "In TMUX session" && {
_cmd="${EXEC} -S $_socket_file -r -c 'echo {}' AAA BBB CCC"
create_tmux_session "$_socket_file"
exec_tmux_session "$_socket_file" "$_cmd"
# If there is only one pane, -r acts like -x
# There must be 4 pane though.
wait_panes_separation "$_socket_file" ".*" "4"
assert_tiled_four_panes "$_socket_file" ".*"
close_tmux_session "$_socket_file"
}
return 0
}

# @case: 87
# @skip:
test_x_r_option() {
local _socket_file="${SHUNIT_TMPDIR}/.xpanes-shunit"
local _tmpdir="${SHUNIT_TMPDIR}"
mkdir -p "${_tmpdir}/fin"
local _cmd
: "In TMUX session" && {
_cmd="${EXEC} -S $_socket_file -x -c 'echo {}' AAA BBB CCC"
create_tmux_session "$_socket_file"
exec_tmux_session "$_socket_file" "$_cmd"
# If there is only one pane, -r acts like -x
# There must be 4 pane though.
wait_panes_separation "$_socket_file" ".*" "4"
_cmd="${EXEC} -S $_socket_file -r -c 'echo {} > ${_tmpdir}/fin/{}' DDD EEE FFF"
exec_tmux_session "$_socket_file" "$_cmd"
wait_existing_file_number "${_tmpdir}/fin" "3" # DDD EEE FFF files should exist
close_tmux_session "$_socket_file"
rm -f "${_tmpdir}"/fin/*
rmdir "${_tmpdir}"/fin
}
return 0
}

# @case: 88
# @skip:
test_x_r_option_invalid_pane_count() {
local _socket_file="${SHUNIT_TMPDIR}/.xpanes-shunit"
local _tmpdir="${SHUNIT_TMPDIR}"
mkdir -p "${_tmpdir}/fin"
local _cmd
: "In TMUX session" && {
_cmd="${EXEC} -S $_socket_file -x -c 'echo {}' AAA BBB CCC"
create_tmux_session "$_socket_file"
exec_tmux_session "$_socket_file" "$_cmd"
# If there is only one pane, -r acts like -x
# There must be 4 pane though.
wait_panes_separation "$_socket_file" ".*" "4"
_cmd="${EXEC} -S $_socket_file -r -c 'echo {}' DDD EEE FFF GGG; echo \$? > ${_tmpdir}/fin/status"
exec_tmux_session "$_socket_file" "$_cmd"
assertEquals 4 "$(<"${_tmpdir}"/fin/status)"
close_tmux_session "$_socket_file"
rm -f "${_tmpdir}"/fin/*
rmdir "${_tmpdir}"/fin
}
return 0
}

###:-:-:END_TESTING:-:-:###

###:-:-:INSERT_TESTING:-:-:###
Expand Down
2 changes: 1 addition & 1 deletion test/config.pict
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ tmux:1.8,1.9,1.9a,2.0,2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.9,2.9a,3.0a,3.1,3.1b,3.1

## Create test cases
# cat cases_all.sh | grep '@case:' | awk '{print $NF}' | xargs | tr ' ' ',' | awk '{print "case:"$0}'
case: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,84
case: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,84,85,86,87,88

## Create exceptional conditions
# cat cases_all.sh | grep -E '@skip: ?.' -B1 | awk '{print $2,$3}' | awk 'NF{print $2}' | xargs -n 2 | tr , ' ' | awk '{for (i=2;i<=NF;i++){print $1,$i}}' | awk '{print "IF[case] = "$1" THEN [tmux] <> \""$2"\";"}'
Expand Down