diff --git a/bin/main.js b/bin/main.js index 8534e24..ff5a472 100644 --- a/bin/main.js +++ b/bin/main.js @@ -1,19 +1,31 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; exports.__esModule = true; -var i2c_bus_1 = require("i2c-bus"); -var oled_i2c_bus_1 = __importDefault(require("oled-i2c-bus")); -var oled_font_5x7_1 = __importDefault(require("oled-font-5x7")); -var i2cbus = (0, i2c_bus_1.openSync)(1); -var opts = { - width: 128, - height: 64, - address: 0x3C -}; -var oled = new oled_i2c_bus_1["default"](i2cbus, opts); -oled.clearDisplay(); -oled.setCursor(1, 1); -oled.writeString(oled_font_5x7_1["default"], 1, "This is a string I am writing to the screen", 1, true); -oled.turnOffDisplay(); +var menu_1 = require("./menu/menu"); +var interface_1 = require("./menu/interface"); +var menu = new menu_1.Menu([ + { + display: "df -h", + type: interface_1.MenuType.ExecCommand, + command: ["df", "-h"] + }, + { + display: "Games", + type: interface_1.MenuType.SubMenu, + subMenu: [ + { + display: "Chess", + type: interface_1.MenuType.ExecCommand, + command: ["df", "-h"] + }, + ] + }, + { + display: "Reboot", + type: interface_1.MenuType.Reboot + }, + { + display: "Shutdown", + type: interface_1.MenuType.Shutdown + }, +], true); +menu.getSelection(); diff --git a/bin/menu/console.js b/bin/menu/console.js new file mode 100644 index 0000000..2e2bfa6 --- /dev/null +++ b/bin/menu/console.js @@ -0,0 +1,91 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +exports.__esModule = true; +exports.ConsolePrinter = void 0; +var interface_1 = require("./interface"); +var readline = __importStar(require("readline")); +var ConsolePrinter = /** @class */ (function () { + function ConsolePrinter(config) { + this._path = []; + this._selectedIndex = 0; + this._config = config; + } + ConsolePrinter.prototype.printMenu = function (curMenu) { + console.clear(); + for (var i = 0; i < curMenu.length; i++) { + var line = (i === this._selectedIndex + ? "> " + : " ") + curMenu[i].display; + console.log(line); + } + }; + ConsolePrinter.prototype.getSelection = function () { + var _this = this; + var curMenu = this._config; + this.printMenu(curMenu); + // get user input + readline.emitKeypressEvents(process.stdin); + process.stdin.setRawMode(true); + process.stdin.on('keypress', function (_letter, key) { + 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++; + if (_this._selectedIndex > curMenu.length - 1) { + _this._selectedIndex = curMenu.length - 1; + } + } + else if (key.name === 'left') { + if (_this._path.length > 0) { + _this._path.pop(); + } + } + else if (key.name === 'right' || key.name === 'enter') { + if (curMenu[_this._selectedIndex].type === interface_1.MenuType.SubMenu) { + _this._path.push(_this._selectedIndex); + _this._selectedIndex = 0; + } + else { + process.exit(); + } + } + curMenu = _this._config; + for (var i = 0; i < _this._path.length; i++) { + curMenu = curMenu[_this._path[i]].subMenu; + } + _this.printMenu(curMenu); + }); + return this._config[this._selectedIndex]; + }; + return ConsolePrinter; +}()); +exports.ConsolePrinter = ConsolePrinter; diff --git a/bin/menu/interface.js b/bin/menu/interface.js new file mode 100644 index 0000000..93c4760 --- /dev/null +++ b/bin/menu/interface.js @@ -0,0 +1,10 @@ +"use strict"; +exports.__esModule = true; +exports.MenuType = void 0; +var MenuType; +(function (MenuType) { + MenuType[MenuType["ExecCommand"] = 0] = "ExecCommand"; + MenuType[MenuType["Reboot"] = 1] = "Reboot"; + MenuType[MenuType["Shutdown"] = 2] = "Shutdown"; + MenuType[MenuType["SubMenu"] = 3] = "SubMenu"; +})(MenuType = exports.MenuType || (exports.MenuType = {})); diff --git a/bin/menu/menu.js b/bin/menu/menu.js new file mode 100644 index 0000000..09f6b9e --- /dev/null +++ b/bin/menu/menu.js @@ -0,0 +1,18 @@ +"use strict"; +exports.__esModule = true; +exports.Menu = void 0; +var console_1 = require("./console"); +var oled_1 = require("./oled"); +var Menu = /** @class */ (function () { + function Menu(config, isConsole) { + if (isConsole === void 0) { isConsole = false; } + this._printer = isConsole + ? new console_1.ConsolePrinter(config) + : new oled_1.OledPrinter(config); + } + Menu.prototype.getSelection = function () { + return this._printer.getSelection(); + }; + return Menu; +}()); +exports.Menu = Menu; diff --git a/bin/menu/oled.js b/bin/menu/oled.js new file mode 100644 index 0000000..6d405cc --- /dev/null +++ b/bin/menu/oled.js @@ -0,0 +1,26 @@ +"use strict"; +exports.__esModule = true; +exports.OledPrinter = void 0; +/*const i2cbus = openSync(1); +const opts = { + width: 128, + height: 64, + address: 0x3C, +}; + +const oled = new Oled(i2cbus, opts); + +oled.clearDisplay(); +oled.setCursor(1, 1); +oled.writeString(font, 1, "This is a string I am writing to the screen", 1, true); +oled.turnOffDisplay();*/ +var OledPrinter = /** @class */ (function () { + function OledPrinter(config) { + this._config = config; + } + OledPrinter.prototype.getSelection = function () { + return this._config[0]; + }; + return OledPrinter; +}()); +exports.OledPrinter = OledPrinter; diff --git a/package.json b/package.json index 0a5b5e5..29fc0f8 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "scripts": { "clean": "rm -rf bin/*", "build": "npm run clean && tsc --project tsconfig.json", - "start": "node bin/main.js" + "start": "ts-node src/main.ts" }, "dependencies": { "i2c-bus": "^5.2.2", diff --git a/src/main.ts b/src/main.ts index 969dd57..5cc8fc5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,17 +1,31 @@ -import { openSync } from 'i2c-bus'; -import Oled from 'oled-i2c-bus'; -import font from 'oled-font-5x7'; +import { Menu } from './menu/menu'; +import { MenuType } from './menu/interface'; -const i2cbus = openSync(1); -const opts = { - width: 128, - height: 64, - address: 0x3C, -}; +const menu = new Menu([ + { + display: "df -h", + type: MenuType.ExecCommand, + command: ["df", "-h"], + }, + { + display: "Games", + type: MenuType.SubMenu, + subMenu: [ + { + display: "Chess", + type: MenuType.ExecCommand, + command: ["df", "-h"], + }, + ], + }, + { + display: "Reboot", + type: MenuType.Reboot, + }, + { + display: "Shutdown", + type: MenuType.Shutdown, + }, +], true); -const oled = new Oled(i2cbus, opts); - -oled.clearDisplay(); -oled.setCursor(1, 1); -oled.writeString(font, 1, "This is a string I am writing to the screen", 1, true); -oled.turnOffDisplay(); +menu.getSelection(); diff --git a/src/menu/console.ts b/src/menu/console.ts new file mode 100644 index 0000000..bf47bfa --- /dev/null +++ b/src/menu/console.ts @@ -0,0 +1,63 @@ +import { MenuConfig, MenuPrinter, MenuType } from './interface'; +import * as readline from 'readline'; + +export class ConsolePrinter implements MenuPrinter { + private _path: number[] = []; + private _selectedIndex: number = 0; + private _config: MenuConfig[]; + + constructor(config: MenuConfig[]) { + this._config = config; + } + + private printMenu(curMenu: MenuConfig[]): void { + console.clear(); + for (let i = 0; i < curMenu.length; i++) { + const line = (i === this._selectedIndex + ? "> " + : " ") + curMenu[i].display; + console.log(line); + } + } + + public getSelection(): MenuConfig { + let curMenu = this._config; + this.printMenu(curMenu); + + // get user input + readline.emitKeypressEvents(process.stdin); + process.stdin.setRawMode(true); + process.stdin.on('keypress', (_letter, key: any) => { + 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++ + if (this._selectedIndex > curMenu.length - 1) { + this._selectedIndex = curMenu.length - 1; + } + } else if (key.name === 'left') { + if (this._path.length > 0) { + this._path.pop(); + } + } else if (key.name === 'right' || key.name === 'enter') { + if (curMenu[this._selectedIndex].type === MenuType.SubMenu) { + this._path.push(this._selectedIndex); + this._selectedIndex = 0; + } else { + process.exit() + } + } + curMenu = this._config; + for (let i = 0; i < this._path.length; i++) { + curMenu = curMenu[this._path[i]].subMenu!; + } + this.printMenu(curMenu); + }); + return this._config[this._selectedIndex]; + } +} diff --git a/src/menu/interface.ts b/src/menu/interface.ts new file mode 100644 index 0000000..39df059 --- /dev/null +++ b/src/menu/interface.ts @@ -0,0 +1,17 @@ +export enum MenuType { + ExecCommand, + Reboot, + Shutdown, + SubMenu, +} + +export interface MenuConfig { + display: string, + type: MenuType, + command?: string[], + subMenu?: MenuConfig[], +} + +export interface MenuPrinter { + getSelection(): MenuConfig; +} diff --git a/src/menu/menu.ts b/src/menu/menu.ts new file mode 100644 index 0000000..d953072 --- /dev/null +++ b/src/menu/menu.ts @@ -0,0 +1,17 @@ +import { MenuConfig, MenuPrinter } from './interface'; +import { ConsolePrinter } from './console'; +import { OledPrinter } from './oled'; + +export class Menu { + private _printer: MenuPrinter; + + constructor(config: MenuConfig[], isConsole: boolean = false) { + this._printer = isConsole + ? new ConsolePrinter(config) + : new OledPrinter(config); + } + + public getSelection(): MenuConfig { + return this._printer.getSelection(); + } +} diff --git a/src/menu/oled.ts b/src/menu/oled.ts new file mode 100644 index 0000000..ef03b5f --- /dev/null +++ b/src/menu/oled.ts @@ -0,0 +1,30 @@ +/*import { openSync } from 'i2c-bus'; +import Oled from 'oled-i2c-bus'; +import font from 'oled-font-5x7';*/ +import { MenuConfig, MenuPrinter } from './interface'; + +/*const i2cbus = openSync(1); +const opts = { + width: 128, + height: 64, + address: 0x3C, +}; + +const oled = new Oled(i2cbus, opts); + +oled.clearDisplay(); +oled.setCursor(1, 1); +oled.writeString(font, 1, "This is a string I am writing to the screen", 1, true); +oled.turnOffDisplay();*/ + +export class OledPrinter implements MenuPrinter { + private _config: MenuConfig[]; + + constructor(config: MenuConfig[]) { + this._config = config; + } + + public getSelection(): MenuConfig { + return this._config[0]; + } +}