Skip to content

Commit 631b8e2

Browse files
save file
1 parent 73dbe40 commit 631b8e2

1 file changed

Lines changed: 146 additions & 95 deletions

File tree

utils/misc/nodejs-terminal/nodejs-terminal.html

Lines changed: 146 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
console.log('nodejs-terminal-v2.0.html');
5151
console.log();
5252
console.json=v=>console.log(JSON.stringify(v,null,4));
53+
console.hex=v=>console.log(v,'Hex:',[...v].map(c=>c.charCodeAt(0).toString(16).padStart(2,'0')).join(' '));
5354
var version='v2.0';
5455
var df=true;
5556

@@ -410,9 +411,13 @@
410411
}//snippet-console
411412

412413

413-
btn.test = async function(){console.log('test');
414-
415-
414+
btn.test = async function(){
415+
console.log('test');
416+
417+
cursor.to(5,1);
418+
cursor.xy();
419+
return;
420+
416421
term.write.brightGreen('hello');
417422
term.write.red('world');
418423
return;
@@ -457,7 +462,7 @@
457462

458463
term.writeln('');
459464
term.writeln.green('installing https-server ...');
460-
spinner();
465+
var s = spinner();
461466

462467
var mod = await import('https://code.ext-code.com/nodejs/servers/https-server/create-archive.m.js');
463468

@@ -495,7 +500,8 @@
495500
term.writeln.red('an error ocurred exit code : '+code);
496501
}
497502

498-
spinner.stop();
503+
s.stop();
504+
term.write('ok.');
499505
await prompt();
500506

501507
}//https-server
@@ -730,7 +736,7 @@
730736

731737
};
732738

