#!/usr/bin/env python3 """Check compact PDF tags and Mode cycling and Ctrl-B in an isolated 9P session.""" import argparse from pathlib import Path from fs import session, new_pane, execute from column_tags import Input as HostInput from ui_review import capture, panes, require, wait_for def run(args): root = args.output.resolve() root.mkdir(parents=True, mode=0o700, exist_ok=True) root.chmod(0o700) name = 'tag-cleanup' binary = str(args.binary.resolve()) source = Path('docs/design.pdf').resolve() original = source.read_bytes() inherited = {} if args.tty else { 'PARDES_TEST': '1', 'PARDES_TEST_CAPTURE_DIR': str(root), 'PARDES_TEST_COLS': '150', 'PARDES_TEST_ROWS': '48', 'SDL_VIDEODRIVER': 'x11', } launch = ['-c', 'stty cols 150 rows 48; exec "$@"', name, binary, '--9p=' + name, str(source)] terminal = {} with session('/bin/sh', root, name, socket_name=name, tty=True, launch=launch, inherited=inherited, terminal=terminal) as (client, _): keys = HostInput(terminal['input_fd']) pdf = next(serial for serial, tag in panes(client).items() if str(source) in tag) pdf_tag = client.read(f'/pane/{pdf}/tag').decode().strip() require(pdf_tag.startswith(str(source) + ' [1/'), 'PDF name/page prefix missing') require(pdf_tag.endswith('] Tty Del PdfSections PdfTint Collapse'), 'PDF commands missing') require(all(word not in pdf_tag for word in ['PdfFit', 'filtered', 'full', 'disabled']), 'PDF tag contains fit or tint-state clutter') control = new_pane(client, b'') before = set(panes(client)) execute(client, control, 'Tty') tty = require(wait_for(lambda: next((s for s in panes(client) if s not in before), None)), 'terminal missing') client.write(f'/pane/{control}/exec', b'Del\n') # owned command-only scratch def tag_position(): frame = client.screen() for row in range(frame['rows']): text = ''.join(c[0] for c in frame['cells'][row * frame['cols']:(row + 1) * frame['cols']]) if ' Mode Filter' in text: return text.index(' Mode Filter') + 1, row, text[0] return None require(wait_for(lambda: (p := tag_position()) and p[2] == '$'), 'new terminal not in raw mode') x, y, _ = tag_position() keys.click(x, y, button=1) require(wait_for(lambda: (p := tag_position()) and p[2] == ' '), 'Mode click did not enter normal mode') for badge in ('^', '$'): x, y, _ = tag_position() keys.click(x, y, button=1) require(wait_for(lambda: (p := tag_position()) and p[2] == badge), 'Mode cycle did not reach ' + badge) x, y, _ = tag_position() keys.click(x, y, button=1) require(wait_for(lambda: (p := tag_position()) and p[2] == ' '), 'Mode did not return to normal') keys.send(b'\x02') require(wait_for(lambda: (p := tag_position()) and p[2] == '$'), 'Ctrl-B did not restore raw mode') x, y, _ = tag_position() keys.click(x, y) keys.send(b'\t') require(wait_for(lambda: (p := tag_position()) and p[2] == ' '), 'Mode from edited tag ignored parked raw mode') keys.send(b'\x02') client.write(f'/pane/{tty}/pty/data', b"printf 'Mode toggle ready\\n'\r") require(wait_for(lambda: b'Mode toggle ready' in client.read(f'/pane/{tty}/body')), 'terminal input failed') capture(client, root, 'pdf-and-tty-tags', not args.tty) require(source.read_bytes() == original, 'PDF file changed') client.write(f'/pane/{tty}/pty/data', b'exit\r') print('PDF tag, Mode click, Ctrl-B, edited-tag execution and source preservation passed') if __name__ == '__main__': parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('binary', type=Path) parser.add_argument('output', type=Path) parser.add_argument('--tty', action='store_true') run(parser.parse_args())