]> git.madduck.net Git - etc/tmux.git/commitdiff

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

update xpanes to 4.1.3 master
authormartin f. krafft <madduck@madduck.net>
Thu, 22 Dec 2022 08:40:16 +0000 (09:40 +0100)
committermartin f. krafft <madduck@madduck.net>
Thu, 22 Dec 2022 08:40:16 +0000 (09:40 +0100)
.bin/xpanes

index 5b3d1f963a990a5a0be885f41d2c62322c3909ad..27c139f780e53e24c4ea66c60f7242147d62393d 100755 (executable)
@@ -5,17 +5,14 @@ readonly XP_SHELL="/usr/bin/env bash"
 # @Filename xpanes
 
 set -u
-readonly XP_VERSION="4.1.1"
+readonly XP_VERSION="4.1.3"
 
 ## trap might be updated in 'xpns_pre_execution' function
-trap 'rm -f "${XP_CACHE_HOME}"/__xpns_*$$; rm -f "${XP_DEFAULT_SOCKET_PATH}"' EXIT
+trap 'rm -f "${XP_CACHE_HOME}"/__xpns_*$$; xpns_clean_session' EXIT
 
 ## --------------------------------
 # Error constants
 ## --------------------------------
-# Undefined or General errors
-readonly XP_EUNDEF=1
-
 # Invalid option/argument
 readonly XP_EINVAL=4
 
@@ -49,7 +46,7 @@ readonly XP_ENOCMD=127
 
 # XP_THIS_FILE_NAME is supposed to be "xpanes".
 readonly XP_THIS_FILE_NAME="${0##*/}"
-readonly XP_THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-${(%):-%N}}")" && pwd)"
+readonly XP_THIS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
 readonly XP_ABS_THIS_FILE_NAME="${XP_THIS_DIR}/${XP_THIS_FILE_NAME}"
 
 # Prevent cache directory being created under root / directory in any case.
@@ -90,13 +87,14 @@ TMUX_XPANES_LOG_DIRECTORY="${TMUX_XPANES_LOG_DIRECTORY:-${XP_DEFAULT_TMUX_XPANES
 # Initialize Options
 ## --------------------------------
 # options which work individually.
-readonly XP_FLAG_OPTIONS="[hVdetxs]"
+readonly XP_FLAG_OPTIONS="[hVdetxs]"
 # options which need arguments.
 readonly XP_ARG_OPTIONS="[ISclnCRB]"
 readonly XP_DEFAULT_LAYOUT="tiled"
 readonly XP_DEFAULT_REPSTR="{}"
 readonly XP_DEFAULT_CMD_UTILITY="echo {} "
 readonly XP_SSH_CMD_UTILITY="ssh -o StrictHostKeyChecking=no {} "
+readonly XP_OFS="${XP_OFS:- }"
 XP_OPTIONS=()
 XP_ARGS=()
 XP_STDIN=()
@@ -158,7 +156,7 @@ xpns_msg_warning() {
 }
 
 xpns_msg_debug() {
-  if [[ $XP_OPT_DEBUG -eq 1 ]];then
+  if [[ $XP_OPT_DEBUG -eq 1 ]]; then
     xpns_msg "Debug" "$(date "+[%F_%T]"):${FUNCNAME[1]}:$1"
   fi
 }
@@ -180,7 +178,7 @@ _EOS_
 }
 
 xpns_usage() {
-  cat <<USAGE
+  cat << USAGE
 Usage:
   ${XP_THIS_FILE_NAME} [OPTIONS] [argument ...]
 
@@ -216,7 +214,7 @@ OPTIONS:
   --bulk-cols=NUM1[,NUM2 ...]  Set number of columns on multiple rows (i.e, "2,2,2" represents 2 cols x 3 rows).
   --debug                      Print debug message.
 
-Copyright (c) 2019 Yamada, Yasuhiro
+Copyright (c) 2021 Yamada, Yasuhiro
 Released under the MIT License.
 https://github.com/greymd/tmux-xpanes
 USAGE
@@ -234,9 +232,12 @@ xpns_get_tmux_version() {
     # From tmux 0.9 to 1.3, there is no -V option.
     _tmux_version="tmux 0.9-1.3"
   else
-    _tmux_version="$( ${TMUX_XPANES_EXEC} -V )"
+    _tmux_version="$( ${TMUX_XPANES_EXEC} -V)"
   fi
-  ( read -r _ _ver; echo "${_ver}" ) <<<"${_tmux_version}"
+  read -r _ _ver <<< "${_tmux_version}"
+  # Strip the leading "next-" part that is present in tmux versions that are
+  # in development. Eg: next-3.3
+  echo "${_ver//next-/}"
 }
 
 # Check whether the prefered tmux version is greater than host's tmux version.
@@ -256,7 +257,7 @@ xpns_tmux_is_greater_equals() {
   local _check_version="$1"
   local _tmux_version="${2:-$(xpns_get_tmux_version)}"
   # Simple numerical comparison does not work because there is the version like "1.9a".
-  if [[ "$( (echo "${_tmux_version}"; echo "${_check_version}") | sort -n | head -n 1)" != "${_check_version}" ]];then
+  if [[ "$( printf "%s\\n%s" "${_tmux_version}" "${_check_version}" | sort -n | head -n 1)" != "${_check_version}" ]]; then
     return 1
   else
     return 0
@@ -267,38 +268,44 @@ xpns_get_local_tmux_conf() {
   local _conf_name="$1"
   local _session="${2-}"
   {
-    if [[ -z "${_session-}" ]];then
+    if [[ -z "${_session-}" ]]; then
       ${TMUX_XPANES_EXEC} show-window-options
     else
       ${TMUX_XPANES_EXEC} -S "${_session}" show-window-options
     fi
-  } | grep "^${_conf_name}" \
-    | ( read -r _ _v; printf "%s\\n" "${_v}" )
+  } | grep "^${_conf_name}" |
+    {
+      read -r _ _v
+      printf "%s\\n" "${_v}"
+    }
 }
 
 xpns_get_global_tmux_conf() {
   local _conf_name="$1"
   local _session="${2-}"
   {
-    if [[ -z "${_session-}" ]];then
+    if [[ -z "${_session-}" ]]; then
       ${TMUX_XPANES_EXEC} show-window-options -g
     else
       ${TMUX_XPANES_EXEC} -S "${_session}" show-window-options -g
     fi
-  } | grep "^${_conf_name}" \
-    | ( read -r _ _v; printf "%s\\n" "${_v}" )
+  } | grep "^${_conf_name}" |
+    {
+      read -r _ _v
+      printf "%s\\n" "${_v}"
+    }
 }
 
 # Disable allow-rename because
 # window separation does not work correctly
 # if "allow-rename" option is on
