Compare commits
2 Commits
d8b2c061df
...
2e033026f0
Author | SHA1 | Date |
---|---|---|
b1ek | 2e033026f0 | |
b1ek | 0bfaf89c9b |
|
@ -1,2 +1,3 @@
|
|||
.parcel-cache
|
||||
parcel-bundle-reports
|
||||
dist
|
|
@ -6,17 +6,29 @@
|
|||
"author": "blek",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"assert": "^2.0.0",
|
||||
"events": "^3.1.0",
|
||||
"parcel": "^2.8.3",
|
||||
"parcel-namer-without-hash": "^0.0.1",
|
||||
"process": "^0.11.10"
|
||||
"path-browserify": "^1.0.0",
|
||||
"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": {
|
||||
"@parcel/fs": "^2.8.3",
|
||||
"memfs": "^3.4.13",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"xterm": "^5.1.0",
|
||||
"xterm-for-react": "^1.0.4",
|
||||
"xterm-js-shell": "^1.1.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "parcel"
|
||||
"start": "parcel",
|
||||
"build": "parcel build --no-source-maps"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export class Console extends React.Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
require('./emulator')(this.terminal.current.terminal);
|
||||
require('./emulator')(this.terminal.current);
|
||||
this.terminal.current.terminal.focus();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
const fs = require('fs');
|
||||
|
||||
module.exports = (argv, terminal) => {
|
||||
terminal.writeln('hi')
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
let cmds = {
|
||||
'cat': require('./cat')
|
||||
};
|
||||
|
||||
module.exports = cmds;
|
|
@ -0,0 +1,4 @@
|
|||
const { fs } = require('memfs');
|
||||
fs.writeFileSync('README.md', 'uwu');
|
||||
|
||||
module.exports = fs;
|
|
@ -1,8 +1,9 @@
|
|||
module.exports = (terminal) => {
|
||||
module.exports = (dom) => {
|
||||
const terminal = dom.terminal;
|
||||
|
||||
terminal.writeln('Welcome to my online resume!')
|
||||
terminal.writeln('Type \033[1;32mhelp\033[0m for list of commands')
|
||||
terminal.writeln('');
|
||||
|
||||
require('./zsh')(terminal);
|
||||
require('./zsh')(terminal, dom);
|
||||
}
|
|
@ -1,15 +1,23 @@
|
|||
|
||||
import { Terminal } from 'xterm';
|
||||
import { XTerm } from 'xterm-for-react';
|
||||
|
||||
const fs = require('./fs');
|
||||
global.fs = fs;
|
||||
const cmds = require('./commands');
|
||||
|
||||
/**
|
||||
* @type {Terminal}
|
||||
*/
|
||||
let terminal;
|
||||
|
||||
/**
|
||||
* @type { XTerm }
|
||||
*/
|
||||
let dom;
|
||||
|
||||
const prompt = '\033[1;32muser@blek.codes \033[36m~ $ \033[0m';
|
||||
let cmd = '';
|
||||
let history = [];
|
||||
let history_pos = 0;
|
||||
|
||||
function text_prompt() {
|
||||
return prompt.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, '');
|
||||
|
@ -18,21 +26,55 @@ function text_prompt() {
|
|||
function pr_char(char) {
|
||||
cmd += 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() {
|
||||
let c = cmd;
|
||||
reset_cmd();
|
||||
history.push(c);
|
||||
reset_cmd(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);
|
||||
print_prompt();
|
||||
}
|
||||
|
||||
function print_prompt() {
|
||||
terminal.write(prompt);
|
||||
history_pos = 0;
|
||||
}
|
||||
|
||||
function reprint_prompt() {
|
||||
|
@ -40,28 +82,25 @@ function reprint_prompt() {
|
|||
print_prompt();
|
||||
}
|
||||
|
||||
function history_up() {
|
||||
if (history_pos != history.length) {
|
||||
reprint_prompt();
|
||||
terminal.write(history[history_pos]);
|
||||
history_pos++;
|
||||
}
|
||||
}
|
||||
|
||||
function reset_cmd() {
|
||||
cmd = '';
|
||||
terminal.writeln('');
|
||||
}
|
||||
|
||||
function control_char(char) {
|
||||
const id = char.codePointAt(0);
|
||||
/** @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);
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
|
||||
// backspace
|
||||
case 127:
|
||||
if (terminal.buffer.active.cursorX <= text_prompt().length) break;
|
||||
terminal.write('\b \b');
|
||||
cmd = cmd.substring(0, cmd.length - 1);
|
||||
case 8:
|
||||
backspace();
|
||||
break;
|
||||
|
||||
// enter
|
||||
|
@ -70,33 +109,43 @@ function control_char(char) {
|
|||
break;
|
||||
|
||||
// Ctrl+c
|
||||
case 3:
|
||||
case 67:
|
||||
if (dom.ctrlKey) {
|
||||
terminal.write('^C');
|
||||
reset_cmd();
|
||||
print_prompt();
|
||||
break;
|
||||
}
|
||||
|
||||
// history up
|
||||
case 27:
|
||||
history_up();
|
||||
case 37:
|
||||
backspace();
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
console.log('Unknown special char: ' + id);
|
||||
terminal.write('<');
|
||||
if (dom.ctrlKey) terminal.write('C');
|
||||
if (dom.altKey) terminal.write('A');
|
||||
if (dom.shiftKey) terminal.write('S');
|
||||
terminal.write(`${id}>`)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function key(e) {
|
||||
if (RegExp(/^\p{L}/,'u').test(e.key)) {
|
||||
pr_char(e.key);
|
||||
/** @type {KeyboardEvent} */
|
||||
const dom = e.domEvent;
|
||||
if (dom.key.length == 1 && !(dom.ctrlKey || dom.altKey || dom.shiftKey)) {
|
||||
pr_char(e.domEvent.key);
|
||||
} else {
|
||||
control_char(e.key);
|
||||
control_char(e.domEvent.keyCode, dom)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = (t) => {
|
||||
module.exports = (t, d) => {
|
||||
terminal = t;
|
||||
dom = d;
|
||||
|
||||
terminal.onKey(key);
|
||||
terminal.write(prompt);
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
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 */
|
|
@ -0,0 +1,13 @@
|
|||
<!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,6 +1,5 @@
|
|||
import { createRoot } from "react-dom/client";
|
||||
import { Console } from "./Console";
|
||||
import { Console } from './Console';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
|
||||
const container = document.getElementById("resume_js_app");
|
||||
const root = createRoot(container)
|
||||
root.render(<Console />);
|
||||
const root = ReactDOM.createRoot(document.getElementById('resume_js_app'));
|
||||
root.render(<Console />)
|
Loading…
Reference in New Issue