diff --git a/src/display/console.ts b/src/display/console.ts new file mode 100644 index 0000000..d9b2b01 --- /dev/null +++ b/src/display/console.ts @@ -0,0 +1,19 @@ +import { DisplayPrinter } from './interface'; + +export class ConsolePrinter implements DisplayPrinter { + public async displayContent(content: string): Promise { + 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(); + } +} diff --git a/src/display/display.ts b/src/display/display.ts new file mode 100644 index 0000000..4987ad3 --- /dev/null +++ b/src/display/display.ts @@ -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 { + this._display.clear(false); + await this._display.displayContent(content, wrap); + } + + public clear(turnOff: boolean = false): void { + this._display.clear(turnOff); + } +} diff --git a/src/display/interface.ts b/src/display/interface.ts new file mode 100644 index 0000000..44bd03e --- /dev/null +++ b/src/display/interface.ts @@ -0,0 +1,4 @@ +export interface DisplayPrinter { + displayContent(content: string, wrap: boolean): Promise; + clear(turnOff: boolean): void; +} diff --git a/src/display/oled.ts b/src/display/oled.ts new file mode 100644 index 0000000..7a10709 --- /dev/null +++ b/src/display/oled.ts @@ -0,0 +1,9 @@ +import { DisplayPrinter } from './interface'; + +export class OledPrinter implements DisplayPrinter { + public async displayContent(_content: string, _wrap: boolean): Promise { + } + + public clear(_turnOff: boolean): void { + } +} diff --git a/src/main.ts b/src/main.ts index 41e3651..0e3a82a 100644 --- a/src/main.ts +++ b/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 { + 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 { 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; } } diff --git a/src/menu/interface.ts b/src/menu/interface.ts index ada68ca..7388536 100644 --- a/src/menu/interface.ts +++ b/src/menu/interface.ts @@ -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[], }