From b6fca5544747e5f71c6b22f9bc0086d727d57509 Mon Sep 17 00:00:00 2001 From: Nicholas Marriott Date: Thu, 2 Jul 2026 10:26:09 +0100 Subject: [PATCH] Add tests for input path. --- regress/input-common.inc | 176 ++++++++++++++++++++++++++++++++++ regress/input-cursor.sh | 39 ++++++++ regress/input-edit.sh | 54 +++++++++++ regress/input-malformed.sh | 42 ++++++++ regress/input-modes.sh | 15 +++ regress/input-osc.sh | 37 +++++++ regress/input-raw-controls.sh | 84 ++++++++++++++++ regress/input-raw-cursor.sh | 33 +++++++ regress/input-raw-edit.sh | 47 +++++++++ regress/input-raw-history.sh | 23 +++++ regress/input-raw-reflow.sh | 21 ++++ regress/input-raw-scroll.sh | 39 ++++++++ regress/input-raw-sgr.sh | 39 ++++++++ regress/input-raw-unicode.sh | 82 ++++++++++++++++ regress/input-raw-wrap.sh | 28 ++++++ regress/input-replies.sh | 94 ++++++++++++++++++ regress/input-requests.sh | 117 ++++++++++++++++++++++ regress/input-scroll.sh | 73 ++++++++++++++ regress/input-sgr.sh | 26 +++++ regress/input-unicode.sh | 45 +++++++++ 20 files changed, 1114 insertions(+) create mode 100644 regress/input-common.inc create mode 100644 regress/input-cursor.sh create mode 100644 regress/input-edit.sh create mode 100644 regress/input-malformed.sh create mode 100644 regress/input-modes.sh create mode 100644 regress/input-osc.sh create mode 100644 regress/input-raw-controls.sh create mode 100644 regress/input-raw-cursor.sh create mode 100644 regress/input-raw-edit.sh create mode 100644 regress/input-raw-history.sh create mode 100644 regress/input-raw-reflow.sh create mode 100644 regress/input-raw-scroll.sh create mode 100644 regress/input-raw-sgr.sh create mode 100644 regress/input-raw-unicode.sh create mode 100644 regress/input-raw-wrap.sh create mode 100644 regress/input-replies.sh create mode 100644 regress/input-requests.sh create mode 100644 regress/input-scroll.sh create mode 100644 regress/input-sgr.sh create mode 100644 regress/input-unicode.sh diff --git a/regress/input-common.inc b/regress/input-common.inc new file mode 100644 index 000000000..96eec1f09 --- /dev/null +++ b/regress/input-common.inc @@ -0,0 +1,176 @@ +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) +TMUX="$TEST_TMUX -Ltest -f/dev/null" + +TMP=$(mktemp) +EXP=$(mktemp) +trap 'rm -f "$TMP" "$EXP"; $TMUX kill-server 2>/dev/null' 0 1 15 + +exit_status=0 + +fail() +{ + echo "FAIL: $1" + diff -u "$EXP" "$TMP" + exit_status=1 +} + +start_pane() +{ + start_pane_hlimit "$1" "$2" "$3" "$4" 0 +} + +start_pane_history() +{ + start_pane_hlimit "$1" "$2" "$3" "$4" 2000 +} + +start_pane_hlimit() +{ + name=$1 + sx=$2 + sy=$3 + seq=$4 + hlimit=$5 + + $TMUX kill-server 2>/dev/null + sleep 0.1 + $TMUX new-session -d -x 1 -y 1 -s test-setup "sleep 2" || exit 1 + $TMUX set-option -g history-limit "$hlimit" || exit 1 + $TMUX new-session -d -x "$sx" -y "$sy" -s "$name" \ + "printf '$seq'; sleep 2" || exit 1 + $TMUX kill-session -t test-setup + sleep 0.3 +} + +start_cmd() +{ + name=$1 + sx=$2 + sy=$3 + cmd=$4 + + $TMUX kill-server 2>/dev/null + sleep 0.1 + $TMUX new-session -d -x "$sx" -y "$sy" -s "$name" "$cmd" || exit 1 + sleep 0.3 +} + +normalize_capture() +{ + sed 's/[ ]*$//' | + awk '{ line[NR] = $0; if ($0 != "") last = NR } + END { for (i = 1; i <= last; i++) print line[i] }' +} + +capture_grid() +{ + $TMUX capture-pane -pN -t "$1:" -S 0 -E - | normalize_capture +} + +check_capture() +{ + name=$1 + expected=$2 + + capture_grid "$name" >"$TMP" + printf "%s\n" "$expected" >"$EXP" + cmp "$TMP" "$EXP" || fail "$name" +} + +check_cursor() +{ + name=$1 + expected=$2 + + actual=$($TMUX display-message -p -t "$name:" '#{cursor_x},#{cursor_y}') + if [ "$actual" != "$expected" ]; then + printf "%s\n" "$expected" >"$EXP" + printf "%s\n" "$actual" >"$TMP" + fail "$name cursor" + fi +} + +check_flags() +{ + name=$1 + expected=$2 + + $TMUX capture-pane -pNF -t "$name:" -S 0 -E - | + normalize_capture | + awk '$0 != "-"' >"$TMP" + printf "%s\n" "$expected" >"$EXP" + cmp "$TMP" "$EXP" || fail "$name flags" +} + +check_joined() +{ + name=$1 + expected=$2 + + $TMUX capture-pane -pNJ -t "$name:" -S 0 -E - | + normalize_capture >"$TMP" + printf "%s\n" "$expected" >"$EXP" + cmp "$TMP" "$EXP" || fail "$name joined" +} + +capture_raw() +{ + $TMUX capture-pane -pR -t "$1:" +} + +capture_raw_used() +{ + capture_raw "$1" | + awk '/^(G| L)/ || /^ C/ && $3 !~ /^data=\(1,1, \)$/' +} + +check_raw() +{ + name=$1 + expected=$2 + + capture_raw "$name" >"$TMP" + printf "%s\n" "$expected" >"$EXP" + cmp "$TMP" "$EXP" || fail "$name raw" +} + +check_raw_used() +{ + name=$1 + expected=$2 + + capture_raw_used "$name" >"$TMP" + printf "%s\n" "$expected" >"$EXP" + cmp "$TMP" "$EXP" || fail "$name raw used" +} + +check_raw_has() +{ + name=$1 + shift + + capture_raw "$name" >"$TMP" + for expected in "$@"; do + if ! grep -Fqx "$expected" "$TMP"; then + printf "%s\n" "$expected" >"$EXP" + fail "$name raw missing" + fi + done +} + +check_raw_matches() +{ + name=$1 + shift + + capture_raw "$name" >"$TMP" + for expected in "$@"; do + if ! grep -Eq "$expected" "$TMP"; then + printf "%s\n" "$expected" >"$EXP" + fail "$name raw missing" + fi + done +} diff --git a/regress/input-cursor.sh b/regress/input-cursor.sh new file mode 100644 index 000000000..51a825fc1 --- /dev/null +++ b/regress/input-cursor.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane cursor 10 3 'ABCDE\r\033[2Cxy\033[1D!\033[4GZ\n' +check_capture cursor 'ABxZE' +check_cursor cursor '0,1' + +start_pane saverc 10 3 'abc\0337\033[2;5HXY\0338Z\n' +check_capture saverc 'abcZ + XY' +check_cursor saverc '0,1' + +start_pane hvp 10 4 'A\033[3dB\033[5GC\033[2;2fD\n' +check_capture hvp 'A + D + B C' +check_cursor hvp '0,2' + +start_pane cursorlines 8 4 'A\033[2BB\033[1FC\033[1AD\n' +check_capture cursorlines 'AD +C + B' +check_cursor cursorlines '0,1' + +start_pane tabs 12 3 'a\tb\n' +check_capture tabs 'a b' +check_cursor tabs '0,1' + +start_pane tabclear 12 3 '\033H\ta\033[3g\r\tb\n' +check_capture tabclear ' a b' +check_cursor tabclear '0,1' + +start_pane cbt 16 3 '0123456789\r\033[10C\033[Zx\n' +check_capture cbt '01234567x9' +check_cursor cbt '0,1' + +$TMUX kill-server 2>/dev/null +exit $exit_status diff --git a/regress/input-edit.sh b/regress/input-edit.sh new file mode 100644 index 000000000..3c8ad3cef --- /dev/null +++ b/regress/input-edit.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane dch 10 3 'abcdef\r\033[3C\033[2PXY\n' +check_capture dch 'abcXY' + +start_pane ich 10 3 'abcdef\r\033[3C\033[2@XY\n' +check_capture ich 'abcXYdef' + +start_pane erase 10 3 'abcdef\r\033[3C\033[KZ\n' +check_capture erase 'abcZ' + +start_pane el1 10 3 'abcdef\r\033[3C\033[1KZ\n' +check_capture el1 ' Zef' + +start_pane ech 10 3 'abcdef\r\033[3C\033[2XX\n' +check_capture ech 'abcX f' + +start_pane ed 10 3 'one\ntwo\033[2;2H\033[JX\n' +check_capture ed 'one +tX' + +start_pane ed1 10 3 'one\ntwo\033[2;2H\033[1JX\n' +check_capture ed1 ' + Xo' + +start_pane ed2 10 3 'one\ntwo\033[2JZ\n' +check_capture ed2 ' + Z' + +start_pane il 8 4 '111\n222\n333\033[2;1H\033[LAAA\n' +check_capture il '111 +AAA +222 +333' + +start_pane dl 8 4 '111\n222\n333\033[2;1H\033[MZZZ\n' +check_capture dl '111 +ZZZ' + +start_pane irm 10 3 'abcdef\r\033[4h\033[3CXY\033[4lZ\n' +check_capture irm 'abcXYZef' + +start_pane rep 10 3 'A\033[4bB\n' +check_capture rep 'AAAAAB' + +start_pane decaln 6 3 '\033#8' +check_capture decaln 'EEEEEE +EEEEEE +EEEEEE' + +$TMUX kill-server 2>/dev/null +exit $exit_status diff --git a/regress/input-malformed.sh b/regress/input-malformed.sh new file mode 100644 index 000000000..55a7e38c0 --- /dev/null +++ b/regress/input-malformed.sh @@ -0,0 +1,42 @@ +#!/bin/sh + +. ./input-common.inc + +start_cmd csi-param-discard 8 3 \ + "perl -e 'print qq{\e[}, q{1} x 80, qq{\030OK}'; sleep 2" +check_capture csi-param-discard 'OK' + +start_cmd csi-interm-discard 8 3 \ + "perl -e 'print qq{\e[ \030OK}'; sleep 2" +check_capture csi-interm-discard 'OK' + +start_cmd osc-discard 8 3 \ + "perl -e 'print qq{\e]2;}, q{x} x 1100000, qq{\e\\\\OK}'; sleep 2" +check_capture osc-discard 'OK' + +start_cmd apc-discard 8 3 \ + "perl -e 'print qq{\e_}, q{x} x 1100000, qq{\e\\\\OK}'; sleep 2" +check_capture apc-discard 'OK' + +start_pane unknown-csi 8 3 '\033[?9999zOK' +check_capture unknown-csi 'OK' + +start_pane unknown-osc 8 3 '\033]999;bad\aOK' +check_capture unknown-osc 'OK' + +start_pane malformed-osc 8 3 '\033]8;id=a:id=b;http://bad\aX\033]8;id=no-separator\aY\033]9;4;5;200\a\033]9;4;z\a\033]10;notacolour\a\033]11;notacolour\a\033]12;notacolour\a\033]4;999;red\a\033]104;999\a\033]52bad\a\033]52;c;@@@\aOK' +check_capture malformed-osc 'XYOK' +check_raw_matches malformed-osc \ + 'C 0,0 data=\(1,1,X\).* link=NONE linkid=NONE' \ + 'C 0,1 data=\(1,1,Y\).* link=NONE linkid=NONE' \ + 'C 0,2 data=\(1,1,O\).* link=NONE linkid=NONE' \ + 'C 0,3 data=\(1,1,K\).* link=NONE linkid=NONE' + +start_pane malformed-dcs 8 3 '\033P$qBAD\033\\OK' +check_capture malformed-dcs 'OK^[P0$r +^[\' + +start_pane malformed-utf8 8 3 '\360\200\200\200A\355\240\200B' +check_capture malformed-utf8 '�A�B' + +exit $exit_status diff --git a/regress/input-modes.sh b/regress/input-modes.sh new file mode 100644 index 000000000..9bbe44429 --- /dev/null +++ b/regress/input-modes.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane alternate 10 3 'MAIN\033[?1049hALT\033[?1049lZ\n' +check_capture alternate 'MAINZ' + +start_pane osc133 10 4 '\033]133;A\007prompt\n\033]133;C\007output\n' +check_capture osc133 'prompt +output' +check_flags osc133 'P prompt +O output' + +$TMUX kill-server 2>/dev/null +exit $exit_status diff --git a/regress/input-osc.sh b/regress/input-osc.sh new file mode 100644 index 000000000..19b9d400f --- /dev/null +++ b/regress/input-osc.sh @@ -0,0 +1,37 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane hyperlink 20 3 '\033]8;id=1;https://example.com\033\\link\033]8;;\033\\ plain\n' +check_capture hyperlink 'link plain' +check_flags hyperlink 'HX link plain' +$TMUX capture-pane -peH -t hyperlink: -S 0 -E - >/dev/null || exit 1 + +start_pane palette 20 3 '\033]4;1;rgb:11/22/33;2;red\007\033]104;1;2\007X\n' +check_capture palette 'X' + +start_pane osc-colours 20 3 '\033]10;rgb:11/22/33\007\033]11;rgb:44/55/66\007\033]12;rgb:77/88/99\007\033]110\007\033]111\007\033]112\007X\n' +check_capture osc-colours 'X' + +start_pane progress 20 3 '\033]9;4;1;25\007\033]9;4;0\007\033]9;4;5;200\007X\n' +check_capture progress 'X' + +start_pane rename 20 3 '\033krenamed\033\\X\n' +check_capture rename 'X' + +start_pane apc-title 20 3 '\033_test-title\033\\X\n' +check_capture apc-title 'X' + +$TMUX kill-server 2>/dev/null +sleep 0.1 +$TMUX new-session -d -x 20 -y 3 -s osc52 "sleep 2" || exit 1 +$TMUX set-option -s set-clipboard on || exit 1 +$TMUX respawn-pane -k -t osc52: \ + "printf '\033]52;c;SGVsbG8=\007'; sleep 2" || exit 1 +sleep 0.3 +$TMUX save-buffer -b buffer0 - >"$TMP" +printf "Hello" >"$EXP" +cmp "$TMP" "$EXP" || fail "osc52" + +$TMUX kill-server 2>/dev/null +exit $exit_status diff --git a/regress/input-raw-controls.sh b/regress/input-raw-controls.sh new file mode 100644 index 000000000..ef67fe39c --- /dev/null +++ b/regress/input-raw-controls.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane bs 8 3 'abc\bd' +check_capture bs 'abd' +check_raw_matches bs \ + 'C 0,0 data=\(1,1,a\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1,b\) flags=NONE\[0\]' \ + 'C 0,2 data=\(1,1,d\) flags=NONE\[0\]' + +start_pane nel 8 3 'A\033EB' +check_capture nel 'A +B' +check_raw_matches nel \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 1,0 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane tabstops 16 3 '\033H1\t2\033[3g\r\t3' +check_raw_matches tabstops \ + 'C 0,0 data=\(1,1,1\) flags=NONE\[0\]' \ + 'C 0,8 data=\(1,1,2\) flags=NONE\[0\]' \ + 'C 0,15 data=\(1,1,3\) flags=NONE\[0\]' + +start_pane decaln 6 3 '\033#8' +check_raw_matches decaln \ + 'C 0,0 data=\(1,1,E\) flags=NONE\[0\]' \ + 'C 1,5 data=\(1,1,E\) flags=NONE\[0\]' \ + 'C 2,5 data=\(1,1,E\) flags=NONE\[0\]' + +start_pane charset 8 3 '\033(0qxl\033(BZ' +check_raw_matches charset \ + 'C 0,0 data=\(1,1,q\) flags=NONE\[0\] attr=CHARSET\[[0-9a-f]+\]' \ + 'C 0,1 data=\(1,1,x\) flags=NONE\[0\] attr=CHARSET\[[0-9a-f]+\]' \ + 'C 0,2 data=\(1,1,l\) flags=NONE\[0\] attr=CHARSET\[[0-9a-f]+\]' \ + 'C 0,3 data=\(1,1,Z\) flags=NONE\[0\] attr=NONE\[0\]' + +start_pane g1charset 8 3 '\033)0\016q\017Z' +check_raw_matches g1charset \ + 'C 0,0 data=\(1,1,q\) flags=NONE\[0\] attr=CHARSET\[[0-9a-f]+\]' \ + 'C 0,1 data=\(1,1,Z\) flags=NONE\[0\] attr=NONE\[0\]' + +start_pane csisave 8 3 '\033[3;3HS\033[s\033[1;1HA\033[uR' +check_raw_matches csisave \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 2,2 data=\(1,1,S\) flags=NONE\[0\]' \ + 'C 2,3 data=\(1,1,R\) flags=NONE\[0\]' + +start_pane alternate 8 3 'main\033[?1049halt\033[?1049lback' +check_capture alternate 'mainback' +check_raw_matches alternate \ + 'C 0,0 data=\(1,1,m\) flags=NONE\[0\]' \ + 'C 0,4 data=\(1,1,b\) flags=NONE\[0\]' \ + 'C 0,7 data=\(1,1,k\) flags=NONE\[0\]' + +start_pane sync 8 3 '\033P=1signored\033\\A\033P=2s\033\\B' +check_raw_matches sync \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane private 8 3 '\033[?25lA\033[?25hB\033[?1000hC\033[?1000lD' +check_raw_matches private \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1,B\) flags=NONE\[0\]' \ + 'C 0,2 data=\(1,1,C\) flags=NONE\[0\]' \ + 'C 0,3 data=\(1,1,D\) flags=NONE\[0\]' + +start_pane ris 8 3 'A\033cB' +check_capture ris 'B' +check_raw_matches ris \ + 'C 0,0 data=\(1,1,B\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\]' + +start_pane keypad 8 3 '\033=A\033>B' +check_raw_matches keypad \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane cursorstyle 8 3 '\033[5 qA\033[0 qB' +check_raw_matches cursorstyle \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1,B\) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-raw-cursor.sh b/regress/input-raw-cursor.sh new file mode 100644 index 000000000..4cba03eed --- /dev/null +++ b/regress/input-raw-cursor.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane absolute 8 4 'A\033[3;5HB\033[2GC\033[2D!' +check_capture absolute 'A + +!C B' +check_cursor absolute '1,2' +check_raw_matches absolute \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 2,4 data=\(1,1,B\) flags=NONE\[0\]' \ + 'C 2,0 data=\(1,1,!\) flags=NONE\[0\]' \ + 'C 2,1 data=\(1,1,C\) flags=NONE\[0\]' + +start_pane savecursor 8 4 '\033[4;4HS\0337\033[1;1HA\0338R' +check_capture savecursor 'A + + + SR' +check_cursor savecursor '5,3' +check_raw_matches savecursor \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 3,3 data=\(1,1,S\) flags=NONE\[0\]' \ + 'C 3,4 data=\(1,1,R\) flags=NONE\[0\]' + +start_pane origin 8 5 '\033[2;4r\033[?6h\033[1;1HO\033[3;1HP\033[?6lQ' +check_raw_matches origin \ + 'C 1,0 data=\(1,1,O\) flags=NONE\[0\]' \ + 'C 3,0 data=\(1,1,P\) flags=NONE\[0\]' \ + 'C 0,0 data=\(1,1,Q\) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-raw-edit.sh b/regress/input-raw-edit.sh new file mode 100644 index 000000000..6d78cc3c4 --- /dev/null +++ b/regress/input-raw-edit.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane erasechars 8 3 'ABCDEFGH\r\033[3C\033[2X' +check_capture erasechars 'ABC FGH' +check_raw_matches erasechars \ + 'C 0,3 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,4 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,5 data=\(1,1,F\) flags=NONE\[0\]' + +start_pane deletechars 8 3 'ABCDEFGH\r\033[3C\033[3P' +check_capture deletechars 'ABCGH' +check_raw_matches deletechars \ + 'C 0,3 data=\(1,1,G\) flags=NONE\[0\]' \ + 'C 0,4 data=\(1,1,H\) flags=NONE\[0\]' \ + 'C 0,5 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\]' + +start_pane insertchars 8 3 'ABCDEF\r\033[3C\033[2@xy' +check_capture insertchars 'ABCxyDEF' +check_raw_matches insertchars \ + 'C 0,3 data=\(1,1,x\) flags=NONE\[0\]' \ + 'C 0,4 data=\(1,1,y\) flags=NONE\[0\]' \ + 'C 0,5 data=\(1,1,D\) flags=NONE\[0\]' + +start_pane eraseline 8 3 'ABCDEFGH\r\033[4C\033[K' +check_capture eraseline 'ABCD' +check_raw_matches eraseline \ + 'C 0,4 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,7 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\]' + +start_pane erasescreen 8 3 '1111111\033[2;1H2222222\033[H\033[JZ' +check_capture erasescreen 'Z' +check_raw_matches erasescreen \ + '^G 8x3 \(0/0\)$' \ + 'C [0-9]+,0 data=\(1,1,Z\) flags=NONE\[0\]' \ + 'C [0-9]+,1 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\]' + +start_pane tabs 12 3 'A\tB\033[2g\r\033[IC' +check_raw_matches tabs \ + 'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \ + 'C 0,1 data=\(7,7, \) flags=TAB\[[0-9a-f]+\]' \ + 'C 0,2 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\]' \ + 'C 0,8 data=\(1,1,B\) flags=NONE\[0\]' \ + 'C 0,0 data=\(1,1,C\) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-raw-history.sh b/regress/input-raw-history.sh new file mode 100644 index 000000000..d3c7d260c --- /dev/null +++ b/regress/input-raw-history.sh @@ -0,0 +1,23 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane_hlimit trim 6 3 'one\ntwo\nthree\nfour\nfive\nsix' 2 +check_raw_matches trim \ + '^G 6x3 \(2/2\)$' \ + 'L 0 \(-\) flags=NONE\[0\]' \ + 'L 1 \(-\) flags=NONE\[0\]' + +$TMUX clear-history -t trim: +check_raw_matches trim \ + '^G 6x3 \(0/2\)$' \ + 'C 0,0 data=\(1,1,f\) flags=NONE\[0\]' \ + 'C 2,0 data=\(1,1,s\) flags=NONE\[0\]' + +start_pane_hlimit edhistory 6 3 'one\ntwo\nthree\033[H\033[JZ' 5 +check_raw_matches edhistory \ + '^G 6x3 \([1-9][0-9]*/5\)$' \ + 'L [0-9]+ \(-\) flags=NONE\[0\]' \ + 'C [0-9]+,0 data=\(1,1,Z\) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-raw-reflow.sh b/regress/input-raw-reflow.sh new file mode 100644 index 000000000..2e1d6c188 --- /dev/null +++ b/regress/input-raw-reflow.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane_history reflow 8 4 'abcdefgh\nijklmnop\nqrstuvwx\nyz' +$TMUX resize-window -t reflow: -x 4 -y 4 +sleep 0.2 +check_raw_matches reflow \ + '^G 4x4 \([0-9]+/2000\)$' \ + 'L [0-9]+ \([0-9-]+\) flags=WRAPPED\[[0-9a-f]+\]' \ + 'C [0-9]+,0 data=\(1,1,a\) flags=NONE\[0\]' \ + 'C [0-9]+,3 data=\(1,1,d\) flags=NONE\[0\]' + +$TMUX resize-window -t reflow: -x 12 -y 4 +sleep 0.2 +check_raw_matches reflow \ + '^G 12x4 \([0-9]+/2000\)$' \ + 'C [0-9]+,0 data=\(1,1,a\) flags=NONE\[0\]' \ + 'C [0-9]+,7 data=\(1,1,h\) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-raw-scroll.sh b/regress/input-raw-scroll.sh new file mode 100644 index 000000000..8fb2a6f50 --- /dev/null +++ b/regress/input-raw-scroll.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane_history history 6 3 'one\ntwo\nthree\nfour\nfive' +check_raw_matches history \ + '^G 6x3 \([1-9][0-9]*/2000\)$' \ + 'L [0-9]+ \(-\) flags=NONE\[0\]' \ + 'C [0-9]+,0 data=\(1,1,o\) flags=NONE\[0\]' + +start_pane_history index 6 4 'A\nB\nC\033[2;3r\033[2;1HX\033D\033DY' +check_raw_matches index \ + 'C [0-9]+,0 data=\(1,1,X\) flags=NONE\[0\]' \ + 'C [0-9]+,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C [0-9]+,1 data=\(1,1,Y\) flags=NONE\[0\]' + +start_pane reverse 6 4 'A\nB\nC\033[2;3r\033[2;1H\033MY' +check_raw_matches reverse \ + 'C 1,0 data=\(1,1,Y\) flags=NONE\[0\]' \ + 'C 2,0 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane insertline 6 4 'A\nB\nC\033[2;3r\033[2;1H\033[LY' +check_raw_matches insertline \ + 'C 1,0 data=\(1,1,Y\) flags=NONE\[0\]' \ + 'C 2,0 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane deleteline 6 4 'A\nB\nC\033[2;3r\033[2;1H\033[MY' +check_raw_matches deleteline \ + 'C 1,0 data=\(1,1,Y\) flags=NONE\[0\]' \ + 'C 2,0 data=\(1,1, \) flags=NONE\[0\]' + +start_pane region-edge 6 4 'top\033[2;3rmid\033[2;1H\033D\033Mbot' +check_raw_matches region-edge \ + 'C 0,0 data=\(1,1,m\) flags=NONE\[0\]' \ + 'C 1,0 data=\(1,1,b\) flags=NONE\[0\]' \ + 'C 2,0 data=\(1,1, \) flags=NONE\[0\]' \ + 'C 3,0 data=\(1,1, \) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-raw-sgr.sh b/regress/input-raw-sgr.sh new file mode 100644 index 000000000..c9a0b5fba --- /dev/null +++ b/regress/input-raw-sgr.sh @@ -0,0 +1,39 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane attrs 16 3 '\033[1mB\033[2mD\033[3mI\033[4mU\033[5mK\033[7mR\033[8mH\033[9mS\033[53mO' +check_raw_matches attrs \ + 'C 0,0 data=\(1,1,B\) flags=NONE\[0\] attr=BRIGHT\[[0-9a-f]+\]' \ + 'C 0,1 data=\(1,1,D\) flags=NONE\[0\] attr=BRIGHT,DIM\[[0-9a-f]+\]' \ + 'C 0,2 data=\(1,1,I\) flags=NONE\[0\] attr=BRIGHT,DIM,ITALICS\[[0-9a-f]+\]' \ + 'C 0,3 data=\(1,1,U\) flags=NONE\[0\] attr=BRIGHT,DIM,UNDERSCORE,ITALICS\[[0-9a-f]+\]' \ + 'C 0,5 data=\(1,1,R\) flags=NONE\[0\] attr=BRIGHT,DIM,UNDERSCORE,BLINK,REVERSE,ITALICS\[[0-9a-f]+\]' \ + 'C 0,7 data=\(1,1,S\) flags=NONE\[0\] attr=BRIGHT,DIM,UNDERSCORE,BLINK,REVERSE,HIDDEN,ITALICS,STRIKETHROUGH\[[0-9a-f]+\]' \ + 'C 0,8 data=\(1,1,O\) flags=NONE\[0\] attr=BRIGHT,DIM,UNDERSCORE,BLINK,REVERSE,HIDDEN,ITALICS,STRIKETHROUGH,OVERLINE\[[0-9a-f]+\]' + +start_pane colours 12 3 '\033[38;5;196;48;5;17mX\033[58;5;45mY' +check_raw_matches colours \ + 'C 0,0 data=\(1,1,X\) flags=FG256,BG256\[[0-9a-f]+\] attr=NONE\[0\] fg=colour196\[10000c4\] bg=colour17\[1000011\]' \ + 'C 0,1 data=\(1,1,Y\) flags=FG256,BG256\[[0-9a-f]+\] attr=NONE\[0\] fg=colour196\[10000c4\] bg=colour17\[1000011\] us=colour45\[100002d\]' + +start_pane bce 8 3 '\033[44mA\033[K' +check_raw_matches bce \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\] attr=NONE\[0\].* bg=blue\[4\]' \ + 'C 0,1 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\].* bg=blue\[4\]' \ + 'C 0,7 data=\(1,1, \) flags=CLEARED\[[0-9a-f]+\] attr=NONE\[0\].* bg=blue\[4\]' + +start_pane underlines 12 3 '\033[4:2m2\033[4:3m3\033[4:4m4\033[4:5m5' +check_raw_matches underlines \ + 'C 0,0 data=\(1,1,2\) flags=NONE\[0\] attr=UNDERSCORE_2\[[0-9a-f]+\]' \ + 'C 0,1 data=\(1,1,3\) flags=NONE\[0\] attr=UNDERSCORE_3\[[0-9a-f]+\]' \ + 'C 0,2 data=\(1,1,4\) flags=NONE\[0\] attr=UNDERSCORE_4\[[0-9a-f]+\]' \ + 'C 0,3 data=\(1,1,5\) flags=NONE\[0\] attr=UNDERSCORE_5\[[0-9a-f]+\]' + +start_pane hyperlink 12 3 '\033]8;id=id1;https://example.com/a\033\\A\033]8;;\033\\B' +check_raw_matches hyperlink \ + 'L 0 \(0\) flags=EXTENDED,HYPERLINK\[[0-9a-f]+\]' \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\].* link=https://example.com/a linkid=id1' \ + 'C 0,1 data=\(1,1,B\) flags=NONE\[0\].* link=NONE linkid=NONE' + +exit $exit_status diff --git a/regress/input-raw-unicode.sh b/regress/input-raw-unicode.sh new file mode 100644 index 000000000..76e2f5512 --- /dev/null +++ b/regress/input-raw-unicode.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane wide 8 3 'A\343\201\202B' +check_capture wide 'AあB' +check_raw_matches wide \ + 'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \ + 'C 0,1 data=\(2,3,あ\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,2 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,3 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane combining 8 3 'e\314\201x' +check_raw_matches combining \ + 'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \ + 'C 0,0 data=\(1,[0-9]+,.*\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,1 data=\(1,1,x\) flags=NONE\[0\]' + +start_pane emoji 10 3 '\360\237\230\200Z' +check_raw_matches emoji \ + 'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \ + 'C 0,0 data=\(2,4,😀\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,2 data=\(1,1,Z\) flags=NONE\[0\]' + +start_pane flag 10 3 '\360\237\207\254\360\237\207\247!' +check_raw_matches flag \ + 'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \ + 'C 0,0 data=\(2,8,🇬🇧\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,2 data=\(1,1,!\) flags=NONE\[0\]' + +start_pane variation 10 3 '*\357\270\217!' +check_raw_matches variation \ + 'L 0 \(0\) flags=EXTENDED\[[0-9a-f]+\]' \ + 'C 0,0 data=\(2,[0-9]+,.*\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,2 data=\(1,1,!\) flags=NONE\[0\]' + +start_pane invalid 10 3 '\377A' +check_raw_matches invalid \ + 'C 0,0 data=\(1,3,.*\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,1 data=\(1,1,A\) flags=NONE\[0\]' + +start_pane trunc2 10 3 '\303A' +check_raw_matches trunc2 \ + 'C 0,0 data=\(1,3,.*\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,1 data=\(1,1,A\) flags=NONE\[0\]' + +start_pane trunc3 10 3 '\342\202A' +check_raw_matches trunc3 \ + 'C 0,0 data=\(1,3,.*\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,1 data=\(1,1,A\) flags=NONE\[0\]' + +start_pane overwrite-wide-left 10 3 'A\343\201\202B\r\033[1CX' +check_raw_matches overwrite-wide-left \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1,X\) flags=NONE\[0\]' \ + 'C 0,2 data=\(1,1, \) flags=NONE\[0\]' \ + 'C 0,3 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane overwrite-wide-pad 10 3 'A\343\201\202B\r\033[2CX' +check_raw_matches overwrite-wide-pad \ + 'C 0,0 data=\(1,1,A\) flags=NONE\[0\]' \ + 'C 0,1 data=\(1,1, \) flags=NONE\[0\]' \ + 'C 0,2 data=\(1,1,X\) flags=NONE\[0\]' \ + 'C 0,3 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane overwrite-wide-with-wide 10 3 'A\343\201\202B\r\033[1C\347\225\214' +check_raw_matches overwrite-wide-with-wide \ + 'C 0,1 data=\(2,3,界\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 0,2 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 0,3 data=\(1,1,B\) flags=NONE\[0\]' + +start_pane wide-right-edge 4 3 'ABC\343\201\202Z' +check_raw_matches wide-right-edge \ + 'L 0 \(0\) flags=WRAPPED\[[0-9a-f]+\]' \ + 'C 1,0 data=\(2,3,あ\) flags=NONE\[0\] attr=NONE\[0\]' \ + 'C 1,1 data=\(1,1,!\) flags=PADDING\[[0-9a-f]+\] attr=NONE\[0\]' \ + 'C 1,2 data=\(1,1,Z\) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-raw-wrap.sh b/regress/input-raw-wrap.sh new file mode 100644 index 000000000..7ae2634d6 --- /dev/null +++ b/regress/input-raw-wrap.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane wrap 5 3 'ABCDEZ' +check_capture wrap 'ABCDE +Z' +check_raw_matches wrap \ + '^G 5x3 \(0/0\)$' \ + 'L 0 \(0\) flags=WRAPPED\[[0-9a-f]+\]' \ + 'C 0,4 data=\(1,1,E\) flags=NONE\[0\]' \ + 'C 1,0 data=\(1,1,Z\) flags=NONE\[0\]' + +start_pane nowrap 5 3 '\033[?7lABCDEZ' +check_capture nowrap 'ABCDZ' +check_raw_matches nowrap \ + '^G 5x3 \(0/0\)$' \ + 'L 0 \(0\) flags=NONE\[0\]' \ + 'C 0,4 data=\(1,1,Z\) flags=NONE\[0\]' + +start_pane pending 5 3 'ABCD\r\033[4CZ' +check_capture pending 'ABCDZ' +check_cursor pending '5,0' +check_raw_matches pending \ + 'L 0 \(0\) flags=NONE\[0\]' \ + 'C 0,4 data=\(1,1,Z\) flags=NONE\[0\]' + +exit $exit_status diff --git a/regress/input-replies.sh b/regress/input-replies.sh new file mode 100644 index 000000000..9baed827d --- /dev/null +++ b/regress/input-replies.sh @@ -0,0 +1,94 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) +TMUX="$TEST_TMUX -Ltest -f/dev/null" + +$TMUX kill-server 2>/dev/null +sleep 0.1 + +TMP=$(mktemp) +EXP=$(mktemp) +trap 'rm -f "$TMP" "$EXP"; $TMUX kill-server 2>/dev/null' 0 1 15 + +$TMUX new-session -d -x 80 -y 24 -s replies \; \ + set-window-option -t replies:0 remain-on-exit on || exit 1 +$TMUX set-option -s set-clipboard on || exit 1 +$TMUX set-option -s get-clipboard buffer || exit 1 +printf Hello | $TMUX load-buffer - +sleep 0.3 + +exit_status=0 + +fail() +{ + echo "FAIL: $1" + diff -u "$EXP" "$TMP" + exit_status=1 +} + +query() +{ + name=$1 + expected=$2 + seq=$3 + count=$4 + setup=$5 + + $TMUX respawn-window -k -t replies:0 \ + "stty raw -echo min 1 time 20; printf '$setup'; printf '$seq'; dd bs=1 count=$count 2>/dev/null | cat -v >$TMP" + sleep 0.5 + printf "%s" "$expected" >"$EXP" + cmp "$TMP" "$EXP" || fail "$name" +} + +query_timeout() +{ + name=$1 + expected=$2 + seq=$3 + setup=$4 + + $TMUX respawn-window -k -t replies:0 \ + "stty raw -echo min 0 time 5; printf '$setup'; printf '$seq'; sleep 0.1; dd bs=1 count=128 2>/dev/null | cat -v >$TMP" + sleep 0.7 + printf "%s" "$expected" >"$EXP" + cmp "$TMP" "$EXP" || fail "$name" +} + +query "dsr-ok" '^[[0n' '\033[5n' 4 '' +query "dsr-cursor" '^[[1;1R' '\033[6n' 6 '' +query "da-primary" '^[[?1;2c' '\033[c' 7 '' +query "da-secondary" '^[[>84;0;0c' '\033[>c' 10 '' +query "decrqm-irm-reset" '^[[4;2$y' '\033[4$p' 8 '' +query "decrqm-irm-set" '^[[4;1$y' '\033[4$p' 8 '\033[4h' +query "decrqm-cursor-keys-reset" '^[[?1;2$y' '\033[?1$p' 9 '' +query "decrqm-cursor-keys-set" '^[[?1;1$y' '\033[?1$p' 9 '\033[?1h' +query "decrqm-columns" '^[[?3;4$y' '\033[?3$p' 9 '' +query "decrqm-origin-reset" '^[[?6;2$y' '\033[?6$p' 9 '' +query "decrqm-origin-set" '^[[?6;1$y' '\033[?6$p' 9 '\033[?6h' +query "decrqm-wrap-set" '^[[?7;1$y' '\033[?7$p' 9 '' +query "decrqm-wrap-reset" '^[[?7;2$y' '\033[?7$p' 9 '\033[?7l' +query "decrqm-cursor-visible-set" '^[[?25;1$y' '\033[?25$p' 10 '' +query "decrqm-cursor-visible-reset" '^[[?25;2$y' '\033[?25$p' 10 '\033[?25l' +query "decrqm-mouse-standard-set" '^[[?1000;1$y' '\033[?1000$p' 12 '\033[?1000h' +query "decrqm-mouse-button-set" '^[[?1002;1$y' '\033[?1002$p' 12 '\033[?1002h' +query "decrqm-mouse-all-set" '^[[?1003;1$y' '\033[?1003$p' 12 '\033[?1003h' +query "decrqm-focus-set" '^[[?1004;1$y' '\033[?1004$p' 12 '\033[?1004h' +query "decrqm-mouse-utf8-set" '^[[?1005;1$y' '\033[?1005$p' 12 '\033[?1005h' +query "decrqm-mouse-sgr-set" '^[[?1006;1$y' '\033[?1006$p' 12 '\033[?1006h' +query "decrqm-bracket-paste-set" '^[[?2004;1$y' '\033[?2004$p' 12 '\033[?2004h' +query "decrqm-theme-updates-set" '^[[?2031;1$y' '\033[?2031$p' 12 '\033[?2031h' +query "decrqss-cursor-style" '^[P1$r q0 q' '\033P$q q\033\\' 10 '' + +query_timeout "osc-10-query" '^[]10;rgb:ffff/0000/0000^G' '\033]10;?\007' '\033]10;red\007' +query_timeout "osc-11-query" '^[]11;rgb:0000/0000/ffff^G' '\033]11;?\007' '\033]11;blue\007' +query_timeout "osc-12-query" '^[]12;rgb:0000/ffff/0000^G' '\033]12;?\007' '\033]12;green\007' +query_timeout "osc-4-query" '^[]4;1;rgb:ffff/0000/0000^G' '\033]4;1;?\007' '\033]4;1;red\007' +query_timeout "osc-104-reset-query" '' '\033]4;1;?\007' '\033]4;1;red\007\033]104;1\007' +query_timeout "osc-52-query" '^[]52;c;SGVsbG8=^G' '\033]52;c;?\007' '' + +$TMUX kill-server 2>/dev/null +exit $exit_status diff --git a/regress/input-requests.sh b/regress/input-requests.sh new file mode 100644 index 000000000..d9186c673 --- /dev/null +++ b/regress/input-requests.sh @@ -0,0 +1,117 @@ +#!/bin/sh + +PATH=/bin:/usr/bin +TERM=screen + +[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux) + +python3 - "$TEST_TMUX" <<'PY' +import os +import select +import signal +import subprocess +import sys +import tempfile +import time + +tmux = sys.argv[1] +server = [tmux, "-Ltest", "-f/dev/null"] + +def run(*args, check=True): + return subprocess.run(server + list(args), check=check, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + +def attach(): + pid, fd = os.forkpty() + if pid == 0: + os.environ["TERM"] = "xterm-256color" + os.execl(tmux, tmux, "-Ltest", "-f/dev/null", "attach-session", + "-t", "requests") + os.set_blocking(fd, False) + return pid, fd + +def read_until(fd, needle, timeout=5): + end = time.time() + timeout + data = b"" + while time.time() < end: + r, _, _ = select.select([fd], [], [], 0.05) + if fd in r: + try: + chunk = os.read(fd, 4096) + except BlockingIOError: + chunk = b"" + if chunk == b"": + continue + data += chunk + if needle in data: + return data + raise RuntimeError("did not see terminal request %r in %r" % + (needle, data)) + +def wait_file(path, timeout=5): + end = time.time() + timeout + while time.time() < end: + try: + with open(path, "rb") as f: + data = f.read() + if data: + return data + except FileNotFoundError: + pass + time.sleep(0.05) + return b"" + +def respawn(command): + run("respawn-window", "-k", "-t", "requests:0", command) + time.sleep(0.2) + +def cleanup(pid=None): + if pid is not None: + try: + os.kill(pid, signal.SIGHUP) + except ProcessLookupError: + pass + run("kill-server", check=False) + +run("kill-server", check=False) +run("new-session", "-d", "-x", "80", "-y", "24", "-s", "requests", + "sleep 60") + +pid, fd = attach() +try: + time.sleep(0.5) + + with tempfile.NamedTemporaryFile(delete=False) as f: + palette_out = f.name + respawn("stty raw -echo min 1 time 50; " + "printf '\\033]4;99;?\\033\\\\'; " + "dd bs=1 count=64 2>/dev/null | cat -v >%s; sleep 1" % + palette_out) + read_until(fd, b"\033]4;99;?\033\\") + os.write(fd, b"\033]4;99;rgb:0101/0202/0303\033\\") + got = wait_file(palette_out) + expected = b"^[]4;99;rgb:0101/0202/0303^[\\" + if got != expected: + raise AssertionError("palette reply: expected %r got %r" % + (expected, got)) + + run("set-option", "-s", "set-clipboard", "on") + run("set-option", "-s", "get-clipboard", "request") + with tempfile.NamedTemporaryFile(delete=False) as f: + clip_out = f.name + respawn("stty raw -echo min 1 time 50; " + "printf '\\033]52;c;?\\033\\\\'; " + "dd bs=1 count=64 2>/dev/null | cat -v >%s; sleep 1" % + clip_out) + data = read_until(fd, b"]52;") + if b"?" not in data: + raise RuntimeError("clipboard request missing query in %r" % data) + os.write(fd, b"\033]52;c;UmVxdWVzdA==\033\\") + got = wait_file(clip_out) + expected = b"^[]52;c;UmVxdWVzdA==^[\\" + if got != expected: + raise AssertionError("clipboard reply: expected %r got %r" % + (expected, got)) +finally: + cleanup(pid) +PY diff --git a/regress/input-scroll.sh b/regress/input-scroll.sh new file mode 100644 index 000000000..6ae48e96d --- /dev/null +++ b/regress/input-scroll.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane wrap 5 3 'abcdeF' +check_capture wrap 'abcde +F' +check_cursor wrap '1,1' +check_flags wrap 'W abcde +- F' +check_joined wrap 'abcdeF' + +start_pane wraplast 5 3 'abcd\033[5GZQ' +check_capture wraplast 'abcdZ +Q' +check_cursor wraplast '1,1' + +start_pane nowrap 5 3 '\033[?7labcdeF' +check_capture nowrap 'abcdF' +check_cursor nowrap '4,0' + +start_pane origin 6 4 '111111\n222222\n333333\n444444\033[2;3r\033[?6h\033[1;1HAA\033[?6l\033[r' +check_capture origin '111111 +AA2222 +333333 +444444' + +start_pane scrollup 5 4 '11111\n22222\n33333\n44444\033[2;3r\033[3;1HAAAAA\nBBBBB\033[r' +check_capture scrollup '11111 +AAAAA +BBBBB +44444' + +start_pane scrolldown 5 4 '11111\n22222\n33333\n44444\033[2;3r\033[2;1H\033[TZZZZZ\033[r' +check_capture scrolldown '11111 +ZZZZZ +22222 +44444' + +start_pane ri 5 4 '11111\n22222\n33333\n44444\033[2;3r\033[2;1H\033MZZZZZ\033[r' +check_capture ri '11111 +ZZZZZ +22222 +44444' + +start_pane nel 5 3 'AA\033EBC\n' +check_capture nel 'AA +BC' + +$TMUX kill-server 2>/dev/null +sleep 0.1 +$TMUX new-session -d -x 5 -y 3 -s history \; \ + set-option -g history-limit 3 \; \ + respawn-pane -k "printf '01\n02\n03\n04\n05\n06'; sleep 2" || exit 1 +sleep 0.3 +$TMUX capture-pane -pN -t history: -S - -E - | normalize_capture >"$TMP" +printf "%s\n" '01 +02 +03 +04 +05 +06' >"$EXP" +cmp "$TMP" "$EXP" || fail "history limit" + +$TMUX clear-history -t history: +$TMUX capture-pane -pN -t history: -S - -E - | normalize_capture >"$TMP" +printf "%s\n" '04 +05 +06' >"$EXP" +cmp "$TMP" "$EXP" || fail "clear-history" + +$TMUX kill-server 2>/dev/null +exit $exit_status diff --git a/regress/input-sgr.sh b/regress/input-sgr.sh new file mode 100644 index 000000000..435a0a9ab --- /dev/null +++ b/regress/input-sgr.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane sgr-basic 20 3 '\033[1;2;3;4;5;7;8;9mA\033[22;23;24;25;27;28;29mB\n' +check_capture sgr-basic 'AB' +$TMUX capture-pane -peN -t sgr-basic: -S 0 -E - >/dev/null || exit 1 + +start_pane sgr-colour 20 3 '\033[31;42mA\033[38;5;196;48;5;22mB\033[38;2;1;2;3;48;2;4;5;6mC\033[39;49mD\n' +check_capture sgr-colour 'ABCD' +$TMUX capture-pane -peN -t sgr-colour: -S 0 -E - >/dev/null || exit 1 + +start_pane sgr-underline 20 3 '\033[4:1mA\033[4:2mB\033[4:3mC\033[4:4mD\033[4:5mE\033[4:0mF\n' +check_capture sgr-underline 'ABCDEF' +$TMUX capture-pane -peN -t sgr-underline: -S 0 -E - >/dev/null || exit 1 + +start_pane sgr-uscolour 20 3 '\033[58;5;45;4mA\033[58:2::10:20:30mB\033[59mC\n' +check_capture sgr-uscolour 'ABC' +$TMUX capture-pane -peN -t sgr-uscolour: -S 0 -E - >/dev/null || exit 1 + +start_pane sgr-reset 20 3 '\033[90;100mA\033[0mB\033[91;101mC\033[39;49mD\n' +check_capture sgr-reset 'ABCD' +$TMUX capture-pane -peN -t sgr-reset: -S 0 -E - >/dev/null || exit 1 + +$TMUX kill-server 2>/dev/null +exit $exit_status diff --git a/regress/input-unicode.sh b/regress/input-unicode.sh new file mode 100644 index 000000000..ca74a82e8 --- /dev/null +++ b/regress/input-unicode.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +. ./input-common.inc + +start_pane wide 10 3 '\343\201\202B\rX\n' +check_capture wide 'X B' +check_flags wide 'X X B' + +start_pane widepad 10 3 'A\343\201\202B\r\033[2CX\n' +check_capture widepad 'A XB' +check_flags widepad 'X A XB' + +start_pane wideedge 5 3 'abc\343\201\202Z\n' +check_capture wideedge 'abcあ +Z' +check_cursor wideedge '0,2' +check_joined wideedge 'abcあZ' + +start_pane wideeol 5 3 'abcd\343\201\202Z\n' +check_capture wideeol 'abcd +あZ' +check_cursor wideeol '0,2' + +start_pane combine 10 3 'e\314\201\n' +check_capture combine 'é' +check_cursor combine '0,1' + +start_pane combinewide 10 3 '\343\201\202\314\201X\n' +check_capture combinewide 'あ́X' +check_cursor combinewide '0,1' + +start_pane variation 10 3 '\342\234\224\357\270\217X\n' +check_capture variation '✔️X' +check_cursor variation '0,1' + +start_pane flag 10 3 '\360\237\207\254\360\237\207\247X\n' +check_capture flag '🇬🇧X' +check_cursor flag '0,1' + +start_pane combining-left 10 3 '\314\201A\n' +check_capture combining-left 'A' +check_cursor combining-left '0,1' + +$TMUX kill-server 2>/dev/null +exit $exit_status