@codeque/cli
Version:
Multiline code search for every language. Structural code search for JavaScript, TypeScript, HTML and CSS
352 lines (351 loc) โข 13.5 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (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;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.openAsyncEditor = void 0;
//@ts-nocheck
const readline_1 = __importDefault(require("readline"));
const fs_1 = __importDefault(require("fs"));
const colors = __importStar(require("colorette"));
const js_tokens_fork_1 = __importDefault(require("./js-tokens-fork"));
const prettier_1 = require("prettier");
function tokenize(code) {
const tokens = Array.from((0, js_tokens_fork_1.default)(code));
return tokens.reduce((coloredCode, token) => {
let coloredToken = '';
if (token.type === 'StringLiteral') {
coloredToken = colors.green(token.value);
}
else if (token.type === 'IdentifierName') {
const keywords = [
'abstract',
'arguments',
'async',
'await',
'boolean',
'break',
'byte',
'case',
'catch',
'char',
'class',
'const',
'continue',
'debugger',
'default',
'delete',
'do',
'double',
'else',
'enum',
'eval',
'export',
'extends',
'false',
'final',
'finally',
'float',
'for',
'function',
'goto',
'if',
'implements',
'import',
'in',
'instanceof',
'int',
'interface',
'let',
'long',
'native',
'new',
'null',
'package',
'private',
'protected',
'public',
'return',
'short',
'static',
'super',
'switch',
'synchronized',
'this',
'throw',
'throws',
'transient',
'true',
'try',
'typeof',
'var',
'void',
'volatile',
'while',
'with',
'yield',
'type',
'interface',
'as',
'any',
];
if (keywords.includes(token.value)) {
coloredToken = colors.cyan(token.value);
}
else {
coloredToken = colors.white(token.value);
}
}
else if (token.type === 'NumericLiteral') {
coloredToken = colors.magenta(token.value);
}
else if (token.type === 'Punctuator') {
if (['[', ']', '{', '}'].includes(token.value)) {
coloredToken = colors.white(token.value);
}
else {
coloredToken = colors.yellow(token.value);
}
}
else if (token.type === 'RegularExpressionLiteral') {
coloredToken = colors.red(token.value);
}
else {
coloredToken = token.value;
}
return coloredCode + coloredToken;
}, '');
}
const newLineSequence = '\n';
const footerDefault = [
'๐ Ctrl+s ๐ search!' + ' ๐
๐พ Ctrl+f ๐ format code',
'๐ช Ctrl+c ๐ cancel and exit' + ' ๐ข Ctrl+b ๐ toggle line numbers',
'๐งน 2 x Ctrl+x ๐ clean query',
].join(newLineSequence);
const logErrorFileName = 'editor-log.txt';
const openAsyncEditor = ({ header = '', code = '', footer = footerDefault, debug = false, separator, }) => {
if (debug) {
fs_1.default.writeFileSync(logErrorFileName, '');
}
return new Promise((resolve) => {
const log = (...strings) => {
if (debug) {
fs_1.default.appendFileSync(logErrorFileName, strings.join(' ') + '\n');
}
};
const outputStream = process.stdout;
let content = code;
function flush() {
readline_1.default.cursorTo(outputStream, 0, 0);
readline_1.default.clearScreenDown(outputStream);
}
const cursorTopOffset = header.split(newLineSequence).length + separator.split('\n').length + 1;
const defaultLeftOffset = 3 + 1 + 1 + 1; // line num + space + pipe + space
let cursorLeftOffset = defaultLeftOffset;
const cursorPos = {
x: cursorLeftOffset,
y: cursorTopOffset,
};
const getCursorYWithOffset = () => cursorPos.y - cursorTopOffset;
const getCursorXWithOffset = () => cursorPos.x - cursorLeftOffset;
const updateCursor = () => {
readline_1.default.cursorTo(outputStream, cursorPos.x, cursorPos.y);
};
const fixCursorOverflow = (content) => {
const lines = content.split(newLineSequence);
if (getCursorYWithOffset() > lines.length - 1) {
cursorPos.y = lines.length - 1 + cursorTopOffset;
}
const lineLen = lines[getCursorYWithOffset()].length;
if (getCursorXWithOffset() > lineLen) {
cursorPos.x = lineLen + cursorLeftOffset;
}
};
const cursorUp = (content) => {
cursorPos.y = Math.max(cursorPos.y - 1, cursorTopOffset);
fixCursorOverflow(content);
};
const cursorPrevLineEnd = (content) => {
cursorUp(content);
cursorRight(content, Infinity);
};
const cursorLeft = () => {
cursorPos.x = Math.max(getCursorXWithOffset() - 1, 0) + cursorLeftOffset;
};
const cursorRight = (content, progress = 1) => {
const lineLen = content.split(newLineSequence)[getCursorYWithOffset()].length;
cursorPos.x =
Math.min(getCursorXWithOffset() + progress, lineLen) + cursorLeftOffset;
};
const cursorDown = (content, progress = 1) => {
const linesCount = content.split(newLineSequence).length;
cursorPos.y = Math.min(cursorPos.y + progress, linesCount - 1 + cursorTopOffset);
fixCursorOverflow(content);
};
const print = () => {
flush();
const sepWithNewLine = separator ? separator + newLineSequence : '';
const headerFormatted = sepWithNewLine + header + newLineSequence + newLineSequence;
const footerWithSep = newLineSequence + sepWithNewLine + footer;
const footerFormatted = footerWithSep.padStart(footerWithSep.length +
Math.max(1, 5 - content.split(newLineSequence).length), newLineSequence);
log('print');
const tokenized = tokenize(content);
const lines = tokenized.split(newLineSequence);
const contentWithLineNumbers = lines
.map((line, idx) => `${colors.gray(`${idx + 1}`.padStart(3)) + colors.gray(' | ')}${line}`)
.join(newLineSequence);
if (cursorLeftOffset === defaultLeftOffset) {
outputStream.write(headerFormatted + contentWithLineNumbers + footerFormatted);
}
else {
outputStream.write(headerFormatted + tokenized + footerFormatted);
}
updateCursor();
};
let cleanPressCounter = 0;
const keypressListener = (char, key) => {
if (key.name === 's' && key.ctrl) {
flush();
rl.close();
process.stdin.off('keypress', keypressListener);
resolve(content);
return;
}
if (key.name === 'b' && key.ctrl) {
cursorLeftOffset =
cursorLeftOffset === defaultLeftOffset ? 0 : defaultLeftOffset;
cursorRight(content, Infinity);
}
if (key.name === 'x' && key.ctrl) {
cleanPressCounter++;
if (cleanPressCounter > 1) {
content = '';
fixCursorOverflow(content);
cleanPressCounter = 0;
}
}
else {
cleanPressCounter = 0;
}
if (key.name === 'f' && key.ctrl) {
try {
content = (0, prettier_1.format)(content, {
parser: 'babel-ts',
});
fixCursorOverflow(content);
}
catch (e) {
e;
}
}
if (key.name === 'up') {
cursorUp(content);
updateCursor();
return;
}
if (key.name === 'left') {
cursorLeft();
updateCursor();
return;
}
if (key.name === 'right') {
cursorRight(content);
updateCursor();
return;
}
if (key.name === 'down') {
cursorDown(content);
updateCursor();
return;
}
if (key.name === 'return') {
const lines = content.split(newLineSequence);
const currentPositionInContent = lines
.filter((_, idx) => idx < getCursorYWithOffset())
.reduce((len, str) => len + str.length + newLineSequence.length, 0) + getCursorXWithOffset();
content =
content.substring(0, currentPositionInContent) +
newLineSequence +
content.substring(currentPositionInContent);
cursorPos.y++;
cursorPos.x = cursorLeftOffset;
// return
}
if (key.name === 'backspace') {
const lines = content.split(newLineSequence);
const currentPositionInContent = lines
.filter((_, idx) => idx < getCursorYWithOffset())
.reduce((len, str) => len + str.length + newLineSequence.length, 0) + getCursorXWithOffset();
const lastChar = content.charCodeAt(currentPositionInContent - 1);
const isNewLineChar = lastChar === 10;
if (isNewLineChar) {
log('line start');
cursorPrevLineEnd(content);
content =
content.substring(0, currentPositionInContent - 1) +
content.substring(currentPositionInContent);
}
else {
log('no line start');
cursorLeft();
content =
content.substring(0, currentPositionInContent - 1) +
content.substring(currentPositionInContent);
}
}
log('char', char);
log('key.name', key.name);
if (!key.ctrl &&
char !== undefined &&
key.name !== 'backspace' &&
key.name !== 'return') {
if (key.name === 'tab') {
log('adding tab');
char = ` `;
}
const lines = content.split(newLineSequence);
const line = lines[getCursorYWithOffset()];
const newLineChars = content.length === 0
? char
: line.substr(0, getCursorXWithOffset()) +
char +
line.substr(getCursorXWithOffset());
lines[getCursorYWithOffset()] = newLineChars;
content = lines.join(newLineSequence);
cursorRight(content, char.length);
}
print();
};
process.stdin.on('keypress', keypressListener);
const rl = readline_1.default.createInterface({
input: process.stdin,
output: null,
terminal: true,
prompt: '',
});
cursorDown(content, Infinity);
cursorRight(content, Infinity);
print();
});
};
exports.openAsyncEditor = openAsyncEditor;
;