hugo-commandbar/assets/commandbar/js/command.js

112 lines
2.9 KiB
JavaScript

import { NameTerm, NumberTerm } from "./terms.js";
class ParseCommandError extends SyntaxError { }
class Parameter {
name;
value;
constructor(name, value) {
if (!name instanceof NameTerm) {
throw new TypeError("Parameter name must be a NameTerm");
}
this.name = name;
this.value = value;
}
toString() {
return this.value ? `${this.name}=${this.value}` : `${this.name}`;
}
valueOf() {
if (this.value !== undefined) {
return this.value.valueOf();
} else {
return this.name;
}
}
}
export class Command {
static stringRegex = /'[^'"]*'|"[^'"]*"/;
static whitespaceRegex = /\s+/;
static parse(commandString) {
const terms = commandString.split(Command.whitespaceRegex).filter(s => !!s);
if (terms.length < 1) {
return null;
}
let verb;
try {
verb = new NameTerm(terms[0]);
} catch {
throw new ParseCommandError(`Invalid verb: ${verb}`);
}
const parameters = terms.slice(1).map(t => {
const [nameString, valueString, ...rest] = t.split("=");
if (rest.length > 0) {
throw new ParseCommandError(`Invalid parameter: ${t}`);
}
let name;
try {
name = new NameTerm(nameString);
} catch {
throw new ParseCommandError(`Invalid parameter name: ${t}`);
}
let value;
if (valueString) {
for (const termClass of [NameTerm, NumberTerm]) {
try {
value = new termClass(valueString);
break;
} catch {
continue;
}
}
if (!value) {
throw new ParseCommandError(`Invalid parameter value: ${t}`);
}
}
return new Parameter(name, value);
});
return new Command(commandString, verb, parameters);
}
originalString;
verb;
parameters = []
constructor(originalString, verb, parameters) {
if (!verb instanceof String) {
throw new TypeError("Command verb must be a string");
}
this.originalString = originalString;
this.verb = verb;
this.parameters = parameters;
}
parameter(nameOrIndex) {
if (typeof nameOrIndex === "string" || nameOrIndex instanceof String) {
return this.parameters.find(p => p.name == nameOrIndex);
} else if (nameOrIndex instanceof Number) {
return this.parameters[nameOrIndex].valueOf();
}
return null;
}
toString() {
return `Command: {verb: "${this.verb.toString()}", parameters: [${this.parameters.join(", ")}] }`;
}
}