#
# Edit Here - Functional Tests
#

.POSIX:
.SUFFIXES:
.SUFFIXES: .txt .out .cdb

.PHONY: all clean clobber distclean test tests

all: test

clean:
	-rm -f *.core *.stackdump a.out a.txt b.txt
	-rm -rf test/terminfo.cdb

distclean clobber: clean
	-rm -f typescript

#######################################################################
# Tests
#
# The basic terminals, like `dumb`, `glasstty`, `vanilla`, `lpr` are
# insufficient to drive NetBSD Curses.  Try `TERM=ansi-mini` for bare
# bones.
#
# For testing and debugging define a terminal where the defined escape
# sequences are readable text.  This avoids differences between terminal
# definitions across platforms.
#
# However, differences in Curses libraries, ie. NetBSD Curses vs Linux
# NCurses can reorder escape sequences to produce the same visual result.
# Similarly library upgrades might reorder escape sequences as seen between
# NetBSD 9.3 and 10.0.
#
#######################################################################

PROG	?= ./prog

# Set ASK=true to prompt to update a failed test.
ASK	?= false

# Set REBUILD=true to update all the failed tests.
REBUILD	?= false

T		= test
TESTTERM	= $T/${TERM}
DATA		= $T/data
RESET		= rm -f a.txt a.out *.core
TITLE		= printf "%s      %s: " ${PROG} $@ ; ${RESET}
PASS		= printf "\r%s -OK-\r\n" ${PROG}
SKIP		= printf "\r%s SKIP\r\n" ${PROG}
PROMPT		= ( ${ASK} && echo -n "Replace y/N$$PS2" && read yn && test "$$yn" = 'y' )
SAVE		= ( ${REBUILD} || ${PROMPT} ) && cp a.out ${TESTTERM}/$@.out
A_CORE		= test ! -f *.core
A_OUT		= ( diff -u ${TESTTERM}/$@.out a.out || ${SAVE} )
A_TXT		= diff -u ${DATA}/$@.txt a.txt
A_OUT_OR_SKIP	= ( ${A_OUT} >/dev/null && ${PASS} ) || ${SKIP}
A_TXT_OR_SKIP	= ( diff -u ${DATA}/$@.txt a.txt ) || ${SKIP}

# Be sure to build the target binary separately before hand.  This allows
# testing an alternative binary by setting PROG, eg. make PROG=./boo test

test:
	@printf '###\n### YOU ARE HERE >>> %s <<<\n###\n' "$$(pwd)"
	${MAKE} -f $T/Makefile PROG=${PROG} TERM=textterm LINES=24 COLUMNS=80 TERMINFO=$${PWD}/$T/terminfo.cdb tests

TESTS:= tests_have_term_data \
	term0 empty0 empty1 empty3 redraw0 \
	ins0 ins1 ins2 ins3 ins4 ins5 \
	del0 del1 del2 del3 del4 del5 del6 \
	scroll0 scroll1 scroll2 \
	goto0 goto1 goto2 goto3 \
	pgdn0 pgdn1 pgdn2 pgdn3 pgdn4 pgup0 pgup1 pgup2 pgup3 \
	ere0 ere1 ere2 ere3 ere4 ere5 ere6 ere7 ere8 ere9 ere10 ere11 \
	del7 del8 del9 del10 del11 del13 \
	undo0 undo1 undo2 undo3 \
	paste0 paste1 paste2 \
	select0 select1 select2 select3 select4 \
	mb0 mb1 mb2 mb3 mb4

.PHONY : ${TESTS}
.SILENT: ${TESTS}

tests: $T/terminfo.cdb ${TESTS} clean

tests_skipped: \
	arg0 empty2 write1 \
	flip0 flip1 \
	mark0 mark1 mark2 mark3 mark4 mark5 \
	bang0 bang1 bang2 bang3 bang4 bang5 bang6 bang7 \
	replace0 replace1 replace2 write0 read0 read1 \
	del12 \
	paste3 \
	select5

# While the terminal definition will probably contain definitions for
# the number of hardware `lines` and `columns`, we explicitly override
# them to be sure to ensure terminal emulator dimensions are ignored.

$T/terminfo.cdb : $T/terminfo
	tic -x -o $@ $T/terminfo

tests_have_term_data:
	@test -d ${TESTTERM}
	@echo TERM=${TERM}

# Allow missing filename argument.
arg0:
	-${TITLE}
	-printf "\aQ" | ${PROG} >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Dumb terminal.
term0:
	-${TITLE}
	TERM=BOGUS ${PROG} a.txt 2>/dev/null || test $$? -eq 1
	${A_CORE}
	-${PASS}

