added ability to execute commands and display output
This commit is contained in:
parent
3331243872
commit
b5269f03de
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export interface DisplayPrinter {
|
||||||
|
displayContent(content: string, wrap: boolean): Promise<void>;
|
||||||
|
clear(turnOff: boolean): void;
|
||||||
|
}
|
|
@ -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 { 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 {
|
class Main {
|
||||||
private readonly _menu = [
|
private readonly _menu = [
|
||||||
{
|
{
|
||||||
display: "df -h",
|
display: "df -h",
|
||||||
type: MenuType.ExecCommand,
|
type: MenuType.ExecCommand,
|
||||||
command: ["df", "-h"],
|
command: {exe: "df", args: ['-h']},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
display: "Games",
|
display: "Games",
|
||||||
|
@ -15,7 +18,7 @@ class Main {
|
||||||
{
|
{
|
||||||
display: "Chess",
|
display: "Chess",
|
||||||
type: MenuType.ExecCommand,
|
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> {
|
public async runAsync(): Promise<void> {
|
||||||
while (true) {
|
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) {
|
switch(selected.type) {
|
||||||
case MenuType.Shutdown:
|
case MenuType.Shutdown:
|
||||||
|
this._display.clear(true);
|
||||||
|
exec('sudo shutdown now');
|
||||||
process.exit();
|
process.exit();
|
||||||
case MenuType.Reboot:
|
case MenuType.Reboot:
|
||||||
|
this._display.clear();
|
||||||
|
exec('sudo reboot');
|
||||||
process.exit();
|
process.exit();
|
||||||
case MenuType.ExecCommand:
|
case MenuType.ExecCommand:
|
||||||
|
if (selected.command) {
|
||||||
|
await this.runCommand(selected.command);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,16 @@ export enum MenuType {
|
||||||
SubMenu,
|
SubMenu,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MenuCommand {
|
||||||
|
exe: string,
|
||||||
|
args?: string[],
|
||||||
|
wrap?: boolean,
|
||||||
|
}
|
||||||
|
|
||||||
export interface MenuConfig {
|
export interface MenuConfig {
|
||||||
display: string,
|
display: string,
|
||||||
type: MenuType,
|
type: MenuType,
|
||||||
command?: string[],
|
command?: MenuCommand,
|
||||||
subMenu?: MenuConfig[],
|
subMenu?: MenuConfig[],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue