Implement builder classes

This commit is contained in:
Chipmunk 2023-08-31 23:07:38 -04:00
parent b1cb6a2e29
commit 1284de16b3
6 changed files with 128 additions and 4 deletions

View file

@ -0,0 +1,46 @@
const { RootCommandNode } = require('../tree')
class ArgumentBuilder {
arguments = new RootCommandNode()
requirement = s => true
modifier = null
then (argument) {
if (argument instanceof ArgumentBuilder) argument = argument.build()
if (this.target != null) throw new Error('Cannot add children to a redirected node')
this.arguments.addChild(argument)
return this
}
getArguments () { return this.arguments.getChildren() }
executes (command) {
this.command = command
return this
}
requires (requirement) {
this.requirement = requirement
return this
}
redirect (target, modifier = null, fork = false) {
if (this.arguments.getChildren().length !== 0) throw new Error('Cannot forward a node with children')
let _modifier = null
if (modifier != null) {
_modifier = s => {
const result = modifier(s)
return Array.isArray(result) ? result : [result]
}
}
this.target = target
this.modifier = _modifier
this.forks = fork
return this
}
}
module.exports = ArgumentBuilder

View file

@ -0,0 +1,32 @@
const ArgumentBuilder = require('./ArgumentBuilder.js')
const { LiteralCommandNode } = require('../tree')
class LiteralArgumentBuilder extends ArgumentBuilder {
constructor (literal) {
super()
this.literal = literal
}
static literal (name) {
return new LiteralArgumentBuilder(name)
}
build () {
const result = new LiteralCommandNode({
literal: this.literal,
command: this.command,
requirement: this.requirement,
redirect: this.target,
modifier: this.modifier,
forks: this.forks
})
for (const argument of this.getArguments()) {
result.addChild(argument)
}
return result
}
}
module.exports = LiteralArgumentBuilder

View file

@ -0,0 +1,36 @@
const ArgumentBuilder = require('./ArgumentBuilder.js')
const { ArgumentCommandNode } = require('../tree')
class RequiredArgumentBuilder extends ArgumentBuilder {
suggestionsProvider = null
constructor (name, type) {
super()
this.name = name
this.type = type
}
static argument (name, type) {
return new RequiredArgumentBuilder(name)
}
build () {
const result = new ArgumentCommandNode({
literal: this.literal,
command: this.command,
requirement: this.requirement,
redirect: this.target,
modifier: this.modifier,
forks: this.forks,
customSuggestions: this.suggestionsProvider
})
for (const argument of this.getArguments()) {
result.addChild(argument)
}
return result
}
}
module.exports = RequiredArgumentBuilder

9
lib/builder/index.js Normal file
View file

@ -0,0 +1,9 @@
const ArgumentBuilder = require('./ArgumentBuilder.js')
const LiteralArgumentBuilder = require('./LiteralArgumentBuilder.js')
const RequiredArgumentBuilder = require('./RequiredArgumentBuilder.js')
module.exports = {
ArgumentBuilder,
LiteralArgumentBuilder,
RequiredArgumentBuilder
}

View file

@ -3,11 +3,13 @@ const StringReader = require('./StringReader.js')
const context = require('./context')
const suggestion = require('./suggestion')
const tree = require('./tree')
const builder = require('./builder')
const CommandDispatcher = require('./CommandDispatcher.js')
const LiteralMessage = require('./LiteralMessage.js')
const ParseResults = require('./ParseResults.js')
module.exports = {
builder,
context,
exceptions,
suggestion,

View file

@ -22,7 +22,7 @@ class CommandNode {
const child = this.children[node.name]
if (child !== undefined) {
if (child != null) {
// We've found something to merge onto
if (node.command !== undefined) child.command = this.command
for (const grandchild of node.getChildren()) child.addChild(grandchild)
@ -47,7 +47,7 @@ class CommandNode {
}
if (matches.size > 0) {
consumer.ambiguous(this, child, sibling, matches)
consumer(this, child, sibling, matches)
matches = new Set()
}
}
@ -82,8 +82,7 @@ class CommandNode {
const text = input.string.substring(cursor, input.cursor)
input.cursor = cursor
const literal = this.literals[text]
if (literal !== undefined) return [literal]
return Object.values(this.arguments)
if (literal != null) return [literal]
}
return Object.values(this.arguments)