uop-editor
Version:
A TUI program to edit the uop file.
254 lines (253 loc) • 9.8 kB
JavaScript
;
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;
}