UNPKG

uop-editor

Version:
254 lines (253 loc) 9.8 kB
#!/usr/bin/env node "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const commander_1 = require("commander"); const console_gui_tools_1 = require("console-gui-tools"); const fs_1 = require("fs"); const process_1 = require("process"); const constants_1 = require("./constants"); commander_1.program .name("CENG3420 Lab3 UOP Editor") .description("A TUI program for editing uop file.") .version("1.1.1") .argument("<path>", "path of the uop file") .option("-r, --reference <path>", "path of a reference uop file"); commander_1.program.parse(); const opts = commander_1.program.opts(); const uopPath = commander_1.program.processedArgs[0]; const refPath = opts.reference; if (!(0, fs_1.existsSync)(uopPath)) { console.log("Cannot find uop file:", uopPath); (0, process_1.exit)(1); } if (refPath && !(0, fs_1.existsSync)(refPath)) { console.log("Cannot find uop file:", refPath); (0, process_1.exit)(1); } const content = (0, fs_1.readFileSync)(uopPath, { encoding: "utf8" }); const states = [], initStates = []; for (const line of content.split("\n")) { if (line.length != 33) continue; const localStates = []; for (const char of line) { if (char == 'x') localStates.push(-1); else if (char == '0') localStates.push(0); else if (char == '1') localStates.push(1); } states.push(localStates); if (!refPath) initStates.push(Array.from(localStates)); } if (states.length != 128 || states.some(s => s.length != 33)) { console.log("Invalid uop file"); (0, process_1.exit)(2); } if (refPath) { const refContent = (0, fs_1.readFileSync)(refPath, { encoding: "utf8" }); for (const line of refContent.split("\n")) { if (line.length != 33) continue; const localStates = []; for (const char of line) { if (char == 'x') localStates.push(-1); else if (char == '0') localStates.push(0); else if (char == '1') localStates.push(1); } initStates.push(Array.from(localStates)); } if (initStates.length != 128 || initStates.some(s => s.length != 33)) { console.log("Invalid reference uop file"); (0, process_1.exit)(2); } } const GUI = new console_gui_tools_1.ConsoleManager({ title: "UOP Editor", logPageSize: 8 }); let selectedPage = 0, selectedRow = 0, modified = false, filtered = false; const updateConsole = () => __awaiter(void 0, void 0, void 0, function* () { const state = states[selectedPage]; const builder = new console_gui_tools_1.PageBuilder(); if (constants_1.STATE_NAMES.has(selectedPage)) builder.addRow({ text: `State: ${selectedPage} `, color: 'yellow' }, { text: constants_1.STATE_NAMES.get(selectedPage), color: "cyan" }); else builder.addRow({ text: `State: ${selectedPage}`, color: 'yellow' }); builder.addSpacer(); for (let jj = 0; jj < state.length; jj++) { if (filtered && initStates[selectedPage][jj] != -1) continue; const spaces = Array(constants_1.LONGEST_NAME - constants_1.NAMES[jj].length + 1).fill(" ").join(""); const rowOption = { text: `${constants_1.NAMES[jj]}${spaces}` }; const coloredState = { text: `${state[jj] < 0 ? "X" : state[jj]}`, color: state[jj] < 0 ? 'yellow' : (state[jj] ? 'green' : 'red') }; if (jj == selectedRow) builder.addRow(Object.assign(rowOption, { color: 'black', bg: 'bgWhite' }), Object.assign(coloredState, { color: 'black', bg: 'bgWhite' })); else builder.addRow(rowOption, coloredState); } GUI.setPage(builder); }); GUI.on("keypressed", (key) => { switch (key.name) { case "space": modified = true; if (states[selectedPage][selectedRow] != 0) states[selectedPage][selectedRow] = 0; else states[selectedPage][selectedRow] = 1; updateConsole(); break; case "z": modified = true; states[selectedPage][selectedRow] = 1; updateConsole(); break; case "x": modified = true; states[selectedPage][selectedRow] = -1; updateConsole(); break; case "c": modified = true; states[selectedPage][selectedRow] = 0; updateConsole(); break; case "f": filtered = !filtered; if (filtered && initStates[selectedPage][selectedRow] != -1) { const index = initStates[selectedPage].findIndex(x => x == -1); if (index >= 0) selectedRow = index; } updateConsole(); break; case "d": selectedPage = (selectedPage + 1) % 128; if (key.ctrl) { const keys = initStates.map((v, k) => ({ v, k })).filter(x => x.v.some(v => v == -1)).map(x => x.k); const filtered = keys.filter(x => x >= selectedPage); if (!filtered.length) selectedPage = Math.min(...keys); else selectedPage = Math.min(...filtered); } updateConsole(); break; case "a": selectedPage--; if (selectedPage < 0) selectedPage = 127; if (key.ctrl) { const keys = initStates.map((v, k) => ({ v, k })).filter(x => x.v.some(v => v == -1)).map(x => x.k); const filtered = keys.filter(x => x <= selectedPage); if (!filtered.length) selectedPage = Math.max(...keys); else selectedPage = Math.max(...filtered); } updateConsole(); break; case "w": selectedRow--; if (selectedRow < 0) selectedRow = 32; if (filtered) { const arr = initStates[selectedPage].map((v, k) => ({ v, k })).filter(x => x.v == -1); const filtered = arr.filter(x => x.k <= selectedRow); let index = -1; if (filtered.length) index = filtered[filtered.length - 1].k; else if (arr.length) index = arr[arr.length - 1].k; if (index >= 0) selectedRow = index; } updateConsole(); break; case "s": selectedRow = (selectedRow + 1) % 33; if (filtered) { const arr = initStates[selectedPage].map((v, k) => ({ v, k })).filter(x => x.v == -1); const filtered = arr.filter(x => x.k >= selectedRow); let index = -1; if (filtered.length) index = filtered[0].k; else if (arr.length) index = arr[0].k; if (index >= 0) selectedRow = index; } updateConsole(); break; case "e": (0, fs_1.writeFileSync)(uopPath, convertStatesToString(), { encoding: "utf8" }); GUI.log("Saved!"); modified = false; break; case "q": if (!modified) quit(); else { const popup = new console_gui_tools_1.OptionPopup({ id: "saveAndQuit", title: "Save before quitting?", options: ["Yes", "No", "Cancel"], selected: "Cancel" }).show().on("confirm", (selected) => { switch (selected) { case "Yes": (0, fs_1.writeFileSync)(uopPath, convertStatesToString(), { encoding: "utf8" }); case "No": quit(); break; default: popup.hide(); break; } }); } break; case "h": GUI.log("Key bindings for this editor:"); GUI.log("a, d: Navigate different states. Hold ctrl to skip unnecessary states."); GUI.log("w, s: Navigate different signals."); GUI.log("z, x, c: Set signal to 1, x or 0."); GUI.log("space: Toggle signal."); GUI.log("f: Toggle show X only."); GUI.log("e: Save."); GUI.log("q: Quit, and ask to save if modified."); break; } }); updateConsole(); function quit() { (0, process_1.exit)(0); } function convertStatesToString() { let str = ""; for (const state of states) { for (const signal of state) { if (signal == -1) str += "x"; else str += signal; } str += "\n"; } return str; }