better terminal support
This commit is contained in:
parent
3a8d170f05
commit
2f9ae98c96
72
term.py
72
term.py
|
@ -1,51 +1,49 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# ./term.py term.rom /bin/bash
|
||||
#/usr/bin/env python
|
||||
|
||||
from select import select
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
import fcntl
|
||||
import os
|
||||
import pty
|
||||
import sys
|
||||
|
||||
# currently unbuffered
|
||||
#
|
||||
# TODO: figure out a more reasonable buffering strategy
|
||||
def run(args):
|
||||
return Popen(args, stdin=PIPE, stdout=PIPE, stderr=STDOUT, bufsize=0)
|
||||
import struct
|
||||
import termios
|
||||
|
||||
def main():
|
||||
|
||||
# check usage
|
||||
args = sys.argv[1:]
|
||||
if len(args) < 2:
|
||||
print('usage: %s ROM SHELL [ ARGS... ]')
|
||||
if len(args) < 1:
|
||||
print('usage: %s ROM')
|
||||
print('')
|
||||
print('execute the given uxn terminal program (ROM)')
|
||||
print('and start a shell process (SHELL + ARGS).')
|
||||
print('')
|
||||
print('example: %s term.rom /bin/bash -i' % sys.argv[0])
|
||||
print(' ROM: the rom file to launch')
|
||||
sys.exit(1)
|
||||
|
||||
term = run(['uxnemu', args[0]])
|
||||
term_out = term.stdout.fileno()
|
||||
# path to rom to run
|
||||
rom = args[0]
|
||||
|
||||
shell = run(args[1:])
|
||||
shell_out = shell.stdout.fileno()
|
||||
# fork with a new pty
|
||||
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 pid == 0:
|
||||
# set TERM to something we can handle
|
||||
env = dict(os.environ)
|
||||
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)
|
||||
|
||||
if shell.poll() is None:
|
||||
shell.kill()
|
||||
if term.poll() is None:
|
||||
term.kill()
|
||||
# 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__":
|
||||
main()
|
||||
|
|
49
term.tal
49
term.tal
|
@ -18,18 +18,18 @@
|
|||
@subinput $1 ( reading from subprocess? )
|
||||
|
||||
|0100
|
||||
( 32 characters = 256 pixels )
|
||||
#0020 .rows STZ2
|
||||
#0040 .cols STZ2
|
||||
( 80 cols x 24 rows )
|
||||
#0028 .rows STZ2
|
||||
#0050 .cols STZ2
|
||||
|
||||
( set screen height/width based on rows/cols )
|
||||
.rows LDZ2 #30 SFT2 .Screen/h DEO2
|
||||
.cols LDZ2 #30 SFT2 .Screen/w DEO2
|
||||
|
||||
( set colors )
|
||||
#0ff0 .System/r DEO2
|
||||
#0f88 .System/g DEO2
|
||||
#0f0f .System/b DEO2
|
||||
#0cf0 .System/r DEO2
|
||||
#0c88 .System/g DEO2
|
||||
#0c0f .System/b DEO2
|
||||
|
||||
( set pos, subinput flag )
|
||||
.buffer .pos STZ
|
||||
|
@ -99,15 +99,15 @@
|
|||
;draw-tile JMP2
|
||||
|
||||
@on-key
|
||||
.Controller/key DEI #00 EQU ,&skip JCN
|
||||
#00 .subinput STZ
|
||||
.Controller/key DEI #00 EQU ,&skip JCN
|
||||
#41 .tint STZ
|
||||
.Controller/key DEI ;read JSR2
|
||||
&skip BRK
|
||||
|
||||
@on-input
|
||||
.Console/r DEI #00 EQU ,&skip JCN
|
||||
#01 .subinput STZ
|
||||
.Console/r DEI #00 EQU ,&skip JCN
|
||||
#41 .tint STZ
|
||||
.Console/r DEI ;read JSR2
|
||||
&skip BRK
|
||||
|
@ -123,11 +123,10 @@
|
|||
;read-normal JMP2
|
||||
|
||||
( TODO: we need line-editing! )
|
||||
@read-bel JMP2r
|
||||
@read-bs JMP2r ( POP ;scroll JMP2 )
|
||||
@read-tab JMP2r ( POP POP2r #0000 DIV )
|
||||
@read-esc JMP2r
|
||||
@read-del JMP2r
|
||||
@read-bel POP JMP2r
|
||||
@read-bs POP JMP2r ( POP ;scroll JMP2 )
|
||||
@read-esc POP JMP2r
|
||||
@read-del POP JMP2r
|
||||
|
||||
@write-line ( -> )
|
||||
.pos LDZ .buffer
|
||||
|
@ -135,17 +134,33 @@
|
|||
&next LDZk .Console/w DEO INC ,&loop JMP
|
||||
&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 -> )
|
||||
POP
|
||||
.subinput LDZ ,&display JCN
|
||||
;write-line JSR2
|
||||
&display
|
||||
POP
|
||||
;hide-cursor JSR2
|
||||
#0000 .cur-x STZ2
|
||||
;down JMP2
|
||||
|
||||
@read-nl ( 0a -> )
|
||||
,read-cr JMP
|
||||
POP
|
||||
JMP2r
|
||||
( ,read-cr JMP )
|
||||
|
||||
@forward ( -> )
|
||||
.cur-x LDZ2 INC2 DUP2 .cols LDZ2 LTH2 ,&ok JCN
|
||||
|
@ -179,7 +194,6 @@
|
|||
.subinput LDZ ,&display JCN
|
||||
.pos LDZ STZk INC .pos STZ
|
||||
&display
|
||||
;hide-cursor JSR2
|
||||
DUP ;cursor-addr JSR2 STA
|
||||
;draw-tile JSR2
|
||||
;forward JMP2
|
||||
|
@ -213,5 +227,6 @@
|
|||
~chr/ascii.tal
|
||||
|
||||
( screen to store characters for redraw, etc. )
|
||||
@screen $0800 ( 64 x 32 )
|
||||
( @screen $0800 ( 64 x 32 ) )
|
||||
@screen $0c80 ( 64 x 32 )
|
||||
@end-screen
|
||||
|
|
Loading…
Reference in New Issue