# An unknown command character redraws the screen.
redraw0:
	-${TITLE}
	printf "\aQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Start and stop.
empty0:
	-${TITLE}
	printf "Q" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Start, write an empty buffer, and stop.  Creates a.txt.
empty1:
	-${TITLE}
	printf "W\nQ" | ${PROG} a.txt >a.out
	diff -u ${DATA}/empty.txt a.txt
	${A_CORE}
	${A_OUT}
	-${PASS}

# This test does not work since backspace in redirected input is
# treated differently from a tty.  See NetBSD 10.0 lib/58151
empty2:
	-${TITLE}
	printf 'W\b\b\b\b\bb.txt\nQ' | ${PROG} a.txt >a.out
	test ! -f a.txt && diff -u ${DATA}/empty.txt b.txt
	${A_CORE}
	${A_OUT}
	-${PASS}

# Start and stop.
empty3:
	-${TITLE}
	printf "\003" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

flip0:
	-${TITLE}
	printf "iHELLO world!\e|~~~~~~~~~~~~W\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

flip1:
	-${TITLE}
	printf "iHello World!\e|12~W\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Start, insert nothing, and stop.
ins0:
	-${TITLE}
	printf "i\eQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Insert newline terminated, write, and stop.
ins1:
	-${TITLE}
	printf "iHello\n\tworld!\n\eW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Insert not newline terminated, write, and stop.
#
# + Insert `i` and type some text, newline, more text, `ESC`.  TOP should
#   remain unchanged, newline pushes `^D` down a row.
ins2:
	-${TITLE}
	printf "iHello\n\twoot!\eW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# + Word right `L`, insert `i`, type some text, then `ESC`.  Any text
#   right of cursor should shift as new text inserted.
ins3:
	-${TITLE}
	printf "iHello world!\e|wiWOOT! \eW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# + `G`, insert `i` and type in a word, newline, next word, `ESC`.  TOP
#    should remain unchanged, newline pushes `^D` down a row.
ins4:
	-${TITLE}
	printf "Hello\n\tworld!\n" >a.txt
	printf "Giinsert at EOF\npush EOF down\neach newline\n\eW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

ins5:
	-${TITLE}
	printf "Hello\n\tworld!\n" >a.txt
	printf 'j99|i WOOT!\eW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Delete from empty buffer.
del0:
	-${TITLE}
	printf "xQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Insert nothing, delete from empty buffer.
del1:
	-${TITLE}
	printf "i\exQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Insert single character, delete from buffer.
del2:
	-${TITLE}
	printf "iZ\ehxW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	diff -u ${DATA}/empty.txt a.txt
	-${PASS}

# Insert some characters, delete last from buffer.
del3:
	-${TITLE}
	printf "i123Z\ehxW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Insert some characters with newline, delete newline from buffer.
del4:
	-${TITLE}
	printf "i123Z\n\ehxW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# + Delete `x` a character.  Text to the right of cursor shifts left one.
del5:
	-${TITLE}
	printf "Hello\n\tworld!\n" >a.txt
	printf "GkxhxW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

del6:
	-${TITLE}
	printf "Hello\n\tworld!\n" >a.txt
	printf "Gk6xW\nQ" | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# + Cursor down `j` from BOF to EOF.  Only cursor moves.
# + Cursor up `k` from EOF to BOF.  Only cursor moves.
scroll0:
	-${TITLE}
	printf "jjjjjjjjjjjkkkkkkkkkkkQ" | ${PROG} $T/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# + Cursor down `j` from BOF to BOP.  Only cursor moves.
# + Cursor down `j` twice from BOP.  Screen scrolls up two logical lines.
# + Cursor up `k` to TOP.  Only cursor moves.
# + Cursor up `k` twice from TOP.  Screen scrolls down two logical lines.
scroll1:
	-${TITLE}
	printf "jjjjjjjjjjjjjjjjjjjjjjjjkkkkkkkkkkkkkkkkkkkkkkkkQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

scroll2:
	-${TITLE}
	printf "24j24kQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# The goto line `G` always repositions the target line at the top of
# the page by design.  This can look a little odd on short less than
# a screen of text, since it does not simply reposition the cursor
# within the screen.  Or jumping to the EOF, since there is no context
# displayed (just cursor up and down a line).
#
# One can debate the merits of this design choice when compared to
# other editors that try to position the target line in the middle
# of the screen or highlight the cursor row or both.  While pretty
# and probably less shocking, positioning the target line at top
# makes for consistency display and easier testing.

# Goto line `<num>G` where `<num>` is on the screen.  Screen redraws
# with target line at TOP.
goto0:
	-${TITLE}
	printf "7G15G2G1GQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Cursor at BOF, cursor down `j` a few lines on the screen, `1G`.
