mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
222 lines
5.7 KiB
JavaScript
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; |