Compare commits
No commits in common. "2e033026f0c9f322e0ed3e36bc9b5d0b7fba7192" and "d8b2c061df908b5854974b9a66c836a573fef6b7" have entirely different histories.
2e033026f0
...
d8b2c061df
|
@ -1,3 +1,2 @@
|
||||||
.parcel-cache
|
.parcel-cache
|
||||||
parcel-bundle-reports
|
|
||||||
dist
|
dist
|
|
@ -6,29 +6,17 @@
|
||||||
"author": "blek",
|
"author": "blek",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"assert": "^2.0.0",
|
|
||||||
"events": "^3.1.0",
|
|
||||||
"parcel": "^2.8.3",
|
"parcel": "^2.8.3",
|
||||||
"parcel-namer-without-hash": "^0.0.1",
|
"parcel-namer-without-hash": "^0.0.1",
|
||||||
"path-browserify": "^1.0.0",
|
"process": "^0.11.10"
|
||||||
"process": "^0.11.10",
|
|
||||||
"punycode": "^1.4.1",
|
|
||||||
"querystring-es3": "^0.2.1",
|
|
||||||
"stream-browserify": "^3.0.0",
|
|
||||||
"url": "^0.11.0",
|
|
||||||
"util": "^0.12.3"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@parcel/fs": "^2.8.3",
|
|
||||||
"memfs": "^3.4.13",
|
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"xterm": "^5.1.0",
|
|
||||||
"xterm-for-react": "^1.0.4",
|
"xterm-for-react": "^1.0.4",
|
||||||
"xterm-js-shell": "^1.1.3"
|
"xterm-js-shell": "^1.1.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "parcel",
|
"start": "parcel"
|
||||||
"build": "parcel build --no-source-maps"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class Console extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
require('./emulator')(this.terminal.current);
|
require('./emulator')(this.terminal.current.terminal);
|
||||||
this.terminal.current.terminal.focus();
|
this.terminal.current.terminal.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
module.exports = (argv, terminal) => {
|
|
||||||
terminal.writeln('hi')
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
let cmds = {
|
|
||||||
'cat': require('./cat')
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = cmds;
|
|
|
@ -1,4 +0,0 @@
|
||||||
const { fs } = require('memfs');
|
|
||||||
fs.writeFileSync('README.md', 'uwu');
|
|
||||||
|
|
||||||
module.exports = fs;
|
|
|
@ -1,9 +1,8 @@
|
||||||
module.exports = (dom) => {
|
module.exports = (terminal) => {
|
||||||
const terminal = dom.terminal;
|
|
||||||
|
|
||||||
terminal.writeln('Welcome to my online resume!')
|
terminal.writeln('Welcome to my online resume!')
|
||||||
terminal.writeln('Type \033[1;32mhelp\033[0m for list of commands')
|
terminal.writeln('Type \033[1;32mhelp\033[0m for list of commands')
|
||||||
terminal.writeln('');
|
terminal.writeln('');
|
||||||
|
|
||||||
require('./zsh')(terminal, dom);
|
require('./zsh')(terminal);
|
||||||
}
|
}
|
|
@ -1,23 +1,15 @@
|
||||||
|
|
||||||
import { Terminal } from 'xterm';
|
import { Terminal } from 'xterm';
|
||||||
import { XTerm } from 'xterm-for-react';
|
|
||||||
|
|
||||||
const fs = require('./fs');
|
|
||||||
global.fs = fs;
|
|
||||||
const cmds = require('./commands');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {Terminal}
|
* @type {Terminal}
|
||||||
*/
|
*/
|
||||||
let terminal;
|
let terminal;
|
||||||
|
|
||||||
/**
|
|
||||||
* @type { XTerm }
|
|
||||||
*/
|
|
||||||
let dom;
|
|
||||||
|
|
||||||
const prompt = '\033[1;32muser@blek.codes \033[36m~ $ \033[0m';
|
const prompt = '\033[1;32muser@blek.codes \033[36m~ $ \033[0m';
|
||||||
let cmd = '';
|
let cmd = '';
|
||||||
|
let history = [];
|
||||||
|
let history_pos = 0;
|
||||||
|
|
||||||
function text_prompt() {
|
function text_prompt() {
|
||||||
return prompt.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
|
return prompt.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
|
||||||
|
@ -26,55 +18,21 @@ function text_prompt() {
|
||||||
function pr_char(char) {
|
function pr_char(char) {
|
||||||
cmd += char;
|
cmd += char;
|
||||||
terminal.write(char);
|
terminal.write(char);
|
||||||
}
|
// console.log(char.charCodeAt(0));
|
||||||
|
if (history_pos != 0) history_pos = 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec_cmd() {
|
function exec_cmd() {
|
||||||
let c = cmd;
|
let c = cmd;
|
||||||
reset_cmd(c);
|
reset_cmd();
|
||||||
|
history.push(c);
|
||||||
if (c == '') {
|
|
||||||
print_prompt();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if path
|
|
||||||
if (c.match(/^((\.|\.\.)\/|\/).+$/gm)) {
|
|
||||||
exec_file(c);
|
|
||||||
terminal.writeln('');
|
|
||||||
print_prompt();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmds[c] != undefined) {
|
|
||||||
cmds[c](c.split(' '), terminal);
|
|
||||||
print_prompt();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
terminal.writeln('zsh: command not found: ' + c);
|
terminal.writeln('zsh: command not found: ' + c);
|
||||||
print_prompt();
|
print_prompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
function print_prompt() {
|
function print_prompt() {
|
||||||
terminal.write(prompt);
|
terminal.write(prompt);
|
||||||
|
history_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reprint_prompt() {
|
function reprint_prompt() {
|
||||||
|
@ -82,25 +40,28 @@ function reprint_prompt() {
|
||||||
print_prompt();
|
print_prompt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function history_up() {
|
||||||
|
if (history_pos != history.length) {
|
||||||
|
reprint_prompt();
|
||||||
|
terminal.write(history[history_pos]);
|
||||||
|
history_pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function reset_cmd() {
|
function reset_cmd() {
|
||||||
cmd = '';
|
cmd = '';
|
||||||
terminal.writeln('');
|
terminal.writeln('');
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param { KeyboardEvent } dom */
|
function control_char(char) {
|
||||||
function control_char(id, dom) {
|
const id = char.codePointAt(0);
|
||||||
|
|
||||||
const backspace = () => {
|
|
||||||
if (terminal.buffer.active.cursorX <= text_prompt().length) return;
|
|
||||||
terminal.write('\b \b');
|
|
||||||
cmd = cmd.substring(0, cmd.length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
|
||||||
// backspace
|
// backspace
|
||||||
case 8:
|
case 127:
|
||||||
backspace();
|
if (terminal.buffer.active.cursorX <= text_prompt().length) break;
|
||||||
|
terminal.write('\b \b');
|
||||||
|
cmd = cmd.substring(0, cmd.length - 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// enter
|
// enter
|
||||||
|
@ -109,43 +70,33 @@ function control_char(id, dom) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Ctrl+c
|
// Ctrl+c
|
||||||
case 67:
|
case 3:
|
||||||
if (dom.ctrlKey) {
|
|
||||||
terminal.write('^C');
|
terminal.write('^C');
|
||||||
reset_cmd();
|
reset_cmd();
|
||||||
print_prompt();
|
print_prompt();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case 37:
|
// history up
|
||||||
backspace();
|
case 27:
|
||||||
|
history_up();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
terminal.write('<');
|
console.log('Unknown special char: ' + id);
|
||||||
if (dom.ctrlKey) terminal.write('C');
|
|
||||||
if (dom.altKey) terminal.write('A');
|
|
||||||
if (dom.shiftKey) terminal.write('S');
|
|
||||||
terminal.write(`${id}>`)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function key(e) {
|
function key(e) {
|
||||||
/** @type {KeyboardEvent} */
|
if (RegExp(/^\p{L}/,'u').test(e.key)) {
|
||||||
const dom = e.domEvent;
|
pr_char(e.key);
|
||||||
if (dom.key.length == 1 && !(dom.ctrlKey || dom.altKey || dom.shiftKey)) {
|
|
||||||
pr_char(e.domEvent.key);
|
|
||||||
} else {
|
} else {
|
||||||
control_char(e.domEvent.keyCode, dom)
|
control_char(e.key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (t, d) => {
|
module.exports = (t) => {
|
||||||
terminal = t;
|
terminal = t;
|
||||||
dom = d;
|
|
||||||
|
|
||||||
terminal.onKey(key);
|
terminal.onKey(key);
|
||||||
terminal.write(prompt);
|
terminal.write(prompt);
|
||||||
}
|
}
|
|
@ -1,52 +0,0 @@
|
||||||
div#resume_js_app {
|
|
||||||
width: 800px;
|
|
||||||
height: 600px;
|
|
||||||
background: #212121;
|
|
||||||
border: 1px solid #e1e1e1;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 2px;
|
|
||||||
font-family: monospace;
|
|
||||||
transition: all .15s;
|
|
||||||
box-shadow: 0 2px 1px #303030a0;
|
|
||||||
color: #e1e1e1 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#resume_js_app:hover {
|
|
||||||
box-shadow: 0 2px 3px #303030;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#resume_js_app p.js_loading_indicator {
|
|
||||||
width: -moz-fit-content;
|
|
||||||
width: fit-content;
|
|
||||||
text-align: center;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
position: relative;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
div#resume_js_app * {
|
|
||||||
color: #e1e1e1;
|
|
||||||
font-family: Source Code Pro, monospace !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#resume_js_app a, div#resume_js_app a:visited {
|
|
||||||
text-shadow: 0 0 #24557e30;
|
|
||||||
font-weight: 500;
|
|
||||||
text-decoration: none;
|
|
||||||
transition: all .15s;
|
|
||||||
color: #24557e !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#resume_js_app a:hover {
|
|
||||||
text-shadow: 0 0 4px #24557e30;
|
|
||||||
}
|
|
||||||
|
|
||||||
div#resume_js_app table * {
|
|
||||||
text-align: left;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*# sourceMappingURL=resume.css.map */
|
|
|
@ -1,13 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>resume.js</title>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<link rel="stylesheet" href="/resume.css">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="resume_js_app"></div>
|
|
||||||
<script src="/resume.js" type="module"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Console } from './Console';
|
import { createRoot } from "react-dom/client";
|
||||||
import ReactDOM from 'react-dom/client';
|
import { Console } from "./Console";
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById('resume_js_app'));
|
const container = document.getElementById("resume_js_app");
|
||||||
root.render(<Console />)
|
const root = createRoot(container)
|
||||||
|
root.render(<Console />);
|
Loading…
Reference in New Issue