mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
command.js: no sign of old filesystem from now on
This commit is contained in:
@@ -1,150 +1,150 @@
|
||||
let PROMPT_TEXT = ">";
|
||||
let CURRENT_DRIVE = "A";
|
||||
let shell_pwd = [""];
|
||||
let PROMPT_TEXT = ">"
|
||||
let CURRENT_DRIVE = "A"
|
||||
let shell_pwd = [""]
|
||||
|
||||
let goInteractive = false;
|
||||
let goFancy = false;
|
||||
let goInteractive = false
|
||||
let goFancy = false
|
||||
|
||||
let DEBUG_PRINT = true;
|
||||
let DEBUG_PRINT = true
|
||||
|
||||
let errorlevel = 0;
|
||||
let errorlevel = 0
|
||||
|
||||
const termWidth = con.getmaxyx()[1];
|
||||
const termHeight = con.getmaxyx()[0];
|
||||
const termWidth = con.getmaxyx()[1]
|
||||
const termHeight = con.getmaxyx()[0]
|
||||
const welcome_text = (termWidth > 40) ? "TSVM Disk Operating System, version " + _TVDOS.VERSION
|
||||
: "TSVM Disk Operating System " + _TVDOS.VERSION;
|
||||
const greetLeftPad = (termWidth - welcome_text.length - 6) >> 1;
|
||||
const greetRightPad = termWidth - greetLeftPad - welcome_text.length - 6;
|
||||
: "TSVM Disk Operating System " + _TVDOS.VERSION
|
||||
const greetLeftPad = (termWidth - welcome_text.length - 6) >> 1
|
||||
const greetRightPad = termWidth - greetLeftPad - welcome_text.length - 6
|
||||
|
||||
function makeHash() {
|
||||
let e = "YBNDRFG8EJKMCPQXOTLVWIS2A345H769";
|
||||
let m = e.length;
|
||||
let e = "YBNDRFG8EJKMCPQXOTLVWIS2A345H769"
|
||||
let m = e.length
|
||||
return e[Math.floor(Math.random()*m)] + e[Math.floor(Math.random()*m)] + e[Math.floor(Math.random()*m)] + e[Math.floor(Math.random()*m)] + e[Math.floor(Math.random()*m)]
|
||||
}
|
||||
|
||||
const shellID = makeHash();
|
||||
const shellID = makeHash()
|
||||
|
||||
function print_prompt_text() {
|
||||
if (goFancy) {
|
||||
con.color_pair(239,161);
|
||||
print(" "+CURRENT_DRIVE+":");
|
||||
con.color_pair(161,253);
|
||||
con.addch(16);con.curs_right();
|
||||
con.color_pair(0,253);
|
||||
print(" \\"+shell_pwd.join("\\").substring(1)+" ");
|
||||
con.color_pair(239,161)
|
||||
print(" "+CURRENT_DRIVE+":")
|
||||
con.color_pair(161,253)
|
||||
con.addch(16);con.curs_right()
|
||||
con.color_pair(0,253)
|
||||
print(" \\"+shell_pwd.join("\\").substring(1)+" ")
|
||||
if (errorlevel != 0) {
|
||||
con.color_pair(166,253);
|
||||
print("["+errorlevel+"] ");
|
||||
con.color_pair(166,253)
|
||||
print("["+errorlevel+"] ")
|
||||
}
|
||||
con.color_pair(253,255);
|
||||
con.addch(16);con.curs_right();
|
||||
con.addch(32);con.curs_right();
|
||||
con.color_pair(253,255);
|
||||
con.color_pair(253,255)
|
||||
con.addch(16);con.curs_right()
|
||||
con.addch(32);con.curs_right()
|
||||
con.color_pair(253,255)
|
||||
}
|
||||
else {
|
||||
// con.color_pair(253,255);
|
||||
// con.color_pair(253,255)
|
||||
if (errorlevel != 0)
|
||||
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + " [" + errorlevel + "]" + PROMPT_TEXT);
|
||||
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + " [" + errorlevel + "]" + PROMPT_TEXT)
|
||||
else
|
||||
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT);
|
||||
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT)
|
||||
}
|
||||
}
|
||||
|
||||
function greet() {
|
||||
if (goFancy) {
|
||||
con.color_pair(239,255);
|
||||
con.clear();
|
||||
con.color_pair(253,255);
|
||||
print(' ');con.addch(17);con.curs_right();
|
||||
con.color_pair(0,253);
|
||||
print(" ".repeat(greetLeftPad)+welcome_text+" ".repeat(greetRightPad));
|
||||
con.color_pair(253,255);
|
||||
con.addch(16);con.curs_right();print(' ');
|
||||
con.move(3,1);
|
||||
con.color_pair(239,255)
|
||||
con.clear()
|
||||
con.color_pair(253,255)
|
||||
print(' ');con.addch(17);con.curs_right()
|
||||
con.color_pair(0,253)
|
||||
print(" ".repeat(greetLeftPad)+welcome_text+" ".repeat(greetRightPad))
|
||||
con.color_pair(253,255)
|
||||
con.addch(16);con.curs_right();print(' ')
|
||||
con.move(3,1)
|
||||
}
|
||||
else
|
||||
println(welcome_text);
|
||||
println(welcome_text)
|
||||
}
|
||||
|
||||
/*uninterruptible*/ function sendLcdMsg(s) {
|
||||
// making it uninterruptible
|
||||
sys.poke(-1025, (s === undefined) ? 0 : s.charCodeAt(0)|0);
|
||||
sys.poke(-1026, (s === undefined) ? 0 : s.charCodeAt(1)|0);
|
||||
sys.poke(-1027, (s === undefined) ? 0 : s.charCodeAt(2)|0);
|
||||
sys.poke(-1028, (s === undefined) ? 0 : s.charCodeAt(3)|0);
|
||||
sys.poke(-1029, (s === undefined) ? 0 : s.charCodeAt(4)|0);
|
||||
sys.poke(-1030, (s === undefined) ? 0 : s.charCodeAt(5)|0);
|
||||
sys.poke(-1031, (s === undefined) ? 0 : s.charCodeAt(6)|0);
|
||||
sys.poke(-1032, (s === undefined) ? 0 : s.charCodeAt(7)|0);
|
||||
sys.poke(-1033, (s === undefined) ? 0 : s.charCodeAt(8)|0);
|
||||
sys.poke(-1034, (s === undefined) ? 0 : s.charCodeAt(9)|0);
|
||||
sys.poke(-1035, (s === undefined) ? 0 : s.charCodeAt(10)|0);
|
||||
sys.poke(-1036, (s === undefined) ? 0 : s.charCodeAt(11)|0);
|
||||
sys.poke(-1037, (s === undefined) ? 0 : s.charCodeAt(12)|0);
|
||||
sys.poke(-1038, (s === undefined) ? 0 : s.charCodeAt(13)|0);
|
||||
sys.poke(-1039, (s === undefined) ? 0 : s.charCodeAt(14)|0);
|
||||
sys.poke(-1040, (s === undefined) ? 0 : s.charCodeAt(15)|0);
|
||||
sys.poke(-1041, (s === undefined) ? 0 : s.charCodeAt(16)|0);
|
||||
sys.poke(-1042, (s === undefined) ? 0 : s.charCodeAt(17)|0);
|
||||
sys.poke(-1043, (s === undefined) ? 0 : s.charCodeAt(18)|0);
|
||||
sys.poke(-1044, (s === undefined) ? 0 : s.charCodeAt(19)|0);
|
||||
sys.poke(-1045, (s === undefined) ? 0 : s.charCodeAt(20)|0);
|
||||
sys.poke(-1046, (s === undefined) ? 0 : s.charCodeAt(21)|0);
|
||||
sys.poke(-1047, (s === undefined) ? 0 : s.charCodeAt(22)|0);
|
||||
sys.poke(-1048, (s === undefined) ? 0 : s.charCodeAt(23)|0);
|
||||
sys.poke(-1025, (s === undefined) ? 0 : s.charCodeAt(0)|0)
|
||||
sys.poke(-1026, (s === undefined) ? 0 : s.charCodeAt(1)|0)
|
||||
sys.poke(-1027, (s === undefined) ? 0 : s.charCodeAt(2)|0)
|
||||
sys.poke(-1028, (s === undefined) ? 0 : s.charCodeAt(3)|0)
|
||||
sys.poke(-1029, (s === undefined) ? 0 : s.charCodeAt(4)|0)
|
||||
sys.poke(-1030, (s === undefined) ? 0 : s.charCodeAt(5)|0)
|
||||
sys.poke(-1031, (s === undefined) ? 0 : s.charCodeAt(6)|0)
|
||||
sys.poke(-1032, (s === undefined) ? 0 : s.charCodeAt(7)|0)
|
||||
sys.poke(-1033, (s === undefined) ? 0 : s.charCodeAt(8)|0)
|
||||
sys.poke(-1034, (s === undefined) ? 0 : s.charCodeAt(9)|0)
|
||||
sys.poke(-1035, (s === undefined) ? 0 : s.charCodeAt(10)|0)
|
||||
sys.poke(-1036, (s === undefined) ? 0 : s.charCodeAt(11)|0)
|
||||
sys.poke(-1037, (s === undefined) ? 0 : s.charCodeAt(12)|0)
|
||||
sys.poke(-1038, (s === undefined) ? 0 : s.charCodeAt(13)|0)
|
||||
sys.poke(-1039, (s === undefined) ? 0 : s.charCodeAt(14)|0)
|
||||
sys.poke(-1040, (s === undefined) ? 0 : s.charCodeAt(15)|0)
|
||||
sys.poke(-1041, (s === undefined) ? 0 : s.charCodeAt(16)|0)
|
||||
sys.poke(-1042, (s === undefined) ? 0 : s.charCodeAt(17)|0)
|
||||
sys.poke(-1043, (s === undefined) ? 0 : s.charCodeAt(18)|0)
|
||||
sys.poke(-1044, (s === undefined) ? 0 : s.charCodeAt(19)|0)
|
||||
sys.poke(-1045, (s === undefined) ? 0 : s.charCodeAt(20)|0)
|
||||
sys.poke(-1046, (s === undefined) ? 0 : s.charCodeAt(21)|0)
|
||||
sys.poke(-1047, (s === undefined) ? 0 : s.charCodeAt(22)|0)
|
||||
sys.poke(-1048, (s === undefined) ? 0 : s.charCodeAt(23)|0)
|
||||
}
|
||||
|
||||
function trimStartRevSlash(s) {
|
||||
var cnt = 0;
|
||||
var cnt = 0
|
||||
while (cnt < s.length) {
|
||||
var chr = s[cnt];
|
||||
var chr = s[cnt]
|
||||
|
||||
if (chr != '\\') break;
|
||||
if (chr != '\\') break
|
||||
|
||||
cnt += 1;
|
||||
cnt += 1
|
||||
}
|
||||
|
||||
return s.substring(cnt);
|
||||
return s.substring(cnt)
|
||||
}
|
||||
|
||||
let shell = {};
|
||||
let shell = {}
|
||||
shell.usrcfg = {textCol: 254}
|
||||
shell.replaceVarCall = function(value) {
|
||||
// syntax:
|
||||
// line = literal [varcall] [literal] ;
|
||||
// varcall = "$" ident ;
|
||||
// ident = ? regex: [A-Za-z_]+ ? ;
|
||||
// literal = ? you know what it is ? ;
|
||||
let replaceMap = [];
|
||||
let varMode = false;
|
||||
let sb = '';
|
||||
// line = literal [varcall] [literal]
|
||||
// varcall = "$" ident
|
||||
// ident = ? regex: [A-Za-z_]+ ?
|
||||
// literal = ? you know what it is ?
|
||||
let replaceMap = []
|
||||
let varMode = false
|
||||
let sb = ''
|
||||
for (let i=0; i<value.length; i++) {
|
||||
let char = value.charAt(i);
|
||||
let cp = value.charCodeAt(i);
|
||||
let char = value.charAt(i)
|
||||
let cp = value.charCodeAt(i)
|
||||
if (!varMode && char == '$') {
|
||||
replaceMap.push({s:sb,r:false});
|
||||
sb = ''; varMode = true;
|
||||
replaceMap.push({s:sb,r:false})
|
||||
sb = ''; varMode = true
|
||||
}
|
||||
else if (varMode && !(cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp == 95 || cp >= 97 && cp <= 122)) {
|
||||
replaceMap.push({s:sb,r:true});
|
||||
sb = ''+char; varMode = false;
|
||||
replaceMap.push({s:sb,r:true})
|
||||
sb = ''+char; varMode = false
|
||||
}
|
||||
else sb += char;
|
||||
}; replaceMap.push({s:sb,r:(varMode)});
|
||||
else sb += char
|
||||
}; replaceMap.push({s:sb,r:(varMode)})
|
||||
|
||||
return replaceMap.map(it => (it.r) ? _TVDOS.variables[it.s] : it.s).join('');
|
||||
return replaceMap.map(it => (it.r) ? _TVDOS.variables[it.s] : it.s).join('')
|
||||
}
|
||||
shell.getPwd = function() { return shell_pwd; }
|
||||
shell.getPwdString = function() { return "\\" + (shell_pwd.concat([""])).join("\\"); }
|
||||
shell.getCurrentDrive = function() { return CURRENT_DRIVE; }
|
||||
// example input: echo "the string" > subdir\test.txt
|
||||
shell.parse = function(input) {
|
||||
let tokens = [];
|
||||
let stringBuffer = "";
|
||||
let tokens = []
|
||||
let stringBuffer = ""
|
||||
let mode = "LITERAL"; // LITERAL, QUOTE, ESCAPE, LIMBO, OP
|
||||
let i = 0
|
||||
while (i < input.length) {
|
||||
const c = input[i];
|
||||
const c = input[i]
|
||||
/*digraph g {
|
||||
LITERAL -> QUOTE [label="\""]
|
||||
LITERAL -> OP [label="pipe"]
|
||||
@@ -168,75 +168,75 @@ shell.parse = function(input) {
|
||||
}*/
|
||||
if ("LITERAL" == mode) {
|
||||
if (' ' == c) {
|
||||
tokens.push(stringBuffer); stringBuffer = "";
|
||||
mode = "LIMBO";
|
||||
tokens.push(stringBuffer); stringBuffer = ""
|
||||
mode = "LIMBO"
|
||||
}
|
||||
else if ('"' == c) {
|
||||
tokens.push(stringBuffer); stringBuffer = "";
|
||||
mode = "QUOTE";
|
||||
tokens.push(stringBuffer); stringBuffer = ""
|
||||
mode = "QUOTE"
|
||||
}
|
||||
else if ('|' == c || '>' == c || '&' == c || '<' == c) {
|
||||
tokens.push(stringBuffer); stringBuffer = "";
|
||||
tokens.push(stringBuffer); stringBuffer = ""
|
||||
mode = "OP"
|
||||
}
|
||||
else {
|
||||
stringBuffer += c;
|
||||
stringBuffer += c
|
||||
}
|
||||
}
|
||||
else if ("LIMBO" == mode) {
|
||||
if ('"' == c) {
|
||||
mode = "QUOTE";
|
||||
mode = "QUOTE"
|
||||
}
|
||||
else if ('|' == c || '>' == c || '&' == c || '<' == c) {
|
||||
mode = "OP"
|
||||
stringBuffer += c
|
||||
}
|
||||
else if (c != ' ') {
|
||||
mode = "LITERAL";
|
||||
stringBuffer += c;
|
||||
mode = "LITERAL"
|
||||
stringBuffer += c
|
||||
}
|
||||
}
|
||||
else if ("QUOTE" == mode) {
|
||||
if ('"' == c) {
|
||||
tokens.push(stringBuffer); stringBuffer = "";
|
||||
mode = "LIMBO";
|
||||
tokens.push(stringBuffer); stringBuffer = ""
|
||||
mode = "LIMBO"
|
||||
}
|
||||
else if ('^' == c) {
|
||||
mode = "ESCAPE";
|
||||
mode = "ESCAPE"
|
||||
}
|
||||
else {
|
||||
stringBuffer += c;
|
||||
stringBuffer += c
|
||||
}
|
||||
}
|
||||
else if ("OP" == mode) {
|
||||
if (' ' == c) {
|
||||
tokens.push(stringBuffer); stringBuffer = "";
|
||||
mode = "LIMBO";
|
||||
tokens.push(stringBuffer); stringBuffer = ""
|
||||
mode = "LIMBO"
|
||||
}
|
||||
else if ('|' == c || '>' == c || '&' == c || '<' == c) {
|
||||
stringBuffer += c
|
||||
}
|
||||
else if ('"' == c) {
|
||||
tokens.push(stringBuffer); stringBuffer = "";
|
||||
mode = "QUOTE";
|
||||
tokens.push(stringBuffer); stringBuffer = ""
|
||||
mode = "QUOTE"
|
||||
}
|
||||
else {
|
||||
tokens.push(stringBuffer); stringBuffer = "";
|
||||
mode = "LITERAL";
|
||||
tokens.push(stringBuffer); stringBuffer = ""
|
||||
mode = "LITERAL"
|
||||
}
|
||||
}
|
||||
else if ("ESCAPE" == mode) {
|
||||
TODO();
|
||||
TODO()
|
||||
}
|
||||
|
||||
i += 1;
|
||||
i += 1
|
||||
}
|
||||
|
||||
if (stringBuffer.length > 0) {
|
||||
tokens.push(stringBuffer);
|
||||
tokens.push(stringBuffer)
|
||||
}
|
||||
|
||||
return tokens;
|
||||
return tokens
|
||||
}
|
||||
/** @return fully resolved path, starting with '\' but not a drive letter */
|
||||
shell.resolvePathInput = function(input) {
|
||||
@@ -457,7 +457,7 @@ shell.coreutils = {
|
||||
panic: function(args) {
|
||||
throw Error("Panicking command.js")
|
||||
}
|
||||
};
|
||||
}
|
||||
// define command aliases here
|
||||
shell.coreutils.chdir = shell.coreutils.cd
|
||||
shell.coreutils.copy = shell.coreutils.cp
|
||||
@@ -466,7 +466,7 @@ shell.coreutils.rm = shell.coreutils.del
|
||||
shell.coreutils.ls = shell.coreutils.dir
|
||||
shell.coreutils.time = shell.coreutils.date
|
||||
// end of command aliases
|
||||
Object.freeze(shell.coreutils);
|
||||
Object.freeze(shell.coreutils)
|
||||
shell.stdio = {
|
||||
out: {
|
||||
print: function(s) { sys.print(s) },
|
||||
@@ -483,8 +483,8 @@ shell.stdio = {
|
||||
}
|
||||
Object.freeze(shell.stdio)
|
||||
shell.execute = function(line) {
|
||||
if (0 == line.size) return;
|
||||
let parsedTokens = shell.parse(line); // echo, "hai", |, less
|
||||
if (0 == line.size) return
|
||||
let parsedTokens = shell.parse(line) // echo, "hai", |, less
|
||||
let statements = [] // [[echo, "hai"], [less]]
|
||||
let operators = [] // [|]
|
||||
|
||||
@@ -530,114 +530,116 @@ shell.execute = function(line) {
|
||||
|
||||
let tokens = statements[c]
|
||||
|
||||
let cmd = tokens[0];
|
||||
let cmd = tokens[0]
|
||||
if (cmd === undefined || cmd === '') {
|
||||
retValue = 0;
|
||||
retValue = 0
|
||||
continue
|
||||
}
|
||||
|
||||
// handle Ctrl-C
|
||||
if (con.hitterminate()) {
|
||||
retValue = 1;
|
||||
retValue = 1
|
||||
continue
|
||||
}
|
||||
|
||||
if (shell.coreutils[cmd.toLowerCase()] !== undefined) {
|
||||
var retval = shell.coreutils[cmd.toLowerCase()](tokens);
|
||||
retValue = retval|0; // return value of undefined will cast into 0
|
||||
var retval = shell.coreutils[cmd.toLowerCase()](tokens)
|
||||
retValue = retval|0 // return value of undefined will cast into 0
|
||||
continue
|
||||
}
|
||||
else {
|
||||
// search through PATH for execution
|
||||
|
||||
var fileExists = false;
|
||||
var searchDir = (cmd.startsWith("/")) ? [""] : ["/"+shell_pwd.join("/")].concat(_TVDOS.getPath());
|
||||
var fileExists = false
|
||||
var searchDir = (cmd.startsWith("/")) ? [""] : ["/"+shell_pwd.join("/")].concat(_TVDOS.getPath())
|
||||
|
||||
var pathExt = []; // it seems Nashorn does not like 'let' too much? this line gets ignored sometimes
|
||||
var pathExt = [] // it seems Nashorn does not like 'let' too much? this line gets ignored sometimes
|
||||
// fill pathExt using %PATHEXT% but also capitalise them
|
||||
if (cmd.split(".")[1] === undefined)
|
||||
_TVDOS.variables.PATHEXT.split(';').forEach(function(it) { pathExt.push(it); pathExt.push(it.toUpperCase()); });
|
||||
_TVDOS.variables.PATHEXT.split(';').forEach(function(it) { pathExt.push(it); pathExt.push(it.toUpperCase()); })
|
||||
else
|
||||
pathExt.push(""); // final empty extension
|
||||
pathExt.push("") // final empty extension
|
||||
|
||||
var searchPath = ""
|
||||
let searchPath = ""
|
||||
let searchFile = 0
|
||||
|
||||
searchLoop:
|
||||
for (var i = 0; i < searchDir.length; i++) {
|
||||
for (var j = 0; j < pathExt.length; j++) {
|
||||
var search = searchDir[i]; if (!search.endsWith('\\')) search += '\\';
|
||||
searchPath = trimStartRevSlash(search + cmd + pathExt[j]);
|
||||
let search = searchDir[i]; if (!search.endsWith('\\')) search += '\\'
|
||||
searchPath = trimStartRevSlash(search + cmd + pathExt[j])
|
||||
|
||||
if (DEBUG_PRINT) {
|
||||
serial.println("[command.js > shell.execute] file search path: "+searchPath);
|
||||
serial.println("[command.js > shell.execute] file search path: "+searchPath)
|
||||
}
|
||||
|
||||
if (0 == filesystem.open(CURRENT_DRIVE, searchPath, "R")) {
|
||||
fileExists = true;
|
||||
break searchLoop;
|
||||
searchFile = files.open(`${CURRENT_DRIVE}:\\${searchPath}`)
|
||||
if (searchFile.exists) {
|
||||
fileExists = true
|
||||
break searchLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileExists) {
|
||||
printerrln('Bad command or filename: "'+cmd+'"');
|
||||
retValue = 127;
|
||||
printerrln('Bad command or filename: "'+cmd+'"')
|
||||
retValue = 127
|
||||
continue
|
||||
}
|
||||
else {
|
||||
var programCode = filesystem.readAll(CURRENT_DRIVE);
|
||||
var extension = undefined;
|
||||
let programCode = searchFile.sread()
|
||||
let extension = undefined
|
||||
// get proper extension
|
||||
var dotSepTokens = cmd.split('.');
|
||||
if (dotSepTokens.length > 1) extension = dotSepTokens[dotSepTokens.length - 1].toUpperCase();
|
||||
let dotSepTokens = cmd.split('.')
|
||||
if (dotSepTokens.length > 1) extension = dotSepTokens[dotSepTokens.length - 1].toUpperCase()
|
||||
|
||||
if ("BAT" == extension) {
|
||||
// parse and run as batch file
|
||||
var lines = programCode.split('\n').filter(function(it) { return it.length > 0 }); // this return is not shell's return!
|
||||
var lines = programCode.split('\n').filter(function(it) { return it.length > 0 }) // this return is not shell's return!
|
||||
lines.forEach(function(line) {
|
||||
shell.execute(line);
|
||||
});
|
||||
shell.execute(line)
|
||||
})
|
||||
}
|
||||
else {
|
||||
let gotError = false;
|
||||
let gotError = false
|
||||
|
||||
try {
|
||||
errorlevel = 0; // reset the number
|
||||
errorlevel = 0 // reset the number
|
||||
|
||||
if (_G.shellProgramTitles === undefined) _G.shellProgramTitles = [];
|
||||
if (_G.shellProgramTitles === undefined) _G.shellProgramTitles = []
|
||||
_G.shellProgramTitles.push(cmd.toUpperCase())
|
||||
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1]);
|
||||
//serial.println(_G.shellProgramTitles);
|
||||
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1])
|
||||
//serial.println(_G.shellProgramTitles)
|
||||
|
||||
errorlevel = execApp(programCode, tokens, `tvdosExec$${cmd}$${searchPath}`.replaceAll(/[^A-Za-z0-9_]/g, "$")); // return value of undefined will cast into 0
|
||||
errorlevel = execApp(programCode, tokens, `tvdosExec$${cmd}$${searchPath}`.replaceAll(/[^A-Za-z0-9_]/g, "$")) // return value of undefined will cast into 0
|
||||
}
|
||||
catch (e) {
|
||||
gotError = true;
|
||||
gotError = true
|
||||
|
||||
serial.printerr(`[command.js] program quit with ${e}:\n${e.stack || '(stack trace unavailable)'}`);
|
||||
printerrln(`Program quit with error:\n${e.stack || '(stack trace unavailable)'}`);
|
||||
serial.printerr(`[command.js] program quit with ${e}:\n${e.stack || '(stack trace unavailable)'}`)
|
||||
printerrln(`Program quit with error:\n${e.stack || '(stack trace unavailable)'}`)
|
||||
|
||||
if (`${e}`.startsWith("InterruptedException"))
|
||||
errorlevel = SIGTERM.name;
|
||||
errorlevel = SIGTERM.name
|
||||
else if (e instanceof IllegalAccessException || `${e}`.startsWith("net.torvald.tsvm.ErrorIllegalAccess"))
|
||||
errorlevel = SIGSEGV.name;
|
||||
errorlevel = SIGSEGV.name
|
||||
|
||||
// exception catched means something went wrong, so if errorlevel is found to be zero, force set to 1.
|
||||
if (errorlevel === 0 || errorlevel == undefined)
|
||||
errorlevel = 1;
|
||||
errorlevel = 1
|
||||
}
|
||||
finally {
|
||||
// sometimes no-error program may return nothing as the errorlevel; force set to 0 then.
|
||||
if (!gotError && (errorlevel == undefined || (typeof errorlevel.trim == "function" && errorlevel.trim().length == 0) || isNaN(errorlevel)))
|
||||
errorlevel = 0;
|
||||
errorlevel = 0
|
||||
|
||||
serial.printerr(`errorlevel: ${errorlevel}`);
|
||||
serial.printerr(`errorlevel: ${errorlevel}`)
|
||||
|
||||
_G.shellProgramTitles.pop();
|
||||
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1]);
|
||||
//serial.println(_G.shellProgramTitles);
|
||||
_G.shellProgramTitles.pop()
|
||||
sendLcdMsg(_G.shellProgramTitles[_G.shellProgramTitles.length - 1])
|
||||
//serial.println(_G.shellProgramTitles)
|
||||
|
||||
retValue = errorlevel;
|
||||
retValue = errorlevel
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -654,9 +656,9 @@ shell.execute = function(line) {
|
||||
|
||||
return retValue
|
||||
}
|
||||
};
|
||||
shell.pipes = {}; // syntax: _G.shell.pipes[name] = contents; all pipes are named pipes just like in Windows
|
||||
shell.currentlyActivePipes = []; // Queue of pipe's names. Use shell.removePipe() to dequeue and shell.pushPipe() to enqueue.
|
||||
}
|
||||
shell.pipes = {} // syntax: _G.shell.pipes[name] = contents; all pipes are named pipes just like in Windows
|
||||
shell.currentlyActivePipes = [] // Queue of pipe's names. Use shell.removePipe() to dequeue and shell.pushPipe() to enqueue.
|
||||
shell._rndstr = '0123456789+qwfpgjluyarstdhneiozxcvbkm/QWFPGJLUYARSTDHNEIOZXCVBKM'
|
||||
shell.generateRandomName = function() {
|
||||
let name = ''
|
||||
@@ -693,115 +695,115 @@ shell.removePipe = function() {
|
||||
let n = shell.currentlyActivePipes.shift()
|
||||
return (n != undefined) ? shell.pipes[n] : undefined
|
||||
}
|
||||
Object.freeze(shell);
|
||||
_G.shell = shell;
|
||||
Object.freeze(shell)
|
||||
_G.shell = shell
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (exec_args[1] !== undefined) {
|
||||
// only meaningful switches would be either /c or /k anyway
|
||||
var firstSwitch = exec_args[1].toLowerCase();
|
||||
var firstSwitch = exec_args[1].toLowerCase()
|
||||
|
||||
// command /c <commands>
|
||||
// ^[0] ^[1] ^[2]
|
||||
if ("/c" == firstSwitch) {
|
||||
if ("" == exec_args[2]) return 0; // no commands were given, just exit successfully
|
||||
return shell.execute(exec_args[2]);
|
||||
if ("" == exec_args[2]) return 0 // no commands were given, just exit successfully
|
||||
return shell.execute(exec_args[2])
|
||||
}
|
||||
else if ("/k" == firstSwitch) {
|
||||
if ("" == exec_args[2]) return 0; // no commands were given, just exit successfully
|
||||
shell.execute(exec_args[2]);
|
||||
goInteractive = true;
|
||||
if ("" == exec_args[2]) return 0 // no commands were given, just exit successfully
|
||||
shell.execute(exec_args[2])
|
||||
goInteractive = true
|
||||
}
|
||||
else if ("/fancy" == firstSwitch) {
|
||||
graphics.setBackground(2,3,4);
|
||||
goFancy = true;
|
||||
goInteractive = true;
|
||||
graphics.setBackground(2,3,4)
|
||||
goFancy = true
|
||||
goInteractive = true
|
||||
}
|
||||
else {
|
||||
printerrln("Invalid switch: "+exec_args[1]);
|
||||
return 1;
|
||||
printerrln("Invalid switch: "+exec_args[1])
|
||||
return 1
|
||||
}
|
||||
}
|
||||
else {
|
||||
goInteractive = true;
|
||||
goInteractive = true
|
||||
}
|
||||
|
||||
let cmdExit = false;
|
||||
let cmdExit = false
|
||||
if (goInteractive) {
|
||||
con.curs_set(1);
|
||||
greet();
|
||||
con.curs_set(1)
|
||||
greet()
|
||||
|
||||
let cmdHistory = []; // zeroth element is the oldest
|
||||
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
|
||||
let cmdHistory = [] // zeroth element is the oldest
|
||||
let cmdHistoryScroll = 0 // 0 for outside-of-buffer, 1 for most recent
|
||||
while (!cmdExit) {
|
||||
con.curs_set(1);
|
||||
con.curs_set(1)
|
||||
con.color_pair(shell.usrcfg.textCol,255)
|
||||
print_prompt_text();
|
||||
print_prompt_text()
|
||||
|
||||
var cmdbuf = "";
|
||||
var cmdbuf = ""
|
||||
|
||||
while (true) {
|
||||
let key = con.getch();
|
||||
let key = con.getch()
|
||||
|
||||
// printable chars
|
||||
if (key >= 32 && key <= 126) {
|
||||
var s = String.fromCharCode(key);
|
||||
cmdbuf += s;
|
||||
print(s);
|
||||
var s = String.fromCharCode(key)
|
||||
cmdbuf += s
|
||||
print(s)
|
||||
}
|
||||
// backspace
|
||||
else if (key === con.KEY_BACKSPACE && cmdbuf.length > 0) {
|
||||
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
|
||||
print(String.fromCharCode(key));
|
||||
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1)
|
||||
print(String.fromCharCode(key))
|
||||
}
|
||||
// enter
|
||||
else if (key === 10 || key === con.KEY_RETURN) {
|
||||
println();
|
||||
println()
|
||||
|
||||
shell.execute(cmdbuf);
|
||||
shell.execute(cmdbuf)
|
||||
|
||||
if (cmdbuf.trim().length > 0)
|
||||
cmdHistory.push(cmdbuf);
|
||||
cmdHistory.push(cmdbuf)
|
||||
|
||||
cmdHistoryScroll = 0;
|
||||
con.curs_set(1);
|
||||
cmdHistoryScroll = 0
|
||||
con.curs_set(1)
|
||||
|
||||
break;
|
||||
break
|
||||
}
|
||||
// up arrow
|
||||
else if (key === con.KEY_UP && cmdHistory.length > 0 && cmdHistoryScroll < cmdHistory.length) {
|
||||
cmdHistoryScroll += 1;
|
||||
cmdHistoryScroll += 1
|
||||
|
||||
// back the cursor in order to type new cmd
|
||||
var x = 0;
|
||||
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
|
||||
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
|
||||
var x = 0
|
||||
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8))
|
||||
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll]
|
||||
// re-type the new command
|
||||
print(cmdbuf);
|
||||
print(cmdbuf)
|
||||
|
||||
}
|
||||
// down arrow
|
||||
else if (key === con.KEY_DOWN) {
|
||||
if (cmdHistoryScroll > 0) {
|
||||
// back the cursor in order to type new cmd
|
||||
var x = 0;
|
||||
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
|
||||
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
|
||||
var x = 0
|
||||
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8))
|
||||
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll]
|
||||
// re-type the new command
|
||||
print(cmdbuf);
|
||||
print(cmdbuf)
|
||||
|
||||
cmdHistoryScroll -= 1;
|
||||
cmdHistoryScroll -= 1
|
||||
}
|
||||
else {
|
||||
// back the cursor in order to type new cmd
|
||||
var x = 0;
|
||||
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
|
||||
cmdbuf = "";
|
||||
var x = 0
|
||||
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8))
|
||||
cmdbuf = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0
|
||||
Reference in New Issue
Block a user