command.js: no sign of old filesystem from now on

This commit is contained in:
minjaesong
2022-08-18 18:59:41 +09:00
parent 70b9530948
commit b3ac861946

View File

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