UNPKG

hygen-create

Version:

simplifies creation of hygen templates from existing projects

322 lines 27.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const program = require("commander"); const _ = require("lodash"); const chalk_1 = require("chalk"); const cli_app_1 = require("./cli-app"); // import { AbsPath } from "@ronp001/ts-utils/dist/path_helper" const hygen_create_1 = require("./hygen-create"); const ts_utils_1 = require("@ronp001/ts-utils"); class HygenCreateCli extends cli_app_1.CliApp { constructor() { super(...arguments); this.hgc = new hygen_create_1.HygenCreate(); } beforeCommand() { if (program.verbose) { // console.log("beforeCommand - project:", program.project) // this.hpg.activateDebug() this.hgc.outputFunc = console.log; } let project_search_path = process.cwd(); if (program.project) { this.hgc.session_file_name = program.project; } this.hgc.setPathAndLoadSessionIfExists(project_search_path); } afterCommand() { // this.hpg.outputFunc("afterCommand") this.hgc.saveSessionIfActiveAndChanged(); } _init() { program .description('hygen-create - create hygen templates from an existing project') .version('0.2.0') .option('-v, --verbose', "provide more info") .option('-p, --project <filename>', `name of session definitions file (default: ${hygen_create_1.HygenCreate.default_session_file_name})`); //------------------------- // Control commands //------------------------- program.command('start <generator-name>') .description("initiate a definition session for the generator <generator-name>") .option('-n, --usename <name>', "templatize files using <name>") .action(this.action(this.start)); program.command('rename <generator-name>') .description("change the name of the target generator to <generator-name>") .action(this.action(this.rename)); //------------------------- // File selection commands //------------------------- program.command('add <file|dir> [file|dir...]') .description("add files or directories to be templatized") .action(this.action(this.add)); program.command('remove <file|dir> [file|dir...]') .alias('rm') .description("do not templatize specified files/directories") .action(this.action(this.remove)); //------------------------- // Parameter definition commands //------------------------- program.command('usename <name>') .description("set <name> as the templatization param") .action(this.action(this.usename)); program.command('setopt') .description("configure options for the generator") .option('--gen-parent-dir', "the resulting generator will create a parent directory (using the hygen --name param)") .option('--no-parent-dir', "the resulting generator will not create a parent directory for the content") .action(this.action(this.setopt)); //------------------------- // Info commands //------------------------- program.command('status [file] [files...]') .alias('s') .option('-l, --detailed', "show detailed information") .description("show replacements to be made in (all|specified) files") .action(this.action(this.show)); //------------------------- // Generator generation //------------------------- program.command('generate') .alias('g') .description("generate a generator from the added files") // .option('-f, --force', "overwrite generator files even if they exist") .action(this.action(this.generate)); } setopt(options) { if (this.hgc.session == null) throw new hygen_create_1.HygenCreateError.NoSessionInProgress; if (options.genParentDir == true) { this.hgc.session.gen_parent_dir = true; console.log("parent dir generation is now on"); } else if (options.parentDir == false) { this.hgc.session.gen_parent_dir = false; console.log("parent dir generation is now off"); } else { console.log("no options specified"); } } start(name, options) { this.hgc.startSession(name); console.log("created " + this.hgc.session_file_name); if (options.usename) { this.hgc.useName(options.usename); } } rename(name) { this.hgc.renameSession(name); } add(fileOrDir, otherFilesOrDirs) { let allfiles = this.fix(fileOrDir, otherFilesOrDirs); this.hgc.add(allfiles); } remove(fileOrDir, otherFilesOrDirs) { let allfiles = this.fix(fileOrDir, otherFilesOrDirs); this.hgc.remove(allfiles); } printTemplateInfo(tinfo) { let lines = tinfo.abspath.contentsLines; let replacement_lines = tinfo.replacements.map((e) => { return e.linenum - 1; }); // console.log(tinfo.replacements) // console.log(replacement_lines) if (tinfo.is_binary) { console.log("<binary file>"); return; } //------------------------------- // show the template header //------------------------------- console.log("hygen template file: " + chalk_1.default.bold(tinfo.template_filename)); console.log(tinfo.header); //------------------------------- // compare the template to the original file //------------------------------- let Action; (function (Action) { Action[Action["Explain"] = 0] = "Explain"; Action[Action["Show"] = 1] = "Show"; Action[Action["Hide"] = 2] = "Hide"; })(Action || (Action = {})); function getReplacementLine(linenum) { let entry = _.find(tinfo.replacements, { linenum: linenum + 1 }); if (!entry) return "???"; return entry.new_text; } function chooseAction(for_line_num) { let idx = _.sortedIndex(replacement_lines, for_line_num); let prev_line_num = replacement_lines[idx - 1] === undefined ? (for_line_num - 1000) : replacement_lines[idx - 1]; let following_line_num = replacement_lines[idx] === undefined ? (for_line_num + 1000) : replacement_lines[idx]; // console.log('following_line_num', following_line_num) let dist = Math.min(Math.abs(prev_line_num - for_line_num), Math.abs(following_line_num - for_line_num)); // console.log('for_line_num', for_line_num, 'l', replacement_lines, 'l[idx]', replacement_lines[idx], 'idx', idx, 'prev_line_num', prev_line_num, 'following_line_num', following_line_num, 'dist', dist) if (dist == 0) return Action.Explain; if (dist < 4 && dist > 0) return Action.Show; if (for_line_num < 2) return Action.Show; if (lines.length - for_line_num < 3) return Action.Show; return Action.Hide; } function colorize(line) { let segs = line.split(/(<%=.*?%>)/); // console.log("segs:", segs) let result = ""; for (let segnum = 0; segnum < segs.length; segnum++) { // console.log(segnum) if (segnum % 2 == 1) { result += chalk_1.default.green(segs[segnum]); // console.log(chalk.green(segs[segnum])) } else { result += segs[segnum]; } } return result; } let did_hide = false; let len = lines.length; for (let linenum = 0; linenum < len; linenum++) { let action = chooseAction(linenum); switch (action) { case Action.Explain: console.log(chalk_1.default.red("%d - %s"), linenum, (lines[linenum])); console.log(chalk_1.default.green("%d + %s"), linenum, colorize(getReplacementLine(linenum))); did_hide = false; break; case Action.Show: console.log("%d %s", linenum, lines[linenum]); did_hide = false; break; case Action.Hide: if (!did_hide) { did_hide = true; console.log("..."); } break; } // console.log(linenum, action) } console.log("----"); } usename(name) { this.hgc.useName(name); let tinfos = this.hgc.templates; let count = 0; for (let tinfo of tinfos) { count += tinfo.replacements.length; } // console.log(tinfos) console.log(`${count} matching lines found in ${tinfos.length} included files`); } show(fileOrDir, otherFilesOrDirs) { if (this.hgc.session == null) throw new hygen_create_1.HygenCreateError.NoSessionInProgress; let single = (fileOrDir != undefined); let allfiles = this.fix(fileOrDir, otherFilesOrDirs); let info = this.hgc.getFileInfo(allfiles, program.verbose); if (this.hgc.session.templatize_using_name) { console.log(chalk_1.default `\nUsing the string "{bold ${this.hgc.session.templatize_using_name}}" to templatize files (Change using 'hygen-create usename <name>')`); } else { console.log(""); console.log(chalk_1.default.redBright(`\nNo word set for templatizing files. Set using 'hygen-create usename <name>'`)); console.log(""); } if (typeof fileOrDir == "undefined") { if (info.length == 0) { console.log(chalk_1.default.red("No files included in the generator")); } else { console.log("\nThe following files are included in the generator:"); } } const currentDir = new ts_utils_1.AbsPath("."); for (let finfo of info) { let p = finfo.path; let f = finfo.path.relativeFrom(currentDir); if (f == null) throw new Error(`unexpected error - could not calculate relative path for ${p.toString()}`); let line; let fname; let color; let num_replacement_lines = 0; let tinfo = null; if (!p.exists) { fname = `${f} (not found)`; color = chalk_1.default.bgYellow; } else { if (p.isDir) { fname = `${f}/`; color = chalk_1.default.blue; } else if (p.isSymLink) { fname = `${f}@`; color = chalk_1.default.magenta; } else if (p.isFile) { fname = `${f}`; color = chalk_1.default.green; } else { fname = `${f}???`; color = chalk_1.default.cyan; } if (this.hgc.session.templatize_using_name) { tinfo = this.hgc.getTemplate(f, null); num_replacement_lines = tinfo.numReplacementLines; } } if (finfo.included) { line = chalk_1.default.blue('[included] - ') + color(fname); if (finfo.is_binary) { line = chalk_1.default.red(`[ignored ] - ${fname} (binary file)`); } } else { line = chalk_1.default.gray(`[excluded] - ${fname}`); } if (num_replacement_lines > 0) { line += chalk_1.default.blue(` [${num_replacement_lines} lines parameterized]`); } console.log(line); if ((program.verbose || program.detailed) && tinfo) { this.printTemplateInfo(tinfo); } } if (!single) { console.log(""); if (this.hgc.session.name) { if (this.hgc.targetDirForGenerators.isSet) { console.log(chalk_1.default.green(`Target dir: ${this.hgc.targetDirForGenerators.add(this.hgc.session.name).abspath}`) + (chalk_1.default.gray(` ${this.hgc.targetDirForGeneratorsReason}`))); } else { console.log(chalk_1.default.red(`No target dir: ${this.hgc.targetDirForGeneratorsReason}`)); } } else { console.log(chalk_1.default.red("Generator name not set (use hygen-create rename <name> to set it)")); } console.log(""); if (this.hgc.session.gen_parent_dir) { console.log(`Parent dir generation: ON (the resulting generator will create a <name> directory as parent for the content)`); } else { console.log("Parent dir generation: OFF (the resulting generator will add content to the current directory)"); } console.log(""); } } generate(options) { let force = !!options.force; // if ( force ) console.log("FORCE!") this.hgc.generate(); } } exports.default = HygenCreateCli; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHlnZW4tY3JlYXRlLWNsaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9oeWdlbi1jcmVhdGUtY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEscUNBQW9DO0FBRXBDLDRCQUEyQjtBQUMzQixpQ0FBeUI7QUFDekIsdUNBQWtDO0FBQ2xDLCtEQUErRDtBQUMvRCxpREFBOEQ7QUFFOUQsZ0RBQTRDO0FBRTVDLE1BQXFCLGNBQWUsU0FBUSxnQkFBTTtJQUFsRDs7UUFFWSxRQUFHLEdBQWdCLElBQUksMEJBQVcsRUFBRSxDQUFDO0lBb1ZqRCxDQUFDO0lBbFZhLGFBQWE7UUFFbkIsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFO1lBQ2pCLDJEQUEyRDtZQUMzRCwyQkFBMkI7WUFDM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQTtTQUNwQztRQUVELElBQUksbUJBQW1CLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFBO1FBQ3ZDLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRTtZQUNqQixJQUFJLENBQUMsR0FBRyxDQUFDLGlCQUFpQixHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUE7U0FDL0M7UUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLG1CQUFtQixDQUFDLENBQUE7SUFDL0QsQ0FBQztJQUVTLFlBQVk7UUFDbEIsc0NBQXNDO1FBQ3RDLElBQUksQ0FBQyxHQUFHLENBQUMsNkJBQTZCLEVBQUUsQ0FBQTtJQUM1QyxDQUFDO0lBRVMsS0FBSztRQUVYLE9BQU87YUFDRixXQUFXLENBQUMsZ0VBQWdFLENBQUM7YUFDN0UsT0FBTyxDQUFDLE9BQU8sQ0FBQzthQUNoQixNQUFNLENBQUMsZUFBZSxFQUFFLG1CQUFtQixDQUFDO2FBQzVDLE1BQU0sQ0FBQywwQkFBMEIsRUFBRSw4Q0FBOEMsMEJBQVcsQ0FBQyx5QkFBeUIsR0FBRyxDQUFDLENBQUE7UUFFL0gsMkJB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