kit.program/argv/CmdLine.js
2024-02-27 16:54:41 +08:00

96 lines
2.6 KiB
JavaScript

const CliParam = require("./CliParam")
/**
* 特色命令行交互格式
* 有且只有一个命令码
* 可以有多个参数
* 可以有多个标记,标记分无参/单参/多参
*/
module.exports = class CmdLine {
constructor(line, cmd, info) {
// 命令
this.cmd = cmd
// 说明
this.info = info
// 参数
this.params = {}
// 完整命令
this.line = line
}
addParams(name, param){
this.params[name] = param
}
/**
* 将命令描述解释成命令格式
* @param cmdLine
* @param info
*/
static parse(cmdLine, info) {
let pp = cmdLine.trim().split(/\s+/);
let cl = new CmdLine(cmdLine, pp[0], info);
let canFlagOptionalMode = true;
let canParamOptionalMode = true;
for ( let i = 1 ;i < pp.length; i++ ) {
let p = pp[i];
let isOptional = true;
let isFlag = false;
if ( p.startsWith("[") && p.endsWith("]")){
isOptional = true;
}
else if ( p.startsWith("<") && p.endsWith(">")){
isOptional = false;
}
else {
throw "不合法的命令格式 - " + cmdLine;
}
// 去掉两端标记
p = p.substring( 1, p.length -1 );
if( p.startsWith("--") ) {
if ( ! isOptional && ! canFlagOptionalMode ) {
throw "参数解析错误 - 必选参数必须在可选参数前面 - " + cmdLine;
}
if ( isOptional ) {
canFlagOptionalMode = false;
}
p = p.substring(2);
isFlag = true;
}
else if( p.startsWith("-") ) {
if ( ! isOptional && ! canFlagOptionalMode ) {
throw "参数解析错误 - 必选参数必须在可选参数前面 - " + cmdLine;
}
if ( isOptional ) {
canFlagOptionalMode = false;
}
// 无值
p = p.substring(1);
cl.addParams( p, new CliParam( p, isOptional , true) );
continue;
} else {
if ( ! isOptional && ! canParamOptionalMode ) {
throw "参数解析错误 - 必选参数必须在可选参数前面 - " + cmdLine;
}
if ( isOptional ) {
canParamOptionalMode = false;
}
}
cl.addParams( p, new CliParam( p, isOptional , isFlag, true ) );
}
return cl;
}
}