// utilities for creating cli programsimport{makeSpaces}from"./string";import{bold,color}from"./printstyle";/** * Configure a single command line option. */classOption{publicname: string;publicapply: Function;publicdescription: string;privatecreator: CLI;constructor(name: string,creator: CLI){this.name=name;this.description="";this.apply=()=>{};this.creator=creator;}/** * Provide a description for this CLI option. */describe(desc: string){this.description=desc;returnthis;}/** * Add an action to be called with this CLI option. */action(fn: ()=>any){this.apply=fn;returnthis;}/** * Create the next CLI option. * @param name the name of the next option. */option(name: string){returnthis.creator.option(name);}/** * Execute this CLI option. * Allows us to execute the CLI regardless of where we are * in the builder process. */exec(args: string[]){returnthis.creator.exec(args);}}classCLI{privatename="";privateoptions: Option[]=[];privatedescription: string="";constructor(name: string="<command>"){this.name=name;this.options=[];}option(name: string){constoption=newOption(name,this);this.options.push(option);returnoption;}describe(desc: string){this.description=desc;returnthis;}exec(args: string[]){this.addHelpOption();constoption=this.options.find((o)=>o.name===args[0]);if(option){option.apply(args.slice(1));}else{this.printHelp();}}// add the help option// the help option needs to reference `this`,// so it can't be added in the constructoraddHelpOption(){this.option("help").describe("Show help").action(()=>this.printHelp());returnthis;}printHelp(){console.log(`${bold(this.name)}${this.description ? `: ${this.description}` : ""}\n`);constmaxNameLength=this.options.reduce((max,o)=>Math.max(max,o.name.length),0);this.options.forEach((o)=>{constspaces=makeSpaces(maxNameLength-o.name.length);console.log(` ${color(o.name,"blue")}${spaces}${o.description}`);});}}/** * Create a new CLI. * @param args the string of arguments passed to the cli wehn created. * * api: * cli('name') * .describe('description') * .option(name).describe(desc).action(fn) * .option(name).describe(desc).action(fn) * .exec(argv) */functioncli(...args: string[]){returnnewCLI(...args);}export{cli};