Files
tsvm/assets/tvdos/command.js
2020-11-03 15:00:17 +09:00

222 lines
5.7 KiB
JavaScript

let PROMPT_TEXT = ">";
let CURRENT_DRIVE = "A";
let shell_pwd = [];
const welcome_text = "TSVM Disk Operating System, version " + _TVDOS.VERSION;
function print_prompt_text() {
//print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT);
con.color_pair(239,161);
print(" "+CURRENT_DRIVE+":");
con.color_pair(161,253);
con.addch(16);
con.color_pair(0,253);
print(" \\"+shell_pwd.join("\\")+" ");
con.color_pair(253,255);
con.addch(16);
con.addch(32);
con.color_pair(239,255);
}
function greet() {
con.color_pair(0,253);
//print(welcome_text + " ".repeat(_fsh.scrwidth - welcome_text.length));
print(welcome_text + " ".repeat(80 - welcome_text.length));
con.color_pair(239,255);
println();
}
let shell = {};
// example input: echo "the string" > subdir\test.txt
shell.parse = function(input) {
let tokens = [];
let stringBuffer = "";
let mode = "LITERAL"; // LITERAL, QUOTE, ESCAPE, LIMBO
let i = 0
while (i < input.length) {
const c = input[i];
/*digraph g {
LITERAL -> QUOTE [label="\""]
LITERAL -> LIMBO [label="space"]
LITERAL -> LITERAL [label=else]
QUOTE -> LIMBO [label="\""]
QUOTE -> ESCAPE [label="\\"]
QUOTE -> QUOTE [label=else]
ESCAPE -> QUOTE
LIMBO -> LITERAL [label="not space"]
LIMBO -> QUOTE [label="\""]
LIMBO -> LIMBO [label="space"]
}*/
if (mode == "LITERAL") {
if (c == ' ') {
tokens.push(stringBuffer); stringBuffer = "";
mode = "LIMBO";
}
else if (c == '"') {
tokens.push(stringBuffer); stringBuffer = "";
mode = "QUOTE";
}
else {
stringBuffer += c;
}
}
else if (mode == "LIMBO") {
if (c == '"') {
mode = "QUOTE";
}
else if (c != ' ') {
mode = "LITERAL";
stringBuffer += c;
}
}
else if (mode == "QUOTE") {
if (c == '"') {
tokens.push(stringBuffer); stringBuffer = "";
mode = "LIMBO";
}
else if (c == '^') {
mode = "ESCAPE";
}
else {
stringBuffer += c;
}
}
else if (mode == "ESCAPE") {
}
i += 1;
}
if (stringBuffer.length > 0) {
tokens.push(stringBuffer);
}
return tokens;
}
shell.coreutils = {
cd: function(args) {
if (args[1] === undefined) {
println(shell_pwd.join("\\"));
return
}
shell_pwd = args[1].split("\\");
},
cls: function(args) {
con.clear();
},
exit: function(args) {
cmdExit = true;
},
ver: function(args) {
println(welcome_text);
},
echo: function(args) {
if (args[1] !== undefined) {
args.forEach(function(it,i) { if (i > 0) print(it+" ") });
}
println();
}
};
Object.freeze(shell.coreutils);
shell.execute = function(line) {
if (line.size == 0) return;
let tokens = shell.parse(line);
let cmd = tokens[0].toLowerCase();
if (shell.coreutils[cmd] !== undefined) {
shell.coreutils[cmd](tokens);
}
else {
printerrln('Bad command or filename: "'+cmd+'"');
}
};
if (exec_args !== undefined) return Object.freeze(shell);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
println("Starting TVDOS...");
greet();
let cmdHistory = []; // zeroth element is the oldest
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
let cmdExit = false;
while (!cmdExit) {
print_prompt_text();
let cmdbuf = "";
while (true) {
let key = con.getch();
// printable chars
if (key >= 32 && key <= 126) {
let s = String.fromCharCode(key);
cmdbuf += s;
print(s);
}
// backspace
else if (key === 8 && cmdbuf.length > 0) {
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
print(String.fromCharCode(key));
}
// enter
else if (key === 10 || key === 13) {
println();
try {
shell.execute(cmdbuf);
}
catch (e) {
printerrln(e);
}
finally {
if (cmdbuf.trim().length > 0)
cmdHistory.push(cmdbuf);
cmdHistoryScroll = 0;
break;
}
}
// up arrow
else if (key === 19 && cmdHistory.length > 0 && cmdHistoryScroll < cmdHistory.length) {
cmdHistoryScroll += 1;
// back the cursor in order to type new cmd
let 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);
}
// down arrow
else if (key === 20) {
if (cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd
let 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);
cmdHistoryScroll -= 1;
}
else {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = "";
}
}
}
}
return 0;