js-shell-emulator
Version:
JS Shell Emulator is a dead simple JavaScript library for emulating a terminal environment
216 lines (193 loc) • 6.29 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>jsShell.js demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
</head>
<style>
html, body {
margin: 0;
padding: 0;
}
.jsShell a {
color: white;
text-decoration: underline;
}
</style>
<body>
<h1 class="text-xl my-8 text-center">JS Shell Emulator CLI demo</h1>
<main class="mx-auto w-full lg:w-3/4 max-w-[90rem]">
<div id="shell-1" class="shell"></div>
</main>
<script type="module">
import { JsShell } from '../jsShell.js';
const commands = {
color: {
handler: changeColor,
description: 'Random background & text color'
},
clear: {
handler: (shell) => {
shell.clear();
},
description: 'Clear console.'
},
cd: {
handler: (shell, argv) => {
shell.setPrompt(makePS1(argv[1] || '~'));
},
description: 'cd [dir] Change working directory.'
},
form: {
handler: form,
description: 'Run a cli form, just to demonstrate.'
},
github: {
handler: () => {
window.location.href = 'https://github.com/francoisburdy/js-shell-emulator';
},
description: 'Redirect to package Github repo'
},
help: {
handler: helpMenu,
description: 'Show available commands'
},
joke: {
handler: joke,
description: 'Tell a joke'
},
reboot: {
handler: startShell,
description: 'restart shell process'
},
time: {
handler: (shell) => {
shell.print((new Date()).toString());
},
description: 'What time is it?'
},
exit: {
handler: (shell) => {
shell.print('Bye!');
},
description: 'Stop the shell prompt'
}
};
const bgColors = [
'#000',
'rgb(33,42,56)',
'rgb(85,16,16)',
'rgb(82,34,7)',
'rgb(9,64,61)',
'rgb(9,66,97)',
'rgb(63 63 70)',
'rgb(58,8,99)',
'rgb(57,27,2)'
];
const textColors = [
'#FFF',
'#0F0',
'#fffd2f',
'#ff1c1c'
];
function padToNChars(string, size) {
let newString = '';
for (let index = 0; index < (size - string.length); index++) {
newString = newString + ' ';
}
return string + newString;
}
function helpMenu(shell) {
shell.printHTML('GNU Fake Shell, version 0.1.12-not-released\n' +
'These shell commands are defined internally. Type \'help\' to see this list.\n' +
'Use Google to find out more about the shell in general and to find out more about commands not in this list.');
shell.print('--------------------------------------------------------------');
shell.print('| Command | Description |');
shell.print('|---------------|--------------------------------------------|');
for (const key in commands) {
shell.print(`| ${padToNChars(key, 14)}| ${padToNChars(commands[key].description, 43)}|`);
}
shell.print('--------------------------------------------------------------');
}
async function joke(shell) {
const response = await fetch('https://icanhazdadjoke.com/', { headers: { Accept: 'application/json' } });
const body = await response.json();
if (response.ok) {
await shell.type(body.joke, 20);
}
shell.newLine();
}
async function form(shell) {
const originalPS1 = shell._promptPS1.innerHTML;
shell.clear()
.setPrompt('> ')
.printHTML('<strong class="text-green-400">Please fulfill the following form. Believe it or not, data won\'t leave the browser.</strong>');
const name = await shell.input('What\'s your name ?');
shell.print(`Hello ${name}`);
await shell.newLine().input('Enter your email address');
await shell.newLine().password('Enter your password');
shell.newLine().print('Thanks... Let me check that...just a second');
await JsShell.sleep(1500);
const really = await shell.newLine().confirm('You didn\'t enter your real password, did you?');
if (really) {
shell.print('Oh gosh... Be sure I accept no responsibility.').newLine();
} else {
shell.print('I like this better.');
}
shell.print('We\'re done. Thank you!').newLine();
await shell.pause('PRESS ANY KEY TO CONTINUE');
shell.setPrompt(originalPS1);
}
function changeColor(shell) {
let newBgColor, newTextColor;
do {
newBgColor = bgColors[Math.floor(Math.random() * bgColors.length)];
} while (newBgColor === shell.html.style.background);
do {
newTextColor = textColors[Math.floor(Math.random() * textColors.length)];
} while (newTextColor === shell.html.style.color);
shell
.setBackgroundColor(newBgColor)
.setTextColor(newTextColor);
}
function makePS1(path) {
if (path.slice(-1) !== '/') {
path += '/';
}
return `<strong class="text-green-400">\nuser@machine:${path}\n$ </strong>`;
}
async function startShell(shell) {
shell
.clear()
.print('Hello, world!')
.printHTML('This is a more sophisticated <a href=\'https://github.com/francoisburdy/js-shell-emulator\'>francoisburdy/js-shell-emulator</a> demo.')
.printHTML('See source code <a href="https://github.com/francoisburdy/js-shell-emulator/blob/master/demos/complex.html">here</a>.')
.print('Type "help" to see the commands list.');
let input = '';
while (input !== 'exit') {
input = await shell.input();
input = input.trim();
if (!input.length) {
continue;
}
const argv = input.split(' ');
if (Object.hasOwn(commands, argv[0])) {
await commands[argv[0]].handler(shell, argv);
} else {
shell.print(`${argv[0]}: command not found`);
}
}
}
const shell1 = new JsShell('shell-1', {
width: '100%',
height: '80vh',
textSize: '0.9rem',
backgroundColor: bgColors[0],
promptPS: makePS1('~/fake/path')
});
startShell(shell1);
</script>
</body>
</html>