@codeque/cli
Advanced tools
Comparing version 0.1.0-beta.5 to 0.1.0-beta.6
199
dist/cli.js
"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()); | ||
}); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const path_1 = __importDefault(require("path")); | ||
const fs_1 = __importDefault(require("fs")); | ||
const core_1 = require("@codeque/core"); | ||
const colorette_1 = require("colorette"); | ||
const terminalEditor_1 = require("./terminalEditor"); | ||
const commander_1 = require("commander"); | ||
const ora_1 = __importDefault(require("ora")); | ||
const search_1 = require("./search"); | ||
const program = new commander_1.Command(); | ||
const print = console.log; | ||
const textEllipsis = (text, maxLength) => { | ||
const charsToReplace = Math.max(text.length - maxLength, 0); | ||
const ellipsis = '...'; | ||
const shortenedRoot = charsToReplace > 0 | ||
? text.replace(new RegExp(`^(.){${charsToReplace + ellipsis.length}}`), ellipsis) | ||
: text; | ||
return shortenedRoot; | ||
}; | ||
const prepareHintText = (hint) => { | ||
return hint.tokens | ||
.map(({ content, type }) => (type === 'code' ? `\`${content}\`` : content)) | ||
.join(' '); | ||
}; | ||
program | ||
@@ -47,165 +16,5 @@ .option('-m, --mode [mode]', 'search mode: exact, include, include-with-order', 'include') | ||
.option('-iec, --invertExitCode', 'Return non-zero exit code if matches are found', false) | ||
.action(({ mode, caseInsensitive, root = process.cwd(), limit, queryPath: queryPaths = [], query: queries = [], entry, git, invertExitCode }) => __awaiter(void 0, void 0, void 0, function* () { | ||
const resultsLimitCount = parseInt(limit, 10); | ||
const resolvedRoot = path_1.default.resolve(root); | ||
mode = (0, core_1.getMode)(mode); | ||
let prevQuery = ''; | ||
const queryCachePath = path_1.default.resolve(__dirname + '/cliQuery'); | ||
try { | ||
prevQuery = fs_1.default.readFileSync(queryCachePath).toString(); | ||
} | ||
catch (e) { | ||
e; | ||
} | ||
const cols = process.stdout.columns; | ||
const separator = ''.padStart(process.stdout.columns, '━'); | ||
const dot = ' • '; | ||
const modeLabel = 'Mode: '; | ||
const caseLabel = 'Case: '; | ||
const caseText = caseInsensitive ? 'insensitive' : 'sensitive'; | ||
const modeAndCaseText = `${(0, colorette_1.cyan)((0, colorette_1.bold)(modeLabel))}${(0, colorette_1.green)(mode)}${dot}${(0, colorette_1.cyan)((0, colorette_1.bold)(caseLabel))}${(0, colorette_1.green)(caseText)}\n`; | ||
const remainingCharsForRoot = cols - | ||
modeLabel.length - | ||
mode.length - | ||
caseLabel.length - | ||
caseText.length - | ||
dot.length; | ||
const rootLabel = 'Root: '; | ||
const minLen = dot.length + rootLabel.length + 5; | ||
const remainingSpaceForRootPath = remainingCharsForRoot - (dot.length + rootLabel.length); | ||
const shortenedRoot = textEllipsis(resolvedRoot, remainingSpaceForRootPath); | ||
const rootText = remainingCharsForRoot > minLen | ||
? `${(0, colorette_1.cyan)((0, colorette_1.bold)(rootLabel))}${(0, colorette_1.green)(shortenedRoot)}${dot}` | ||
: ''; | ||
if (queries.length === 0 && queryPaths.length === 0) { | ||
const q = yield (0, terminalEditor_1.openAsyncEditor)({ | ||
header: `${rootText}${modeAndCaseText}\n✨ Type query:`, | ||
code: prevQuery, | ||
separator | ||
}); | ||
fs_1.default.writeFileSync(queryCachePath, q); | ||
queries = [q]; | ||
} | ||
else if (queryPaths.length > 0) { | ||
try { | ||
queries = queryPaths.map((qp) => fs_1.default.readFileSync(path_1.default.resolve(qp)).toString()); | ||
} | ||
catch (e) { | ||
print('\n' + (0, colorette_1.red)((0, colorette_1.bold)(`Query file not found:`)), e.message, '\n'); | ||
process.exit(1); | ||
} | ||
} | ||
const startTime = Date.now(); | ||
const [queryParseResults, parseOk] = (0, core_1.parseQueries)(queries, caseInsensitive); | ||
if (mode === 'text') { | ||
print(separator + '\n' + rootText + modeAndCaseText); | ||
queries.forEach((q) => { | ||
print((0, colorette_1.cyan)((0, colorette_1.bold)('Query:\n\n')) + q + '\n'); | ||
}); | ||
} | ||
else if (parseOk) { | ||
print(separator + '\n' + rootText + modeAndCaseText); | ||
queries.forEach((q) => { | ||
print((0, colorette_1.cyan)((0, colorette_1.bold)('Query:\n\n')) + (0, core_1.getCodeFrame)(q, 1, true) + '\n'); | ||
}); | ||
} | ||
else { | ||
queries.forEach((q, index) => { | ||
const error = queryParseResults[index].error; | ||
const hints = queryParseResults[index].hints; | ||
if (error) { | ||
if (q.length > 0) { | ||
print((0, colorette_1.red)((0, colorette_1.bold)('Query parse error:\n\n')), (0, core_1.getCodeFrame)(q, 1, false, error === null || error === void 0 ? void 0 : error.location), '\n'); | ||
} | ||
print((0, colorette_1.red)((0, colorette_1.bold)('Error:')), error === null || error === void 0 ? void 0 : error.text, '\n'); | ||
} | ||
if (hints.length > 0) { | ||
const preparedText = prepareHintText(hints[0]); | ||
print((0, colorette_1.blue)((0, colorette_1.bold)('Hint:')), preparedText, '\n'); | ||
} | ||
}); | ||
process.exit(1); | ||
} | ||
let spinner = (0, ora_1.default)(`Getting files list `).start(); | ||
const filePaths = yield (0, core_1.getFilesList)(resolvedRoot, entry, git); | ||
spinner.stop(); | ||
spinner = (0, ora_1.default)(`Searching `).start(); | ||
const { matches, errors } = yield (0, core_1.searchMultiThread)({ | ||
mode, | ||
filePaths, | ||
caseInsensitive, | ||
queryCodes: queries | ||
}); | ||
spinner.stop(); | ||
const endTime = Date.now(); | ||
if (matches.length > 0) { | ||
const groupedMatches = Object.entries((0, core_1.groupMatchesByFile)(matches)); | ||
const resultsText = matches.length <= resultsLimitCount | ||
? `Results:\n` | ||
: `First ${resultsLimitCount} results:\n`; | ||
print((0, colorette_1.cyan)((0, colorette_1.bold)(resultsText))); | ||
let printedResultsCounter = 0; | ||
let currentFileIndex = 0; | ||
while (printedResultsCounter < resultsLimitCount && | ||
groupedMatches[currentFileIndex] !== undefined) { | ||
const [filePath, matches] = groupedMatches[currentFileIndex]; | ||
const relativePath = root === process.cwd() | ||
? path_1.default.relative(resolvedRoot, filePath) | ||
: filePath; | ||
const maxRelativePathDisplayLength = cols - 4; | ||
const shortenRelativePath = textEllipsis(relativePath, maxRelativePathDisplayLength); | ||
const leftPaddingForCentering = Math.trunc((cols - shortenRelativePath.length - 4) / 2); | ||
const leftPaddingStr = ''.padStart(leftPaddingForCentering, ' '); | ||
print(''.padStart(leftPaddingForCentering, '━') + | ||
'┯'.padEnd(shortenRelativePath.length + 3, '━') + | ||
'┯' + | ||
''.padEnd(cols - | ||
(leftPaddingForCentering + shortenRelativePath.length + 4), '━')); | ||
print(leftPaddingStr + '│ ' + (0, colorette_1.bold)((0, colorette_1.green)(shortenRelativePath)) + ' │'); | ||
print(leftPaddingStr + | ||
'╰'.padEnd(shortenRelativePath.length + 3, '─') + | ||
'╯'); | ||
print(''); | ||
for (const match of matches) { | ||
if (printedResultsCounter >= resultsLimitCount) { | ||
break; | ||
} | ||
const resultCode = match.extendedCodeFrame | ||
? match.extendedCodeFrame.code | ||
: match.code; | ||
const matchStartLine = match.loc.start.line; | ||
const codeFrameStartLine = match.extendedCodeFrame | ||
? match.extendedCodeFrame.startLine | ||
: matchStartLine; | ||
const codeFrame = (0, core_1.getCodeFrame)(resultCode, codeFrameStartLine); | ||
print(`${(0, colorette_1.green)(relativePath)}:${(0, colorette_1.magenta)(matchStartLine)}:${(0, colorette_1.yellow)(match.loc.start.column + 1)}`); | ||
print('\n' + codeFrame + '\n'); | ||
printedResultsCounter++; | ||
} | ||
currentFileIndex++; | ||
} | ||
print(separator); | ||
print((0, colorette_1.cyan)((0, colorette_1.bold)('Total count:')), (0, colorette_1.magenta)(matches.length)); | ||
} | ||
else { | ||
print((0, colorette_1.cyan)((0, colorette_1.bold)(`No results found${invertExitCode ? '!' : ' :c'}`))); | ||
} | ||
queryParseResults.forEach(({ hints }, queryIndex) => { | ||
hints.forEach((hint, hintIndex) => { | ||
if (queryIndex === 0 && hintIndex === 0) { | ||
print(''); // new line | ||
} | ||
print((0, colorette_1.blue)((0, colorette_1.bold)('Hint:')), prepareHintText(hint), '\n'); | ||
}); | ||
}); | ||
print((0, colorette_1.cyan)((0, colorette_1.bold)('Found in:')), (0, colorette_1.magenta)((endTime - startTime) / 1000), 's'); | ||
print((0, colorette_1.cyan)((0, colorette_1.bold)('Searched files:')), (0, colorette_1.magenta)(filePaths.length)); | ||
if (errors.length > 0) { | ||
print((0, colorette_1.red)((0, colorette_1.bold)('Search failed for:')), (0, colorette_1.magenta)(errors.length), 'file(s)'); | ||
} | ||
print(''); // new line | ||
const hasMatches = matches.length > 0; | ||
const shouldFail = hasMatches === invertExitCode; | ||
process.exit(shouldFail ? 1 : 0); | ||
})); | ||
.option('-v, --version', 'print CLI version', false) | ||
.option('-pfl, --printFilesList', 'print list of searched files', false) | ||
.action(search_1.search); | ||
program.parse(process.argv); |
@@ -211,6 +211,3 @@ "use strict"; | ||
Math.max(1, 5 - content.split(newLineSequence).length), newLineSequence); | ||
log(footerFormatted.split(newLineSequence).length, cursorTopOffset + | ||
footerWithSep.split(newLineSequence).length + | ||
Math.max(1, 100 - content.split(newLineSequence).length)); | ||
log(footerFormatted); | ||
log('print'); | ||
const tokenized = tokenize(content); | ||
@@ -230,6 +227,7 @@ const lines = tokenized.split(newLineSequence); | ||
let cleanPressCounter = 0; | ||
process.stdin.on('keypress', (char, key) => { | ||
const keypressListener = (char, key) => { | ||
if (key.name === 's' && key.ctrl) { | ||
flush(); | ||
rl.close(); | ||
process.stdin.off('keypress', keypressListener); | ||
resolve(content); | ||
@@ -342,3 +340,4 @@ return; | ||
print(); | ||
}); | ||
}; | ||
process.stdin.on('keypress', keypressListener); | ||
const rl = readline_1.default.createInterface({ | ||
@@ -345,0 +344,0 @@ input: process.stdin, |
{ | ||
"name": "@codeque/cli", | ||
"version": "0.1.0-beta.5", | ||
"version": "0.1.0-beta.6", | ||
"description": "Supercharged multiline code search and replace tool", | ||
@@ -5,0 +5,0 @@ "bin": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
54746
11
1094
0
5