2023-03-12 16:09:19 +01:00
|
|
|
|
|
|
|
import { Terminal } from 'xterm';
|
2023-03-15 06:58:14 +01:00
|
|
|
import { XTerm } from 'xterm-for-react';
|
|
|
|
|
|
|
|
const fs = require('./fs');
|
|
|
|
global.fs = fs;
|
|
|
|
const cmds = require('./commands');
|
2023-03-12 16:09:19 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @type {Terminal}
|
|
|
|
*/
|
|
|
|
let terminal;
|
|
|
|
|
2023-03-15 06:58:14 +01:00
|
|
|
/**
|
|
|
|
* @type { XTerm }
|
|
|
|
*/
|
|
|
|
let dom;
|
|
|
|
|
2023-03-12 16:09:19 +01:00
|
|
|
const prompt = '\033[1;32muser@blek.codes \033[36m~ $ \033[0m';
|
|
|
|
let cmd = '';
|
2023-03-16 05:10:22 +01:00
|
|
|
let lastcmd = window.sessionStorage.getItem('last_cmd') || '';
|
2023-03-12 16:20:34 +01:00
|
|
|
|
|
|
|
function text_prompt() {
|
|
|
|
return prompt.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
|
|
|
|
}
|
2023-03-12 16:09:19 +01:00
|
|
|
|
|
|
|
function pr_char(char) {
|
|
|
|
cmd += char;
|
|
|
|
terminal.write(char);
|
2023-03-15 06:58:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function exec_file(f) {
|
|
|
|
|
|
|
|
const exists = fs.existsSync(f);
|
|
|
|
if (!exists) {
|
|
|
|
terminal.write('zsh: no such file or directory: ' + f);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const executable = fs.accessSync(f, fs.constants.X_OK);
|
|
|
|
if (!executable) {
|
|
|
|
terminal.writeln('zsh: permission denied: ' + f);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
terminal.writeln('This is an online resume. It is not big enough to have a script runtime.\n');
|
|
|
|
return;
|
2023-03-12 16:09:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function exec_cmd() {
|
|
|
|
let c = cmd;
|
2023-03-15 07:13:25 +01:00
|
|
|
const command = c.split(' ')[0];
|
2023-03-15 06:58:14 +01:00
|
|
|
reset_cmd(c);
|
2023-03-15 07:13:25 +01:00
|
|
|
lastcmd = c;
|
2023-03-16 05:10:22 +01:00
|
|
|
window.sessionStorage.setItem('last_cmd', c);
|
2023-03-15 06:58:14 +01:00
|
|
|
|
2023-03-15 07:13:25 +01:00
|
|
|
if (command == '') {
|
2023-03-15 06:58:14 +01:00
|
|
|
print_prompt();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if path
|
2023-03-15 07:13:25 +01:00
|
|
|
if (command.match(/^((\.|\.\.)\/|\/).+$/gm)) {
|
|
|
|
exec_file(command);
|
2023-03-15 06:58:14 +01:00
|
|
|
terminal.writeln('');
|
|
|
|
print_prompt();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-15 07:13:25 +01:00
|
|
|
if (cmds[command] != undefined) {
|
|
|
|
cmds[command](c.split(' '), terminal);
|
2023-03-16 05:25:41 +01:00
|
|
|
if (terminal.buffer.active.cursorX != 0) {
|
|
|
|
terminal.write('\033[30;47m%\033[0m\n');
|
|
|
|
}
|
2023-03-15 06:58:14 +01:00
|
|
|
print_prompt();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-15 07:13:25 +01:00
|
|
|
terminal.writeln('zsh: command not found: ' + command);
|
2023-03-12 16:09:19 +01:00
|
|
|
print_prompt();
|
|
|
|
}
|
|
|
|
|
|
|
|
function print_prompt() {
|
|
|
|
terminal.write(prompt);
|
2023-03-12 16:20:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function reprint_prompt() {
|
|
|
|
terminal.write('\033[2K\r');
|
|
|
|
print_prompt();
|
|
|
|
}
|
|
|
|
|
2023-03-12 16:09:19 +01:00
|
|
|
function reset_cmd() {
|
|
|
|
cmd = '';
|
|
|
|
terminal.writeln('');
|
|
|
|
}
|
|
|
|
|
2023-03-15 06:58:14 +01:00
|
|
|
/** @param { KeyboardEvent } dom */
|
|
|
|
function control_char(id, dom) {
|
|
|
|
|
|
|
|
const backspace = () => {
|
|
|
|
if (terminal.buffer.active.cursorX <= text_prompt().length) return;
|
|
|
|
terminal.write('\b \b');
|
|
|
|
cmd = cmd.substring(0, cmd.length - 1);
|
|
|
|
}
|
|
|
|
|
2023-03-12 16:09:19 +01:00
|
|
|
switch (id) {
|
|
|
|
|
|
|
|
// backspace
|
2023-03-15 06:58:14 +01:00
|
|
|
case 8:
|
|
|
|
backspace();
|
2023-03-12 16:09:19 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
// enter
|
|
|
|
case 13:
|
|
|
|
exec_cmd();
|
|
|
|
break;
|
|
|
|
|
2023-03-15 07:13:25 +01:00
|
|
|
case 38:
|
|
|
|
if (lastcmd == '') break;
|
|
|
|
cmd = lastcmd;
|
|
|
|
reprint_prompt();
|
|
|
|
terminal.write(lastcmd);
|
|
|
|
break;
|
|
|
|
|
2023-03-12 16:09:19 +01:00
|
|
|
// Ctrl+c
|
2023-03-15 06:58:14 +01:00
|
|
|
case 67:
|
|
|
|
if (dom.ctrlKey) {
|
|
|
|
terminal.write('^C');
|
|
|
|
reset_cmd();
|
|
|
|
print_prompt();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case 37:
|
|
|
|
backspace();
|
2023-03-12 16:09:19 +01:00
|
|
|
break;
|
|
|
|
|
2023-03-12 16:20:34 +01:00
|
|
|
|
2023-03-12 16:09:19 +01:00
|
|
|
default:
|
2023-03-15 06:58:14 +01:00
|
|
|
terminal.write('<');
|
|
|
|
if (dom.ctrlKey) terminal.write('C');
|
|
|
|
if (dom.altKey) terminal.write('A');
|
|
|
|
if (dom.shiftKey) terminal.write('S');
|
|
|
|
terminal.write(`${id}>`)
|
2023-03-12 16:09:19 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function key(e) {
|
2023-03-15 06:58:14 +01:00
|
|
|
/** @type {KeyboardEvent} */
|
|
|
|
const dom = e.domEvent;
|
2023-03-15 07:13:25 +01:00
|
|
|
if (dom.key.length == 1 && !(dom.ctrlKey || dom.altKey)) {
|
2023-03-15 06:58:14 +01:00
|
|
|
pr_char(e.domEvent.key);
|
2023-03-12 16:09:19 +01:00
|
|
|
} else {
|
2023-03-15 06:58:14 +01:00
|
|
|
control_char(e.domEvent.keyCode, dom)
|
2023-03-12 16:09:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-15 06:58:14 +01:00
|
|
|
module.exports = (t, d) => {
|
2023-03-12 16:09:19 +01:00
|
|
|
terminal = t;
|
2023-03-15 06:58:14 +01:00
|
|
|
dom = d;
|
|
|
|
|
2023-03-12 16:09:19 +01:00
|
|
|
terminal.onKey(key);
|
2023-03-15 06:58:14 +01:00
|
|
|
terminal.write(prompt);
|
2023-03-12 16:09:19 +01:00
|
|
|
}
|