@kearisp/cli
Advanced tools
Comparing version 1.0.0 to 1.0.1
import { Command } from "./Command"; | ||
import { Logger } from "../types"; | ||
declare class Cli extends Command { | ||
protected scriptPath: string; | ||
constructor(); | ||
constructor(logger?: Logger); | ||
completionScript(): string; | ||
protected parseCommand(command: string): string[]; | ||
run(argv: string[]): Promise<any>; | ||
} | ||
export { Cli }; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Cli = void 0; | ||
const OS = require("os"); | ||
const Command_1 = require("./Command"); | ||
const utils_1 = require("../utils"); | ||
class Cli extends Command_1.Command { | ||
constructor() { | ||
super(""); | ||
constructor(logger) { | ||
super("", logger); | ||
} | ||
completionScript() { | ||
const name = "cli"; | ||
return (0, utils_1.generateCompletion)(name); | ||
return (0, utils_1.generateCompletion)(this._command); | ||
} | ||
parseCommand(command) { | ||
const parts = []; | ||
let current = "", quotes = "", escape = 0; | ||
for (let i = 0; i < command.length; i++) { | ||
const char = command.charAt(i); | ||
if (char === "\\") { | ||
escape++; | ||
} | ||
else if ((char === "\"" || char === "'") && !escape && !quotes) { | ||
quotes = char; | ||
} | ||
else if (char === quotes && !escape) { | ||
if (current) { | ||
parts.push(current); | ||
} | ||
quotes = ""; | ||
current = ""; | ||
} | ||
else if (char === " " && !escape && !quotes) { | ||
if (current) { | ||
parts.push(current); | ||
} | ||
current = ""; | ||
} | ||
else { | ||
current += (escape ? "\\".repeat(escape - 1) : "") + char; | ||
escape = 0; | ||
} | ||
} | ||
if (current) { | ||
parts.push(current); | ||
} | ||
return parts; | ||
} | ||
async run(argv) { | ||
const [nodePath, script, ...parts] = argv; | ||
this.scriptPath = script; | ||
if (parts.indexOf("--completion") > -1 || parts.indexOf("--compgen") > -1) { | ||
return this.complete(parts); | ||
const [, scriptPath, ...rest] = argv; | ||
this.scriptPath = scriptPath; | ||
const [, name] = /^.+\/(.+)$/.exec(scriptPath) || []; | ||
const parts = [name, ...rest]; | ||
this._command = name; | ||
if (parts.indexOf("--completion") > -1 || parts.indexOf("--compbash") > -1 || parts.indexOf("--compgen") > -1) { | ||
const completion = new Command_1.Command(`${name} <index> <prev> <command>`, this._logger); | ||
const promise = new Promise((resolve) => { | ||
completion | ||
.option("completion", { | ||
type: "boolean" | ||
}) | ||
.option("compbash", { | ||
type: "boolean" | ||
}) | ||
.option("compgen", { | ||
type: "boolean" | ||
}) | ||
.action((options, index, prev, command) => { | ||
this.info(parts, options, { | ||
index, | ||
prev, | ||
command | ||
}); | ||
resolve([index, command]); | ||
return "1"; | ||
}); | ||
}); | ||
try { | ||
const res = await completion.process(parts); | ||
if (res === "1") { | ||
const [index, command] = await promise; | ||
const p = this.parseCommand(command); | ||
const res = await this.complete(p.length - 1 < parseInt(index) ? [...p, ""] : p); | ||
this.info(index, p.length, p, res); | ||
return res | ||
.map((predict) => { | ||
if (/\s/.test(predict)) { | ||
return predict.replace(/\s/g, "\\ "); | ||
} | ||
return predict; | ||
}) | ||
.join(OS.EOL); | ||
} | ||
} | ||
catch (err) { | ||
this.error(err.message); | ||
} | ||
return ""; | ||
} | ||
@@ -20,0 +99,0 @@ return this.process(parts); |
@@ -0,1 +1,2 @@ | ||
import { Logger } from "../types"; | ||
type Option = { | ||
@@ -14,5 +15,5 @@ name: string; | ||
isOption?: boolean; | ||
action: (options: any, ...args: string[]) => string[] | Promise<string[]>; | ||
action: (options: any, ...args: (string | string[])[]) => string[] | Promise<string[]>; | ||
}; | ||
type Action = (options: any, ...args: string[]) => string | Promise<string>; | ||
type Action = (options: any, ...args: (string | string[])[]) => void | string | Promise<void | string>; | ||
declare class Command { | ||
@@ -24,3 +25,4 @@ protected _command: string; | ||
protected _completions: Completion[]; | ||
constructor(command: string); | ||
protected _logger?: Logger; | ||
constructor(command: string, logger?: Logger); | ||
getName(): string; | ||
@@ -32,3 +34,3 @@ command(name: string): Command; | ||
parse(parts: string[], partial?: boolean): { | ||
args: string[]; | ||
args: (string | string[])[]; | ||
options: { | ||
@@ -41,3 +43,3 @@ [name: string]: string | number | boolean; | ||
} | { | ||
args: string[]; | ||
args: (string | string[])[]; | ||
options: { | ||
@@ -50,4 +52,4 @@ [name: string]: string | number | boolean; | ||
}; | ||
process(parts: string[], parentOptions?: any, parentArgs?: string[]): any; | ||
predictCommand(command: string, part: string, options?: any, args?: string[]): Promise<string[]>; | ||
process(parts: string[], parentOptions?: any, parentArgs?: (string | string[])[]): any; | ||
predictCommand(command: string, part: string, options?: any, args?: (string | string[])[]): Promise<string[]>; | ||
complete(parts: string[]): Promise<string[]>; | ||
@@ -57,3 +59,6 @@ isMatch(part: string): boolean; | ||
getReg(partial?: boolean): RegExp; | ||
info(...args: any[]): void; | ||
warning(...args: any[]): void; | ||
error(...args: any[]): void; | ||
} | ||
export { Command }; |
@@ -9,3 +9,3 @@ "use strict"; | ||
class Command { | ||
constructor(command) { | ||
constructor(command, logger) { | ||
this._commands = []; | ||
@@ -15,2 +15,3 @@ this._options = []; | ||
this._command = command; | ||
this._logger = logger; | ||
} | ||
@@ -25,3 +26,3 @@ getName() { | ||
if (!command) { | ||
command = new Command(name); | ||
command = new Command(name, this._logger); | ||
this._commands.push(command); | ||
@@ -63,3 +64,11 @@ } | ||
let isLast = current === parts.length - 1; | ||
if ((0, utils_1.isCommand)(part)) { | ||
if ((0, utils_1.isSpread)(command)) { | ||
let value = []; | ||
while (current < parts.length) { | ||
value.push(parts[current]); | ||
current++; | ||
} | ||
args.push(value); | ||
} | ||
else if ((0, utils_1.isCommand)(command)) { | ||
const regExp = (0, utils_1.generateCommandRegExp)(command); | ||
@@ -93,6 +102,6 @@ if (!regExp) { | ||
const option = this._options.find((option) => { | ||
return option.name === name || option.alias === alias; | ||
return (name && option.name === name) || (alias && option.alias === alias); | ||
}); | ||
if (!option) { | ||
throw new Error(`Option "${name}" is not defined`); | ||
throw new Error(`Option "${name}" is not defined (1)`); | ||
} | ||
@@ -124,3 +133,3 @@ switch (option.type) { | ||
if (!option) { | ||
throw new Error(`Option not found ${name || alias}`); | ||
throw new Error(`Option not found ${name || alias} (2)`); | ||
} | ||
@@ -335,3 +344,21 @@ switch (option.type) { | ||
} | ||
info(...args) { | ||
if (!this._logger) { | ||
return; | ||
} | ||
this._logger.info(...args); | ||
} | ||
warning(...args) { | ||
if (!this._logger) { | ||
return; | ||
} | ||
this._logger.warning(...args); | ||
} | ||
error(...args) { | ||
if (!this._logger) { | ||
return; | ||
} | ||
this._logger.error(...args); | ||
} | ||
} | ||
exports.Command = Command; |
@@ -5,1 +5,2 @@ export * from "./escapeRegExp"; | ||
export * from "./isCommand"; | ||
export * from "./isSpread"; |
@@ -21,1 +21,2 @@ "use strict"; | ||
__exportStar(require("./isCommand"), exports); | ||
__exportStar(require("./isSpread"), exports); |
@@ -1,1 +0,1 @@ | ||
export declare const isCommand: (part: string) => boolean; | ||
export declare const isCommand: (command: string) => boolean; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isCommand = void 0; | ||
const isCommand = (part) => { | ||
return !part.startsWith("-"); | ||
const generateCommandRegExp_1 = require("./generateCommandRegExp"); | ||
const isCommand = (command) => { | ||
return !!(0, generateCommandRegExp_1.generateCommandRegExp)(command); | ||
}; | ||
exports.isCommand = isCommand; |
{ | ||
"name": "@kearisp/cli", | ||
"version": "1.0.0", | ||
"version": "1.0.1", | ||
"license": "MIT", | ||
@@ -11,3 +11,2 @@ "author": "Kris Papercut <krispcut@gmail.com>", | ||
], | ||
"private": false, | ||
"main": "dist/index.js", | ||
@@ -24,25 +23,20 @@ "types": "dist/index.d.ts", | ||
"build": "tsc", | ||
"babel:build": "babel src --out-dir lib --extensions .js --extensions .ts", | ||
"babel:watch": "npm run babel:build -- --watch", | ||
"test": "jest --colors", | ||
"test-watch": "jest --colors --watch" | ||
}, | ||
"dependencies": { | ||
"os": "^0.1.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.22.8", | ||
"@babel/eslint-parser": "^7.22.7", | ||
"@babel/eslint-plugin": "^7.22.5", | ||
"@babel/preset-env": "^7.22.9", | ||
"@babel/core": "^7.22.10", | ||
"@babel/preset-env": "^7.22.10", | ||
"@babel/preset-typescript": "^7.22.5", | ||
"@types/jest": "^29.5.2", | ||
"@types/node": "^20.4.4", | ||
"child_process": "^1.0.2", | ||
"date-fns": "^2.30.0", | ||
"@types/jest": "^29.5.3", | ||
"@types/node": "^20.5.1", | ||
"babel-jest": "^29.6.2", | ||
"dotenv": "^16.3.1", | ||
"fs": "^0.0.1-security", | ||
"jest": "^29.6.1", | ||
"omelette": "^0.4.17", | ||
"jest": "^29.6.3", | ||
"path": "^0.12.7", | ||
"ts-node": "^10.9.1", | ||
"typescript": "^5.1.6" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
102921
10
30
1
771