1- /// <reference path="../../../bower_components/polymer-ts/polymer-ts.d.ts"/>
1+ /// <reference path="../../../node_modules/xterm/typings/xterm.d.ts"/>
2+
3+ //import { Terminal } from 'xterm';
24
35interface ExitCallback {
46 ( pid : number , code : number ) : void ;
@@ -14,98 +16,95 @@ interface Kernel {
1416 kill ( pid : number ) : void ;
1517}
1618
17- namespace Terminal {
19+ namespace BrowsixTerminal {
1820 'use strict' ;
1921
2022 const ERROR = 'FLAGRANT SYSTEM ERROR' ;
2123
22- @component ( 'browsix-terminal' )
23- class Terminal extends polymer . Base {
24- @property ( { type : Object } )
25- kernel : any ;
26-
27- @property ( { type : String } )
28- ps1 : string = '$ ' ;
24+ class BrowsixTerminal {
25+ kernel : Kernel ;
26+ stdin : any ;
27+ terminal : Terminal ;
28+ line : string = "" ;
29+ lineidx : number = 0 ;
30+
31+ constructor ( element : HTMLElement ) {
32+ this . terminal = new Terminal ( {
33+ // According to xterm.js docs, unnecessary with pty
34+ "convertEol" : true
35+ } ) ;
36+ this . terminal . open ( element ) ;
37+ this . terminal . on ( 'key' , ( key : string , ev : KeyboardEvent ) => this . keyCallback ( key , ev ) ) ;
2938
30- constructor ( ) {
31- super ( ) ;
3239 ( < any > window ) . Boot (
3340 'XmlHttpRequest' ,
3441 [ 'index.json' , 'fs' , true ] ,
3542 ( err : any , k : Kernel ) => {
3643 if ( err ) {
3744 console . log ( err ) ;
38- this . $ . output . innerHTML = ERROR ;
45+ this . terminal . clear ( ) ;
46+ this . terminal . writeln ( ERROR ) ;
3947 throw new Error ( err ) ;
4048 }
4149 this . kernel = k ;
42- } ,
43- { readOnly : false } ) ;
44- }
4550
46- attached ( ) : void {
47- this . $ . input . addEventListener ( 'keypress' , this . onInput . bind ( this ) ) ;
48- ( < any > document ) . body . addEventListener ( 'click' , this . focus . bind ( this ) ) ;
49- }
50-
51- onInput ( ev : any ) : void {
52- // If key pressed is not Return/Enter, skip
53- if ( ev . keyCode !== 13 ) return ;
54-
55- let cmd = this . $ . input . value ;
56- this . $ . output . innerHTML += this . ps1 + cmd + '<br>' ;
57- if ( cmd === '' ) {
58- this . scrollBottom ( ) ;
59- return ;
60- }
61- this . setEditable ( false ) ;
62- let bg = cmd [ cmd . length - 1 ] === '&' ;
63- if ( bg ) {
64- cmd = cmd . slice ( 0 , - 1 ) . trim ( ) ;
65- setTimeout ( ( ) => { this . setEditable ( true ) ; } , 0 ) ;
66- }
51+ let completed = ( pid : number , code : number ) => {
52+ this . stdin = null ;
53+ this . terminal . writeln ( "'sh' exited with status " + code ) ;
54+ } ;
6755
68- let completed = ( pid : number , code : number ) => {
69- this . setEditable ( true ) ;
70- this . $ . input . value = '' ;
71- this . focus ( ) ;
72- this . scrollBottom ( ) ;
73- } ;
56+ let onInput = ( pid : number , out : string ) => {
57+ this . terminal . write ( out ) ;
58+ } ;
7459
75- let onInput = ( pid : number , out : string ) => {
76- // Replace all LF with HTML breaks
77- out = out . split ( '\n' ) . join ( '<br>' ) ;
78- this . $ . output . innerHTML += out ;
79- this . scrollBottom ( ) ;
80- } ;
60+ let onHaveStdin = ( stdin : any ) => {
61+ this . stdin = stdin ;
62+ }
8163
82- this . kernel . system ( cmd , completed , onInput , onInput ) ;
64+ this . kernel . system ( "sh" , completed , onInput , onInput , onHaveStdin ) ;
65+ } ,
66+ { readOnly : false } ) ;
8367 }
8468
85- @observe ( 'kernel' )
86- kernelChanged ( _ : Kernel , oldKernel : Kernel ) : void {
87- // we expect this to be called once, after
88- // we've booted the kernel.
89- if ( oldKernel ) {
90- console . log ( 'unexpected kernel change' ) ;
91- return ;
69+ keyCallback ( key : string , ev : KeyboardEvent ) : void {
70+ // Newline
71+ if ( ev . keyCode == 13 ) {
72+ this . terminal . writeln ( "" ) ;
73+ this . line += '\n'
74+ if ( this . stdin !== null ) {
75+ this . stdin . write ( new Buffer ( this . line ) , - 1 , ( error : any ) => { } ) ;
76+ }
77+ this . line = '' ;
78+ this . lineidx = 0 ;
79+ // Backspace
80+ } else if ( ev . keyCode == 8 ) {
81+ const previous = this . line . slice ( 0 , this . lineidx - 1 ) ;
82+ const rest = this . line . slice ( this . lineidx ) ;
83+ this . terminal . write ( '\b' + rest + ' ' + '\b' . repeat ( rest . length + 1 ) ) ;
84+ this . line = previous + rest ;
85+ this . lineidx -- ;
86+ // Up and down arrows
87+ } else if ( ev . keyCode == 38 || ev . keyCode == 40 ) {
88+ // Left arrow
89+ } else if ( ev . keyCode == 37 ) {
90+ this . terminal . write ( key ) ;
91+ this . lineidx -- ;
92+ if ( this . lineidx == - 1 ) {
93+ this . lineidx = 0 ;
94+ }
95+ // Right arrow
96+ } else if ( ev . keyCode == 39 ) {
97+ if ( this . lineidx < this . line . length ) {
98+ this . lineidx ++ ;
99+ this . terminal . write ( key ) ;
100+ }
101+ } else {
102+ this . terminal . write ( key ) ;
103+ this . line += key ;
104+ this . lineidx ++ ;
92105 }
93106 }
94-
95- focus ( ) : void {
96- this . $ . input . focus ( ) ;
97- }
98-
99- setEditable ( editable : boolean ) : void {
100- // Hide input if not editable
101- this . $ . input_container . style . visibility = ( editable ) ? '' : 'hidden' ;
102- }
103-
104- scrollBottom ( ) : void {
105- ( < any > window ) . scrollTo ( 0 , document . documentElement . scrollHeight
106- || document . body . scrollHeight ) ;
107- }
108107 }
109108
110- Terminal . register ( ) ;
109+ var terminal = new BrowsixTerminal ( document . getElementById ( 'browsix-terminal' ) ) ;
111110}
0 commit comments