1#!/bin/sh 2# 3# $OpenBSD: emacs.sh,v 1.15 2021/09/02 07:14:15 jasper Exp $ 4# 5# Copyright (c) 2017 Anton Lindqvist <anton@openbsd.org> 6# Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org> 7# 8# Permission to use, copy, modify, and distribute this software for any 9# purpose with or without fee is hereby granted, provided that the above 10# copyright notice and this permission notice appear in all copies. 11# 12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 20. "${1:-.}/subr.sh" 21 22KSH=$2 23 24EDITOR= 25ENV= 26HISTFILE= 27MAIL= 28PS1=' # ' 29VISUAL=emacs 30export EDITOR ENV HISTFILE MAIL PS1 VISUAL 31 32# The function testseq() sets up a pseudo terminal and feeds its first 33# argument to a shell on standard input. It then checks that output 34# from the shell to the pseudo terminal agrees with the second argument. 35 36# auto-insert 37testseq "abc" " # abc" 38 39# insertion of valid UTF-8 40testseq "z\0002\0302\0200" " # z\b\0302\0200z\b" 41testseq "z\0002\0337\0277" " # z\b\0337\0277z\b" 42testseq "z\0002\0340\0240\0200" " # z\b\0340\0240\0200z\b" 43testseq "z\0002\0354\0277\0277" " # z\b\0354\0277\0277z\b" 44testseq "z\0002\0355\0200\0200" " # z\b\0355\0200\0200z\b" 45testseq "z\0002\0355\0237\0277" " # z\b\0355\0237\0277z\b" 46testseq "z\0002\0356\0200\0200" " # z\b\0356\0200\0200z\b" 47testseq "z\0002\0357\0277\0277" " # z\b\0357\0277\0277z\b" 48testseq "z\0002\0360\0220\0200\0200" " # z\b\0360\0220\0200\0200z\b" 49testseq "z\0002\0360\0277\0277\0277" " # z\b\0360\0277\0277\0277z\b" 50testseq "z\0002\0361\0200\0200\0200" " # z\b\0361\0200\0200\0200z\b" 51testseq "z\0002\0363\0277\0277\0277" " # z\b\0363\0277\0277\0277z\b" 52testseq "z\0002\0364\0200\0200\0200" " # z\b\0364\0200\0200\0200z\b" 53testseq "z\0002\0364\0217\0277\0277" " # z\b\0364\0217\0277\0277z\b" 54 55# insertion of incomplete UTF-8 56testseq "z\0002\0302\0006" " # z\b\0302z\bz" 57testseq "z\0002\0377\0006" " # z\b\0377z\bz" 58testseq "z\0002\0337\0006" " # z\b\0337z\bz" 59testseq "z\0002\0340\0006" " # z\b\0340z\bz" 60testseq "z\0002\0357\0006" " # z\b\0357z\bz" 61testseq "z\0002\0364\0006" " # z\b\0364z\bz" 62testseq "z\0002\0340\0240\0006" " # z\b\0340\0240z\bz" 63testseq "z\0002\0354\0277\0006" " # z\b\0354\0277z\bz" 64testseq "z\0002\0355\0200\0006" " # z\b\0355\0200z\bz" 65testseq "z\0002\0355\0237\0006" " # z\b\0355\0237z\bz" 66testseq "z\0002\0356\0200\0006" " # z\b\0356\0200z\bz" 67testseq "z\0002\0357\0277\0006" " # z\b\0357\0277z\bz" 68testseq "z\0002\0360\0220\0200\0006" " # z\b\0360\0220\0200z\bz" 69testseq "z\0002\0360\0277\0277\0006" " # z\b\0360\0277\0277z\bz" 70testseq "z\0002\0361\0200\0200\0006" " # z\b\0361\0200\0200z\bz" 71testseq "z\0002\0363\0200\0200\0006" " # z\b\0363\0200\0200z\bz" 72testseq "z\0002\0363\0277\0277\0006" " # z\b\0363\0277\0277z\bz" 73testseq "z\0002\0364\0200\0200\0006" " # z\b\0364\0200\0200z\bz" 74testseq "z\0002\0364\0217\0277\0006" " # z\b\0364\0217\0277z\bz" 75 76# insertion of invalid bytes 77testseq "z\0002\0300\0277" " # z\b\0300z\b\b\0300\0277z\b" 78testseq "z\0002\0301\0277" " # z\b\0301z\b\b\0301\0277z\b" 79testseq "z\0002\0360\0217" " # z\b\0360z\b\b\0360\0217z\b" 80testseq "z\0002\0365\0217" " # z\b\0365z\b\b\0365\0217z\b" 81testseq "z\0002\0367\0217" " # z\b\0367z\b\b\0367\0217z\b" 82testseq "z\0002\0370\0217" " # z\b\0370z\b\b\0370\0217z\b" 83testseq "z\0002\0377\0217" " # z\b\0377z\b\b\0377\0217z\b" 84 85# insertion of excessively long encodings 86testseq "z\0002\0340\0200\0200" \ 87 " # z\b\0340z\b\b\0340\0200z\b\b\0340\0200\0200z\b" 88testseq "z\0002\0340\0201\0277" \ 89 " # z\b\0340z\b\b\0340\0201z\b\b\0340\0201\0277z\b" 90testseq "z\0002\0340\0202\0200" \ 91 " # z\b\0340z\b\b\0340\0202z\b\b\0340\0202\0200z\b" 92testseq "z\0002\0340\0237\0277" \ 93 " # z\b\0340z\b\b\0340\0237z\b\b\0340\0237\0277z\b" 94testseq "z\0002\0360\0200\0200\0200" \ 95 " # z\b\0360z\b\b\0360\0200z\b\b\0360\0200\0200z\b\b\0360\0200\0200\0200z\b" 96testseq "z\0002\0360\0217\0277\0277" \ 97 " # z\b\0360z\b\b\0360\0217z\b\b\0360\0217\0277z\b\b\0360\0217\0277\0277z\b" 98 99# insertion of surrogates and execessive code points 100testseq "z\0002\0355\0240\0200" \ 101 " # z\b\0355z\b\b\0355\0240z\b\b\0355\0240\0200z\b" 102testseq "z\0002\0355\0277\0277" \ 103 " # z\b\0355z\b\b\0355\0277z\b\b\0355\0277\0277z\b" 104testseq "z\0002\0364\0220\0200\0200" \ 105 " # z\b\0364z\b\b\0364\0220z\b\b\0364\0220\0200z\b\b\0364\0220\0200\0200z\b" 106testseq "z\0002\0364\0277\0277\0277" \ 107 " # z\b\0364z\b\b\0364\0277z\b\b\0364\0277\0277z\b\b\0364\0277\0277\0277z\b" 108 109# insertion of unmatched meta sequence 110testseq "z\0002\0033[3z" " # z\b\0007" 111 112# ^C, ^G: abort 113testseq "echo 1\0003" " # echo 1\r\n # " 114testseq "echo 1\0007" " # echo 1\r\n # " 115 116# ^B, Left: backward-char 117testseq "\0002" " # \0007" 118testseq "a\0002" " # a\0010" 119testseq "\0303\0266\0002" " # \0303\0266\0010" 120testseq "a\0033[D" " # a\0010" 121testseq "a\0033OD" " # a\0010" 122 123# ^[b, Ctrl-Left: backward-word 124testseq "\0033b" " # \0007" 125testseq "a1_$\0033b" " # a1_$\0010\0010\0010\0010" 126testseq "a1 \0303\0266\0033b\0033b" " # a1 \0303\0266\0010\0010\0010\0010" 127testseq "a1_$\0033[1;5D" " # a1_$\0010\0010\0010\0010" 128 129# ^[<: beginning-of-history 130testseq "\0033<" " # \0007" 131testseq ": 1\n: 2\n\0033<" " # : 1\r\r\n # : 2\r\r\n # \r # : 1 \0010" 132 133# ^A, Home, Ctrl-Down: beginning-of-line 134testseq "\0001" " # " 135testseq "aa\0001" " # aa\0010\0010" 136testseq "\0303\0266\0001" " # \0303\0266\0010" 137testseq "aa\0033[H" " # aa\0010\0010" 138testseq "aa\0033OH" " # aa\0010\0010" 139testseq "aa\0033[1~" " # aa\0010\0010" 140testseq "aa\0033[1;5B" " # aa\0010\0010" 141 142# [n] ^[C, ^[c: capitalize-word 143testseq "\0033C\0033c" " # \0007\0007" 144testseq "ab cd\0001\0033C" " # ab cd\0010\0010\0010\0010\0010Ab" 145testseq "ab\0001\00332\0033C" " # ab\0010\0010Ab" 146testseq "ab cd\0001\00332\0033C" " # ab cd\0010\0010\0010\0010\0010Ab Cd" 147testseq "1a\0001\0033C" " # 1a\0010\00101a" 148testseq "\0026\0002\0001\0033C" " # ^B\0010\0010^B" 149testseq "\0303\0266b\0001\0033C" " # \0303\0266b\0010\0010\0303\0266b" 150 151# ^[#: comment 152testseq "\0033#" " # \r # \0010\r\r\n # " 153testseq "a\0033#" " # a\r # #a \0010\0010\0010\r\r\n # " 154 155# XXX ^[^[: complete 156# XXX ^X^[: complete-command 157# XXX ^[^X: complete-file 158# XXX ^I, ^[=: complete-list 159 160# [n] ERASE, ^?, ^H: delete-char-backward 161testseq "\0177\0010" " # \0007\0007" 162testseq "ab\00332\0177" " # ab\0010\0010 \0010\0010" 163testseq "a\00332\0177" " # a\0010 \0010" 164testseq "\0303\0266\0177" " # \0303\0266\0010 \0010" 165 166# [n] Delete: delete-char-forward 167testseq "\0033[3~" " # \0007" 168testseq "a\0033[3~" " # a\0007" 169testseq "a\0001\0033[3~" " # a\0010 \0010" 170testseq "ab\0001\00332\0033[3~" " # ab\0010\0010 \0010\0010" 171testseq "a\0001\00332\0033[3~" " # a\0010 \0010" 172testseq "\0303\0266\0001\0033[3~" " # \0303\0266\0010 \0010" 173 174# [n] ^[ERASE, ^[^?, ^[^H, ^[h: delete-word-backward 175testseq "\0033\0177\033\0010\0033h" " # \0007\0007\0007" 176testseq "ab\0033\0177" " # ab\0010\0010 \0010\0010" 177testseq "ab cd\00332\0033\0177" \ 178 " # ab cd\0010\0010\0010\0010\0010 \0010\0010\0010\0010\0010" 179testseq "ab\00332\0033\0177" " # ab\0010\0010 \0010\0010" 180testseq "ab \0303\0266\0033\0177" " # ab \0303\0266\0010 \0010" 181 182# [n] ^[d: delete-word-forward 183testseq "\0033d" " # \0007" 184testseq "ab\0001\0033d" " # ab\0010\0010 \0010\0010" 185testseq "ab cd\0001\00332\0033d" \ 186 " # ab cd\0010\0010\0010\0010\0010 \0010\0010\0010\0010\0010" 187testseq "ab\0001\00332\0033d" " # ab\0010\0010 \0010\0010" 188 189# [n] ^N, ^XB, Down: down-history 190# [n] ^P, ^XA, Up: up-history 191testseq "\0016\0030B\0020\0030A" " # \0007\0007\0007\0007" 192testseq ": 1\n\0020\0016" " # : 1\r\r\n # \r # : 1 \0010\0007" 193testseq ": 1\n: 2\n\0020\0020\0016" \ 194 " # : 1\r\r\n # : 2\r\r\n # \r # : 2 \0010\r # : 1 \0010\r # : 2 \0010" 195testseq ": 1\n: 2\n\0033[A\0033[A\0033[B" \ 196 " # : 1\r\r\n # : 2\r\r\n # \r # : 2 \0010\r # : 1 \0010\r # : 2 \0010" 197testseq ": 1\n: 2\n\0033OA\0033OA\0033OB" \ 198 " # : 1\r\r\n # : 2\r\r\n # \r # : 2 \0010\r # : 1 \0010\r # : 2 \0010" 199 200# [n] ^[L, ^[l: downcase-word 201testseq "\0033L\0033l" " # \0007\0007" 202testseq "AB\0001\0033L" " # AB\0010\0010ab" 203testseq "AB CD\0001\00332\0033L" " # AB CD\0010\0010\0010\0010\0010ab cd" 204testseq "AB\0001\00332\0033L" " # AB\0010\0010ab" 205testseq "1A\0001\0033L" " # 1A\0010\00101a" 206testseq "\0026\0002A\0001\0033L" " # ^BA\0010\0010\0010^Ba" 207testseq "\0303\0266A\0001\0033L" " # \0303\0266A\0010\0010\0303\0266a" 208 209# ^[>: end-of-history 210testseq "\0033>" " # \0007" 211testseq ": 1\n\0033>" " # : 1\r\r\n # \r # : 1 \0010" 212 213# ^E, End, Ctrl-Up: end-of-line 214testseq "\0005" " # " 215testseq "abc\0001\0005" " # abc\0010\0010\0010abc" 216testseq "\0303\0266\0001\0005" " # \0303\0266\0010\0303\0266" 217testseq "abc\0001\0033[F" " # abc\0010\0010\0010abc" 218testseq "abc\0001\0033OF" " # abc\0010\0010\0010abc" 219testseq "abc\0001\0033[4~" " # abc\0010\0010\0010abc" 220testseq "abc\0001\0033[1;5A" " # abc\0010\0010\0010abc" 221 222# ^_: eot 223testseq "\0037" " # ^D\r\r" 224 225# [n] ^D: eot-or-delete 226testseq "\0004" " # ^D\r\r" 227 228# ^X^X: exchange-point-and-mark 229# ^[space: set-mark-command 230testseq "\0030\0030" " # \0007" 231testseq "abc\0033 \0001\0030\0030" " # abc\0010\0010\0010abc" 232testseq "\0303\0266\0033 \0001\0030\0030" " # \0303\0266\0010\0303\0266" 233 234# XXX ^[*: expand-file 235 236# [n] ^F, ^XC, Right: forward-char 237testseq "\0006\0030C" " # \0007\0007" 238testseq "abc\0001\0006" " # abc\0010\0010\0010a" 239testseq "abc\0001\00332\0006" " # abc\0010\0010\0010ab" 240testseq "a\0001\00332\0006" " # a\0010a" 241testseq "\0303\0266\0001\0006" " # \0303\0266\0010\0303\0266" 242testseq "abc\0001\0033[C" " # abc\0010\0010\0010a" 243testseq "abc\0001\0033OC" " # abc\0010\0010\0010a" 244 245# [n] ^[f, Ctrl-Right: forward-word 246testseq "\0033f" " # \0007" 247testseq "ab\0001\0033f" " # ab\0010\0010ab" 248testseq "ab cd\0001\00332\0033f" " # ab cd\0010\0010\0010\0010\0010ab cd" 249testseq "ab\0001\00332\0033f" " # ab\0010\0010ab" 250testseq "\0303\0266\0001\0033f" " # \0303\0266\0010\0303\0266" 251testseq "ab\0001\0033[1;5C" " # ab\0010\0010ab" 252 253# [n] ^[g: goto-history 254testseq "\0033g" " # \0007" 255testseq ": 1\n\0033g" " # : 1\r\r\n # \r # : 1 \0010" 256testseq ": 1\n: 2\n\00332\0033g" " # : 1\r\r\n # : 2\r\r\n # \r # : 2 \0010" 257testseq ": 1\n\00332\0033g" " # : 1\r\r\n # \0007" 258 259# KILL: kill-line 260testseq "\0025" " # \r # \0010" 261testseq "ab\0025" " # ab\r # \0010\0010\0010" 262 263# [n] ^K: kill-to-eol 264testseq "\0013" " # " 265testseq "abc\0002\0002\0013" " # abc\0010\0010 \0010\0010" 266 267# XXX ^[?: list 268# XXX ^X?: list-command 269# XXX ^X^Y: list-file 270 271# ^J, ^M: newline 272testseq "\0012\0015" " # \r\r\n # \r\r\n # " 273testseq ": 1\0012" " # : 1\r\r\n # " 274testseq ": 1\0001\0012" " # : 1\0010\0010\0010\r\r\n # " 275 276# ^O: newline-and-next 277testseq "\0017" " # \r\r\n # \0007" 278testseq ": 1\n: 2\n\0020\0020\0017" \ 279 " # : 1\r\r\n # : 2\r\r\n # \r # : 2 \0010\r # : 1 \0010\r\r\n # \r # : 2 \0010" 280 281# QUIT: no-op 282testseq "\0034" " # " 283 284# [n] ^[., ^[_: prev-hist-word 285testseq "\0033.\0033_" " # \0007\0007" 286testseq ": 1\n\0033." " # : 1\r\r\n # 1" 287testseq ": 1\n\00331\0033." " # : 1\r\r\n # :" 288testseq ": 1\n\00333\0033." " # : 1\r\r\n # " 289 290# ^V, ^^: quote 291testseq "\0026\0001" " # ^A" 292testseq "\0036\0001" " # ^A" 293 294# [n] ^[^]: search-character-backward 295testseq "\0033\0035a" " # \0007" 296testseq "echo\0033\0035e" " # echo\0010\0010\0010\0010" 297testseq "echo\0033\0035a" " # echo\0007" 298testseq "eecho\00332\0033\0035e" " # eecho\0010\0010\0010\0010\0010" 299testseq "echo\00332\0033\0035e" " # echo\0007" 300 301# [n] ^]: search-character-forward 302testseq "\0035a" " # \0007" 303testseq "echo\0001\0035o" " # echo\0010\0010\0010\0010ech" 304testseq "echo\0001\0035a" " # echo\0010\0010\0010\0010\0007" 305testseq "echoo\0001\00332\0035o" " # echoo\0010\0010\0010\0010\0010echo" 306# XXX differs from search-character-backward, should ring bell 307testseq "echo\0001\00332\0035o" " # echo\0010\0010\0010\0010ech" 308 309# ^R: search-history 310testseq "\0022" " # \r\nI-search: " 311testseq "echo\n\0022e" \ 312 " # echo\r\r\n\r\n # \r\nI-search: \r\n\r # echo \0010\0010\0010\0010" 313testseq "echo\n\0022a" " # echo\r\r\n\r\n # \r\nI-search: \0007\r\nI-search: a" 314 315# ^T: transpose-chars 316testseq "\0024" " # \0007" 317testseq "a\0024" " # a\0007" 318testseq "ab\0024" " # ab\0010\0010ba" 319testseq "ab\0001\0024" " # ab\0010\0010\0007" 320# XXX UTF-8 testseq "\0303\0266a\0024" " # \0303\0266a\0010\0010a\303\0266" 321 322# [n] ^[U, ^[u: upcase-word 323testseq "\0033U\0033u" " # \0007\0007" 324testseq "ab\0001\0033U" " # ab\0010\0010AB" 325testseq "ab cd\0001\00332\0033U" " # ab cd\0010\0010\0010\0010\0010AB CD" 326testseq "ab\0001\00332\0033U" " # ab\0010\0010AB" 327testseq "1a\0001\0033U" " # 1a\0010\00101A" 328testseq "\0026\0002a\0001\0033U" " # ^Ba\0010\0010\0010^BA" 329testseq "\0303\0266a\0001\0033U" " # \0303\0266a\0010\0010\0303\0266A" 330 331# ^Y: yank 332testseq "\0031" " # \r\nnothing to yank\r\n # " 333testseq "abc\0027\0031" " # abc\0010\0010\0010 \0010\0010\0010abc" 334testseq "ab/cd\0027\0001\0031" \ 335 " # ab/cd\0010\0010 \0010\0010\0010\0010\0010cdab/\0010\0010\0010" 336 337# ^[y: yank-pop 338testseq "\0033y" " # \r\nyank something first\r\n # " 339testseq "ab/cd\0027\0027\0031\0033y" \ 340 " # ab/cd\0010\0010 \0010\0010\0010\0010\0010 \0010\0010\0010ab/\0010\0010\0010 \0010\0010\0010cd" 341