gnablib
Version:
A lean, zero dependency library to provide a useful base for your project.
2 lines • 7.56 kB
JavaScript
/*! Copyright 2024 the gnablib contributors MPL-1.1 */
var t,r=this&&this.__classPrivateFieldGet||function(t,r,e,s){if("a"===e&&!s)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof r?t!==r||!s:!r.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?s:"a"===e?s.call(t):s?s.value:r.get(t)},e=this&&this.__classPrivateFieldSet||function(t,r,e,s,i){if("m"===s)throw new TypeError("Private method is not writable");if("a"===s&&!i)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof r?t!==r||!i:!r.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===s?i.call(t,e):i?i.value=e:r.set(t,e),e};import{Color as s}from"./tty.js";import{color as i}from"./csi-tables.js";import{config as o}from"../runtime/Config.js";import{callFrom as n}from"../runtime/callFrom.js";s.blue.now();const{cyan:h,yellow:a,red:l,reset:f}=i;class u{constructor(t,r=!1){this.descr=t,this.defValue=r,this.value=r}}class c{constructor(t,r,e=void 0){this.key=t,this.descr=r,this.defValue=e,this.value=e}}function _(){process.exit(0)}export class Cli{constructor(r,e,s){this.name=r,this.descr=e,this._prog=[],this._finalized=!1,t.set(this,new Map),this._args=[],this._aliasMap=new Map,this._resIdx=new Map,this._log=console.log,this._logError=console.error,this._errExitStatus=1,this._prog.push(r),this.flag("no-color","Don't use colors in output",!1,"_no-colour"),this.flag("help","Display this message",!1,"h"),this.flag("version","Display version information",!1,"v"),s&&(this._log=s)}cyan(t){return o.getBool("color")?h+t+f:t}get hasError(){return null!=this._error}ver(t){if(this.hasError)return this;const r=this.cyan(null==t?"":""+t);return this._finalized?(this._error=`Cannot set version=${r} after finalization`,this._errorLine=n()):null!=this._ver&&t!==this._ver?(this._error=`Version already set to ${this.cyan(this._ver)}, cannot set to ${r}`,this._errorLine=n()):this._ver=null==t?void 0:""+t,this}require(t,r,e){return this.hasError||(this._finalized?(this._error=`Cannot define a required value ${this.cyan(t)} after finalization`,this._errorLine=n()):this._resIdx.has(t)?(this._error=`Cannot redefine ${this.cyan(t)}`,this._errorLine=n()):(this._args.push(new c(t,r,e)),this._prog.push(t),this._resIdx.set(t,"argument"))),this}flag(e,s,i=!1,...o){var h;if(this.hasError)return this;if(this._finalized)return this._error=`Cannot define flag ${this.cyan(e)} after finalization`,this._errorLine=n(),this;if(e.startsWith("_"))return this._error="Flag-key cannot be hidden (start with underscore): "+this.cyan(e),this._errorLine=n(),this;const a=new u(s,i);this._resIdx.has(e)&&(this._error=`Cannot redefine ${this.cyan(e)}`,this._errorLine=n()),r(this,t,"f").set(e,a),this._resIdx.set(e,"option");for(const t of o){const r=this._resIdx.size;if(this._resIdx.set(t,"alias"),r==this._resIdx.size)return this._error=`${t} already assigned to ${this._aliasMap.get(t)}`,this._errorLine=n(),this;this._aliasMap.has(e)||this._aliasMap.set(e,[]),null===(h=this._aliasMap.get(e))||void 0===h||h.push(t)}return this}resolveAlias(t){for(const[r,e]of this._aliasMap)if(e.includes(t))return r}removeOpt(...e){if(this.hasError)return this;if(this._finalized)return this._error="Cannot remove keys after finalization",this._errorLine=n(),this;for(const s of e){if(!r(this,t,"f").has(s))return this._error="Unable to remove "+this.cyan(s)+" - not found as an option",this._errorLine=n(),this;r(this,t,"f").delete(s),this._resIdx.delete(s);const e=this._aliasMap.get(s);if(e){for(const t of e)this._resIdx.delete(t);this._aliasMap.delete(s)}}return this}removeAlt(...t){if(this.hasError)return this;if(this._finalized)return this._error="Cannot remove keys after finalization",this._errorLine=n(),this;for(const r of t){if(!this._resIdx.has(r))return this._error=`Cannot remove ${this.cyan(r)} - not found`,this._errorLine=n(),this;for(const[t,e]of this._aliasMap)for(let s=0;s<e.length;s++){if((e[s].startsWith("_")?e[s].substring(1):e[s])==r){e.splice(s,1),this._resIdx.delete(r),0==e.length&&this._aliasMap.delete(t);break}}}return this}getOption(e){if(!this._resIdx.has(e))return;const s=r(this,t,"f").get(e);if(s)return s;const i=this.resolveAlias(e);return i?r(this,t,"f").get(i):void 0}setOption(t,r){const e=this.getOption(t);if(!e)throw new Error("Option not found: "+t);return e.value=r,this}value(t){var r,e;const s=this._resIdx.get(t);if(null!=s){if("argument"==s)for(const r of this._args)if(r.key===t)return r.value;return"alias"==s&&(t=null!==(r=this.resolveAlias(t))&&void 0!==r?r:""),null===(e=this.getOption(t))||void 0===e?void 0:e.value}}optionValue(e){var s;return null===(s=r(this,t,"f").get(e))||void 0===s?void 0:s.value}optionValues(){const e=[];return r(this,t,"f").forEach(((t,r)=>e.push([r,t.value]))),e}finalize(){for(let t=1;t<this._prog.length;t++)this._prog[t]="["+this.cyan(this._prog[t])+"]";r(this,t,"f").size>0&&this._prog.push("["+this.cyan("OPTIONS")+"]"),e(this,t,new Map([...r(this,t,"f")].sort(((t,r)=>t[0].localeCompare(r[0])))),"f"),this._finalized=!0}parse(t=2,r=process.argv){if(this.hasError)return this;let e=0;for(let s=t;s<r.length;s++){const t=r[s];if(t.startsWith("--")){const r=t.substring(2),e=this.getOption(r);if(e instanceof u){e.value=!e.value;continue}this._error=`Not a flag ${this.cyan(r)}`}else if(t.startsWith("-"))for(let r=1;r<t.length;r++){const e=t[r],s=this.getOption(e);if(!s){this._error=`Unknown flag ${this.cyan(e)}`;break}if(!(s instanceof u)){this._error=`Not a flag ${this.cyan(e)}`;break}s.value=!s.value}else{if(e>=this._args.length){this._error=`Unknown argument ${this.cyan((e+1).toString())}`;break}this._args[e++].value=t}}!0===this.optionValue("no-color")&&o.set("color",!1,"set by --no-color"),this._finalized||this.finalize();for(let t=e;t<this._args.length;t++)if(null==this._args[t].value){this._error=`Argument '${this.cyan(this._args[t].key)}' is required but not defined`;break}return this}error(t,r){let e="Error";o.getBool("color")&&(e=l+e+f),e+=": "+t,r&&(e+="\n "+r),this._logError(e),this._errExitStatus>=0&&process.exit(this._errExitStatus)}ifComplete(t=_){return!0===this.optionValue("help")?(this._log(this.helpBlock()),t(),this):!0===this.optionValue("version")?(this._log(this.versionBlock()),t(),this):(null!=this._error&&this.error(this._error,this._errorLine),this)}onError(t={}){return t.target&&(this._logError=t.target),t.exitStatus&&(this._errExitStatus=t.exitStatus),this}renderKey(t,r){return t.startsWith("_")?-1:1==t.length?(r.unshift("-"+this.cyan(t)),t.length+1):(r.push("--"+this.cyan(t)),t.length+2)}renderArgs(){const t=[];let r=0;for(const e of this._args){const s=this.cyan(e.key);s.length>r&&(r=s.length),t.push([s,e.descr])}const e=[],s=" ".repeat(r);for(const[i,o]of t)e.push(` ${(i+s).substring(0,r)} ${o}`);return e}renderOpts(){const e=[];let s=0;r(this,t,"f").forEach(((t,r)=>{const i=[];let o=this.renderKey(r,i);const n=this._aliasMap.get(r);if(n)for(const t of n)o+=this.renderKey(t,i)+1;const h=i.join(",");o>s&&(s=o),e.push([h,o,t.descr])}));const i=" ".repeat(s),o=[];for(const[t,r,n]of e)o.push(` ${t+i.substring(0,s-r)} ${n}`);return o}versionBlock(){var t;let r=null!==(t=this._ver)&&void 0!==t?t:0;return o.getBool("color")&&(r=a+r+f),"Version: "+r+"\n"}helpBlock(){return this._finalized||this.finalize(),"Usage: "+this._prog.join(" ")+"\n"+this.descr+"\n\n"+this.renderArgs().join("\n")+"\n\nOptions:\n"+this.renderOpts().join("\n")+"\n\n"}}t=new WeakMap;