# Cursor moves to BOF.
goto1:
	-${TITLE}
	printf "jjjjjjjjjjjjjjj1GQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Goto EOF `G`.  No terminating newline.
goto2:
	-${TITLE}
	printf "GhkkQ" | ${PROG} test/usage-nonl.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Goto EOF `G`.
goto3:
	-${TITLE}
	printf "GhkkQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Page down `J`.  Short file, no terminating newline.
pgdn0:
	-${TITLE}
	printf "JQ" | ${PROG} test/short-nonl.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Page down `J`.  Short file, terminating newline.
pgdn1:
	-${TITLE}
	printf "JQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Page down to EOF.
pgdn2:
	-${TITLE}
	printf "JJJJQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

pgdn3:
	-${TITLE}
	printf "3JQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

pgdn4:
	-${TITLE}
	printf "3JJQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# + Page up `K` once.  Screen remains unchanged with cursor at TOP and BOF.
# + Page down `J` once.  Cursor moves to EOF.
# + Page up `K`.  Screen redraws its starting point with cursor at TOP and BOF.
pgup0:
	-${TITLE}
	printf "KJKQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Page down and up a couple of pages.
pgup1:
	-${TITLE}
	printf "JJKKQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Goto EOF and page up to BOF.
pgup2:
	-${TITLE}
	printf "GKKKKQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

pgup3:
	-${TITLE}
	printf "G3KKQ" | ${PROG} test/usage.md >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Invalid ERE pattern.
ere0:
	-${TITLE}
	printf "/)(\nQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Start of lines.
ere1:
	-${TITLE}
	printf "/^\nnnnnnnnnnnQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Start of lines.
ere2:
	-${TITLE}
	printf "/^\nnnnnnnnnnQ" | ${PROG} test/short-nonl.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# End of lines.
ere3:
	-${TITLE}
	printf "/$$\nnnnnnnnnnnQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# End of lines.
ere4:
	-${TITLE}
	printf "/$$\nnnnnnnnnnnQ" | ${PROG} test/short-nonl.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Last character of line.
ere5:
	-${TITLE}
	printf "/.$$\nnnnnnnnnQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Last character of line.
ere6:
	-${TITLE}
	printf "/.$$\nnnnnnnnnQ" | ${PROG} test/short-nonl.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Blank lines.
ere7:
	-${TITLE}
	printf "/^$$\nnnQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Blank lines.
ere8:
	-${TITLE}
	printf "/^$$\nnnQ" | ${PROG} test/short-nonl.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Plain text
ere9:
	-${TITLE}
	printf "/line\nnnnQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Blank lines.
ere10:
	-${TITLE}
	printf "/line\nnnnQ" | ${PROG} test/short-nonl.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# No match found.
ere11:
	-${TITLE}
	printf "5w/WOOT\nQ" | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Unset set mark moves cursor to BOF.
mark0:
	-${TITLE}
	printf '3w``Q' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	printf '3w`aQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	printf '3w`zQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Set a mark, move, goto mark, goto previous.
mark1:
	-${TITLE}
	printf 'wm`Jb````Q' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	printf 'wmaJb`a``Q' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	printf 'wmzJb`z``Q' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Set some marks, edit before the marks, marks remain unchanged.
mark2:
	-${TITLE}
	printf '/butt\nmajmb/rude\nifuzz\e`a`bu`a`bQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

mark3:
	-${TITLE}
	printf '/butt\nmajmb/rude\nd2w`a`bu`a`bQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

mark4:
	-${TITLE}
	printf '/butt\nmajmb/rude\ny2wPP`a`bu`a`bQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# BUG: The last undo failed to adjmarks correctly.  Must adjustment
# marks above the `gap`, _not_ `here`.
mark5:
	-${TITLE}
	printf '/butt\nma/rude\nifuzz\e`au`au`aQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}


# `dd` not supported.
del7:
	-${TITLE}
	printf '3wddQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Delete from cursor to same column of next line.
del8:
	-${TITLE}
	cp test/short.txt a.txt
	printf '3wdjW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Delete whole line.
del9:
	-${TITLE}
	cp test/short.txt a.txt
	printf '3w|djW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Delete to pattern and then next.
del10:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'wd/line\ndnW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Delete entire buffer.
del11:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'dGW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Delete back to mark.
del12:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'wma2jd`aW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Delete six words, ie. [count]d[count]motion
del13:
	-${TITLE}
	cp test/short.txt a.txt
	printf '3w2d3wW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Undo read file.
