forked from tools/josh
1
0
Fork 0
josh/js/commands.js

284 lines
8.4 KiB
JavaScript
Raw Normal View History

2018-11-28 22:07:51 +01:00
class Commands {
2018-11-28 22:23:11 +01:00
constructor(terminal, fileSystem) {
this._terminal = terminal;
2018-11-28 23:22:17 +01:00
this._fs = fileSystem;
2018-11-28 22:23:11 +01:00
2018-11-28 22:07:51 +01:00
this._list = {
clear: {
2018-11-28 22:23:11 +01:00
fun: this.clear,
2018-11-28 22:07:51 +01:00
summary: `clear terminal output`,
usage: `clear`,
2018-11-28 23:22:17 +01:00
desc: `Clears all previous terminal output.`
2018-11-28 22:07:51 +01:00
},
cd: {
2018-11-28 22:23:11 +01:00
fun: this.cd,
2018-11-28 22:07:51 +01:00
summary: `change directory`,
usage: `cd [DIRECTORY]`,
desc: "" +
`Changes the current working directory to [DIRECTORY].
2018-11-29 01:08:58 +01:00
If [DIRECTORY] is empty, nothing happens.`.trimLines()
2018-11-28 22:07:51 +01:00
},
echo: {
fun: Commands.echo,
summary: `display text`,
usage: `echo [TEXT]`,
desc: `Displays [TEXT].`.trimLines()
},
exit: {
fun: Commands.exit,
summary: `close session`,
usage: `exit`,
2018-11-28 23:22:17 +01:00
desc: `Closes the terminal session.`
2018-11-28 22:07:51 +01:00
},
help: {
fun: this.help,
summary: `display documentation`,
usage: `help [COMMAND]`,
desc: "" +
`Displays help documentation for [COMMAND].
2018-11-29 01:08:58 +01:00
If [COMMAND] is empty, a list of all commands is shown.`.trimLines()
2018-11-28 22:07:51 +01:00
},
ls: {
fun: this.ls,
summary: `list directory contents`,
usage: `ls [DIRECTORY]`,
desc: "" +
`Displays the files and directories in [DIRECTORY].
2018-11-29 01:08:58 +01:00
If [DIRECTORY] is empty, the files and directories in the current working directory are shown.`.trimLines()
2018-11-28 22:07:51 +01:00
},
mkdir: {
2018-11-28 22:23:11 +01:00
fun: this.mkdir,
summary: `make directories`,
usage: `mkdir DIRECTORY...`,
desc: "" +
`Creates the directories given by DIRECTORY.
If more than one directory is given, the directories are created in the order they are given in`.trimLines()
2018-11-28 23:22:17 +01:00
},
2018-11-29 00:15:08 +01:00
open: {
fun: this.open,
summary: `open web page`,
usage: `open [-b | --blank] FILE`,
desc: "" +
2018-11-29 01:08:58 +01:00
`Opens the web page linked to by FILE in this browser window.
2018-11-29 00:15:08 +01:00
2018-11-29 01:08:58 +01:00
If -b or --blank is set, the web page is opened in a new tab.`.trimLines()
2018-11-29 00:15:08 +01:00
},
2018-11-28 23:22:17 +01:00
poweroff: {
fun: Commands.poweroff,
2018-11-28 23:47:11 +01:00
summary: `close down the system`,
2018-11-28 23:22:17 +01:00
usage: `poweroff`,
2018-11-28 23:47:11 +01:00
desc: `Automated shutdown procedure to nicely notify users when the system is shutting down.`
2018-11-28 22:07:51 +01:00
},
pwd: {
2018-11-28 22:23:11 +01:00
fun: this.pwd,
2018-11-28 22:07:51 +01:00
summary: `print working directory`,
usage: `pwd`,
2018-11-28 23:22:17 +01:00
desc: `Displays the current working directory.`
2018-11-28 22:07:51 +01:00
},
rm: {
2018-11-28 22:23:11 +01:00
fun: this.rm,
2018-11-28 22:07:51 +01:00
summary: `remove file`,
2018-11-29 09:37:42 +01:00
usage: `rm [-f | --f] FILE...`,
2018-11-29 09:20:23 +01:00
desc:
`Removes the files given by FILE.
2018-11-29 09:37:42 +01:00
If more than one file is given, the files are removed in the order they are given in.
If -f or --force is set, no warning is given if a file could not be removed.`.trimLines()
2018-11-28 22:07:51 +01:00
},
rmdir: {
2018-11-28 22:23:11 +01:00
fun: this.rmdir,
summary: `remove directories`,
usage: `rmdir [-f | --force] DIRECTORY...`,
2018-11-29 00:15:08 +01:00
desc: "" +
`Removes the directories given by DIRECTORY.
If more than one directory is given, the directories are removed in the order they are given in.s
2018-11-29 00:15:08 +01:00
2018-11-29 09:37:42 +01:00
If -f or --force is set, the directories are deleted even if they contain files or other directories, and no warning is given if a directory could not be removed.`.trimLines()
2018-11-28 22:07:51 +01:00
}
};
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:07:51 +01:00
parse(input) {
2018-11-29 08:58:53 +01:00
const args = new InputArgs(input);
2018-11-28 19:51:48 +01:00
2018-11-29 08:58:53 +01:00
if (Object.keys(this._list).indexOf(args.getCommand()) >= 0) {
return this._list[args.getCommand()].fun.bind(this)(args);
} else if (args.getCommand().trim() === "") {
2018-11-28 22:41:59 +01:00
return "";
2018-11-28 22:07:51 +01:00
} else {
2018-11-29 13:11:57 +01:00
return `Unknown command '${args.getCommand()}'`
2018-11-28 22:07:51 +01:00
}
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:23:11 +01:00
cd(args) {
2018-11-29 08:58:53 +01:00
return this._fs.cd(args.getArg(0));
2018-11-28 22:07:51 +01:00
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:23:11 +01:00
clear() {
this._terminal.clear();
2018-11-28 22:41:59 +01:00
return "";
2018-11-28 22:07:51 +01:00
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:07:51 +01:00
static echo(args) {
2018-11-29 08:58:53 +01:00
return args.getArgs()
.join(" ")
2018-11-28 22:41:59 +01:00
.replace("hunter2", "*******");
2018-11-28 22:07:51 +01:00
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:07:51 +01:00
static exit() {
terminal.reset();
2018-11-28 22:41:59 +01:00
return "";
2018-11-28 22:07:51 +01:00
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:07:51 +01:00
help(args) {
2018-11-29 08:58:53 +01:00
const command = args.getArg(0, "").toLowerCase();
2018-11-28 22:07:51 +01:00
const commandNames = Object.keys(this._list);
2018-11-28 19:51:48 +01:00
2018-11-28 22:07:51 +01:00
if (commandNames.indexOf(command) >= 0) {
const info = this._list[command];
2018-11-28 19:51:48 +01:00
2018-11-28 22:07:51 +01:00
return "" +
`${command} - ${info.summary}
2018-11-28 19:51:48 +01:00
2018-11-29 01:08:58 +01:00
<b>Usage</b>
${info.usage}
2018-11-28 19:51:48 +01:00
2018-11-29 01:08:58 +01:00
<b>Description</b>
${info.desc}`.trimLines();
2018-11-28 22:07:51 +01:00
} else {
const commandWidth = Math.max.apply(null, commandNames.map(it => it.length)) + 4;
const commandEntries = commandNames.map(
it => `${it.padEnd(commandWidth, ' ')}${this._list[it].summary}`
);
2018-11-28 19:51:48 +01:00
2018-11-28 22:07:51 +01:00
return "" +
`<b>List of commands</b>
2018-11-29 01:08:58 +01:00
${commandEntries.join("\n")}
2018-11-28 19:51:48 +01:00
2018-11-29 01:08:58 +01:00
Write "help [COMMAND]" for more information on a command.`.trimLines();
2018-11-28 22:07:51 +01:00
}
2018-11-28 19:51:48 +01:00
}
2018-11-28 22:07:51 +01:00
ls(args) {
2018-11-29 08:58:53 +01:00
return this._fs.ls(args.getArg(0));
2018-11-28 19:51:48 +01:00
}
2018-11-28 22:23:11 +01:00
mkdir(args) {
return this._fs.mkdirs(args.getArgs());
2018-11-28 23:22:17 +01:00
}
2018-11-29 00:15:08 +01:00
open(args) {
2018-11-29 08:58:53 +01:00
const fileName = args.getArg(0);
const target = args.hasAnyOption(["-b", "--blank"]) ? "_blank" : "_self";
2018-11-29 00:15:08 +01:00
const file = this._fs._getFile(fileName);
if (file === undefined) {
return `The file '${fileName}' does not exist`;
}
if (!FileSystem.isFile(file)) {
return `'${fileName} is not a file'`;
}
if (!(file instanceof LinkFile)) {
2018-11-29 00:15:08 +01:00
return `Could not open '${fileName}'`;
}
window.open(file.url, target);
2018-11-29 00:15:08 +01:00
return "";
}
2018-11-28 23:22:17 +01:00
static poweroff() {
const date = new Date();
date.setSeconds(date.getSeconds() + 30);
document.cookie = `poweroff=true; expires=${date.toUTCString()}; path=/`;
setTimeout(() => location.reload(), 2000);
return "" +
`Shutdown NOW!
*** FINAL System shutdown message from felix@fwdekker.com ***
System going down IMMEDIATELY
System shutdown time has arrived`.trimLines();
2018-11-28 19:51:48 +01:00
}
2018-11-28 22:23:11 +01:00
pwd() {
2018-11-28 23:22:17 +01:00
return this._fs.pwd;
2018-11-28 22:07:51 +01:00
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:23:11 +01:00
rm(args) {
2018-11-29 09:20:23 +01:00
return this._fs.rms(args.getArgs());
2018-11-28 22:07:51 +01:00
}
2018-11-28 19:51:48 +01:00
2018-11-28 22:23:11 +01:00
rmdir(args) {
return this._fs.rmdirs(args.getArgs(), args.hasAnyOption(["-f", "--force"]));
2018-11-28 19:51:48 +01:00
}
2018-11-28 22:07:51 +01:00
}
2018-11-29 08:58:53 +01:00
class InputArgs {
constructor(input) {
this._options = {};
2018-11-29 10:08:44 +01:00
const args = input.match(/("[^"]+"|[^"\s]+)/g)
.map(it => it.replace(/^"/, "").replace(/"$/, ""));
2018-11-29 08:58:53 +01:00
let i;
for (i = 1; i < args.length; i++) {
const arg = args[i];
if (!arg.startsWith("-")) {
break;
}
const argParts = arg.split("=");
this._options[argParts[0]] = (argParts[1] || "");
}
this._command = (args[0] || "").toLowerCase();
this._args = args.slice(i);
}
getArgs() {
return this._args.slice();
}
getArg(index, def) {
return (def === undefined)
? this._args[index]
: this._args[index] || def;
}
hasArg(index) {
return (this._args[index] !== undefined);
}
getCommand() {
return this._command;
}
getOption(key, def) {
return (def === undefined)
? this._options[key]
: this._options[key] || def;
}
hasOption(key) {
return (this.getOption(key) !== undefined);
}
hasAnyOption(keys) {
for (let i = 0; i < keys.length; i++) {
if (this.hasOption(keys[i])) {
return true;
}
}
return false;
}
}