Using printer as tty duplicate

I’d like to be able to have the DevTerm in a CLI REPL, such as a text game, a Python interpreter, etc, and keep a live trace of the session printed on thermal paper.

Here are some experiments I’ve done:

I’ve used script(1) from util-linux, which is functional but a bit overzealous:

script places everything in the log file, including linefeeds and backspaces. This is not what the naive user expects.

I agree with this statement from the manpage, but would have hoped for an alternative to be mentioned alongside. In practice, you get extra characters (carriage returns show up as music notes) and you can see backspaces, etc.

$ script - | tee /tmp/DEVTERM_PRINTER_IN
$ reset
$ fizmo-console Zork1.dat
...

I couldn’t find any way to convert this raw output into something cleaner (apply ^H linefeed operations, etc), but I’m sure it exists.

Alternately I tried just teeing stdout+stderr to the printer, but I feel like the print is a bit useless without input.

I also wish I could print with a larger font than the 5 provided by default. If printing a .txt file with lp I get a huge font which I’m not fond of. I guess I could probably add another medium size ttf (maybe of Terminus or some similar bitmap font) and recompile the driver, but I don’t feel like doing that right now.

Another thing I tried is coding a basic duplicating REPL in Python but I haven’t really got anywhere yet:

#!/usr/bin/env python3

from io import StringIO
import sys
import logging
import traceback

with open("/tmp/DEVTERM_PRINTER_IN", "w") as printer:
    # Use least tiny font
    printer.write("\x1b\x21\x04")
    while True:
        try:
            old_stdout = sys.stdout
            sys.stdout = mystdout = StringIO()
            old_stdout.write("> ")
            old_stdout.flush()
            cmd = input()
            printer.write(f"> {cmd}\n")
            out = eval(cmd)
            sys.stdout = old_stdout
            message = mystdout.getvalue()
            print(message, end="")
            printer.write(message)
            if out is not None:
                print(out)
                printer.write(f"{out}\n")
        except EOFError:
            printer.write("\n" * 14)
            break
        except Exception:
            err = traceback.format_exc()
            logging.error(err)
            printer.write(err)
            sys.stdout = old_stdout

Neither eval nor exec is really what I want, and the whole exchanging stdout thing is still messy. Also I’m using \x04 for the font size instead of the documented \x4 because the latter is invalid in Python strings; but I’m not entirely sure it’s equivalent.
I don’t have a proper print of the output on hand but you can’t easily get return values printed with either prints out as well or manipulating variables …

I also looked through stty but haven’t found anything useful.

Is anyone else interested in this kind of project?

2 Likes

So you’re trying to turn a DevTerm into a thermal TeleType? I love it!

Would this be of any help? It’s exactly what you’re trying to do, as far as I can see, but on a dot-matrix line printer.

1 Like

Thanks for the encouragement, and I’ll be sure to read the blog post in detail! :relaxed:

But just before that, here’s a small script which cleans up backspaces, tabs, carriage returns:

#!/usr/bin/env python3

from sys import stdin, stdout
import re

bs = re.compile(".?\b")
for line in stdin:
    line = line.replace("\r", "").replace("\a", "")
    while True:
        line, n = re.subn(bs, "", line, 1)
        if n == 0:
            break
    stdout.write(line)

And an example Zork session:

$ script >( ./cleantty.py > /tmp/DEVTERM_PRINTER_IN)
$ reset
...

That’s good enough for some basic stuff :smiley:

4 Likes

I’ve done some progress!

Here’s some extracts from my .bashrc to simplify usage:

... # can be placed early

if test "$(tty)" = /dev/tty1 && test "$TERM" = linux
then
        tmux
        exit
fi

... # most of the body is here

duptty () {
        script -f -c "$@" \
                >($HOME/src/cleantty/cleantty.py > /tmp/DEVTERM_PRINTER_IN)
        printf '\n\n\n\n\n\n\n\n\n\n\n\n\n\n' > /tmp/DEVTERM_PRINTER_IN
}

zork () {
        pushd $HOME/Games/Infocom/Zork/
        duptty "fizmo-console Zork1.dat"
        popd
}

hhgg () {
        pushd $HOME/Games/Infocom/HHGG
        duptty "fizmo-console hhgttg_59.z3"
        popd
}

Note that I disabled gdm3.service and autologin.

Here’s my tmux.conf with battery percentage (without any plugin):

set -g default-terminal tmux-256color
set -ga update-environment LANG
set -ga terminal-overrides ",*col*:Tc"

unbind C-b
set-option -g prefix C-z
bind-key C-z send-prefix

bind | split-window -h
bind _ split-window -v
unbind '"'
unbind %

bind r source-file ~/.tmux.conf

bind -n M-Left select-pane -L
bind -n M-Right select-pane -R
bind -n M-Up select-pane -U
bind -n M-Down select-pane -D

set -g mouse on

#set -g status-utf8 on
set -g status-keys vi
set -g status-interval 10
#set -g status-attr bright
set -g status-fg white
set -g status-bg black
set -g status-left-length 20
set -g status-left '#[fg=green][#[fg=red]#S#[fg=green]]#[default]'
set -g status-justify centre
set -g status-right "#[fg=green][ %m/%d %H:%M:%S ][ battery #(upower -i /org/freedesktop/UPower/devices/battery_axp20x_battery | grep percentage | grep -o '[0-9].*') ]#[default]"
setw -g window-status-current-format '#[fg=yellow](#I.#P#F#W)#[default]'
setw -g window-status-format '#I#F#W'

And most importantly, here’s another gratuitous cat pic:

4 Likes

BTW I don’t think I can use sircmpwn’s approach because as far as I can tell his printer can feed backwards and directly interprets special characters (such as \b for which it apparently moves the head backwards). So, different problems.

You should use coolterminal :slight_smile:

1 Like

Beauty is in the eye of the beholder :wink:

But I do recommend using a basic CLI Z-machine interpreter rather than a TUI/Curses one if you want to have the duplicate-to-printer behaviour.

Also if I can stay in true text-mode (or fbterm) rather than a terminal emulator that feels more like a “pure” terminal experience to me. I generally can’t do that, but on this device it’s mostly fine. It’s annoying that I can’t rotate the retroarch menu properly but other than I get a significant performance boost from avoiding any graphics server.