-xpns_suppress_allow_rename () {
+xpns_suppress_allow_rename()  {
   local _default_allow_rename="$1"
   local _session="${2-}"
   if [[ "${_default_allow_rename-}" == "on"  ]]; then
     ## Temporary, disable "allow-rename"
     xpns_msg_debug "'allow-rename' option is 'off' temporarily."
-    if [[ -z "${_session-}" ]];then
+    if [[ -z "${_session-}" ]]; then
       ${TMUX_XPANES_EXEC} set-window-option -g allow-rename off
     else
       ${TMUX_XPANES_EXEC} -S "${_session}" set-window-option -g allow-rename off
@@ -309,12 +316,12 @@ xpns_suppress_allow_rename () {
 # Restore default "allow-rename"
 # Do not write like 'xpns_restore_allow_rename "some value" "some value" > /dev/null'
 # In tmux 1.6, 'tmux set-window-option' might be stopped in case of redirection.
-xpns_restore_allow_rename () {
+xpns_restore_allow_rename()  {
   local _default_allow_rename="$1"
   local _session="${2-}"
   if [[ "${_default_allow_rename-}" == "on"  ]]; then
     xpns_msg_debug "Restore original value of 'allow-rename' option."
-    if [[ -z "${_session-}" ]];then
+    if [[ -z "${_session-}" ]]; then
       ${TMUX_XPANES_EXEC} set-window-option -g allow-rename on
     else
       ${TMUX_XPANES_EXEC} -S "${_session}" set-window-option -g allow-rename on
@@ -325,33 +332,35 @@ xpns_restore_allow_rename () {
 # func "11" "2"
 #  => 6
 # 11 / 2 = 5.5 => ceiling => 6
-xpns_ceiling () {
-  local _divide="$1";shift
+xpns_ceiling()  {
+  local _divide="$1"
+  shift
   local _by="$1"
-  printf "%s\\n" $(( ( _divide + _by - 1 ) / _by ))
+  printf "%s\\n" $(((_divide + _by - 1) / _by))
 }
 
 # func "10" "3"
 #  => 4 3 3
 # Divide 10 into 3 parts as equally as possible.
-xpns_divide_equally () {
-  local _number="$1";shift
+xpns_divide_equally()  {
+  local _number="$1"
+  shift
   local _count="$1"
   local _upper _lower _upper_count _lower_count
   _upper="$(xpns_ceiling "$_number" "$_count")"
-  _lower=$(( _upper - 1 ))
-  _lower_count=$(( _upper * _count - _number ))
-  _upper_count=$(( _count - _lower_count ))
+  _lower=$((_upper - 1))
+  _lower_count=$((_upper * _count - _number))
+  _upper_count=$((_count - _lower_count))
   eval "printf '${_upper} %.0s' {1..$_upper_count}"
-  (( _lower_count > 0 )) && eval "printf '${_lower} %.0s' {1..$_lower_count}"
+  ((_lower_count > 0))   && eval "printf '${_lower} %.0s' {1..$_lower_count}"
 }
 
 # echo 3 3 3 3 | func
 # => 3 6 9 12
-xpns_nums_accumulate_sum () {
+xpns_nums_accumulate_sum()  {
   local s=0
   while read -r n; do
-    ((s = s + n ))
+    ((s = s + n))
     printf "%s " "$s"
   done < <( cat | tr ' ' '\n')
 }
@@ -371,12 +380,12 @@ xpns_nums_accumulate_sum () {
 # 1 [] [] [] [] => 4 rows
 # 2 [] [] [] [] => 4 rows
 # 3 []          => 1 rows
-xpns_nums_transpose () {
+xpns_nums_transpose()  {
   local _colnum="$1"
   local _spaces=
   local _result=
   xpns_msg_debug "column num = $_colnum, input = $*"
-  _spaces="$(for i in "$@";do
+  _spaces="$(for i in "$@"; do
     printf "%${i}s\\n"
   done)"
 
@@ -386,7 +395,7 @@ xpns_nums_transpose () {
     ## $ echo 1234 | cut -c 5
     ## => result is supposed to be empty
     printf "%s\\n" "$_spaces" | cut -c "$i" | grep -c ' '
-  done < <(xpns_seq 1 "${_colnum}") | xargs)"
+  done < <(xpns_seq 1 "${_colnum}") | xpns_newline2space)"
   xpns_msg_debug "result = $_result"
   printf "%s\\n" "$_result"
 }
@@ -399,33 +408,36 @@ xpns_nums_transpose () {
 #     func "6" 0 20
 #       => returns 6 4
 xpns_adjust_col_row() {
-  local col="${1:-0}" ;shift
-  local row="${1:-0}" ;shift
-  local N="$1"   ;shift
+  local col="${1:-0}"
+  shift
+  local row="${1:-0}"
+  shift
+  local N="$1"
+  shift
   local fix_col_flg
   local fix_row_flg
-  (( col != 0 )) && fix_col_flg=1 || fix_col_flg=0
-  (( row != 0 )) && fix_row_flg=1 || fix_row_flg=0
+  ((col != 0))   && fix_col_flg=1 || fix_col_flg=0
+  ((row != 0))   && fix_row_flg=1 || fix_row_flg=0
 
   # This is just a author (@greymd)'s preference.
-  if (( fix_col_flg == 0 )) && (( fix_row_flg == 0 )) && (( N == 2)) ;then
+  if ((fix_col_flg == 0))   && ((fix_row_flg == 0))   && ((N == 2)); then
     col=2
     row=1
     printf "%d %d\\n" "${col}" "${row}"
     return
   fi
 
-  # If both valures are provided, col is used.
-  if (( fix_col_flg == 1 )) && (( fix_row_flg == 1 ));then
+  # If both values are provided, col is used.
+  if ((fix_col_flg == 1))   && ((fix_row_flg == 1)); then
     row=0
     fix_row_flg=0
   fi
   # This algorhythm is almost same as tmux default
   #   https://github.com/tmux/tmux/blob/2.8/layout-set.c#L436
-  while (( col * row < N )) ;do
-    (( fix_row_flg != 1 )) && (( row = row + 1 ))
-    if (( col * row < N ));then
-      (( fix_col_flg != 1 )) &&  (( col = col + 1 ))
+  while ((col * row < N)); do
+    ((fix_row_flg != 1))   && ((row = row + 1))
+    if ((col * row < N)); then
+      ((fix_col_flg != 1))   &&  ((col = col + 1))
     fi
   done
   printf "%d %d\\n" "${col}" "${row}"
@@ -441,7 +453,7 @@ xpns_adjust_col_row() {
 #  ccc-3
 #
 # Eval is used because associative array is not supported before bash 4.2
-xpns_unique_line () {
+xpns_unique_line()  {
   local _val_name
   while read -r line; do
     _val_name="__xpns_hash_$(printf "%s" "${line}" | xpns_value2key)"
@@ -468,19 +480,17 @@ xpns_unique_line () {
 #        ccc-2_1234_20160101.log
 #        ccc-3_1234_20160101.log
 #
-xpns_log_filenames () {
+xpns_log_filenames()  {
   local _arg_fmt="$1"
   local _full_fmt=
   _full_fmt="$(date "+${_arg_fmt}")"
-  cat \
-    | \
+  cat |
     # 1st argument + '-' + unique number (avoid same argument has same name)
-    xpns_unique_line \
-    | while read -r _arg
-    do
-      cat <<<"${_full_fmt}" \
-        | sed "s/\\[:ARG:\\]/${_arg}/g" \
-        | sed "s/\\[:PID:\\]/$$/g"
+    xpns_unique_line |
+    while   read -r _arg; do
+      cat <<< "${_full_fmt}" |
+        sed   "s/\\[:ARG:\\]/${_arg}/g" |
+        sed   "s/\\[:PID:\\]/$$/g"
     done
 }
 
@@ -547,18 +557,15 @@ xpns_arr2args() {
   if [[ $# -lt 1 ]]; then
     return 0
   fi
-  for i in "$@" ;do
+  for i in "$@"do
     _arg="${i}"
     # Use 'cat <<<"input"' command instead of 'echo',
     # because such the command recognizes option like '-e'.
-    cat <<<"${_arg}" \
-      | \
+    cat <<< "${_arg}" |
       # Escaping single quotations.
-      sed "s/'/'\"'\"'/g" \
-      | \
+      sed "s/'/'\"'\"'/g" |
       # Surround argument with single quotations.
-      sed "s/^/'/;s/$/' /" \
-      | \
+      sed "s/^/'/;s/$/' /" |
       # Remove new lines
       tr -d '\n'
   done
@@ -568,14 +575,16 @@ xpns_arr2args() {
 # ex, $2     =  'aaa bbb ccc'
 #   return   =  aaa-12345(PID)
 xpns_generate_window_name() {
-  local _unprintable_str="${1-}"; shift
+  local _unprintable_str="${1-}"
+  shift
   # Leave first 200 characters to prevent
   # the name exceed the maximum length of tmux window name (2000 byte).
-  printf "%s\\n" "${1:-${_unprintable_str}}" \
-    | ( read -r _name _ && printf "%s\\n" "${_name:0:200}-$$" )
+  printf "%s\\n" "${1:-${_unprintable_str}}" |
+    (   read -r _name _ && printf "%s\\n" "${_name:0:200}-$$" )
 }
 
-# Convert string to another string which can be handled as tmux window name.
+# Convert any string (including multi-byte chars) to another string
+# which can be handled as tmux window name.
 xpns_value2key() {
   od -v -tx1 -An  | tr -dc 'a-zA-Z0-9' | tr -d '\n'
 }
@@ -590,7 +599,10 @@ xpns_key2value() {
 # Remove empty lines
 # This function behaves like `awk NF`
 xpns_rm_empty_line() {
-  { cat; printf "\\n";} | while IFS= read -r line;do
+  {
+    cat
+    printf "\\n"
+  } | while IFS= read -r line; do
     # shellcheck disable=SC2086
     set -- ${line-}
     if [[ $# != 0 ]]; then
@@ -599,47 +611,41 @@ xpns_rm_empty_line() {
   done
 }
 
-# Extract matched patterns from string
-# $ xpns_extract_matched "aaa123bbb" "[0-9]{3}"
-# => "123"
-xpns_extract_matched() {
-  local _args="$1" ;shift
-  local _regex="($1)"
-  if [[ $_args =~ $_regex ]];then
-    printf "%s" "${BASH_REMATCH[0]}"
-  fi
-}
-
 # Enable logging feature to the all the panes in the target window.
 xpns_enable_logging() {
-  local _window_name="$1"     ; shift
-  local _index_offset="$1"    ; shift
-  local _log_dir="$1"         ; shift
-  local _log_format="$1"      ; shift
-  local _unprintable_str="$1" ; shift
+  local _window_name="$1"
+  shift
+  local _index_offset="$1"
+  shift
+  local _log_dir="$1"
+  shift
+  local _log_format="$1"
+  shift
+  local _unprintable_str="$1"
+  shift
   local _args=("$@")
   local _args_num=$(($# - 1))
   # Generate log files from arguments.
   local _idx=0
-  while read -r _logfile ; do
+  while read -r _logfile; do
     # Start logging
     xpns_msg_debug "Start logging pipe-pane(cat >> '${_log_dir}/${_logfile}')"
     ${TMUX_XPANES_EXEC} \
-      pipe-pane -t "${_window_name}.$(( _idx + _index_offset ))" \
+      pipe-pane -t "${_window_name}.$((_idx + _index_offset))" \
       "cat >> '${_log_dir}/${_logfile}'" # Tilde expansion does not work here.
-    _idx=$(( _idx + 1 ))
+    _idx=$((_idx + 1))
   done < <(
-  for i in $(xpns_seq 0 "${_args_num}")
-  do
-    # Replace empty string.
-    printf "%s\\n" "${_args[i]:-${_unprintable_str}}"
-  done | xpns_log_filenames "${_log_format}"
+    for i in $(xpns_seq 0 "${_args_num}"); do
+      # Replace empty string.
+      printf "%s\\n" "${_args[i]:-${_unprintable_str}}"
+    done | xpns_log_filenames "${_log_format}"
   )
 }
 
 ## Print "1" on the particular named pipe
 xpns_notify() {
-  local _wait_id="$1" ; shift
+  local _wait_id="$1"
+  shift
   local _fifo=
   _fifo="${XP_CACHE_HOME}/__xpns_${_wait_id}"
   xpns_msg_debug "Notify to $_fifo"
@@ -647,7 +653,8 @@ xpns_notify() {
 }
 
 xpns_notify_logging() {
-  local _window_name="$1" ; shift
+  local _window_name="$1"
+  shift
   local _args_num=$(($# - 1))
   for i in $(xpns_seq 0 "${_args_num}"); do
     xpns_notify "log_${_window_name}-${i}-$$"
@@ -655,7 +662,8 @@ xpns_notify_logging() {
 }
 
 xpns_notify_sync() {
-  local _window_name="$1" ; shift
+  local _window_name="$1"
+  shift
   local _args_num=$(($# - 1))
   for i in $(xpns_seq 0 "${_args_num}"); do
     xpns_notify "sync_${_window_name}-${i}-$$" &
@@ -663,12 +671,15 @@ xpns_notify_sync() {
 }
 
 xpns_is_window_alive() {
-  local _window_name="$1" ;shift
-  local _speedy_await_flag="$1" ;shift
-  local _def_allow_rename="$1" ;shift
-  if ! ${TMUX_XPANES_EXEC} display-message -t "$_window_name" -p > /dev/null 2>&1 ;then
+  local _window_name="$1"
+  shift
+  local _speedy_await_flag="$1"
+  shift
+  local _def_allow_rename="$1"
+  shift
+  if ! ${TMUX_XPANES_EXEC} display-message -t "$_window_name" -p > /dev/null 2>&1; then
     xpns_msg_info "All the panes are closed before displaying the result."
-    if [[ "${_speedy_await_flag}" -eq 0 ]] ;then
+    if [[ "${_speedy_await_flag}" -eq 0 ]]then
       xpns_msg_info "Use '-s' option instead of '-ss' option to avoid this behavior."
     fi
     xpns_restore_allow_rename "${_def_allow_rename-}"
@@ -677,24 +688,28 @@ xpns_is_window_alive() {
 }
 
 xpns_inject_title() {
-  local _target_pane="$1" ;shift
-  local _message="$1"     ;shift
+  local _target_pane="$1"
+  shift
+  local _message="$1"
+  shift
   local _pane_tty=
-  _pane_tty="$( ${TMUX_XPANES_EXEC} display-message -t "${_target_pane}" -p "#{pane_tty}" )"
+  _pane_tty="$( ${TMUX_XPANES_EXEC} display-message -t "${_target_pane}" -p "#{pane_tty}")"
   printf "\\033]2;%s\\033\\\\" "${_message}" > "${_pane_tty}"
   xpns_msg_debug "target_pane=${_target_pane} pane_title=${_message} pane_tty=${_pane_tty}"
 }
 
 xpns_is_pane_title_required() {
-  local _title_flag="$1"   ; shift
-  local _extra_flag="$1"   ; shift
+  local _title_flag="$1"
+  shift
+  local _extra_flag="$1"
+  shift
   local _pane_border_status=
   _pane_border_status=$(xpns_get_local_tmux_conf "pane-border-status")
   if [[ $_title_flag -eq 1 ]]; then
     return 0
-  elif [[ ${_extra_flag} -eq 1 ]] && \
-       [[ "${_pane_border_status}" != "off" ]] && \
-       [[ -n "${_pane_border_status}" ]] ;then
+  elif [[ ${_extra_flag} -eq 1 ]] &&
+    [[ "${_pane_border_status}" != "off"    ]] &&
+    [[ -n "${_pane_border_status}"    ]]; then
     ## For -x option
     # Even the -t option is not specified, it is required to inject pane title here.
     # Because user expects the title is displayed on the pane if the original window is
@@ -706,39 +721,44 @@ xpns_is_pane_title_required() {
 
 # Set pane titles for each pane for -t option
 xpns_set_titles() {
-  local _window_name="$1"  ; shift
-  local _index_offset="$1" ; shift
+  local _window_name="$1"
+  shift
+  local _index_offset="$1"
+  shift
   local _index=0
   local _pane_index=
-  for arg in "$@"
-  do
-    _pane_index=$(( _index + _index_offset ))
+  for arg in "$@"; do
+    _pane_index=$((_index + _index_offset))
     xpns_inject_title "${_window_name}.${_pane_index}" "${arg}"
-    _index=$(( _index + 1 ))
+    _index=$((_index + 1))
   done
 }
 
 # Send command to the all the panes in the target window.
 xpns_send_commands() {
-  local _window_name="$1"  ; shift
-  local _index_offset="$1" ; shift
-  local _repstr="$1"       ; shift
-  local _cmd="$1"          ; shift
+  local _window_name="$1"
+  shift
+  local _index_offset="$1"
+  shift
+  local _repstr="$1"
+  shift
+  local _cmd="$1"
+  shift
   local _index=0
   local _pane_index=
   local _exec_cmd=
-  for arg in "$@"
-  do
+  for arg in "$@"; do
     _exec_cmd="${_cmd//${_repstr}/${arg}}"
-    _pane_index=$(( _index + _index_offset ))
+    _pane_index=$((_index + _index_offset))
     ${TMUX_XPANES_EXEC} send-keys -t "${_window_name}.${_pane_index}" "${_exec_cmd}" C-m
-    _index=$(( _index + 1 ))
+    _index=$((_index + 1))
   done
 }
 
 # Separate window vertically, when the number of panes is 1 or 2.
 xpns_organize_panes() {
-  local _window_name="$1" ; shift
+  local _window_name="$1"
+  shift
   local _args_num="$1"
   ## ----------------
   # Default behavior
@@ -759,14 +779,14 @@ xpns_organize_panes() {
 #
 # Generate sequential number descending order.
 # seq is not used because old version of
-# seq does not generate descending oorder.
+# seq does not generate descending order.
 # $ xpns_seq 3 0
 # 3
 # 2
 # 1
 # 0
 #
-xpns_seq () {
+xpns_seq()  {
   local _num1="$1"
   local _num2="$2"
   eval "printf \"%d\\n\" {$_num1..$_num2}"
@@ -787,21 +807,28 @@ xpns_wait_func() {
 # Split a new window into multiple panes.
 #
 xpns_split_window() {
-  local _window_name="$1"     ; shift
-  local _log_flag="$1"        ; shift
-  local _title_flag="$1"      ; shift
-  local _speedy_flag="$1"     ; shift
-  local _await_flag="$1"      ; shift
-  local _pane_base_index="$1" ; shift
-  local _repstr="$1"          ; shift
-  local _cmd_template="$1"    ; shift
+  local _window_name="$1"
+  shift
+  local _log_flag="$1"
+  shift
+  local _title_flag="$1"
+  shift
+  local _speedy_flag="$1"
+  shift
+  local _await_flag="$1"
+  shift
+  local _pane_base_index="$1"
+  shift
+  local _repstr="$1"
+  shift
+  local _cmd_template="$1"
+  shift
   local _exec_cmd=
   local _sep_count=0
   local args=("$@")
-  _last_idx=$(( ${#args[@]} - 1 ))
+  _last_idx=$((${#args[@]} - 1))
 
-  for i in $(xpns_seq $_last_idx 0)
-  do
+  for i in $(xpns_seq $_last_idx 0); do
     xpns_msg_debug "Index:${i} Argument:${args[i]}"
     _sep_count=$((_sep_count + 1))
     _exec_cmd="${_cmd_template//${_repstr}/${args[i]}}"
@@ -825,17 +852,23 @@ xpns_split_window() {
 }
 
 #
-# Create new panes to the  existing window.
+# Create new panes on existing window.
 # Usage:
 #    func <window name> <offset of index> <number of pane>
 #
 xpns_prepare_extra_panes() {
-  local _window_name="$1"     ; shift
-  local _pane_base_index="$1" ; shift
-  local _log_flag="$1"        ; shift
-  local _title_flag="$1"      ; shift
-  local _speedy_flg="$1"      ; shift
-  local _await_flg="$1"       ; shift
+  local _window_name="$1"
+  shift
+  local _pane_base_index="$1"
+  shift
+  local _log_flag="$1"
+  shift
+  local _title_flag="$1"
+  shift
+  local _speedy_flg="$1"
+  shift
+  local _await_flg="$1"
+  shift
   # specify a pane which has the biggest index number.
   #   Because pane_id may not be immutable.
   #   If the small number of index is specified here, correspondance between pane_title and command can be slip off.
@@ -852,7 +885,7 @@ xpns_prepare_extra_panes() {
     "$@"
 }
 
-xpns_get_joined_begin_commands () {
+xpns_get_joined_begin_commands()  {
   local _commands="$1"
   if [[ "${#XP_BEGIN_ARGS[*]}" -lt 1 ]]; then
     printf "%s" "${_commands}"
@@ -861,13 +894,19 @@ xpns_get_joined_begin_commands () {
   printf "%s\\n" "${XP_BEGIN_ARGS[@]}" "${_commands}"
 }
 
-xpns_inject_wait_command () {
-  local _log_flag="$1"    ; shift
-  local _title_flag="$1"  ; shift
-  local _speedy_flg="$1"  ; shift
-  local _await_flg="$1"   ; shift
-  local _idx="$1"         ; shift
-  local _exec_cmd="$1"    ; shift
+xpns_inject_wait_command()  {
+  local _log_flag="$1"
+  shift
+  local _title_flag="$1"
+  shift
+  local _speedy_flg="$1"
+  shift
+  local _await_flg="$1"
+  shift
+  local _idx="$1"
+  shift
+  local _exec_cmd="$1"
+  shift
 
   ## Speedy mode + logging
   if [[ "${_log_flag}" -eq 1 ]] && [[ "${_speedy_flg}" -eq 1 ]]; then
@@ -891,11 +930,15 @@ xpns_inject_wait_command () {
   printf "%s" "${_exec_cmd}"
 }
 
-xpns_new_window () {
-  local _window_name="$1" ; shift
-  local _attach_flg="$1"  ; shift
-  local _speedy_flg="$1"  ; shift
-  local _exec_cmd="$1"    ; shift
+xpns_new_window()  {
+  local _window_name="$1"
+  shift
+  local _attach_flg="$1"
+  shift
+  local _speedy_flg="$1"
+  shift
+  local _exec_cmd="$1"
+  shift
   local _window_id=
 
   # Create new window.
@@ -903,7 +946,7 @@ xpns_new_window () {
     if [[ "${_speedy_flg}" -eq 1 ]]; then
       _window_id=$(${TMUX_XPANES_EXEC} new-window -n "${_window_name}" -F '#{window_id}' -P "${_exec_cmd}")
     else
-      _window_id=$(${TMUX_XPANES_EXEC} new-window -n "${_window_name}" -F '#{window_id}' -P )
+      _window_id=$(${TMUX_XPANES_EXEC} new-window -n "${_window_name}" -F '#{window_id}' -P)
     fi
   else
     # Keep background
@@ -916,11 +959,15 @@ xpns_new_window () {
   printf "%s" "${_window_id}"
 }
 
-xpns_new_pane_vertical () {
-  local _window_id="$1"   ; shift
-  local _cell_height="$1" ; shift
-  local _speedy_flg="$1"  ; shift
-  local _exec_cmd="$1"    ; shift
+xpns_new_pane_vertical()  {
+  local _window_id="$1"
+  shift
+  local _cell_height="$1"
+  shift
+  local _speedy_flg="$1"
+  shift
+  local _exec_cmd="$1"
+  shift
   local _pane_id=
   if [[ "${_speedy_flg}" -eq 1 ]]; then
     _pane_id="$(${TMUX_XPANES_EXEC} split-window -t "$_window_id" -v -d -l "${_cell_height}" -F '#{pane_id}' -P "${_exec_cmd}")"
@@ -930,11 +977,15 @@ xpns_new_pane_vertical () {
   printf "%s\\n" "${_pane_id}"
 }
 
-xpns_split_pane_horizontal () {
-  local _target_pane_id="$1" ; shift
-  local _cell_width="$1"     ; shift
-  local _speedy_flg="$1"     ; shift
-  local _exec_cmd="$1"       ; shift
+xpns_split_pane_horizontal()  {
+  local _target_pane_id="$1"
+  shift
+  local _cell_width="$1"
+  shift
+  local _speedy_flg="$1"
+  shift
+  local _exec_cmd="$1"
+  shift
   if [[ "${_speedy_flg}" -eq 1 ]]; then
     ${TMUX_XPANES_EXEC} split-window -t "$_target_pane_id" -h -d -l "$_cell_width" "${_exec_cmd}"
   else
@@ -942,15 +993,23 @@ xpns_split_pane_horizontal () {
   fi
 }
 
-xpns_prepare_window () {
-  local _window_name="$1"     ; shift
-  local _log_flag="$1"        ; shift
-  local _title_flag="$1"      ; shift
-  local _attach_flg="$1"      ; shift
-  local _speedy_flg="$1"      ; shift
-  local _await_flg="$1"       ; shift
-  local _repstr="$1"          ; shift
-  local _cmd_template="$1"    ; shift
+xpns_prepare_window()  {
+  local _window_name="$1"
+  shift
+  local _log_flag="$1"
+  shift
+  local _title_flag="$1"
+  shift
+  local _attach_flg="$1"
+  shift
+  local _speedy_flg="$1"
+  shift
+  local _await_flg="$1"
+  shift
+  local _repstr="$1"
+  shift
+  local _cmd_template="$1"
+  shift
   local _args=("$@")
   local _window_height="$XP_WINDOW_HEIGHT"
   local _window_width="$XP_WINDOW_WIDTH"
@@ -972,7 +1031,7 @@ xpns_prepare_window () {
   local _rest_row=
   local _offset=
 
-  _cell_height=$(( ( _window_height - _row + 1 ) / _row ))
+  _cell_height=$(((_window_height - _row + 1) / _row))
   ## Insert first element
   _exec_cmd="${_cmd_template//${_repstr}/${_args[0]}}"
   _exec_cmd="$(xpns_inject_wait_command "${_log_flag}" "${_title_flag}" "${_speedy_flg}" "${_await_flg}" 0 "${_exec_cmd}")"
@@ -980,14 +1039,14 @@ xpns_prepare_window () {
   _first_pane_id=$(${TMUX_XPANES_EXEC} display-message -t "$_window_id" -p -F '#{pane_id}' | head -n 1)
 
   ## Start from last row
-  for (( i = _row - 1 ; i > 0 ; i-- ));do
+  for ((i = _row - 1; i > 0; i--)); do
     _col="${_cols[i]}"
-    _cell_width=$(( ( _window_width - _col + 1 ) / _col ))
+    _cell_width=$(((_window_width - _col + 1) / _col))
     xpns_msg_debug "_col=$_col"
-    (( _offset = _cols_offset[i] ))
-    for (( j = 0 ; j < _col ; j++ ));do
-      if (( j == 0 )) ;then
-        (( idx = _offset - _col ))
+    ((_offset = _cols_offset[i]))
+    for ((j = 0; j < _col; j++)); do
+      if ((j == 0)); then
+        ((idx = _offset - _col))
         # Create new row
         # Insert first element of the row first
         _exec_cmd="${_cmd_template//${_repstr}/${_args[idx]}}"
@@ -995,34 +1054,34 @@ xpns_prepare_window () {
         _pane_id=$(xpns_new_pane_vertical "${_window_name}" "${_cell_height}" "${_speedy_flg}" "${_exec_cmd}")
       fi
       # Separate row into columns
-      if (( j != 0 )) ;then
-        (( idx = _offset - j ))
+      if ((j != 0)); then
+        ((idx = _offset - j))
         _exec_cmd="${_cmd_template//${_repstr}/${_args[idx]}}"
         _exec_cmd="$(xpns_inject_wait_command "${_log_flag}" "${_title_flag}" "${_speedy_flg}" "${_await_flg}" "${idx}" "${_exec_cmd}")"
         ## Separate row into columns
         _current_pane_width=$(${TMUX_XPANES_EXEC} display-message -t "$_pane_id" -p '#{pane_width}' | head -n 1)
-        _rest_col=$(( _col - j + 1 ))
-        _cell_width=$(( ( _current_pane_width - _rest_col + 1 ) / _rest_col ))
+        _rest_col=$((_col - j + 1))
+        _cell_width=$(((_current_pane_width - _rest_col + 1) / _rest_col))
         xpns_split_pane_horizontal "$_pane_id" "$_cell_width" "${_speedy_flg}" "${_exec_cmd}"
       fi
     done
 
     # Adjust height
     _top_pane_height=$(${TMUX_XPANES_EXEC} display-message -t "$_window_id" -p '#{pane_height}' | head -n 1)
-    _rest_row=$(( i ))
+    _rest_row=$((i))
     xpns_msg_debug "_top_pane_height=$_top_pane_height _rest_row=$_rest_row"
-    _cell_height=$(( ( _top_pane_height - _rest_row + 1 ) / _rest_row ))
+    _cell_height=$(((_top_pane_height - _rest_row + 1) / _rest_row))
   done
 
   # Split first row into columns
   _col="${_cols[0]}"
-  _cell_width=$(( ( _window_width - _col + 1 ) / _col ))
-  for (( j = 1 ; j < _col ; j++ ));do
-    idx=$(( _cols_offset[0] - j ))
+  _cell_width=$(((_window_width - _col + 1) / _col))
+  for ((j = 1; j < _col; j++)); do
+    idx=$((_cols_offset[0] - j))
     # Adjust width
     _current_pane_width=$(${TMUX_XPANES_EXEC} display-message -t "$_first_pane_id" -p '#{pane_width}' | head -n 1)
-    _rest_col=$(( _col - j + 1 ))
-    _cell_width=$(( ( _current_pane_width - _rest_col + 1 ) / _rest_col ))
+    _rest_col=$((_col - j + 1))
+    _cell_width=$(((_current_pane_width - _rest_col + 1) / _rest_col))
     ## Split top row into columns
     _exec_cmd="${_cmd_template//${_repstr}/${_args[idx]}}"
     _exec_cmd="$(xpns_inject_wait_command "${_log_flag}" "${_title_flag}" "${_speedy_flg}" "${_await_flg}" "${idx}" "${_exec_cmd}")"
@@ -1036,21 +1095,21 @@ xpns_is_session_running() {
 }
 
 # Remove unnecessary session files as much as possible
-# to let xpanes avoids to load old .tmux.conf.
+# to make xpanes avoid loading old .tmux.conf.
 xpns_clean_session() {
   if [[ "${XP_SOCKET_PATH}" != "${XP_DEFAULT_SOCKET_PATH}" ]]; then
     return
   fi
   # Delete old socket file (xpanes v3.1.0 or before).
   if [[ -e "${XP_DEFAULT_SOCKET_PATH_BASE}" ]]; then
-    if ! xpns_is_session_running "${XP_DEFAULT_SOCKET_PATH_BASE}" ;then
+    if ! xpns_is_session_running "${XP_DEFAULT_SOCKET_PATH_BASE}"then
       xpns_msg_debug "socket(${XP_DEFAULT_SOCKET_PATH_BASE}) is not running. Remove it"
       rm -f "${XP_DEFAULT_SOCKET_PATH_BASE}"
     fi
   fi
-  for _socket in "${XP_CACHE_HOME}"/socket.* ;do
+  for _socket in "${XP_CACHE_HOME}"/socket.*do
     xpns_msg_debug "file = ${_socket}"
-    if ! xpns_is_session_running "${_socket}" ;then
+    if ! xpns_is_session_running "${_socket}"then
       xpns_msg_debug "socket(${_socket}) is not running. Remove it"
       rm -f "${_socket}"
     else
@@ -1060,18 +1119,25 @@ xpns_clean_session() {
 }
 
 #
-# Split a new window which was created by tmux into multiple panes.
+# Split a new window into multiple panes.
 # Usage:
 #    xpns_prepare_preset_layout_window <window name> <offset of index> <number of pane> <attach or not>
 #
 xpns_prepare_preset_layout_window() {
-  local _window_name="$1"     ; shift
-  local _pane_base_index="$1" ; shift
-  local _log_flag="$1"        ; shift
-  local _title_flag="$1"      ; shift
-  local _attach_flg="$1"      ; shift
-  local _speedy_flg="$1"      ; shift
-  local _await_flg="$1"       ; shift
+  local _window_name="$1"
+  shift
+  local _pane_base_index="$1"
+  shift
+  local _log_flag="$1"
+  shift
+  local _title_flag="$1"
+  shift
+  local _attach_flg="$1"
+  shift
+  local _speedy_flg="$1"
+  shift
+  local _await_flg="$1"
+  shift
   # Create new window.
   if [[ "${_attach_flg}" -eq 1 ]]; then
     ${TMUX_XPANES_EXEC} new-window -n "${_window_name}"
@@ -1107,7 +1173,7 @@ xpns_prepare_preset_layout_window() {
 # Check whether given command is in the PATH or not.
 xpns_check_env() {
   local _cmds="$1"
-  while read -r cmd ; do
+  while read -r cmd; do
     if ! type "${cmd}" > /dev/null 2>&1; then
       if [[ "${cmd}" == "tmux" ]] && [[ "${TMUX_XPANES_EXEC}" == "tmux" ]]; then
         xpns_msg_error "${cmd} is required. Install ${cmd} or set TMUX_XPANES_EXEC variable."
@@ -1119,7 +1185,7 @@ xpns_check_env() {
     fi
   done < <(echo "${_cmds}" | tr ' ' '\n')
 
-  if ! mkdir -p "${XP_CACHE_HOME}";then
+  if ! mkdir -p "${XP_CACHE_HOME}"; then
     xpns_msg_warning "failed to create cache directory '${XP_CACHE_HOME}'."
   fi
 
@@ -1127,11 +1193,11 @@ xpns_check_env() {
   TMUX_XPANES_TMUX_VERSION="${TMUX_XPANES_TMUX_VERSION:-$(xpns_get_tmux_version)}"
   if ( xpns_tmux_is_greater_equals \
     "${XP_SUPPORT_TMUX_VERSION_LOWER}" \
-    "${TMUX_XPANES_TMUX_VERSION}" ) ;then
+    "${TMUX_XPANES_TMUX_VERSION}" )then
     : "Supported tmux version"
   else
     xpns_msg_warning \
-"'${XP_THIS_FILE_NAME}' may not work correctly! Please check followings.
+      "'${XP_THIS_FILE_NAME}' may not work correctly! Please check followings.
 * tmux is installed correctly.
 * Supported tmux version is installed.
   Version ${XP_SUPPORT_TMUX_VERSION_LOWER} and over is officially supported."
@@ -1149,13 +1215,48 @@ xpns_pipe_filter() {
   fi
 }
 
-xpns_set_args_per_pane() {
-  local _pane_num="$1"; shift
+# Merge array's element by combining with space.
+#   i.e
+#   array=(1 2 3 4 5)
+#   func 3 "array"
+#   => array is going to be ("1 2 3" "4 5")
+xpns_merge_array_elements() {
+  local _line=""
+  local _pane_num="$1"
+  shift
+  local _arr_name="$1"
+  shift
   local _filtered_args=()
-  while read -r _line; do
+  eval 'set -- "${'"$_arr_name"'[@]}"'
+  local _num="$#"
+  for ((i = 1; i <= _num; i++)); do
+    if [[ -z "$_line" ]]; then
+      _line="$1"
+    else
+      _line="${_line}${XP_OFS}$1"
+    fi
+    shift
+    if ((i % _pane_num == 0)); then
+      _filtered_args+=("${_line}")
+      _line=""
+    fi
+  done
+  if [[ -n "$_line" ]]; then
     _filtered_args+=("${_line}")
-  done < <(xargs -n "${_pane_num}" <<<"$(xpns_arr2args "${XP_ARGS[@]}")")
-  XP_ARGS=("${_filtered_args[@]}")
+  fi
+  eval "$_arr_name"'=("${_filtered_args[@]}")'
+}
+
+xpns_newline2space() {
+  local _result=""
+  while read -r _line; do
+    if [[ -z "$_result" ]]; then
+      _result="$_line"
+    else
+      _result="${_result}${XP_OFS}${_line}"
+    fi
+  done
+  printf "%s\\n" "${_result}"
 }
 
 xpns_get_window_height_width() {
@@ -1177,7 +1278,7 @@ xpns_get_window_height_width() {
     fi
   fi
   if [[ $XP_IS_PIPE_MODE -eq 0 ]]; then
-    if _result=$(stty size 2> /dev/null) && [[ "$_result" =~ $_pattern ]];then
+    if _result=$(stty size 2> /dev/null) && [[ "$_result" =~ $_pattern ]]; then
       _height="${BASH_REMATCH[1]}"
       _width="${BASH_REMATCH[2]}"
       xpns_msg_debug "window height: $_height, width: $_width"
@@ -1185,13 +1286,16 @@ xpns_get_window_height_width() {
       return 0
     fi
   else
-    if ! type ps > /dev/null 2>&1 ;then
+    if ! type ps > /dev/null 2>&1then
       xpns_msg_debug "'ps' does not exist: Failed to get window height and size. Skip checking"
       return 1
     fi
-    { read -r; read -r _dev; } < <(ps -o tty -p $$)
+    {
+      read -r       # Remove first line
+      read -r _dev
+    } < <(ps -o tty -p $$ 2> /dev/null)
     ## If it's Linux, -F option is used
-    if _result=$(stty -F "/dev/${_dev}" size 2> /dev/null) && [[ "$_result" =~ $_pattern ]];then
+    if _result=$(stty -F "/dev/${_dev}" size 2> /dev/null) && [[ "$_result" =~ $_pattern ]]; then
       _height="${BASH_REMATCH[1]}"
       _width="${BASH_REMATCH[2]}"
       xpns_msg_debug "window height: $_height, width: $_width"
@@ -1199,7 +1303,7 @@ xpns_get_window_height_width() {
       return 0
     fi
     ## If it's BSD, macOS, -F option is used
-    if _result=$(stty -f "/dev/${_dev}" size 2> /dev/null) && [[ "$_result" =~ $_pattern ]];then
+    if _result=$(stty -f "/dev/${_dev}" size 2> /dev/null) && [[ "$_result" =~ $_pattern ]]; then
       _height="${BASH_REMATCH[1]}"
       _width="${BASH_REMATCH[2]}"
       xpns_msg_debug "window height: $_height, width: $_width"
@@ -1212,11 +1316,16 @@ xpns_get_window_height_width() {
 }
 
 xpns_check_cell_size_bulk() {
-  local _cell_num="$1"    ; shift
-  local _bulk_cols="$1"   ; shift
-  local _win_height="$1"  ; shift
-  local _win_width="$1"   ; shift
-  local _ignore_flag="$1" ; shift
+  local _cell_num="$1"
+  shift
+  local _bulk_cols="$1"
+  shift
+  local _win_height="$1"
+  shift
+  local _win_width="$1"
+  shift
+  local _ignore_flag="$1"
+  shift
   local _all_cols=()
   # shellcheck disable=SC2178
   local _cols=0
@@ -1225,16 +1334,16 @@ xpns_check_cell_size_bulk() {
   IFS="," read -r -a _all_cols <<< "${_bulk_cols}"
   _rows="${#_all_cols[@]}"
   for i in "${_all_cols[@]}"; do
-    (( i >= _cols )) && (( _cols = i ))
-    (( _sum_cell = _sum_cell + i ))
+    ((i >= _cols))   && ((_cols = i))
+    ((_sum_cell = _sum_cell + i))
   done
-  if (( _sum_cell != _cell_num )) ;then
+  if ((_sum_cell != _cell_num)); then
     xpns_msg_error "Number of cols does not equals to the number of arguments."
     xpns_msg_error "Expected (# of args) : $_cell_num, Actual (--bulk-cols) : $_sum_cell)."
     return ${XP_ELAYOUT:-6}
   fi
-  local cell_height=$(( ( _win_height - _rows + 1 ) / _rows ))
-  local cell_width=$(( ( _win_width - _cols + 1 ) / _cols ))
+  local cell_height=$(((_win_height - _rows + 1) / _rows))
+  local cell_width=$(((_win_width - _cols + 1) / _cols))
 
   ## Display basic information
   xpns_msg_debug "Window: { Height: $_win_height, Width: $_win_width }"
@@ -1245,7 +1354,7 @@ xpns_check_cell_size_bulk() {
   xpns_msg_debug "    Col[]| ${_all_cols[*]}"
   xpns_msg_debug "    -----+------------------------..."
 
-  if [[ "$_ignore_flag" -ne 1 ]] && ( (( cell_height < 2 )) || (( cell_width < 2 )) ); then
+  if [[ "$_ignore_flag" -ne 1 ]] && ( ((cell_height < 2))   || ((cell_width < 2))   ); then
     xpns_msg_error "Expected pane size is too small (height: $cell_height lines, width: $cell_width chars)"
     return ${XP_ESMLPANE:-7}
   fi
@@ -1253,26 +1362,32 @@ xpns_check_cell_size_bulk() {
 }
 
 xpns_check_cell_size() {
-  local _cell_num="$1"    ; shift
-  local _cols="$1"        ; shift
-  local _rows="$1"        ; shift
-  local _win_height="$1"  ; shift
-  local _win_width="$1"   ; shift
-  local _ignore_flag="$1" ; shift
+  local _cell_num="$1"
+  shift
+  local _cols="$1"
+  shift
+  local _rows="$1"
+  shift
+  local _win_height="$1"
+  shift
+  local _win_width="$1"
+  shift
+  local _ignore_flag="$1"
+  shift
   local _all_cols_num=
   local _all_rows=()
 
-  if [[ -n "${_cols-}" ]] && [[ -n "${_rows-}" ]];then
+  if [[ -n "${_cols-}" ]] && [[ -n "${_rows-}" ]]; then
     xpns_msg_warning "Both col size and row size are provided. Col size is preferentially going to be applied."
   fi
   ## if col is only defined
-  if [[ -n "${_cols-}" ]] ;then
+  if [[ -n "${_cols-}" ]]then
     read -r _cols _rows < <(xpns_adjust_col_row "${_cols-}" 0 "${_cell_num}")
     IFS=" " read -r -a _all_rows <<< "$(xpns_divide_equally "${_cell_num}" "${_cols}")"
     _all_cols_num="$(xpns_nums_transpose "${_all_rows[@]}")"
 
   ## if row is only defined
-  elif [[ -n "${_rows-}" ]] ;then
+  elif [[ -n "${_rows-}" ]]then
     read -r _cols _rows < <(xpns_adjust_col_row 0 "${_rows-}" "${_cell_num}")
     _all_cols_num="$(xpns_divide_equally "${_cell_num}" "${_rows}")"
 
@@ -1282,8 +1397,8 @@ xpns_check_cell_size() {
     _all_cols_num="$(xpns_divide_equally "${_cell_num}" "${_rows}")"
   fi
 
-  local cell_height=$(( ( _win_height - _rows + 1 ) / _rows ))
-  local cell_width=$(( ( _win_width - _cols + 1 ) / _cols ))
+  local cell_height=$(((_win_height - _rows + 1) / _rows))
+  local cell_width=$(((_win_width - _cols + 1) / _cols))
 
   ## Display basic information
   xpns_msg_debug "Window: { Height: $_win_height, Width: $_win_width }"
@@ -1294,7 +1409,7 @@ xpns_check_cell_size() {
   xpns_msg_debug "    Col[]| ${_all_cols_num}"
   xpns_msg_debug "    -----+------------------------..."
 
-  if [[ "$_ignore_flag" -ne 1 ]] && ( (( cell_height < 2 )) || (( cell_width < 2 )) ); then
+  if [[ "$_ignore_flag" -ne 1 ]] && ( ((cell_height < 2))   || ((cell_width < 2))   ); then
     xpns_msg_error "Expected pane size is too small (height: $cell_height lines, width: $cell_width chars)"
     return "${XP_ESMLPANE:-7}"
   fi
@@ -1306,7 +1421,7 @@ xpns_pre_execution() {
   local _opts4args=""
   local _args4args=""
 
-  if [[ ${XP_OPT_EXTRA} -eq 1 ]];then
+  if [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
     xpns_msg_error "'-x' must be used within the running tmux session."
     exit ${XP_EINVAL}
   fi
@@ -1316,8 +1431,8 @@ xpns_pre_execution() {
   IFS=" " read -r XP_WINDOW_HEIGHT XP_WINDOW_WIDTH < <(xpns_get_window_height_width) && {
     local _arg_num="${#XP_ARGS[@]}"
     local _cell_num _tmp_col_row_cols _tmp_cols
-    if [[ -n "$XP_MAX_PANE_ARGS" ]] && (( XP_MAX_PANE_ARGS > 1 ));then
-      _cell_num=$(( _arg_num / XP_MAX_PANE_ARGS ))
+    if [[ -n "$XP_MAX_PANE_ARGS" ]] && ((XP_MAX_PANE_ARGS > 1)); then
+      _cell_num=$((_arg_num / XP_MAX_PANE_ARGS))
     else
       _cell_num="${_arg_num}"
     fi
@@ -1372,13 +1487,13 @@ xpns_pre_execution() {
 
   # Avoid attaching (for unit testing).
   if [[ ${XP_OPT_ATTACH} -eq 1 ]]; then
-    if ! ${TMUX_XPANES_EXEC} -S "${XP_SOCKET_PATH}" attach-session -t "${XP_SESSION_NAME}" \
-      && [[ ${XP_IS_PIPE_MODE} -eq 1 ]]; then
+    if ! ${TMUX_XPANES_EXEC} -S "${XP_SOCKET_PATH}" attach-session -t "${XP_SESSION_NAME}" &&
+      [[ ${XP_IS_PIPE_MODE} -eq 1    ]]; then
       ## In recovery case, overwrite trap to keep socket file
       trap 'rm -f "${XP_CACHE_HOME}"/__xpns_*$$;' EXIT
 
       xpns_msg "Recovery" \
-"Execute below command line to re-attach the new session.
+        "Execute below command line to re-attach the new session.
 
 ${TMUX_XPANES_EXEC} -S ${XP_SOCKET_PATH} attach-session -t ${XP_SESSION_NAME}
 
@@ -1396,8 +1511,8 @@ xpns_execution() {
   local _def_allow_rename=
   local _pane_count=0
 
-  if [[ ${XP_IS_PIPE_MODE} -eq 0 ]] && [[ -n "${XP_MAX_PANE_ARGS-}" ]];then
-    xpns_set_args_per_pane "${XP_MAX_PANE_ARGS}"
+  if [[ ${XP_IS_PIPE_MODE} -eq 0 ]] && [[ -n "${XP_MAX_PANE_ARGS-}" ]]; then
+    xpns_merge_array_elements "${XP_MAX_PANE_ARGS}" 'XP_ARGS'
   fi
 
   ## Fix window size and define pane size
@@ -1439,25 +1554,26 @@ xpns_execution() {
   xpns_suppress_allow_rename "${_def_allow_rename-}"
   XP_CMD_UTILITY="$(xpns_get_joined_begin_commands "${XP_CMD_UTILITY}")"
 
-  if [[ ${XP_OPT_EXTRA} -eq 1 ]];then
+  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 ))
+    _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
     _window_name=$(
       xpns_generate_window_name \
         "${XP_EMPTY_STR}" \
-        "${XP_ARGS[0]}" \
-        | xpns_value2key)
+        "${XP_ARGS[0]}" |
+        xpns_value2key
+    )
   fi
 
   ## --------------------
   # Prepare window and panes
   ## --------------------
-  if [[ ${XP_OPT_EXTRA} -eq 1 ]];then
+  if [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
     xpns_prepare_extra_panes \
       "${_window_name}" \
       "${_pane_base_index}" \
@@ -1468,7 +1584,7 @@ xpns_execution() {
       "${XP_REPSTR}" \
       "${XP_CMD_UTILITY}" \
       "${XP_ARGS[@]}"
-  elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 1 ]];then
+  elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 1 ]]; then
     xpns_prepare_preset_layout_window \
       "${_window_name}" \
       "${_pane_base_index}" \
@@ -1480,7 +1596,7 @@ xpns_execution() {
       "${XP_REPSTR}" \
       "${XP_CMD_UTILITY}" \
       "${XP_ARGS[@]}"
-  elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 0 ]];then
+  elif [[ ${XP_OPT_USE_PRESET_LAYOUT} -eq 0 ]]; then
     xpns_prepare_window \
       "${_window_name}" \
       "${XP_OPT_LOG_STORE}" \
@@ -1494,11 +1610,11 @@ xpns_execution() {
   fi
 
   ## With -ss option, it is possible to close all the panes as of here.
-  ## Check status of the window. If no window exists, there is nothing to do execpt to exit.
+  ## Check status of the window. If no window exists, there is nothing to do any more and just exit.
   xpns_msg_debug "xpns_is_window_alive:1: After window separation"
   xpns_is_window_alive "${_window_name}" "${XP_OPT_SPEEDY_AWAIT}" "${_def_allow_rename-}"
 
-  if [[ ${XP_OPT_EXTRA} -eq 1 ]];then
+  if [[ ${XP_OPT_EXTRA} -eq 1 ]]; then
     # Set offset to avoid sending command to the original pane.
     _pane_base_index=$((_pane_base_index + 1))
     # Avoid to make layout even-horizontal even if there are many panes.
@@ -1528,14 +1644,14 @@ xpns_execution() {
   xpns_is_window_alive "${_window_name}" "${XP_OPT_SPEEDY_AWAIT}" "${_def_allow_rename-}"
 
   # Set pane titles for each pane.
-  if xpns_is_pane_title_required "${XP_OPT_SET_TITLE}" "${XP_OPT_EXTRA}" ;then
+  if xpns_is_pane_title_required "${XP_OPT_SET_TITLE}" "${XP_OPT_EXTRA}"then
     xpns_set_titles \
       "${_window_name}" \
       "${_pane_base_index}" \
       "${XP_ARGS[@]}"
   fi
 
-  if [[ $XP_OPT_SPEEDY -eq 1 ]];then
+  if [[ $XP_OPT_SPEEDY -eq 1 ]]; then
     xpns_notify_sync \
       "${_window_name}" \
       "${XP_ARGS[@]}"
@@ -1586,7 +1702,7 @@ xpns_execution() {
   fi
 
   # In case of -x, this statement is skipped to keep the original window name
-  if [[ ${XP_OPT_EXTRA} -eq 0 ]];then
+  if [[ ${XP_OPT_EXTRA} -eq 0 ]]; then
     # Restore original window name.
     ${TMUX_XPANES_EXEC} \
       rename-window -t "${_window_name}" \
@@ -1632,13 +1748,11 @@ xpns_switch_pipe_mode() {
     fi
   fi
 
-  while read -r line;
-  do
+  while read -r line; do
     XP_STDIN+=("${line}")
-  done < <(cat | xpns_rm_empty_line | \
+  done < <(cat | xpns_rm_empty_line |
     xpns_pipe_filter "${_pane_num4new_term:-${XP_MAX_PANE_ARGS}}")
 
-
   # Merge them into command.
   if [[ -n "${XP_ARGS[*]-}" ]]; then
     # Attention: It might be wrong result if IFS is changed.
@@ -1678,7 +1792,7 @@ xpns_layout_short2long() {
 xpns_is_valid_layout() {
   local _layout="${1-}"
   local _pat='^(tiled|even-horizontal|even-vertical|main-horizontal|main-vertical)$'
-  if ! [[ $_layout =~ $_pat ]]  ; then
+  if ! [[ $_layout =~ $_pat ]]; then
     xpns_msg_error "Invalid layout '${_layout}'."
     exit ${XP_ELAYOUT}
   fi
@@ -1688,7 +1802,7 @@ xpns_warning_before_extra() {
   local _ans=
   local _synchronized=
   _synchronized="$(xpns_get_local_tmux_conf "synchronize-panes")"
-  if [[ "on" == "${_synchronized}" ]];then
+  if [[ "on" == "${_synchronized}" ]]; then
     xpns_msg_warning "Panes are now synchronized.
 '-x' option may cause unexpected behavior on the synchronized panes."
     printf "Are you really sure? [y/n]: "
@@ -1699,289 +1813,276 @@ xpns_warning_before_extra() {
   fi
 }
 
-xpns_load_flag_options() {
-  if [[ "$1" =~ h ]]; then
-    xpns_usage
-    exit 0
-  fi
-  if [[ "$1" =~ V ]]; then
-    xpns_version
-    exit 0
-  fi
-  if [[ "$1" =~ x ]]; 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
-  fi
-  if [[ "$1" =~ d ]]; then
-    XP_OPT_IS_SYNC=0
-  fi
-  if [[ "$1" =~ e ]]; then
-    XP_REPSTR="{}"
-    XP_CMD_UTILITY="{}"
-  fi
-  if [[ "$1" =~ t ]]; then
-    if ( xpns_tmux_is_greater_equals 2.3 ) ; then
-      XP_OPT_SET_TITLE=1
-      XP_OPT_CHANGE_BORDER=1
-    else
-      xpns_msg_warning "-t option cannot be used by tmux version less than 2.3. Disabled."
-      sleep 1
-    fi
-  fi
-  if [[ "$1" =~ s ]]; then
-    XP_OPT_SPEEDY=1
-    XP_OPT_SPEEDY_AWAIT=1
-  fi
-  if [[ "$1" =~ ss ]]; then
-    XP_OPT_SPEEDY_AWAIT=0
+xpns_opt_check_num() {
+  local _option="$1"
+  shift
+  local _arg="$1"
+  if [[ -n "$_arg" ]] && [[ -z "${_arg//[0-9]/}" ]]; then
+    return 0
   fi
-  return 1
+  xpns_msg_error "Invalid argument '$_arg' for $_option option"
+  exit ${XP_EINVAL}
 }
 
-xpns_load_arg_options() {
-  # Extract flag options only.
-  local _pattern=
-  xpns_load_flag_options "$(xpns_extract_matched "$1" "^-${XP_FLAG_OPTIONS}+")" > /dev/null
-  if [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*I ]]; then
-    # Behavior like this.
-    # -IAAA       -- XP_REPSTR="AAA"
-    # -I AAA BBB  -- XP_REPSTR="AAA", XP_ARGS=("BBB")
-    # -I"AAA BBB" -- XP_REPSTR="AAA BBB"
-    # -IAAA BBB   -- XP_REPSTR="AAA", XP_ARGS=("BBB")
-    # -I -d ...   -- XP_REPSTR=""
-    _pattern="^-${XP_FLAG_OPTIONS}*I(.+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_REPSTR="${BASH_REMATCH[1]}"
-      return 0
-    elif ! [[ "$2" =~ ^-.* ]]; then
-      XP_REPSTR="$2"
-      return 0
-    else
-      xpns_msg_error "invalid argument '$2' for -I option"
-      exit ${XP_EINVAL}
-    fi
-  elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*l ]]; then
-    _pattern="^-${XP_FLAG_OPTIONS}*l(.+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_OPT_USE_PRESET_LAYOUT=1
-      XP_LAYOUT="$(cat <<<"${BASH_REMATCH[1]}" | xpns_layout_short2long)"
-      xpns_is_valid_layout "${XP_LAYOUT}"
-      return 0
-    elif ! [[ "$2" =~ ^-.* ]]; then
-      XP_OPT_USE_PRESET_LAYOUT=1
-      XP_LAYOUT="$(cat <<<"$2" |  xpns_layout_short2long )"
-      xpns_is_valid_layout "${XP_LAYOUT}"
-      return 0
-    else
-      xpns_msg_error "invalid argument '$2' for -l option"
-      exit ${XP_EINVAL}
-    fi
-  elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*c ]]; then
-    _pattern="^-${XP_FLAG_OPTIONS}*c(.+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_CMD_UTILITY="${BASH_REMATCH[1]}"
-      XP_OPT_CMD_UTILITY=1
-      return 0
-    elif ! [[ "$2" =~ ^-.* ]]; then
-      XP_CMD_UTILITY="$2"
-      XP_OPT_CMD_UTILITY=1
-      return 0
-    else
-      xpns_msg_error "invalid argument '$2' for -c option"
-      exit ${XP_EINVAL}
-    fi
-  elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*n ]]; then
-    _pattern="^-${XP_FLAG_OPTIONS}*n([0-9]+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_MAX_PANE_ARGS="${BASH_REMATCH[1]}"
-      return 0
-    elif [[ "$2" =~ ^[0-9]+$ ]]; then
-      XP_MAX_PANE_ARGS="$2"
-      return 0
-    else
-      xpns_msg_error "invalid argument '$2' for -n option"
-      exit ${XP_EINVAL}
-    fi
-  elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*S ]]; then
-    _pattern="^-${XP_FLAG_OPTIONS}*S(.+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_SOCKET_PATH="${BASH_REMATCH[1]}"
-      return 0
-    elif ! [[ "$2" =~ ^-.* ]]; then
-      XP_SOCKET_PATH="$2"
-      return 0
-    else
-      xpns_msg_error "invalid argument '$2' for -S option"
-      exit ${XP_EINVAL}
-    fi
-  elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*C ]]; then
-    _pattern="^-${XP_FLAG_OPTIONS}*C([0-9]+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_OPT_CUSTOM_SIZE_COLS="${BASH_REMATCH[1]}"
-      return 0
-    elif [[ "$2" =~ ^[0-9]+$ ]];then
-      XP_OPT_CUSTOM_SIZE_COLS="$2"
-      return 0
-    else
-      xpns_msg_error "invalid argument '$2' for -C option"
-      exit ${XP_EINVAL}
-    fi
-  elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*R ]]; then
-    _pattern="^-${XP_FLAG_OPTIONS}*R([0-9]+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_OPT_CUSTOM_SIZE_ROWS="${BASH_REMATCH[1]}"
-      return 0
-    elif [[ "$2" =~ ^[0-9]+$ ]];then
-      XP_OPT_CUSTOM_SIZE_ROWS="$2"
-      return 0
-    else
-      xpns_msg_error "invalid argument '$2' for -R option"
-      exit ${XP_EINVAL}
-    fi
-  elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*B ]]; then
-    _pattern="^-${XP_FLAG_OPTIONS}*B(.+)"
-    if [[ "$1" =~ $_pattern ]]; then
-      XP_BEGIN_ARGS+=("${BASH_REMATCH[1]}")
-      return 0
-    else
-      XP_BEGIN_ARGS+=("$2")
-      return 0
-    fi
+xpns_opt_check_str() {
+  local _option="$1"
+  shift
+  local _arg="$1"
+  if [[ -n "$_arg" ]]; then
+    return 0
   fi
-  return 0
+  xpns_msg_error "Invalid argument '$_arg' for $_option option"
+  exit ${XP_EINVAL}
 }
 
-xpns_load_long_options() {
-  if [[ "$1" =~ ^--help$ ]]; then
-    xpns_usage
-    exit 0
-  elif [[ "$1" =~ ^--version$ ]]; then
-    xpns_version
-    exit 0
-  elif [[ "$1" =~ ^--desync$ ]]; then
-    XP_OPT_IS_SYNC=0
-    return 1
-  elif [[ "$1" =~ ^--log-format=.*$ ]]; then
-    XP_OPT_LOG_STORE=1
-    TMUX_XPANES_LOG_FORMAT="${1#--log-format=}"
-    return 1
-  elif [[ "$1" =~ ^--log ]]; then
-    XP_OPT_LOG_STORE=1
-    if [[ "$1" =~ ^--log=.*$  ]]; then
-      TMUX_XPANES_LOG_DIRECTORY="${1#--log=}"
-    fi
-    return 1
-  elif [[ "$1" =~ ^--ssh$ ]]; then
-    XP_CMD_UTILITY="${XP_SSH_CMD_UTILITY}"
-    # Enable -t option as well
-    XP_OPT_SET_TITLE=1
-    XP_OPT_CHANGE_BORDER=1
-    # Enable -s option
-    XP_OPT_SPEEDY=1
-    XP_OPT_SPEEDY_AWAIT=1
-    return 1
-  elif [[ "$1" =~ ^--stay$ ]]; then
-    XP_OPT_ATTACH=0
-    return 1
-  elif [[ "$1" =~ ^--cols=[0-9]+$ ]]; then
-    XP_OPT_CUSTOM_SIZE_COLS="${1#--cols=}"
-    return 1
-  elif [[ "$1" =~ ^--rows=[0-9]+$ ]]; then
-    XP_OPT_CUSTOM_SIZE_ROWS="${1#--rows=}"
-    return 1
-  elif [[ "$1" =~ ^--bulk-cols=[0-9,]*[0-9]+$ ]]; then
-    XP_OPT_BULK_COLS="${1#--bulk-cols=}"
-    return 1
-  elif [[ "$1" =~ ^--debug$ ]]; then
-    XP_OPT_DEBUG=1
-    return 1
-  elif [[ "$1" =~ ^--dry-run$ ]]; then # For unit testing
-    XP_OPT_DRY_RUN=1
-    return 1
-  elif [[ "$1" =~ ^--ignore-size-limit$ ]]; then
-    XP_OPT_IGNORE_SIZE_LIMIT=1
-    return 1
-
-  ## ----------------
-  # Other options
-  ## ----------------
-  else
-    xpns_msg_error "invalid option -- '${1#--}'"
-    xpns_usage_warn
-    exit ${XP_EINVAL}
+xpns_opt_check_num_csv() {
+  local _option="$1"
+  shift
+  local _arg="$1"
+  if [[ "$1" =~ ^([0-9][0-9]*,?)+$ ]]; then
+    return 0
   fi
+  xpns_msg_error "Invalid argument '$_arg' for $_option option"
+  exit ${XP_EINVAL}
 }
 
 xpns_parse_options() {
-  while (( $# > 0 )); do
-    case "$1" in
+  while (($# > 0)); do
+    opt="$1"
+    shift
+    if [[ ${XP_NO_OPT} -eq 1 ]]; then
+      XP_ARGS+=("$opt")
+      continue
+    fi
+
+    ## Skip regularization if the arg is empty or --log= option
+    if [[ -n "$opt" ]] && [[ -n "${opt##--log=*}" ]]; then
+      ## -ovalue → -o value
+      if [[ -z "${opt##-${XP_ARG_OPTIONS}?*}" ]]; then
+        set -- "${opt#??}" ${1+"$@"}
+        opt="${opt%$1}"
+      ## -abc → -a -bc
+      elif [[ -z "${opt##-[!-]?*}" ]]; then
+        set -- "-${opt#??}" ${1+"$@"}
+        opt="${opt%${1#-}}"
+      ## --option=value → --option value
+      elif [[ -z "${opt##--*=*}" ]]; then
+        set -- "${opt#--*=}" ${1+"$@"}
+        opt="${opt%%=*}"
+      fi
+    fi
+
+    case "$opt" in
       --)
-      if [[ ${XP_NO_OPT} -eq 1 ]]; then
-        XP_ARGS+=("$1")
-        shift
-      else
         # Disable any more options
         XP_NO_OPT=1
-        shift
-      fi
-      ;;
+        ;;
       ## ----------------
       # Long options
       ## ----------------
-      --*)
-      if [[ ${XP_NO_OPT} -eq 1 ]]; then
-        XP_ARGS+=("$1")
+      --help)
+        xpns_usage
+        exit 0
+        ;;
+      --version)
+        xpns_version
+        exit 0
+        ;;
+      --desync)
+        XP_OPTIONS+=("$opt")
+        XP_OPT_IS_SYNC=0
+        ;;
+      --log-format)
+        xpns_opt_check_str "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_OPT_LOG_STORE=1
+        TMUX_XPANES_LOG_FORMAT="$1"
+        XP_OPTIONS+=("$1")
         shift
-      else
-        local _shift_count="0"
-        xpns_load_long_options "$@"
-        _shift_count="$?"
-        [[ "${_shift_count}" = "1" ]] && XP_OPTIONS+=("$1") && shift
-      fi
-      ;;
+        ;;
+      --log=*)
+        XP_OPT_LOG_STORE=1
+        XP_OPTIONS+=("$opt")
+        TMUX_XPANES_LOG_DIRECTORY="${opt#--log=}"
+        xpns_opt_check_str "${opt%=}" "$TMUX_XPANES_LOG_DIRECTORY"
+        ;;
+      --log)
+        XP_OPT_LOG_STORE=1
+        XP_OPTIONS+=("$opt")
+        ;;
+      --ssh)
+        XP_OPTIONS+=("$opt")
+        XP_CMD_UTILITY="${XP_SSH_CMD_UTILITY}"
+        # Enable -t option
+        XP_OPT_SET_TITLE=1
+        XP_OPT_CHANGE_BORDER=1
+        # Enable -s option
+        XP_OPT_SPEEDY=1
+        XP_OPT_SPEEDY_AWAIT=1
+        ;;
+      --stay)
+        XP_OPTIONS+=("$opt")
+        XP_OPT_ATTACH=0
+        ;;
+      --cols)
+        xpns_opt_check_num "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_OPT_CUSTOM_SIZE_COLS="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      --rows)
+        xpns_opt_check_num "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_OPT_CUSTOM_SIZE_ROWS="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      --bulk-cols)
+        xpns_opt_check_num_csv "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_OPT_BULK_COLS="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      --debug)
+        XP_OPTIONS+=("$opt")
+        XP_OPT_DEBUG=1
+        ;;
+      --dry-run)
+        XP_OPTIONS+=("$opt")
+        XP_OPT_DRY_RUN=1
+        ;;
+      --ignore-size-limit)
+        XP_OPTIONS+=("$opt")
+        XP_OPT_IGNORE_SIZE_LIMIT=1
+        ;;
       ## ----------------
-      # Short options
+      # Short options without argument
       ## ----------------
-      -*)
-      if [[ ${XP_NO_OPT} -eq 1 ]]; then
-        XP_ARGS+=("$1")
-        shift
-      else
-        local _shift_count="0"
-        if [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*${XP_ARG_OPTIONS}. ]];then
-          xpns_load_arg_options "$@"
-          XP_OPTIONS+=("$1") && shift
-        elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}*${XP_ARG_OPTIONS}$ ]] && [[ -n "${2-}" ]];then
-          xpns_load_arg_options "$@"
-          _shift_count="$?"
-          XP_OPTIONS+=("$1" "$2") && shift && shift
-        elif [[ "$1" =~ ^-${XP_FLAG_OPTIONS}+$  ]];then
-          xpns_load_flag_options "$1"
-          XP_OPTIONS+=("$1") && shift
-        ## ----------------
-        # Other options
-        ## ----------------
+      -h)
+        xpns_usage
+        exit 0
+        ;;
+      -V)
+        xpns_version
+        exit 0
+        ;;
+      -x)
+        XP_OPTIONS+=("$opt")
+        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
+        ;;
+      -d)
+        XP_OPTIONS+=("$opt")
+        XP_OPT_IS_SYNC=0
+        ;;
+      -e)
+        XP_OPTIONS+=("$opt")
+        XP_REPSTR="{}"
+        XP_CMD_UTILITY="{}"
+        ;;
+      -t)
+        XP_OPTIONS+=("$opt")
+        if ( xpns_tmux_is_greater_equals 2.3 ); then
+          XP_OPT_SET_TITLE=1
+          XP_OPT_CHANGE_BORDER=1
         else
-          xpns_msg_error "Invalid option -- '${1#-}'"
-          xpns_usage_warn
-          exit ${XP_EINVAL}
+          xpns_msg_warning "-t option cannot be used by tmux version less than 2.3. Disabled."
+          sleep 1
         fi
-      fi
-      ;;
+        ;;
+      -s)
+        XP_OPTIONS+=("$opt")
+        XP_OPT_SPEEDY=1
+        XP_OPT_SPEEDY_AWAIT=1
+        if [[ -z "${1#-s}" ]]; then
+          XP_OPT_SPEEDY_AWAIT=0
+          XP_OPTIONS+=("$1")
+          shift
+        fi
+        ;;
+      ## ----------------
+      # Short options with argument
+      ## ----------------
+      -I)
+        xpns_opt_check_str "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_REPSTR="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -l)
+        xpns_opt_check_str "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_OPT_USE_PRESET_LAYOUT=1
+        XP_LAYOUT="$(printf '%s\n' "$1" | xpns_layout_short2long)"
+        xpns_is_valid_layout "${XP_LAYOUT}"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -c)
+        # -c allows empty
+        # xpns_opt_check_str "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_CMD_UTILITY="$1"
+        XP_OPT_CMD_UTILITY=1
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -n)
+        xpns_opt_check_num "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_MAX_PANE_ARGS="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -S)
+        xpns_opt_check_str "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_SOCKET_PATH="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -C)
+        xpns_opt_check_num "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_OPT_CUSTOM_SIZE_COLS="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -R)
+        xpns_opt_check_num "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_OPT_CUSTOM_SIZE_ROWS="$1"
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -B)
+        # -B allows empty
+        # xpns_opt_check_str "$opt" "$1"
+        XP_OPTIONS+=("$opt")
+        XP_BEGIN_ARGS+=("$1")
+        XP_OPTIONS+=("$1")
+        shift
+        ;;
+      -*)
+        xpns_msg_error "Invalid option -- '${opt}'"
+        xpns_usage_warn
+        exit ${XP_EINVAL}
+        ;;
       ## ----------------
       # Other arguments
       ## ----------------
       *)
-      XP_ARGS+=("$1")
-      XP_NO_OPT=1
-      shift
-      ;;
+        XP_ARGS+=("$opt")
+        XP_NO_OPT=1
+        ;;
     esac
   done
-
   # If there is any standard input from pipe,
   # 1 line handled as 1 argument.
   if [[ ! -t 0 ]]; then
@@ -1989,7 +2090,7 @@ xpns_parse_options() {
     xpns_switch_pipe_mode
   fi
 
-  # When no argument arr given, exit.
+  # When no argument is given, exit.
   if [[ -z "${XP_ARGS[*]-}" ]]; then
     xpns_msg_error "No arguments."
     xpns_usage_warn
@@ -2012,10 +2113,9 @@ xpns_parse_options() {
   XP_REPSTR="${XP_REPSTR:-${XP_DEFAULT_REPSTR}}"
 
   # To set command on pre_execution, set -c option manually.
-  if [[ ${XP_OPT_CMD_UTILITY} -eq 0 ]];then
+  if [[ ${XP_OPT_CMD_UTILITY} -eq 0 ]]; then
     XP_OPTIONS+=("-c" "${XP_CMD_UTILITY}")
   fi
-
 }
 
 ## --------------------------------
@@ -2034,8 +2134,8 @@ xpns_main() {
   # Validate log directory.
   if [[ ${XP_OPT_LOG_STORE} -eq 1 ]]; then
     TMUX_XPANES_LOG_DIRECTORY=$(xpns_normalize_directory "${TMUX_XPANES_LOG_DIRECTORY}")
-    xpns_is_valid_directory "${TMUX_XPANES_LOG_DIRECTORY}" && \
-    TMUX_XPANES_LOG_DIRECTORY=$(cd "${TMUX_XPANES_LOG_DIRECTORY}" && pwd)
+    xpns_is_valid_directory "${TMUX_XPANES_LOG_DIRECTORY}" &&
+      TMUX_XPANES_LOG_DIRECTORY=$(cd "${TMUX_XPANES_LOG_DIRECTORY}" && pwd)
   fi
   ## --------------------------------
   # If current shell is outside of tmux session.