733-
var chr = {
739+
const chr = {
734740

735741
warn : '\u26A0',
736742
cross : '\u274C',
@@ -743,7 +749,7 @@
743749

744750
};
745751

746-
var colors = {
752+
const colors = {
747753

748754
black : '\x1b[30m',
749755
red : '\x1b[31m',
@@ -762,7 +768,7 @@
762768
brightMagenta : '\x1b[1;35m',
763769
brightCyan : '\x1b[1;36m',
764770
brightWhite : '\x1b[1;37m',
765-
// Custom Mahogany (RGB: 150, 40, 20)
771+
// Custom Mahogany (RGB:150,40,20)
766772
mahogany : '\x1b[38;2;150;40;20m',
767773

768774
// Utility
@@ -771,8 +777,32 @@
771777
};
772778

773779

774-
775-
780+
const cursor = {
781+
782+
to : (x,y)=>`\x1b[${y+1};${x+1}H`,
783+
up : (n=1)=>`\x1b[${n}A`,
784+
down : (n=1)=>`\x1b[${n}B`,
785+
home : '\x1b[H',
786+
save : '\x1b[s',
787+
restore : '\x1b[u',
788+
hide : '\x1b[?25l',
789+
show : '\x1b[?25h',
790+
xy : ()=>{
791+
// Note: These are 0-indexed, so the top-left is 0,0.
792+
// ANSI sequences are usually 1-indexed (1,1).
793+
// Current Column
794+
var x = term.buffer.active.cursorX;
795+
// Current Row
796+
var y = term.buffer.active.cursorY;
797+
console.log(`cursor is at: ${x}, ${y}`);
798+
return {x,y};
799+
800+
},//xy
801+
802+
};
803+
// \x1b[K clears from cursor to end of line
804+
// \x1b[J: Clears the screen from the cursor down.
805+
776806
var files = {};
777807

778808
/*
@@ -851,19 +881,38 @@
851881
}//resume
852882
term.write.xy = (x,y,txt)=>{
853883

854-
term.write('\x1b[s'); // Save current spot
855-
term.write(`\x1b[${y};${x}H`); // Jump to top left
856-
term.write(txt);
857-
term.write('\x1b[u'); // Jump back to where we were
884+
term.write(`${cursor.save}${cursor.to(x,y)}${txt}${cursor.restore}`);
858885

859886
}//xy
860887

861-
862-
863-
888+
term.end_of_text = function(y){
889+
// xterm.js uses 0-based indexing for the buffer,
890+
// but 1-based for ANSI
891+
var line = term.buffer.active.getLine(y-1);
892+
if(!line){
893+
return 1;
894+
}
895+
896+
var last = 0;
897+
for(var i=term.cols-1;i>=0;i--){
898+
899+
var cell = line.getCell(i);
900+
// Check if the cell is not empty/whitespace
901+
if(cell&&cell.getChars().trim()!==''){
902+
last = i+1;
903+
break;
904+
}
905+
906+
}//for
907+
return last+1;
908+
909+
}//end_of_text
910+
911+
912+
864913
for(let key in colors){
865914

866-
if (key === 'reset') continue;
915+
if(key=='reset')continue;
867916

868917
term.write[key] = (...args)=>term.write(colors[key]+args.join(' ')+colors.reset);
869918
term.writeln[key] = (...args)=>term.writeln(colors[key]+args.join(' ')+colors.reset);
@@ -894,63 +943,68 @@
894943

895944
});
896945

897-
898-
946+
/*
947+
~/rt4gcbtwdausp1nng6uyw4vpasf83c-wlvi
948+
❯ 
949+
[?2004h
950+
*/
951+
899952
var fitAddon = new FitAddon();
900953
term.loadAddon(fitAddon);
901954
term.open(terminal);
902955
fitAddon.fit();
903956

904-
term.write('booting container ... ')
957+
term.write('booting container ... ');
958+
var s = spinner();
905959
webcontainer = await WebContainer.boot();
906960
mod.stack.complete;
907-
term.writeln.green('ok'); //24
908-
961+
s.stop();
962+
term.writeln.green('ok.'); //24
909963

964+
term.write.xy(30,0,'node');
965+
var s1 = spinner({x:35,y:0});
966+
term.write.xy(45,0,'npm');
967+
var s2 = spinner({x:49,y:0});
968+
term.writeln('spawn jsh ... ');
969+
var s3 = spinner({x:14,y:1});
970+
910971
var phase = {};
911972
phase.ct = 1;
912973
phase.p1 = result=>{
913974

975+
s1.stop();
914976
var str = '??';
915977
if(result.code==0)str = result.output;
916-
var x = end_of_text(1);
917-
x++;
918-
term.write.xy(x,1,', node '+str)
919-
phase.ct = 2
920-
phase.p2()
978+
term.write.xy(35,0,str)
921979

922980
}//p1
923981
phase.p2 = result=>{
924982

925-
if(result)phase.p2.result = result;
926-
if(phase.ct!=2)return;
927-
if(!phase.p2.result)return;
983+
s2.stop();
928984
var str = '??';
929-
if(phase.p2.result.code==0)str = phase.p2.result.output;
930-
var x = end_of_text(1);
931-
x++;
932-
term.write.xy(x,1,', npm '+str);
933-
phase.ct = 3;
934-
phase.p3();
985+
if(result.code==0)str = result.output;
986+
str = str.replace(/\x1b\[1G/g, '').replace(/\x1b\[0K/g, '');
987+
//console.hex(str);
988+
term.write.xy(49,0,str);
935989

936990
}//p2
937-
phase.p3 = result=>{console.log('phase.p3',!!result);
938-
939-
if(result)shell = result;
940-
if(phase.ct!=3)return;
941-
if(!shell)return;
991+
phase.p3 = result=>{
992+
console.log('phase.p3',!!result);
993+
shell = result;
994+
s3.stop();
995+
term.write.xy(14,1,`${colors.green}ok.${colors.reset}`);
942996
shell.output.pipeTo(output);
943997
input = shell.input.getWriter();
944998
term.onData(data=>input.write(data));
945999
//term.resize();
946-
term.focus();
1000+
setTimeout(()=>term.focus(),50);
9471001

9481002
}//p3
9491003

9501004

9511005
spawn('node -v',true).then(phase.p1);
9521006
spawn('npm -v',true).then(phase.p2);
953-
webcontainer.spawn('jsh').then(phase.p3);
1007+
setTimeout(()=>webcontainer.spawn('jsh').then(phase.p3),50);
9541008

9551009

9561010

@@ -964,12 +1018,9 @@
9641018

9651019

9661020

967-
//term.write('spawn jsh ... ')
968-
//shell = await webcontainer.spawn('jsh');
969-
//term.writeln.green('ok');
9701021
output = new WritableStream({
9711022
write(data){
972-
//console.log(data);
1023+
console.log(data);
9731024
var str = data;
9741025
str = str.replaceAll('\r','');
9751026
var lines = str.split('\n');
@@ -1107,70 +1158,70 @@
11071158

11081159

11091160
async function prompt(){
1110-
1161+
console.log('prompt');
11111162
//await input.write('\u0003'); // Sends Ctrl+C to clear any junk
11121163
await input.write('\n'); // Sends Enter to get a clean prompt
11131164

11141165
}//prompt
11151166

11161167

1117-
spinner.timer = null;
1118-
1119-
function spinner(msg='Processing'){
1168+
function spinner({x,y}={}){
11201169

1121-
const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
1122-
let i = 0;
1170+
var spinner = {};
1171+
spinner.timer = null;
1172+
spinner.stop = null;
1173+
spinner.x = x;
1174+
spinner.y = y;
1175+
1176+
var frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
1177+
var i = 0;
1178+
// Hide the cursor so it doesn't flicker
1179+
//term.write(cursor.hide);
1180+
setTimeout(setup,50);
1181+
//setup();
1182+
1183+
return spinner;
11231184

1124-
// Hide the cursor so it doesn't flicker
1125-
term.write('\x1b[?25l');
11261185

1127-
spinner.timer = setInterval(() => {
1186+
function setup(){
1187+
1188+
if(x===undefined){
1189+
({x,y} = cursor.xy());
1190+
spinner.x = x;
1191+
spinner.y = y;
1192+
}
1193+
1194+
1195+
spinner.timer = setInterval(()=>{
11281196
// \r moves to start of line, colors.cyan makes it pop
1129-
term.write(`\r${colors.cyan}${frames[i]}${colors.reset} ${msg}...`);
1130-
i = (i + 1) % frames.length;
1131-
},80);
1197+
term.write(`${cursor.save}${cursor.to(x,y)}${colors.cyan}${frames[i]}${colors.reset}${cursor.restore}`);
1198+
i = (i+1)%frames.length;
1199+
1200+
},80);
1201+
1202+
1203+
spinner.stop = function(){
1204+
1205+
if(!spinner.timer){
1206+
return;
1207+
}
1208+
1209+
clearInterval(spinner.timer);
1210+
spinner.timer = null;
1211+
term.write(`${cursor.save}${cursor.to(x,y)} ${cursor.restore}`);
1212+
// Show cursor
1213+
//term.write(cursor.show);
1214+
1215+
}//stop
1216+
1217+
}//setup
11321218

11331219
}//spinner
11341220

11351221

1136-
spinner.stop = function(finalMsg='done!'){
11371222

1138-
if(spinner.timer){
1139-
clearInterval(spinner.timer);
1140-
spinner.timer = null;
1141-
}
1142-
// Clear the line, show cursor, and print final message
1143-
// \x1b[K clears from cursor to end of line
1144-
term.write(`\r\x1b[K${colors.green}${colors.reset} ${finalMsg}\r`);
1145-
// Show cursor
1146-
term.write('\x1b[?25h');
1147-
1148-
}//stop
11491223

11501224

1151-
function end_of_text(y){
1152-
// xterm.js uses 0-based indexing for the buffer,
1153-
// but 1-based for ANSI
1154-
var line = term.buffer.active.getLine(y-1);
1155-
if(!line){
1156-
return 1;
1157-
}
1158-
1159-
var last = 0;
1160-
for(var i=term.cols-1;i>=0;i--){
1161-
1162-
var cell = line.getCell(i);
1163-
// Check if the cell is not empty/whitespace
1164-
if(cell&&cell.getChars().trim()!==''){
1165-
last = i+1;
1166-
break;
1167-
}
1168-
1169-
}//for
1170-
return last+1;
1171-
1172-
}//end_of_text
1173-
11741225

11751226
//:
11761227

0 commit comments

Comments
 (0)