feat(voyage)!: marketplace handoff — rename plugins/ultraplan-local to plugins/voyage [skip-docs]
Session 5 of voyage-rebrand (V6). Operator-authorized cross-plugin scope. - git mv plugins/ultraplan-local plugins/voyage (rename detected, history preserved) - .claude-plugin/marketplace.json: voyage entry replaces ultraplan-local - CLAUDE.md: voyage row in plugin list, voyage in design-system consumer list - README.md: bulk rename ultra*-local commands -> trek* commands; ultraplan-local refs -> voyage; type discriminators (type: trekbrief/trekreview); session-title pattern (voyage:<command>:<slug>); v4.0.0 release-note paragraph - plugins/voyage/.claude-plugin/plugin.json: homepage/repository URLs point to monorepo voyage path - plugins/voyage/verify.sh: drop URL whitelist exception (no longer needed) Closes voyage-rebrand. bash plugins/voyage/verify.sh PASS 7/7. npm test 361/361.
This commit is contained in:
parent
8f1bf9b7b4
commit
7a90d348ad
149 changed files with 26 additions and 33 deletions
|
|
@ -1,93 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
const HELP = `Usage: tally [options] <pattern> <file>
|
||||
|
||||
Count literal-substring occurrences of <pattern> in <file>.
|
||||
|
||||
Options:
|
||||
-i, --ignore-case Case-insensitive matching
|
||||
--lines Count lines containing pattern (not total occurrences)
|
||||
-r, --regex Interpret <pattern> as a JavaScript regular expression
|
||||
--json Emit a JSON object on stdout
|
||||
-h, --help Show this help and exit
|
||||
|
||||
Exit codes: 0=success 1=file error 2=invalid argv
|
||||
`;
|
||||
|
||||
function fail(msg, code = 2) {
|
||||
process.stderr.write(`tally: ${msg}\n`);
|
||||
process.exit(code);
|
||||
}
|
||||
|
||||
function parseArgs(argv) {
|
||||
const positional = [];
|
||||
const flags = { json: false, ignoreCase: false, lines: false, regex: false };
|
||||
for (const a of argv) {
|
||||
if (a === '--json') flags.json = true;
|
||||
else if (a === '-i' || a === '--ignore-case') flags.ignoreCase = true;
|
||||
else if (a === '--lines') flags.lines = true;
|
||||
else if (a === '--regex' || a === '-r') flags.regex = true;
|
||||
else if (a === '-h' || a === '--help') { process.stdout.write(HELP); process.exit(0); }
|
||||
else if (a.startsWith('-')) fail(`unknown flag: ${a}`);
|
||||
else positional.push(a);
|
||||
}
|
||||
if (positional.length !== 2) fail('expected <pattern> <file>');
|
||||
return { pattern: positional[0], file: positional[1], flags };
|
||||
}
|
||||
|
||||
function compileRegex(pattern) {
|
||||
try { return new RegExp(pattern, 'g'); }
|
||||
catch (e) { fail(`invalid regex: ${e.message}`); }
|
||||
}
|
||||
|
||||
function countOccurrences(text, pattern, ignoreCase) {
|
||||
if (pattern.length === 0) return 0;
|
||||
const haystack = ignoreCase ? text.toLowerCase() : text;
|
||||
const needle = ignoreCase ? pattern.toLowerCase() : pattern;
|
||||
let count = 0, idx = 0;
|
||||
while ((idx = haystack.indexOf(needle, idx)) !== -1) { count++; idx += needle.length; }
|
||||
return count;
|
||||
}
|
||||
|
||||
function countLines(text, pattern, ignoreCase) {
|
||||
if (pattern.length === 0) return 0;
|
||||
const needle = ignoreCase ? pattern.toLowerCase() : pattern;
|
||||
let count = 0;
|
||||
for (const line of text.split('\n')) {
|
||||
const haystack = ignoreCase ? line.toLowerCase() : line;
|
||||
if (haystack.includes(needle)) count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const { pattern, file, flags } = parseArgs(process.argv.slice(2));
|
||||
let text;
|
||||
try {
|
||||
text = readFileSync(file, 'utf8');
|
||||
} catch (err) {
|
||||
const what = err.code === 'ENOENT' ? 'file not found' : 'read error';
|
||||
process.stderr.write(`tally: ${what}: ${file}\n`);
|
||||
process.exit(1);
|
||||
}
|
||||
let count;
|
||||
if (flags.regex) {
|
||||
const re = compileRegex(pattern);
|
||||
count = (text.match(re) || []).length;
|
||||
} else if (flags.lines) {
|
||||
count = countLines(text, pattern, flags.ignoreCase);
|
||||
} else {
|
||||
count = countOccurrences(text, pattern, flags.ignoreCase);
|
||||
}
|
||||
if (flags.json) {
|
||||
process.stdout.write(JSON.stringify({
|
||||
pattern, file, count,
|
||||
flags: { json: flags.json, ignoreCase: flags.ignoreCase, lines: flags.lines, regex: flags.regex },
|
||||
}) + '\n');
|
||||
} else {
|
||||
process.stdout.write(count + '\n');
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
Loading…
Add table
Add a link
Reference in a new issue