undo0:
	-${TITLE}
	printf 'uuQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Undo insert.
undo1:
	-${TITLE}
	cp test/short.txt a.txt
	printf '3liWOOT!\euuW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Undo delete.
undo2:
	-${TITLE}
	cp test/short.txt a.txt
	printf '3wd3wuuW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Delete and undo entire buffer.
undo3:
	-${TITLE}
	printf 'dGuQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Paste empty scrap.
paste0:
	-${TITLE}
	printf 'PQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Delete buffer and paste back.
paste1:
	-${TITLE}
	printf 'dGPQ' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Delete word, paste 3 times.
paste2:
	-${TITLE}
	cp test/short.txt a.txt
	printf '3wdwj2w3PW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Paste at EOF.
paste3:
	-${TITLE}
	cp test/short.txt a.txt
	printf '3wdwuGPkW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Command not found.
bang0:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!!WOOT\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Command fail.
bang1:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!!false\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Command success.
bang2:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!!true\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Command read-only.
bang3:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!!ls test/term*\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Command save and delete region.
bang4:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!2jcat >b.txt\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	test $$(wc -c <b.txt) -eq 43
	-${PASS}

# Command save region.
bang5:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!2jtee b.txt\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	test $$(wc -c <b.txt) -eq 43
	-${PASS}

# Command format region fails.
bang6:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!2jfmt -w40\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Command format region succeeds.
bang7:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j!2jfmt -g32 -w40\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

replace0:
	-${TITLE}
	cp test/short.txt a.txt
	printf '/butt/xyzzy\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

replace1:
	-${TITLE}
	cp test/short.txt a.txt
	printf '/butt/$0hole\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

replace2:
	-${TITLE}
	cp test/short.txt a.txt
	printf '/line/plugh!\nnnnW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

write0:
	-${TITLE}
	printf 'iThe quick brown fox jumps over the lazy dog.\n\eWa.txt\nQ' | ${PROG} >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# This test does not work since line erase in redirected input is
# treated differently from a tty.  See NetBSD 10.0 lib/58151.
# NetBSD 10 kill character visual behaviour in noraw()/nocbreak()
# (line displine on) does appear correctly, though the string buffer
# appears correct.
write1:
	-${TITLE}
	printf 'iThe quick brown fox jumps over the lazy dog.\n\eWa.txt\nW\025b.txt\nQ' | ${PROG} >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Read file into an empty buffer.
read0:
	-${TITLE}
	printf 'Rtest/short.txtWa.txt\nQ' | ${PROG} >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Add text, then read a file into the middle, and save.
read1:
	-${TITLE}
	printf 'iThe quick brown fox jumps over the lazy dog.\n\e/fox\nRtest/short.txt\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Toggle select on/off without selecting anything.
select0:
	-${TITLE}
	printf '\\\\Q' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Select some words right.
select1:
	-${TITLE}
	printf '/rude\n\\3w\\Q' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Select some words left.
select2:
	-${TITLE}
	printf '/rude\n\\4b\\Q' | ${PROG} test/short.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Select some words right, yank, paste.
select3:
	-${TITLE}
	cp test/short.txt a.txt
	printf '/rude\n\\3wy/but\nPW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Select some words left, delete, paste.
select4:
	-${TITLE}
	cp test/short.txt a.txt
	printf '/rude\n\\4bd/but\nPW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Select format selection.
select5:
	-${TITLE}
	cp test/short.txt a.txt
	printf 'j\\3j!fmt -g16 -w24\nW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	${A_TXT}
	-${PASS}

# Insert multibyte character.
mb0:
	-${TITLE}
	printf 'i🔥\n\eW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_TXT}
	${A_OUT}
	-${PASS}

# Move over 2 column wide multibyte character to newline, next line.
#
# There is a visual/redraw bug here with NetBSD Curses that messes
# with the % position and cursor position moving over the wide
# characters and newline; force a redraw fixes it.  NCurses is fine.
#
mb1:
	-${TITLE}
	cp ${DATA}/$@.txt a.txt
	printf 'llQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Move goto end of line containing multibyte character, then next line.
mb2:
	-${TITLE}
	cp ${DATA}/$@.txt a.txt
	printf '$$lQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Cursor back from eof.
mb3:
	-${TITLE}
	cp ${DATA}/$@.txt a.txt
	printf '2jhhhhhhhhQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_OUT}
	-${PASS}

# Insert and erase multibyte character.
mb4:
	-${TITLE}
	printf 'i🔥\b\n\eW\nQ' | ${PROG} a.txt >a.out
	${A_CORE}
	${A_TXT}
	${A_OUT_OR_SKIP}
