417 lines
14 KiB
JavaScript
417 lines
14 KiB
JavaScript
|
var JSXCommands;
|
||
|
(function (JSXCommands) {
|
||
|
/**
|
||
|
* Echoes the given arguments
|
||
|
*/
|
||
|
class Echo {
|
||
|
create(terminal, stdio, args) {
|
||
|
if (args.filter((a) => { return a != ""; }).length == 0) {
|
||
|
stdio.println("Nothing echoes... nothing");
|
||
|
terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
stdio.println(args.join(" "));
|
||
|
terminal.closeProgram(this);
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "Echoes the given arguments" +
|
||
|
"\n\nUsage: echo [anything to echo]";
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.Echo = Echo;
|
||
|
/**
|
||
|
* Lists all files in the given directory or this directory, if path not specified.
|
||
|
*/
|
||
|
class List {
|
||
|
constructor(jsx) {
|
||
|
this.jsx = jsx;
|
||
|
}
|
||
|
create(terminal, stdio, args) {
|
||
|
let folder = this.jsx.currentFolder;
|
||
|
if (args.length > 0) {
|
||
|
let pathStr = args.slice(-1)[0];
|
||
|
let path = this.jsx.findPath(pathStr);
|
||
|
if (path instanceof JavaScriptX.Folder) {
|
||
|
args.splice(-1);
|
||
|
folder = path;
|
||
|
}
|
||
|
}
|
||
|
let argObj = parseArgsToObject(args);
|
||
|
let a = "a" in argObj;
|
||
|
if (a) {
|
||
|
stdio.println(".", "blue");
|
||
|
if (folder.parentFolder != null) {
|
||
|
stdio.println("..", "blue");
|
||
|
}
|
||
|
}
|
||
|
let files = folder.files.filter(f => (!f.hidden || a));
|
||
|
for (let i = 0; i < files.length; i++) {
|
||
|
let f = files[i];
|
||
|
stdio.println(JavaScriptX.formatToLength(f.name, 20), ((f.hidden) ? "blue" : (f instanceof JavaScriptX.Folder) ? "red" : "yellow"));
|
||
|
stdio.print(" " +
|
||
|
((f instanceof JavaScriptX.Folder) ? "DIR" : ((f instanceof JavaScriptX.BinaryFile) ? "BIN" : "TXT")));
|
||
|
stdio.print(" " + new Date(f.created).toLocaleString());
|
||
|
}
|
||
|
terminal.closeProgram(this);
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "Lists all files in the given directory\nor this directory, if path not specified." +
|
||
|
"\n\nUsage: ls [options] [path]" +
|
||
|
"\n\nOptions:\n " + JavaScriptX.formatToLength("-a", 10) + "List all files (incl. hidden)";
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.List = List;
|
||
|
/**
|
||
|
* Changes directory to the specified directory.
|
||
|
*/
|
||
|
class ChangeDirectory {
|
||
|
constructor(jsx) {
|
||
|
this.jsx = jsx;
|
||
|
}
|
||
|
create(terminal, stdio, args) {
|
||
|
if (args.length == 0) {
|
||
|
stdio.println("Insufficent parameters, usage:");
|
||
|
stdio.println("cd [path]");
|
||
|
terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
let path = this.jsx.findPath(args[0]);
|
||
|
let folder = false;
|
||
|
if (path) {
|
||
|
if (path instanceof JavaScriptX.Folder) {
|
||
|
folder = true;
|
||
|
}
|
||
|
else {
|
||
|
stdio.println(`'${args[0]}' is not a folder.`);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
stdio.println(`'${args[0]}' not found.`);
|
||
|
}
|
||
|
if (folder && path instanceof JavaScriptX.Folder) {
|
||
|
this.jsx.currentFolder = path;
|
||
|
}
|
||
|
terminal.closeProgram(this);
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "Changes directory to the specified directory." +
|
||
|
"\n\nUsage: cd [path]";
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.ChangeDirectory = ChangeDirectory;
|
||
|
/**
|
||
|
* Creates a directory at specified location.
|
||
|
*/
|
||
|
class MakeDirectory {
|
||
|
constructor(jsx) {
|
||
|
this.jsx = jsx;
|
||
|
}
|
||
|
create(terminal, stdio, args) {
|
||
|
if (args.length == 0) {
|
||
|
stdio.println("Insufficent parameters, usage:");
|
||
|
stdio.println("mkdir [path]");
|
||
|
terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
let pathArg = args.splice(-1)[0];
|
||
|
let argObj = parseArgsToObject(args);
|
||
|
let h = "h" in argObj;
|
||
|
let origPathpieces = pathArg.split("/");
|
||
|
let curr = [origPathpieces[0]];
|
||
|
let i = 0;
|
||
|
let createFolder = false;
|
||
|
do {
|
||
|
let path = this.jsx.findPath(curr.join("/"));
|
||
|
if (!path) {
|
||
|
if (origPathpieces.length == curr.length) {
|
||
|
createFolder = true;
|
||
|
}
|
||
|
else {
|
||
|
stdio.println(`${curr.join("/")} not found!`);
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
else if (path && origPathpieces.length == curr.length) {
|
||
|
stdio.println(`${curr.join("/")} already exists!`);
|
||
|
}
|
||
|
else if (!(path instanceof JavaScriptX.Folder)) {
|
||
|
stdio.println(`${curr.join("/")} is not a folder!`);
|
||
|
}
|
||
|
if (i < origPathpieces.length) {
|
||
|
i += 1;
|
||
|
curr.push(origPathpieces[i]);
|
||
|
}
|
||
|
} while (curr.length < origPathpieces.length + 1);
|
||
|
if (createFolder) {
|
||
|
let path = origPathpieces.slice(0, -1).join("/");
|
||
|
let name = origPathpieces.slice(-1)[0];
|
||
|
let relative = this.jsx.findPath(path);
|
||
|
if (relative instanceof JavaScriptX.Folder) {
|
||
|
relative.addFile(new JavaScriptX.Folder(name, h));
|
||
|
}
|
||
|
else {
|
||
|
stdio.println("An error occoured creating the folder.");
|
||
|
}
|
||
|
}
|
||
|
terminal.closeProgram(this);
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "Creates a directory at specified location." +
|
||
|
"\n\nUsage: mkdir [options] [path]" +
|
||
|
"\n\nOptions:\n " + JavaScriptX.formatToLength("-h", 10) + "Makes the folder hidden.";
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.MakeDirectory = MakeDirectory;
|
||
|
/**
|
||
|
* The Woman in the JSX equivalent to the UNIX Man.
|
||
|
* It's called Woman (not Man) because of the funny wording,
|
||
|
* where 'man' sounds like the gender 'man'
|
||
|
*/
|
||
|
class Woman {
|
||
|
constructor(jsx) {
|
||
|
this.jsx = jsx;
|
||
|
}
|
||
|
create(terminal, stdio, args) {
|
||
|
if (args.length == 0) {
|
||
|
this.readManual(stdio, this);
|
||
|
terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
let filePath = args.slice(-1)[0];
|
||
|
for (let env in this.jsx.environmentVariables) {
|
||
|
if (filePath == env) {
|
||
|
filePath = env;
|
||
|
break;
|
||
|
}
|
||
|
let envFolder = this.jsx.findPath(this.jsx.environmentVariables[env]);
|
||
|
if (envFolder instanceof JavaScriptX.Folder) {
|
||
|
for (let i = 0; i < envFolder.files.length; i++) {
|
||
|
if (envFolder.files[i].name == filePath) {
|
||
|
filePath = envFolder.files[i].getPath();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
let f = this.jsx.findPath(filePath);
|
||
|
if (f && f instanceof JavaScriptX.BinaryFile && manualGuard(f.program)) {
|
||
|
this.readManual(stdio, f.program);
|
||
|
}
|
||
|
else {
|
||
|
stdio.println("Nothing to womansplain.");
|
||
|
}
|
||
|
terminal.closeProgram(this);
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "The Woman in the JSX equivalent to the UNIX Man. " +
|
||
|
"It's called Woman (not Man) because of the funny wording, " +
|
||
|
"where 'man' sounds like the gender 'man'" +
|
||
|
"\n\nUsage: woman [path]";
|
||
|
}
|
||
|
readManual(stdio, manual) {
|
||
|
stdio.println(manual.getManual());
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.Woman = Woman;
|
||
|
class Caternate {
|
||
|
constructor(jsx) {
|
||
|
this.jsx = jsx;
|
||
|
}
|
||
|
create(terminal, stdio, args) {
|
||
|
if (args.length == 0) {
|
||
|
stdio.println("Insufficent arguments.");
|
||
|
stdio.println("\nUsage: cat [path]");
|
||
|
terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
let path = args.splice(-1)[0];
|
||
|
let file = this.jsx.findPath(path);
|
||
|
if (file instanceof JavaScriptX.BinaryFile) {
|
||
|
stdio.println("Unable to read binary files (yet).");
|
||
|
}
|
||
|
else if (file instanceof JavaScriptX.Folder) {
|
||
|
stdio.println(file.name, "blue");
|
||
|
stdio.print(" is a DIRectory containing ");
|
||
|
stdio.print(file.files.length + "", "red");
|
||
|
stdio.print(" files.");
|
||
|
}
|
||
|
else if (file instanceof JavaScriptX.TextFile) {
|
||
|
let contents = file.readContent();
|
||
|
stdio.println(contents);
|
||
|
}
|
||
|
terminal.closeProgram(this);
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "[cat]ernate reads data from given file and outputs it." +
|
||
|
"\n\nUsage: cat [path]";
|
||
|
}
|
||
|
readManual(stdio, manual) {
|
||
|
stdio.println(manual.getManual());
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.Caternate = Caternate;
|
||
|
class Touch {
|
||
|
constructor(jsx) {
|
||
|
this.jsx = jsx;
|
||
|
}
|
||
|
create(terminal, stdio, args) {
|
||
|
if (args.length == 0) {
|
||
|
stdio.println("Insufficent arguments.");
|
||
|
stdio.println("\nUsage: touch [path]");
|
||
|
terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
let path = args.splice(-1)[0];
|
||
|
let file = this.jsx.findPath(path);
|
||
|
if (file) {
|
||
|
file.created = new Date().getTime();
|
||
|
}
|
||
|
else {
|
||
|
let origPathparts = path.split("/");
|
||
|
let curr = [origPathparts[0]];
|
||
|
for (let i = 1; i < origPathparts.length; i++) {
|
||
|
let currFile = this.jsx.findPath(curr.join("/"));
|
||
|
if (!currFile) {
|
||
|
stdio.println(`${curr.join("/")} not found.`);
|
||
|
terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
curr.push(origPathparts[i]);
|
||
|
}
|
||
|
let filename = curr.splice(-1);
|
||
|
let folder = this.jsx.findPath(curr.join("/"));
|
||
|
if (folder instanceof JavaScriptX.Folder) {
|
||
|
folder.addFile(new JavaScriptX.TextFile(filename[0]));
|
||
|
}
|
||
|
else {
|
||
|
stdio.println(`${curr.join("/")} is not a folder.`);
|
||
|
}
|
||
|
}
|
||
|
terminal.closeProgram(this);
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "Touch touches the file specified updating it's timestamp. If the file doesn't exist, it's created." +
|
||
|
"\n\nUsage: touch [path]";
|
||
|
}
|
||
|
readManual(stdio, manual) {
|
||
|
stdio.println(manual.getManual());
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.Touch = Touch;
|
||
|
class JEdi {
|
||
|
constructor(jsx) {
|
||
|
this.text = [""];
|
||
|
this.row = 0;
|
||
|
this.jsx = jsx;
|
||
|
}
|
||
|
create(terminal, stdio, args) {
|
||
|
this.stdio = stdio;
|
||
|
this.terminal = terminal;
|
||
|
this.doCommand();
|
||
|
}
|
||
|
enable() { }
|
||
|
disable() { }
|
||
|
onClose() { return true; }
|
||
|
getManual() {
|
||
|
return "(J)avascript (Edi)tor is a custom version of the UNIX editor 'ed'." +
|
||
|
"\nIt's quite simpler in the way that all of it's commands are whole words" +
|
||
|
"\n\nUsage: jedi [(optional) path]";
|
||
|
}
|
||
|
readManual(stdio, manual) {
|
||
|
stdio.println(manual.getManual());
|
||
|
}
|
||
|
doCommand() {
|
||
|
let readline = this.stdio.readline({
|
||
|
callback: c => this.exec(c),
|
||
|
prefix: "\n> ",
|
||
|
printAfterDone: true
|
||
|
});
|
||
|
}
|
||
|
exec(command) {
|
||
|
if (command == "exit" || command == "quit") {
|
||
|
this.terminal.closeProgram(this);
|
||
|
return;
|
||
|
}
|
||
|
else if (command.split(" ")[0] == "append") {
|
||
|
let appended = command.split(" ").slice(1).join(" ");
|
||
|
debugger;
|
||
|
console.log(appended);
|
||
|
let rows = appended.split("\n");
|
||
|
console.log(rows);
|
||
|
for (let i = 0; i < rows.length; i++) {
|
||
|
if (this.text.length <= (this.row + i)) {
|
||
|
this.text.push("");
|
||
|
}
|
||
|
this.text[this.row + i] += rows[i];
|
||
|
}
|
||
|
this.row += rows.length - 1;
|
||
|
this.stdio.println(`${this.text[this.row]}`);
|
||
|
}
|
||
|
this.doCommand();
|
||
|
}
|
||
|
}
|
||
|
JSXCommands.JEdi = JEdi;
|
||
|
/**
|
||
|
* Parses all given args from '--arg val' into format {arg: val}
|
||
|
*/
|
||
|
function parseArgsToObject(args, defaults = {}) {
|
||
|
let returned = {};
|
||
|
for (let key in defaults) {
|
||
|
returned[key] = defaults[key];
|
||
|
}
|
||
|
let currArg = null;
|
||
|
args.forEach(arg => {
|
||
|
if (arg.startsWith("-")) {
|
||
|
if (arg.startsWith("--")) {
|
||
|
if (currArg) {
|
||
|
returned[currArg] = null;
|
||
|
}
|
||
|
;
|
||
|
currArg = arg.substr(2);
|
||
|
return;
|
||
|
}
|
||
|
if (currArg) {
|
||
|
returned[currArg] = null;
|
||
|
}
|
||
|
;
|
||
|
currArg = arg.substr(1);
|
||
|
}
|
||
|
else {
|
||
|
if (currArg) {
|
||
|
returned[currArg] = arg;
|
||
|
currArg = null;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
if (currArg) {
|
||
|
returned[currArg] = null;
|
||
|
}
|
||
|
;
|
||
|
return returned;
|
||
|
}
|
||
|
function manualGuard(arg) {
|
||
|
return arg.getManual !== undefined;
|
||
|
}
|
||
|
})(JSXCommands || (JSXCommands = {}));
|