added ability to execute commands and display output

This commit is contained in:
Rudis Muiznieks 2022-04-20 17:31:34 -05:00
parent 3331243872
commit b5269f03de
Signed by: rudism
GPG key ID: CABF2F86EF7884F9
6 changed files with 98 additions and 5 deletions

19
src/display/console.ts Normal file
View file

@ -0,0 +1,19 @@
import { DisplayPrinter } from './interface';
export class ConsolePrinter implements DisplayPrinter {
public async displayContent(content: string): Promise<void> {
console.log(content);
console.log("Press a key...");
return new Promise((resolve) => {
const listener = (_letter: string, _key: any): void => {
process.stdin.removeListener('keypress', listener);
resolve();
}
process.stdin.on('keypress', listener);
});
}
public clear(_: boolean): void {
console.clear();
}
}

22
src/display/display.ts Normal file
View file

@ -0,0 +1,22 @@
import { DisplayPrinter } from './interface';
import { ConsolePrinter } from './console';
import { OledPrinter } from './oled';
export class Display {
private _display: DisplayPrinter;
constructor(useConsole: boolean) {
this._display = useConsole
? new ConsolePrinter()
: new OledPrinter();
}
public async displayContent(content: string, wrap: boolean = true): Promise<void> {
this._display.clear(false);
await this._display.displayContent(content, wrap);
}
public clear(turnOff: boolean = false): void {
this._display.clear(turnOff);
}
}

4
src/display/interface.ts Normal file
View file

@ -0,0 +1,4 @@
export interface DisplayPrinter {
displayContent(content: string, wrap: boolean): Promise<void>;
clear(turnOff: boolean): void;
}

9
src/display/oled.ts Normal file
View file

@ -0,0 +1,9 @@
import { DisplayPrinter } from './interface';
export class OledPrinter implements DisplayPrinter {
public async displayContent(_content: string, _wrap: boolean): Promise<void> {
}
public clear(_turnOff: boolean): void {
}
}

View file

@ -1,12 +1,15 @@
import { Menu } from './menu/menu';
import { MenuType } from './menu/interface';
import { MenuCommand, MenuType } from './menu/interface';
import { Display } from './display/display';
import { exec, spawn } from 'child_process';
class Main {
private readonly _menu = [
{
display: "df -h",
type: MenuType.ExecCommand,
command: ["df", "-h"],
command: {exe: "df", args: ['-h']},
},
{
display: "Games",
@ -15,7 +18,7 @@ class Main {
{
display: "Chess",
type: MenuType.ExecCommand,
command: ["df", "-h"],
command: {exe: "df", args: ['-h']},
},
],
},
@ -29,15 +32,45 @@ class Main {
},
];
private readonly _display: Display;
private readonly _console: boolean = process.env['CONSOLE'] === '1';
constructor() {
this._display = new Display(this._console);
}
private async runCommand(cmd: MenuCommand): Promise<void> {
return new Promise((resolve) => {
this._display.displayContent(
`Executing command:\n> ${cmd.exe} ${cmd.args?.join(' ')}`);
let output = '';
const child = spawn(cmd.exe, cmd.args);
child.stdout.on('data', (data) => {
output += data;
});
child.on('exit', async ()=> {
await this._display.displayContent(output, cmd.wrap);
resolve();
});
});
}
public async runAsync(): Promise<void> {
while (true) {
const selected = await new Menu(this._menu, process.env['CONSOLE'] === '1').getSelection();
const selected = await new Menu(this._menu, this._console).getSelection();
switch(selected.type) {
case MenuType.Shutdown:
this._display.clear(true);
exec('sudo shutdown now');
process.exit();
case MenuType.Reboot:
this._display.clear();
exec('sudo reboot');
process.exit();
case MenuType.ExecCommand:
if (selected.command) {
await this.runCommand(selected.command);
}
break;
}
}

View file

@ -5,10 +5,16 @@ export enum MenuType {
SubMenu,
}
export interface MenuCommand {
exe: string,
args?: string[],
wrap?: boolean,
}
export interface MenuConfig {
display: string,
type: MenuType,
command?: string[],
command?: MenuCommand,
subMenu?: MenuConfig[],
}