added ability to execute commands and display output
This commit is contained in:
parent
3331243872
commit
b5269f03de
6 changed files with 98 additions and 5 deletions
19
src/display/console.ts
Normal file
19
src/display/console.ts
Normal 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
22
src/display/display.ts
Normal 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
4
src/display/interface.ts
Normal 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
9
src/display/oled.ts
Normal 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 {
|
||||
}
|
||||
}
|
41
src/main.ts
41
src/main.ts
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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[],
|
||||
}
|
||||
|
||||
|
|
Reference in a new issue