This repository has been archived on 2022-12-29. You can view files and clone it, but cannot push or open issues or pull requests.
zeropod/src/menu/console.ts

83 lines
2.4 KiB
TypeScript
Raw Normal View History

2022-04-19 21:02:08 -05:00
import { MenuConfig, MenuPrinter, MenuType } from './interface';
import * as readline from 'readline';
2022-04-20 08:05:21 -05:00
type Key = {name: string, ctrl: boolean};
2022-04-19 21:02:08 -05:00
export class ConsolePrinter implements MenuPrinter {
private _path: number[] = [];
private _selectedIndex: number = 0;
private _config: MenuConfig[];
2022-04-22 13:53:26 -05:00
private _curMenu: MenuConfig[];
2022-04-19 21:02:08 -05:00
constructor(config: MenuConfig[]) {
this._config = config;
2022-04-22 13:53:26 -05:00
this._curMenu = config;
2022-04-20 08:05:21 -05:00
readline.emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);
}
private async keypress(): Promise<Key> {
return new Promise((resolve) => {
const listener = (_letter: string, key: Key): void => {
process.stdin.removeListener('keypress', listener);
resolve(key);
}
process.stdin.on('keypress', listener);
});
2022-04-19 21:02:08 -05:00
}
2022-04-22 13:53:26 -05:00
private printMenu(): void {
2022-04-19 21:02:08 -05:00
console.clear();
2022-04-22 13:53:26 -05:00
for (let i = 0; i < this._curMenu.length; i++) {
2022-04-19 21:02:08 -05:00
const line = (i === this._selectedIndex
? "> "
2022-04-22 13:53:26 -05:00
: " ") + this._curMenu[i].display;
2022-04-19 21:02:08 -05:00
console.log(line);
}
}
2022-04-20 08:05:21 -05:00
public async getSelection(): Promise<MenuConfig> {
return new Promise(async (resolve) => {
while (true) {
// print menu
2022-04-22 13:53:26 -05:00
this.printMenu();
2022-04-19 21:02:08 -05:00
2022-04-20 08:05:21 -05:00
// get user input
const key = await this.keypress();
if (key.ctrl && key.name === 'c') {
process.exit();
} else if (key.name === 'up') {
this._selectedIndex--;
if (this._selectedIndex < 0) {
this._selectedIndex = 0;
}
} else if (key.name ==='down') {
this._selectedIndex++
2022-04-22 13:53:26 -05:00
if (this._selectedIndex > this._curMenu.length - 1) {
this._selectedIndex = this._curMenu.length - 1;
2022-04-20 08:05:21 -05:00
}
} else if (key.name === 'left') {
if (this._path.length > 0) {
this._path.pop();
this._selectedIndex = 0;
}
} else if (key.name === 'right' || key.name === 'return') {
2022-04-19 21:02:08 -05:00
this._path.push(this._selectedIndex);
2022-04-20 08:05:21 -05:00
}
2022-04-22 13:53:26 -05:00
this._curMenu = this._config;
2022-04-20 08:05:21 -05:00
for (let i = 0; i < this._path.length; i++) {
2022-04-22 13:53:26 -05:00
if (this._curMenu[this._path[i]].type === MenuType.SubMenu) {
this._curMenu = this._curMenu[this._path[i]].subMenu!;
this._selectedIndex = 0;
2022-04-20 08:05:21 -05:00
} else {
2022-04-22 13:53:26 -05:00
resolve(this._curMenu[this._path[i]]);
this._path.pop();
2022-04-20 08:05:21 -05:00
return;
}
2022-04-19 21:02:08 -05:00
}
}
});
}
}