better terminal support

This commit is contained in:
~d6 2023-01-21 22:54:20 -05:00
parent 3a8d170f05
commit 2f9ae98c96
2 changed files with 68 additions and 55 deletions

74
term.py
View File

@ -1,51 +1,49 @@
#!/usr/bin/python #/usr/bin/env python
#
# ./term.py term.rom /bin/bash
from select import select import fcntl
from subprocess import Popen, PIPE, STDOUT import os
import pty
import sys import sys
import struct
# currently unbuffered import termios
#
# TODO: figure out a more reasonable buffering strategy
def run(args):
return Popen(args, stdin=PIPE, stdout=PIPE, stderr=STDOUT, bufsize=0)
def main(): def main():
# check usage
args = sys.argv[1:] args = sys.argv[1:]
if len(args) < 2: if len(args) < 1:
print('usage: %s ROM SHELL [ ARGS... ]') print('usage: %s ROM')
print('') print('')
print('execute the given uxn terminal program (ROM)') print(' ROM: the rom file to launch')
print('and start a shell process (SHELL + ARGS).')
print('')
print('example: %s term.rom /bin/bash -i' % sys.argv[0])
sys.exit(1) sys.exit(1)
term = run(['uxnemu', args[0]]) # path to rom to run
term_out = term.stdout.fileno() rom = args[0]
shell = run(args[1:]) # fork with a new pty
shell_out = shell.stdout.fileno() pid, fd = pty.fork()
while shell.poll() is None and term.poll() is None:
# wait 100ms to see if anything is ready to write
ns, _, _ = select([term_out, shell_out], [], [], 0.1)
for n in ns:
if n == term_out:
shell.stdin.write(term.stdout.read(1))
shell.stdin.flush()
elif n == shell_out:
term.stdin.write(shell.stdout.read(1))
term.stdin.flush()
else:
raise Exception('unexpected fileno: %d (expected %d or %d)' % (n, term_out, shell_out))
if shell.poll() is None: if pid == 0:
shell.kill() # set TERM to something we can handle
if term.poll() is None: env = dict(os.environ)
term.kill() env['TERM'] = 'dumb'
os.execvpe('bash', ['bash', '--noediting', '-i'], env)
else:
# set the terminal size
#cols, rows = 63, 32
cols, rows = 79, 40
size = struct.pack("HHHH", rows, cols, 8, 8)
fcntl.ioctl(fd, termios.TIOCSWINSZ, size)
# disable terminal echo
attr = termios.tcgetattr(fd)
attr[3] = attr[3] & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSADRAIN, attr)
# use fd for the terminals stdin/stdout
os.dup2(fd, sys.stdin.fileno())
os.dup2(os.dup(fd), sys.stdout.fileno())
os.execvp('uxnemu', ['uxnemu', rom])
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -18,18 +18,18 @@
@subinput $1 ( reading from subprocess? ) @subinput $1 ( reading from subprocess? )
|0100 |0100
( 32 characters = 256 pixels ) ( 80 cols x 24 rows )
#0020 .rows STZ2 #0028 .rows STZ2
#0040 .cols STZ2 #0050 .cols STZ2
( set screen height/width based on rows/cols ) ( set screen height/width based on rows/cols )
.rows LDZ2 #30 SFT2 .Screen/h DEO2 .rows LDZ2 #30 SFT2 .Screen/h DEO2
.cols LDZ2 #30 SFT2 .Screen/w DEO2 .cols LDZ2 #30 SFT2 .Screen/w DEO2
( set colors ) ( set colors )
#0ff0 .System/r DEO2 #0cf0 .System/r DEO2
#0f88 .System/g DEO2 #0c88 .System/g DEO2
#0f0f .System/b DEO2 #0c0f .System/b DEO2
( set pos, subinput flag ) ( set pos, subinput flag )
.buffer .pos STZ .buffer .pos STZ
@ -99,15 +99,15 @@
;draw-tile JMP2 ;draw-tile JMP2
@on-key @on-key
.Controller/key DEI #00 EQU ,&skip JCN
#00 .subinput STZ #00 .subinput STZ
.Controller/key DEI #00 EQU ,&skip JCN
#41 .tint STZ #41 .tint STZ
.Controller/key DEI ;read JSR2 .Controller/key DEI ;read JSR2
&skip BRK &skip BRK
@on-input @on-input
.Console/r DEI #00 EQU ,&skip JCN
#01 .subinput STZ #01 .subinput STZ
.Console/r DEI #00 EQU ,&skip JCN
#41 .tint STZ #41 .tint STZ
.Console/r DEI ;read JSR2 .Console/r DEI ;read JSR2
&skip BRK &skip BRK
@ -123,11 +123,10 @@
;read-normal JMP2 ;read-normal JMP2
( TODO: we need line-editing! ) ( TODO: we need line-editing! )
@read-bel JMP2r @read-bel POP JMP2r
@read-bs JMP2r ( POP ;scroll JMP2 ) @read-bs POP JMP2r ( POP ;scroll JMP2 )
@read-tab JMP2r ( POP POP2r #0000 DIV ) @read-esc POP JMP2r
@read-esc JMP2r @read-del POP JMP2r
@read-del JMP2r
@write-line ( -> ) @write-line ( -> )
.pos LDZ .buffer .pos LDZ .buffer
@ -135,17 +134,33 @@
&next LDZk .Console/w DEO INC ,&loop JMP &next LDZk .Console/w DEO INC ,&loop JMP
&done #0a .Console/w DEO .buffer .pos STZ JMP2r &done #0a .Console/w DEO .buffer .pos STZ JMP2r
( @read-tab POP JMP2r )
@read-tab
POP
.subinput LDZ ,&display JCN
#01 #0e DEO JMP2r ( POP POP2r #0000 DIV )
&display
.cur-x LDZ2 NIP #07 AND #08 SUB
&loop
#20 DUP ;cursor-addr JSR2 STA
;draw-tile JSR2
;forward JSR2
INC DUP ,&loop JCN
POP JMP2r
@read-cr ( 0d -> ) @read-cr ( 0d -> )
POP
.subinput LDZ ,&display JCN .subinput LDZ ,&display JCN
;write-line JSR2 ;write-line JSR2
&display &display
POP
;hide-cursor JSR2 ;hide-cursor JSR2
#0000 .cur-x STZ2 #0000 .cur-x STZ2
;down JMP2 ;down JMP2
@read-nl ( 0a -> ) @read-nl ( 0a -> )
,read-cr JMP POP
JMP2r
( ,read-cr JMP )
@forward ( -> ) @forward ( -> )
.cur-x LDZ2 INC2 DUP2 .cols LDZ2 LTH2 ,&ok JCN .cur-x LDZ2 INC2 DUP2 .cols LDZ2 LTH2 ,&ok JCN
@ -179,7 +194,6 @@
.subinput LDZ ,&display JCN .subinput LDZ ,&display JCN
.pos LDZ STZk INC .pos STZ .pos LDZ STZk INC .pos STZ
&display &display
;hide-cursor JSR2
DUP ;cursor-addr JSR2 STA DUP ;cursor-addr JSR2 STA
;draw-tile JSR2 ;draw-tile JSR2
;forward JMP2 ;forward JMP2
@ -213,5 +227,6 @@
~chr/ascii.tal ~chr/ascii.tal
( screen to store characters for redraw, etc. ) ( screen to store characters for redraw, etc. )
@screen $0800 ( 64 x 32 ) ( @screen $0800 ( 64 x 32 ) )
@screen $0c80 ( 64 x 32 )
@end-screen @end-screen