Skip to content

Commit

Permalink
Added shell
Browse files Browse the repository at this point in the history
  • Loading branch information
james-pre committed Oct 12, 2024
1 parent 7aa8a26 commit bb57335
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 17 deletions.
31 changes: 22 additions & 9 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@zenfs/dom": "^0.2.17",
"@zenfs/iso": "^0.3.0",
"@zenfs/zip": "^0.5.1",
"chalk": "^5.3.0",
"jquery": "^3.7.1",
"utilium": "^0.7.7"
},
Expand Down
9 changes: 1 addition & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
import '@xterm/xterm/css/xterm.css';
import './styles.css';

import { FitAddon } from '@xterm/addon-fit';
import { Terminal } from '@xterm/xterm';
import $ from 'jquery';
import { randomHex, type Entries } from 'utilium';
import { backends, type BackendInput, type BackendInputElement } from './backends.js';
import './shell.js';
import { instantiateTemplate } from './templates.js';

// Switching tabs
Expand Down Expand Up @@ -58,9 +57,3 @@ $('#config .add').on('click', () => {
});

$('#config .update').on('click', () => {});

const terminal = new Terminal();
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);
terminal.open($('#terminal-container')[0]);
fitAddon.fit();
153 changes: 153 additions & 0 deletions src/shell.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { FitAddon } from '@xterm/addon-fit';
import { Terminal } from '@xterm/xterm';
import { fs } from '@zenfs/core';
import { cd, join, resolve, cwd, basename } from '@zenfs/core/emulation/path.js';
import chalk from 'chalk';
import $ from 'jquery';

const terminal = new Terminal();
const fitAddon = new FitAddon();
terminal.loadAddon(fitAddon);
terminal.open($('#terminal-container')[0]);
fitAddon.fit();
terminal.write('\x1b[4h');

function ls(dir: string = '.') {
const list = fs
.readdirSync(dir)
.map(name => (fs.statSync(join(dir, name)).isDirectory() ? chalk.blue(name) : name))
.join(' ');
terminal.writeln(list);
}

const helpText = `
Virtual FS shell.\r
Available commands: help, ls, cp, cd, mv, rm, cat, stat, pwd, exit/quit\r
`;

function prompt(): string {
return `[${chalk.green(cwd == '/root' ? '~' : basename(cwd) || '/')}]$ `;
}

function clear(): void {
terminal.write('\x1b[2K\r' + prompt());
}
terminal.writeln(helpText);
prompt();

let input: string = '';

/**
* The index for which input is being shown
*/
let index: number = -1;

/**
* The current, uncached input
*/
let currentInput: string = '';

/**
* array of previous inputs
*/
const inputs: string[] = [];

function exec(): void {
if (input == '') {
return;
}

const [command, ...args] = input.trim().split(' ');
try {
switch (command) {
case 'help':
terminal.writeln(helpText);
break;
case 'ls':
ls(args[0]);
break;
case 'cd':
cd(args[0] || resolve('.'));
break;
case 'cp':
fs.cpSync(args[0], args[1]);
break;
case 'mv':
fs.renameSync(args[0], args[1]);
break;
case 'rm':
fs.unlinkSync(args[0]);
break;
case 'cat':
terminal.writeln(fs.readFileSync(args[0], 'utf8'));
break;
case 'stat':
//terminal.writeln(inspect(fs.statSync(args[0]), { colors: true }));
break;
case 'pwd':
terminal.writeln(cwd);
break;
case 'exit':
case 'quit':
close();
return;
default:
terminal.writeln('Unknown command: ' + command);
}
} catch (error) {
terminal.writeln('Error: ' + (error as Error).message);
}

prompt();
}

terminal.onData(data => {
if (index == -1) {
currentInput = input;
}
const promptLength = prompt().length;
const x = terminal.buffer.active.cursorX - promptLength;
switch (data) {
case '\x1b[D':
case '\x1b[C':
terminal.write(data);
break;
case 'ArrowUp':
case '\x1b[A':
clear();
if (index < inputs.length - 1) {
input = inputs[++index];
}
terminal.write(input);
break;
case 'ArrowDown':
case '\x1b[B':
clear();
if (index >= 0) {
input = index-- == 0 ? currentInput : inputs[index];
}
terminal.write(input);
break;
case '\x7f':
if (x <= 0) {
return;
}
terminal.write('\b\x1b[P');
input = input.slice(0, x - 1) + input.slice(x);
break;
case '\r':
if (input != inputs[0]) {
inputs.unshift(input);
}
index = -1;
input = '';
clear();
break;
default:
terminal.write(data);
input = input.slice(0, x) + data + input.slice(x);
}
});

terminal.onLineFeed(exec);
clear();

0 comments on commit bb57335

Please sign in to comment.