#!/bin/sh PATH=/bin:/usr/bin TERM=screen LC_ALL=C.UTF-8 export PATH TERM LC_ALL [ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) TMUX="$TEST_TMUX -Lentry-column-$$ -f/dev/null" fail() { echo "$mode: $*" >&2 exit 1 } cleanup() { $TMUX kill-server 2>/dev/null } trap cleanup 0 1 15 x() { $TMUX send-keys -X "$@" || fail "copy command failed: $*" } check_cursor() { actual=$($TMUX display-message -p '#{copy_cursor_x},#{copy_cursor_y}') [ "$actual" = "$1" ] || fail "expected cursor $1, got $actual" } wait_cursor() { i=0 while [ "$i" -lt 50 ]; do actual=$($TMUX display-message -p '#{cursor_x},#{cursor_y}') [ "$actual" = "$1" ] && return 0 sleep 0.1 i=$((i + 1)) done fail "pane cursor did not reach $1" } mode=emacs $TMUX new-session -d -x40 -y10 \ "printf '%s\r\n' ABCDEFGHIJKLMNOPQRST abc ABCDEFGHIJKLMNOPQRST \ abcdefgh ABCDEFGHIJKLMNOP ab 01234567890123456789; \ printf '\033[4;9H'; exec cat" || fail "new-session failed" $TMUX set-option -g status off || fail "set status failed" $TMUX set-option -g window-size manual || fail "set window-size failed" wait_cursor 8,3 for mode in emacs vi; do $TMUX set-window-option -g mode-keys "$mode" || fail "set mode-keys failed" # Ordinary entry still follows line ends; -c starts at the same physical # position but treats its column as a numeric preference. for direction in up down; do if [ "$direction" = up ]; then row=2 end=20 else row=4 end=16 fi [ "$mode" = emacs ] || end=$((end - 1)) $TMUX copy-mode || fail "copy-mode failed" check_cursor 8,3 x "cursor-$direction" check_cursor "$end,$row" x cancel $TMUX copy-mode -c || fail "copy-mode -c failed" check_cursor 8,3 x "cursor-$direction" check_cursor "8,$row" x cancel done # Short lines retain the existing emacs and vi movement rules. Emacs # restores the preferred column; vi resumes from its last-character clamp. $TMUX copy-mode -c || fail "copy-mode -c failed" x cursor-up check_cursor 8,2 x cursor-up if [ "$mode" = emacs ]; then check_cursor 3,1 restored=8 else check_cursor 2,1 restored=2 fi x cursor-up check_cursor "$restored,0" x cancel $TMUX copy-mode -c || fail "copy-mode -c failed" x cursor-down check_cursor 8,4 x cursor-down if [ "$mode" = emacs ]; then check_cursor 2,5 restored=8 else check_cursor 1,5 restored=1 fi x cursor-down check_cursor "$restored,6" x cancel # Horizontal movement before the first vertical move replaces the initial # preference, rather than leaving the entry column permanently fixed. $TMUX copy-mode -c || fail "copy-mode -c failed" x cursor-left check_cursor 7,3 x cursor-up check_cursor 7,2 x cancel done # Passing -c while already in copy mode must not reinitialize its preference. mode=emacs $TMUX set-window-option -g mode-keys "$mode" || fail "set mode-keys failed" $TMUX copy-mode -c || fail "copy-mode -c failed" x cursor-left x cursor-up x cursor-up check_cursor 3,1 $TMUX copy-mode -c || fail "second copy-mode -c failed" check_cursor 3,1 x cursor-up check_cursor 7,0 x cancel # Trailing blanks must not replace the initial preference on the first move. for entry_line in 'prompt> ' ' '; do $TMUX respawn-pane -k \ "printf '\033[H\033[2J'; \ printf '%s\r\n' ABCDEFGHIJKLMNOPQRST abc ABCDEFGHIJKLMNOPQRST \ '$entry_line' ABCDEFGHIJKLMNOP ab 01234567890123456789; \ printf '\033[4;9H'; exec cat" || fail "respawn-pane failed" wait_cursor 8,3 for mode in emacs vi; do $TMUX set-window-option -g mode-keys "$mode" || fail "set mode-keys failed" for direction in up down; do if [ "$direction" = up ]; then row=2 end=20 short=3 last=0 else row=4 end=16 short=2 last=6 fi [ "$mode" = emacs ] || end=$((end - 1)) $TMUX copy-mode || fail "copy-mode failed" x "cursor-$direction" check_cursor "$end,$row" x cancel $TMUX copy-mode -c || fail "copy-mode -c failed" check_cursor 8,3 x "cursor-$direction" check_cursor "8,$row" x "cursor-$direction" x "cursor-$direction" if [ "$mode" = emacs ]; then check_cursor "8,$last" else check_cursor "$((short - 1)),$last" fi x cancel done # Returning to the entry mark must not reenable EOL following. $TMUX copy-mode -c || fail "copy-mode -c failed" x cursor-up check_cursor 8,2 x jump-to-mark check_cursor 8,3 $TMUX copy-mode || fail "second copy-mode failed" x cursor-up check_cursor 8,2 x cancel # A new ordinary visit restores the default. Adding -c to an already # active visit does not change its policy. $TMUX copy-mode || fail "copy-mode failed" $TMUX copy-mode -c || fail "second copy-mode -c failed" x cursor-up end=20 [ "$mode" = emacs ] || end=19 check_cursor "$end,2" x cancel done done # An empty entry line has a numeric column zero with -c. $TMUX respawn-pane -k \ "printf '\033[H\033[2JABCDEFGHIJKLMNOPQRST\033[2;1H'; exec cat" || fail "respawn-pane failed" wait_cursor 0,1 for mode in emacs vi; do $TMUX set-window-option -g mode-keys "$mode" || fail "set mode-keys failed" $TMUX copy-mode -c || fail "copy-mode -c failed" check_cursor 0,1 x cursor-up check_cursor 0,0 x cancel done # The initial preference counts terminal columns, not characters. $TMUX respawn-pane -k \ "printf '\033[H\033[2J'; \ printf '%s\r\n' ABCDEFGHIJKLMNOPQRST ABCDEFGHIJKLMNOPQRST; \ printf 'abc中def'; exec cat" || fail "respawn-pane failed" wait_cursor 8,2 for mode in emacs vi; do $TMUX set-window-option -g mode-keys "$mode" || fail "set mode-keys failed" $TMUX copy-mode -c || fail "copy-mode -c failed" check_cursor 8,2 x cursor-up check_cursor 8,1 x cancel done # Initialize before the optional entry-time page movement. $TMUX respawn-pane -k \ "printf '\033[H\033[2JABCDEFGHIJKLMNOPQRST'; \ printf '\033[9;1Hprompt> \033[10;1HABCDEFGHIJKLMNOP\033[9;9H'; \ exec cat" || fail "respawn-pane failed" wait_cursor 8,8 for mode in emacs vi; do $TMUX set-window-option -g mode-keys "$mode" || fail "set mode-keys failed" $TMUX copy-mode -cu || fail "copy-mode -cu failed" check_cursor 8,0 x cancel $TMUX copy-mode -cd || fail "copy-mode -cd failed" check_cursor 8,9 x cancel done exit 0