UNPKG

@codeque/cli

Version:

Multiline code search for every language. Structural code search for JavaScript, TypeScript, HTML and CSS

221 lines (220 loc) 11.7 kB
"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 }); exports.search = void 0; const core_1 = require("@codeque/core"); const colorette_1 = require("colorette"); const fs_1 = __importDefault(require("fs")); const ora_1 = __importDefault(require("ora")); const path_1 = __importDefault(require("path")); const terminalEditor_1 = require("./terminalEditor"); const utils_1 = require("./utils"); const waitForSearchDecision_1 = require("./waitForSearchDecision"); function search(params) { return __awaiter(this, void 0, void 0, function* () { const { caseInsensitive, root = process.cwd(), limit, queryPath: queryPaths = [], entry, git, invertExitCode, version, printFilesList, omitGitIgnore, allExtensions, } = params; let { mode, query: queries = [] } = params; if (version) { return (0, utils_1.printVersionNumber)(); } const shouldOpenEditor = queries.length === 0 && queryPaths.length === 0; 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 = (0, utils_1.textEllipsis)(resolvedRoot, remainingSpaceForRootPath); const rootText = remainingCharsForRoot > minLen ? `${(0, colorette_1.cyan)((0, colorette_1.bold)(rootLabel))}${(0, colorette_1.green)(shortenedRoot)}${dot}` : ''; if (shouldOpenEditor) { 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) { (0, utils_1.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 parserSettings = core_1.__internal.parserSettingsMap['babel'](); const [queryParseResults, parseOk] = (0, core_1.parseQueries)(queries, caseInsensitive, parserSettings); if (mode === 'text') { (0, utils_1.print)(separator + '\n' + rootText + modeAndCaseText); queries.forEach((q) => { (0, utils_1.print)((0, colorette_1.cyan)((0, colorette_1.bold)('Query:\n\n')) + q + '\n'); }); } else if (parseOk) { (0, utils_1.print)(separator + '\n' + rootText + modeAndCaseText); queries.forEach((q) => { (0, utils_1.print)((0, colorette_1.cyan)((0, colorette_1.bold)('Query:\n\n')) + (0, utils_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) { (0, utils_1.print)((0, colorette_1.red)((0, colorette_1.bold)('Query parse error:\n\n')), (0, utils_1.getCodeFrame)(q, 1, false, error === null || error === void 0 ? void 0 : error.location), '\n'); } (0, utils_1.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 = (0, utils_1.prepareHintText)(hints[0]); (0, utils_1.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(); let filePaths = []; try { filePaths = yield (0, core_1.getFilesList)({ searchRoot: resolvedRoot, entryPoint: entry, byGitChanges: git, omitGitIgnore, extensionTester: allExtensions ? /\.(\w)+$/ : undefined, }); } catch (e) { (0, utils_1.print)('\n'); (0, utils_1.print)((0, colorette_1.bold)((0, colorette_1.red)('Error while getting files list:'))); (0, utils_1.print)(e.message); process.exit(1); } 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`; (0, utils_1.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 = (0, utils_1.textEllipsis)(relativePath, maxRelativePathDisplayLength); const leftPaddingForCentering = Math.trunc((cols - shortenRelativePath.length - 4) / 2); const leftPaddingStr = ''.padStart(leftPaddingForCentering, ' '); (0, utils_1.print)(''.padStart(leftPaddingForCentering, '━') + '┯'.padEnd(shortenRelativePath.length + 3, '━') + '┯' + ''.padEnd(cols - (leftPaddingForCentering + shortenRelativePath.length + 4), '━')); (0, utils_1.print)(leftPaddingStr + '│ ' + (0, colorette_1.bold)((0, colorette_1.green)(shortenRelativePath)) + ' │'); (0, utils_1.print)(leftPaddingStr + '╰'.padEnd(shortenRelativePath.length + 3, '─') + '╯'); (0, utils_1.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, utils_1.getCodeFrame)(resultCode, codeFrameStartLine); (0, utils_1.print)(`${(0, colorette_1.green)(relativePath)}:${(0, colorette_1.magenta)(matchStartLine)}:${(0, colorette_1.yellow)(match.loc.start.column + 1)}`); (0, utils_1.print)('\n' + codeFrame + '\n'); printedResultsCounter++; } currentFileIndex++; } (0, utils_1.print)(separator); (0, utils_1.print)(''); (0, utils_1.print)((0, colorette_1.cyan)((0, colorette_1.bold)('Total count:')), (0, colorette_1.magenta)(matches.length)); } else { (0, utils_1.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) { (0, utils_1.print)(''); // new line } (0, utils_1.print)((0, colorette_1.blue)((0, colorette_1.bold)('Hint:')), (0, utils_1.prepareHintText)(hint), '\n'); }); }); (0, utils_1.print)((0, colorette_1.cyan)((0, colorette_1.bold)('Found in:')), (0, colorette_1.magenta)((endTime - startTime) / 1000), 's'); (0, utils_1.print)((0, colorette_1.cyan)((0, colorette_1.bold)('Searched files:')), (0, colorette_1.magenta)(filePaths.length)); if (errors.length > 0) { (0, utils_1.print)((0, colorette_1.red)((0, colorette_1.bold)('Search failed for:')), (0, colorette_1.magenta)(errors.length), 'file(s)'); } if (printFilesList) { filePaths.forEach((filePath) => (0, utils_1.print)((0, colorette_1.green)(path_1.default.relative(root, filePath)))); } (0, utils_1.print)(''); // new line if (shouldOpenEditor) { const shouldStartNextSearch = yield (0, waitForSearchDecision_1.waitForSearchDecision)(); if (shouldStartNextSearch) { yield search(params); } } else { const hasMatches = matches.length > 0; const shouldFail = hasMatches === invertExitCode; process.exit(shouldFail ? 1 : 0); } }); } exports.search = search;