@trioforge/brigadier 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +73 -2
- package/out/arguments.d.ts +91 -0
- package/out/arguments.luau +475 -0
- package/out/command-dispatcher.d.ts +38 -0
- package/out/command-dispatcher.luau +394 -0
- package/out/command.d.ts +13 -0
- package/out/command.luau +8 -0
- package/out/context.d.ts +121 -0
- package/out/context.luau +576 -0
- package/out/exceptions.d.ts +118 -0
- package/out/exceptions.luau +415 -0
- package/out/index.d.ts +10 -0
- package/out/init.luau +44 -0
- package/out/java.d.ts +40 -0
- package/out/java.luau +424 -0
- package/out/literal-message.d.ts +9 -0
- package/out/literal-message.luau +29 -0
- package/out/string-reader.d.ts +41 -0
- package/out/string-reader.luau +271 -0
- package/out/suggestion.d.ts +60 -0
- package/out/suggestion.luau +340 -0
- package/out/tree.d.ts +126 -0
- package/out/tree.luau +579 -0
- package/package.json +33 -5
package/out/tree.d.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import type { ArgumentType } from "./arguments";
|
|
2
|
+
import type { AmbiguityConsumer, Command, Predicate, RedirectModifier, SingleRedirectModifier, SuggestionProvider } from "./command";
|
|
3
|
+
import { type CommandContext, type CommandContextBuilder } from "./context";
|
|
4
|
+
import { StringReader } from "./string-reader";
|
|
5
|
+
import { Suggestions, type SuggestionsBuilder } from "./suggestion";
|
|
6
|
+
export declare abstract class CommandNode<S> {
|
|
7
|
+
private command;
|
|
8
|
+
private readonly requirement;
|
|
9
|
+
private readonly redirect;
|
|
10
|
+
private readonly modifier;
|
|
11
|
+
private readonly forks;
|
|
12
|
+
private readonly children;
|
|
13
|
+
private readonly childList;
|
|
14
|
+
private readonly literals;
|
|
15
|
+
private readonly argumentList;
|
|
16
|
+
protected constructor(command: Command<S> | undefined, requirement: Predicate<S>, redirect: CommandNode<S> | undefined, modifier: RedirectModifier<S> | undefined, forks: boolean);
|
|
17
|
+
getCommand(): Command<S> | undefined;
|
|
18
|
+
getChildren(): readonly CommandNode<S>[];
|
|
19
|
+
getChild(name: string): CommandNode<S> | undefined;
|
|
20
|
+
getRedirect(): CommandNode<S> | undefined;
|
|
21
|
+
getRedirectModifier(): RedirectModifier<S> | undefined;
|
|
22
|
+
canUse(source: S): boolean;
|
|
23
|
+
addChild(node: CommandNode<S>): void;
|
|
24
|
+
findAmbiguities(consumer: AmbiguityConsumer<S>): void;
|
|
25
|
+
abstract isValidInput(input: string): boolean;
|
|
26
|
+
equals(other: unknown): boolean;
|
|
27
|
+
getRequirement(): Predicate<S>;
|
|
28
|
+
abstract getName(): string;
|
|
29
|
+
abstract getUsageText(): string;
|
|
30
|
+
abstract parse(reader: StringReader, contextBuilder: CommandContextBuilder<S>): void;
|
|
31
|
+
abstract listSuggestions(context: CommandContext<S>, builder: SuggestionsBuilder): Promise<Suggestions>;
|
|
32
|
+
abstract createBuilder(): ArgumentBuilder<S>;
|
|
33
|
+
abstract getSortedKey(): string;
|
|
34
|
+
getRelevantNodes(input: StringReader): readonly CommandNode<S>[];
|
|
35
|
+
compareTo(other: CommandNode<S>): number;
|
|
36
|
+
isFork(): boolean;
|
|
37
|
+
abstract getExamples(): readonly string[];
|
|
38
|
+
}
|
|
39
|
+
export declare class RootCommandNode<S> extends CommandNode<S> {
|
|
40
|
+
constructor();
|
|
41
|
+
getName(): string;
|
|
42
|
+
getUsageText(): string;
|
|
43
|
+
parse(): void;
|
|
44
|
+
listSuggestions(): Promise<Suggestions>;
|
|
45
|
+
isValidInput(): boolean;
|
|
46
|
+
equals(other: unknown): boolean;
|
|
47
|
+
createBuilder(): ArgumentBuilder<S>;
|
|
48
|
+
getSortedKey(): string;
|
|
49
|
+
getExamples(): readonly string[];
|
|
50
|
+
toString(): string;
|
|
51
|
+
}
|
|
52
|
+
export declare class LiteralCommandNode<S> extends CommandNode<S> {
|
|
53
|
+
private readonly literal;
|
|
54
|
+
private readonly literalLowerCase;
|
|
55
|
+
constructor(literal: string, command: Command<S> | undefined, requirement: Predicate<S>, redirect: CommandNode<S> | undefined, modifier: RedirectModifier<S> | undefined, forks: boolean);
|
|
56
|
+
getLiteral(): string;
|
|
57
|
+
getName(): string;
|
|
58
|
+
private parseLiteral;
|
|
59
|
+
parse(reader: StringReader, contextBuilder: CommandContextBuilder<S>): void;
|
|
60
|
+
listSuggestions(_context: CommandContext<S>, builder: SuggestionsBuilder): Promise<Suggestions>;
|
|
61
|
+
isValidInput(input: string): boolean;
|
|
62
|
+
equals(other: unknown): boolean;
|
|
63
|
+
getUsageText(): string;
|
|
64
|
+
createBuilder(): LiteralArgumentBuilder<S>;
|
|
65
|
+
getSortedKey(): string;
|
|
66
|
+
getExamples(): readonly string[];
|
|
67
|
+
toString(): string;
|
|
68
|
+
}
|
|
69
|
+
export declare class ArgumentCommandNode<S, T> extends CommandNode<S> {
|
|
70
|
+
private readonly name;
|
|
71
|
+
private readonly argumentType;
|
|
72
|
+
private readonly customSuggestions;
|
|
73
|
+
constructor(name: string, argumentType: ArgumentType<T>, command: Command<S> | undefined, requirement: Predicate<S>, redirect: CommandNode<S> | undefined, modifier: RedirectModifier<S> | undefined, forks: boolean, customSuggestions: SuggestionProvider<S> | undefined);
|
|
74
|
+
getType(): ArgumentType<T>;
|
|
75
|
+
getName(): string;
|
|
76
|
+
getUsageText(): string;
|
|
77
|
+
getCustomSuggestions(): SuggestionProvider<S> | undefined;
|
|
78
|
+
parse(reader: StringReader, contextBuilder: CommandContextBuilder<S>): void;
|
|
79
|
+
listSuggestions(context: CommandContext<S>, builder: SuggestionsBuilder): Promise<Suggestions>;
|
|
80
|
+
createBuilder(): RequiredArgumentBuilder<S, T>;
|
|
81
|
+
isValidInput(input: string): boolean;
|
|
82
|
+
equals(other: unknown): boolean;
|
|
83
|
+
getSortedKey(): string;
|
|
84
|
+
getExamples(): readonly string[];
|
|
85
|
+
toString(): string;
|
|
86
|
+
}
|
|
87
|
+
export declare abstract class ArgumentBuilder<S> {
|
|
88
|
+
private readonly args;
|
|
89
|
+
private command?;
|
|
90
|
+
private requirement;
|
|
91
|
+
private target?;
|
|
92
|
+
private modifier?;
|
|
93
|
+
private forks;
|
|
94
|
+
then(argument: ArgumentBuilder<S> | CommandNode<S>): this;
|
|
95
|
+
getArguments(): readonly CommandNode<S>[];
|
|
96
|
+
executes(command: Command<S> | undefined): this;
|
|
97
|
+
getCommand(): Command<S> | undefined;
|
|
98
|
+
requires(requirement: Predicate<S>): this;
|
|
99
|
+
getRequirement(): Predicate<S>;
|
|
100
|
+
redirect(target: CommandNode<S> | undefined, modifier?: SingleRedirectModifier<S>): this;
|
|
101
|
+
fork(target: CommandNode<S> | undefined, modifier: RedirectModifier<S> | undefined): this;
|
|
102
|
+
forward(target: CommandNode<S> | undefined, modifier: RedirectModifier<S> | undefined, fork: boolean): this;
|
|
103
|
+
getRedirect(): CommandNode<S> | undefined;
|
|
104
|
+
getRedirectModifier(): RedirectModifier<S> | undefined;
|
|
105
|
+
isFork(): boolean;
|
|
106
|
+
abstract build(): CommandNode<S>;
|
|
107
|
+
}
|
|
108
|
+
export declare class LiteralArgumentBuilder<S> extends ArgumentBuilder<S> {
|
|
109
|
+
private readonly literal;
|
|
110
|
+
constructor(literal: string);
|
|
111
|
+
getLiteral(): string;
|
|
112
|
+
build(): LiteralCommandNode<S>;
|
|
113
|
+
}
|
|
114
|
+
export declare function literal<S>(name: string): LiteralArgumentBuilder<S>;
|
|
115
|
+
export declare class RequiredArgumentBuilder<S, T> extends ArgumentBuilder<S> {
|
|
116
|
+
private readonly name;
|
|
117
|
+
private readonly argumentType;
|
|
118
|
+
private suggestionsProvider?;
|
|
119
|
+
constructor(name: string, argumentType: ArgumentType<T>);
|
|
120
|
+
suggests(provider: SuggestionProvider<S> | undefined): this;
|
|
121
|
+
getSuggestionsProvider(): SuggestionProvider<S> | undefined;
|
|
122
|
+
getType(): ArgumentType<T>;
|
|
123
|
+
getName(): string;
|
|
124
|
+
build(): ArgumentCommandNode<S, T>;
|
|
125
|
+
}
|
|
126
|
+
export declare function argument<S, T>(name: string, argumentType: ArgumentType<T>): RequiredArgumentBuilder<S, T>;
|
package/out/tree.luau
ADDED
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _context = TS.import(script, script.Parent, "context")
|
|
4
|
+
local ParsedArgument = _context.ParsedArgument
|
|
5
|
+
local StringRange = _context.StringRange
|
|
6
|
+
local _exceptions = TS.import(script, script.Parent, "exceptions")
|
|
7
|
+
local CommandSyntaxException = _exceptions.CommandSyntaxException
|
|
8
|
+
local catchSyntax = _exceptions.catchSyntax
|
|
9
|
+
local _java = TS.import(script, script.Parent, "java")
|
|
10
|
+
local IllegalStateException = _java.IllegalStateException
|
|
11
|
+
local UnsupportedOperationException = _java.UnsupportedOperationException
|
|
12
|
+
local compareStrings = _java.compareStrings
|
|
13
|
+
local objectsEquals = _java.objectsEquals
|
|
14
|
+
local startsWith = _java.startsWith
|
|
15
|
+
local substring = _java.substring
|
|
16
|
+
local toLowerCase = _java.toLowerCase
|
|
17
|
+
local StringReader = TS.import(script, script.Parent, "string-reader").StringReader
|
|
18
|
+
local Suggestions = TS.import(script, script.Parent, "suggestion").Suggestions
|
|
19
|
+
-- Nodes create builders and builders create nodes, so both live in this module.
|
|
20
|
+
local function always()
|
|
21
|
+
return true
|
|
22
|
+
end
|
|
23
|
+
local RootCommandNode, LiteralCommandNode, ArgumentCommandNode
|
|
24
|
+
local CommandNode
|
|
25
|
+
do
|
|
26
|
+
CommandNode = {}
|
|
27
|
+
function CommandNode:constructor(command, requirement, redirect, modifier, forks)
|
|
28
|
+
self.command = command
|
|
29
|
+
self.requirement = requirement
|
|
30
|
+
self.redirect = redirect
|
|
31
|
+
self.modifier = modifier
|
|
32
|
+
self.forks = forks
|
|
33
|
+
self.children = {}
|
|
34
|
+
self.childList = {}
|
|
35
|
+
self.literals = {}
|
|
36
|
+
self.argumentList = {}
|
|
37
|
+
end
|
|
38
|
+
function CommandNode:getCommand()
|
|
39
|
+
return self.command
|
|
40
|
+
end
|
|
41
|
+
function CommandNode:getChildren()
|
|
42
|
+
return self.childList
|
|
43
|
+
end
|
|
44
|
+
function CommandNode:getChild(name)
|
|
45
|
+
local _children = self.children
|
|
46
|
+
local _name = name
|
|
47
|
+
return _children[_name]
|
|
48
|
+
end
|
|
49
|
+
function CommandNode:getRedirect()
|
|
50
|
+
return self.redirect
|
|
51
|
+
end
|
|
52
|
+
function CommandNode:getRedirectModifier()
|
|
53
|
+
return self.modifier
|
|
54
|
+
end
|
|
55
|
+
function CommandNode:canUse(source)
|
|
56
|
+
return self.requirement(source)
|
|
57
|
+
end
|
|
58
|
+
function CommandNode:addChild(node)
|
|
59
|
+
if TS.instanceof(node, RootCommandNode) then
|
|
60
|
+
error(UnsupportedOperationException.new("Cannot add a RootCommandNode as a child to any other CommandNode"))
|
|
61
|
+
end
|
|
62
|
+
local _children = self.children
|
|
63
|
+
local _arg0 = node:getName()
|
|
64
|
+
local child = _children[_arg0]
|
|
65
|
+
if child ~= nil then
|
|
66
|
+
-- We've found something to merge onto
|
|
67
|
+
local command = node:getCommand()
|
|
68
|
+
if command ~= nil then
|
|
69
|
+
child.command = command
|
|
70
|
+
end
|
|
71
|
+
for _, grandchild in node:getChildren() do
|
|
72
|
+
child:addChild(grandchild)
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
local _children_1 = self.children
|
|
76
|
+
local _arg0_1 = node:getName()
|
|
77
|
+
local _node = node
|
|
78
|
+
_children_1[_arg0_1] = _node
|
|
79
|
+
local _childList = self.childList
|
|
80
|
+
local _node_1 = node
|
|
81
|
+
table.insert(_childList, _node_1)
|
|
82
|
+
if TS.instanceof(node, LiteralCommandNode) then
|
|
83
|
+
local _literals = self.literals
|
|
84
|
+
local _arg0_2 = node:getName()
|
|
85
|
+
local _node_2 = node
|
|
86
|
+
_literals[_arg0_2] = _node_2
|
|
87
|
+
elseif TS.instanceof(node, ArgumentCommandNode) then
|
|
88
|
+
local _argumentList = self.argumentList
|
|
89
|
+
local _node_2 = node
|
|
90
|
+
table.insert(_argumentList, _node_2)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
function CommandNode:findAmbiguities(consumer)
|
|
95
|
+
local matches = {}
|
|
96
|
+
for _, child in self.childList do
|
|
97
|
+
for _1, sibling in self.childList do
|
|
98
|
+
if rawequal(child, sibling) then
|
|
99
|
+
continue
|
|
100
|
+
end
|
|
101
|
+
for _2, input in child:getExamples() do
|
|
102
|
+
if sibling:isValidInput(input) and not (table.find(matches, input) ~= nil) then
|
|
103
|
+
table.insert(matches, input)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
if #matches > 0 then
|
|
107
|
+
consumer(self, child, sibling, matches)
|
|
108
|
+
matches = {}
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
child:findAmbiguities(consumer)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
function CommandNode:equals(other)
|
|
115
|
+
if rawequal(self, other) then
|
|
116
|
+
return true
|
|
117
|
+
end
|
|
118
|
+
if not (TS.instanceof(other, CommandNode)) then
|
|
119
|
+
return false
|
|
120
|
+
end
|
|
121
|
+
local that = other
|
|
122
|
+
for name, node in self.children do
|
|
123
|
+
local match = that.children[name]
|
|
124
|
+
if match == nil or not node:equals(match) then
|
|
125
|
+
return false
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
for name in that.children do
|
|
129
|
+
if not (self.children[name] ~= nil) then
|
|
130
|
+
return false
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
if if self.command ~= nil then not objectsEquals(self.command, that.command) else that.command ~= nil then
|
|
134
|
+
return false
|
|
135
|
+
end
|
|
136
|
+
return true
|
|
137
|
+
end
|
|
138
|
+
function CommandNode:getRequirement()
|
|
139
|
+
return self.requirement
|
|
140
|
+
end
|
|
141
|
+
function CommandNode:getRelevantNodes(input)
|
|
142
|
+
if not (next(self.literals) == nil) then
|
|
143
|
+
local cursor = input:getCursor()
|
|
144
|
+
while input:canRead() and input:peek() ~= " " do
|
|
145
|
+
input:skip()
|
|
146
|
+
end
|
|
147
|
+
local text = substring(input:getString(), cursor, input:getCursor())
|
|
148
|
+
input:setCursor(cursor)
|
|
149
|
+
local literal = self.literals[text]
|
|
150
|
+
if literal ~= nil then
|
|
151
|
+
return { literal }
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
return self.argumentList
|
|
155
|
+
end
|
|
156
|
+
function CommandNode:compareTo(other)
|
|
157
|
+
if TS.instanceof(self, LiteralCommandNode) == TS.instanceof(other, LiteralCommandNode) then
|
|
158
|
+
return compareStrings(self:getSortedKey(), other:getSortedKey())
|
|
159
|
+
end
|
|
160
|
+
return if TS.instanceof(other, LiteralCommandNode) then 1 else -1
|
|
161
|
+
end
|
|
162
|
+
function CommandNode:isFork()
|
|
163
|
+
return self.forks
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
local function sourceOfContext(context)
|
|
167
|
+
return { context:getSource() }
|
|
168
|
+
end
|
|
169
|
+
do
|
|
170
|
+
local super = CommandNode
|
|
171
|
+
RootCommandNode = setmetatable({}, {
|
|
172
|
+
__tostring = function()
|
|
173
|
+
return "RootCommandNode"
|
|
174
|
+
end,
|
|
175
|
+
__index = super,
|
|
176
|
+
})
|
|
177
|
+
RootCommandNode.__index = RootCommandNode
|
|
178
|
+
function RootCommandNode.new(...)
|
|
179
|
+
local self = setmetatable({}, RootCommandNode)
|
|
180
|
+
return self:constructor(...) or self
|
|
181
|
+
end
|
|
182
|
+
function RootCommandNode:constructor()
|
|
183
|
+
super.constructor(self, nil, always, nil, sourceOfContext, false)
|
|
184
|
+
end
|
|
185
|
+
function RootCommandNode:getName()
|
|
186
|
+
return ""
|
|
187
|
+
end
|
|
188
|
+
function RootCommandNode:getUsageText()
|
|
189
|
+
return ""
|
|
190
|
+
end
|
|
191
|
+
function RootCommandNode:parse()
|
|
192
|
+
end
|
|
193
|
+
function RootCommandNode:listSuggestions()
|
|
194
|
+
return Suggestions:empty()
|
|
195
|
+
end
|
|
196
|
+
function RootCommandNode:isValidInput()
|
|
197
|
+
return false
|
|
198
|
+
end
|
|
199
|
+
function RootCommandNode:equals(other)
|
|
200
|
+
if rawequal(self, other) then
|
|
201
|
+
return true
|
|
202
|
+
end
|
|
203
|
+
if not (TS.instanceof(other, RootCommandNode)) then
|
|
204
|
+
return false
|
|
205
|
+
end
|
|
206
|
+
return super.equals(self, other)
|
|
207
|
+
end
|
|
208
|
+
function RootCommandNode:createBuilder()
|
|
209
|
+
error(IllegalStateException.new("Cannot convert root into a builder"))
|
|
210
|
+
end
|
|
211
|
+
function RootCommandNode:getSortedKey()
|
|
212
|
+
return ""
|
|
213
|
+
end
|
|
214
|
+
function RootCommandNode:getExamples()
|
|
215
|
+
return {}
|
|
216
|
+
end
|
|
217
|
+
function RootCommandNode:toString()
|
|
218
|
+
return "<root>"
|
|
219
|
+
end
|
|
220
|
+
function RootCommandNode:__tostring()
|
|
221
|
+
return self:toString()
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
local literal
|
|
225
|
+
do
|
|
226
|
+
local super = CommandNode
|
|
227
|
+
LiteralCommandNode = setmetatable({}, {
|
|
228
|
+
__tostring = function()
|
|
229
|
+
return "LiteralCommandNode"
|
|
230
|
+
end,
|
|
231
|
+
__index = super,
|
|
232
|
+
})
|
|
233
|
+
LiteralCommandNode.__index = LiteralCommandNode
|
|
234
|
+
function LiteralCommandNode.new(...)
|
|
235
|
+
local self = setmetatable({}, LiteralCommandNode)
|
|
236
|
+
return self:constructor(...) or self
|
|
237
|
+
end
|
|
238
|
+
function LiteralCommandNode:constructor(literal, command, requirement, redirect, modifier, forks)
|
|
239
|
+
super.constructor(self, command, requirement, redirect, modifier, forks)
|
|
240
|
+
self.literal = literal
|
|
241
|
+
self.literalLowerCase = toLowerCase(literal)
|
|
242
|
+
end
|
|
243
|
+
function LiteralCommandNode:getLiteral()
|
|
244
|
+
return self.literal
|
|
245
|
+
end
|
|
246
|
+
function LiteralCommandNode:getName()
|
|
247
|
+
return self.literal
|
|
248
|
+
end
|
|
249
|
+
function LiteralCommandNode:parseLiteral(reader)
|
|
250
|
+
local start = reader:getCursor()
|
|
251
|
+
if reader:canRead(#self.literal) then
|
|
252
|
+
local finish = start + #self.literal
|
|
253
|
+
if substring(reader:getString(), start, finish) == self.literal then
|
|
254
|
+
reader:setCursor(finish)
|
|
255
|
+
if not reader:canRead() or reader:peek() == " " then
|
|
256
|
+
return finish
|
|
257
|
+
end
|
|
258
|
+
reader:setCursor(start)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
return -1
|
|
262
|
+
end
|
|
263
|
+
function LiteralCommandNode:parse(reader, contextBuilder)
|
|
264
|
+
local start = reader:getCursor()
|
|
265
|
+
local finish = self:parseLiteral(reader)
|
|
266
|
+
if finish > -1 then
|
|
267
|
+
contextBuilder:withNode(self, StringRange:between(start, finish))
|
|
268
|
+
return nil
|
|
269
|
+
end
|
|
270
|
+
error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:literalIncorrect():createWithContext(reader, self.literal))
|
|
271
|
+
end
|
|
272
|
+
function LiteralCommandNode:listSuggestions(_context, builder)
|
|
273
|
+
if startsWith(self.literalLowerCase, builder:getRemainingLowerCase()) then
|
|
274
|
+
return builder:suggest(self.literal):buildFuture()
|
|
275
|
+
end
|
|
276
|
+
return Suggestions:empty()
|
|
277
|
+
end
|
|
278
|
+
function LiteralCommandNode:isValidInput(input)
|
|
279
|
+
return self:parseLiteral(StringReader.new(input)) > -1
|
|
280
|
+
end
|
|
281
|
+
function LiteralCommandNode:equals(other)
|
|
282
|
+
if rawequal(self, other) then
|
|
283
|
+
return true
|
|
284
|
+
end
|
|
285
|
+
if not (TS.instanceof(other, LiteralCommandNode)) then
|
|
286
|
+
return false
|
|
287
|
+
end
|
|
288
|
+
if self.literal ~= other.literal then
|
|
289
|
+
return false
|
|
290
|
+
end
|
|
291
|
+
return super.equals(self, other)
|
|
292
|
+
end
|
|
293
|
+
function LiteralCommandNode:getUsageText()
|
|
294
|
+
return self.literal
|
|
295
|
+
end
|
|
296
|
+
function LiteralCommandNode:createBuilder()
|
|
297
|
+
local builder = literal(self.literal)
|
|
298
|
+
builder:requires(self:getRequirement())
|
|
299
|
+
builder:forward(self:getRedirect(), self:getRedirectModifier(), self:isFork())
|
|
300
|
+
local command = self:getCommand()
|
|
301
|
+
if command ~= nil then
|
|
302
|
+
builder:executes(command)
|
|
303
|
+
end
|
|
304
|
+
return builder
|
|
305
|
+
end
|
|
306
|
+
function LiteralCommandNode:getSortedKey()
|
|
307
|
+
return self.literal
|
|
308
|
+
end
|
|
309
|
+
function LiteralCommandNode:getExamples()
|
|
310
|
+
return { self.literal }
|
|
311
|
+
end
|
|
312
|
+
function LiteralCommandNode:toString()
|
|
313
|
+
return `<literal {self.literal}>`
|
|
314
|
+
end
|
|
315
|
+
function LiteralCommandNode:__tostring()
|
|
316
|
+
return self:toString()
|
|
317
|
+
end
|
|
318
|
+
end
|
|
319
|
+
local USAGE_ARGUMENT_OPEN = "<"
|
|
320
|
+
local USAGE_ARGUMENT_CLOSE = ">"
|
|
321
|
+
local argument
|
|
322
|
+
do
|
|
323
|
+
local super = CommandNode
|
|
324
|
+
ArgumentCommandNode = setmetatable({}, {
|
|
325
|
+
__tostring = function()
|
|
326
|
+
return "ArgumentCommandNode"
|
|
327
|
+
end,
|
|
328
|
+
__index = super,
|
|
329
|
+
})
|
|
330
|
+
ArgumentCommandNode.__index = ArgumentCommandNode
|
|
331
|
+
function ArgumentCommandNode.new(...)
|
|
332
|
+
local self = setmetatable({}, ArgumentCommandNode)
|
|
333
|
+
return self:constructor(...) or self
|
|
334
|
+
end
|
|
335
|
+
function ArgumentCommandNode:constructor(name, argumentType, command, requirement, redirect, modifier, forks, customSuggestions)
|
|
336
|
+
super.constructor(self, command, requirement, redirect, modifier, forks)
|
|
337
|
+
self.name = name
|
|
338
|
+
self.argumentType = argumentType
|
|
339
|
+
self.customSuggestions = customSuggestions
|
|
340
|
+
end
|
|
341
|
+
function ArgumentCommandNode:getType()
|
|
342
|
+
return self.argumentType
|
|
343
|
+
end
|
|
344
|
+
function ArgumentCommandNode:getName()
|
|
345
|
+
return self.name
|
|
346
|
+
end
|
|
347
|
+
function ArgumentCommandNode:getUsageText()
|
|
348
|
+
return USAGE_ARGUMENT_OPEN .. self.name .. USAGE_ARGUMENT_CLOSE
|
|
349
|
+
end
|
|
350
|
+
function ArgumentCommandNode:getCustomSuggestions()
|
|
351
|
+
return self.customSuggestions
|
|
352
|
+
end
|
|
353
|
+
function ArgumentCommandNode:parse(reader, contextBuilder)
|
|
354
|
+
local start = reader:getCursor()
|
|
355
|
+
local result = self.argumentType:parse(reader, contextBuilder:getSource())
|
|
356
|
+
local parsed = ParsedArgument.new(start, reader:getCursor(), result)
|
|
357
|
+
contextBuilder:withArgument(self.name, parsed)
|
|
358
|
+
contextBuilder:withNode(self, parsed:getRange())
|
|
359
|
+
end
|
|
360
|
+
function ArgumentCommandNode:listSuggestions(context, builder)
|
|
361
|
+
if self.customSuggestions == nil then
|
|
362
|
+
local _self = self.argumentType
|
|
363
|
+
local _result = _self.listSuggestions
|
|
364
|
+
if _result ~= nil then
|
|
365
|
+
_result = _result(_self, context, builder)
|
|
366
|
+
end
|
|
367
|
+
local _condition = _result
|
|
368
|
+
if _condition == nil then
|
|
369
|
+
_condition = Suggestions:empty()
|
|
370
|
+
end
|
|
371
|
+
return _condition
|
|
372
|
+
end
|
|
373
|
+
return self.customSuggestions(context, builder)
|
|
374
|
+
end
|
|
375
|
+
function ArgumentCommandNode:createBuilder()
|
|
376
|
+
local builder = argument(self.name, self.argumentType)
|
|
377
|
+
builder:requires(self:getRequirement())
|
|
378
|
+
builder:forward(self:getRedirect(), self:getRedirectModifier(), self:isFork())
|
|
379
|
+
builder:suggests(self.customSuggestions)
|
|
380
|
+
local command = self:getCommand()
|
|
381
|
+
if command ~= nil then
|
|
382
|
+
builder:executes(command)
|
|
383
|
+
end
|
|
384
|
+
return builder
|
|
385
|
+
end
|
|
386
|
+
function ArgumentCommandNode:isValidInput(input)
|
|
387
|
+
return catchSyntax(function()
|
|
388
|
+
local reader = StringReader.new(input)
|
|
389
|
+
self.argumentType:parse(reader)
|
|
390
|
+
return not reader:canRead() or reader:peek() == " "
|
|
391
|
+
end, function()
|
|
392
|
+
return false
|
|
393
|
+
end)
|
|
394
|
+
end
|
|
395
|
+
function ArgumentCommandNode:equals(other)
|
|
396
|
+
if rawequal(self, other) then
|
|
397
|
+
return true
|
|
398
|
+
end
|
|
399
|
+
if not (TS.instanceof(other, ArgumentCommandNode)) then
|
|
400
|
+
return false
|
|
401
|
+
end
|
|
402
|
+
if self.name ~= other.name then
|
|
403
|
+
return false
|
|
404
|
+
end
|
|
405
|
+
if not objectsEquals(self.argumentType, other.argumentType) then
|
|
406
|
+
return false
|
|
407
|
+
end
|
|
408
|
+
return super.equals(self, other)
|
|
409
|
+
end
|
|
410
|
+
function ArgumentCommandNode:getSortedKey()
|
|
411
|
+
return self.name
|
|
412
|
+
end
|
|
413
|
+
function ArgumentCommandNode:getExamples()
|
|
414
|
+
local _self = self.argumentType
|
|
415
|
+
local _result = _self.getExamples
|
|
416
|
+
if _result ~= nil then
|
|
417
|
+
_result = _result(_self)
|
|
418
|
+
end
|
|
419
|
+
local _condition = _result
|
|
420
|
+
if _condition == nil then
|
|
421
|
+
_condition = {}
|
|
422
|
+
end
|
|
423
|
+
return _condition
|
|
424
|
+
end
|
|
425
|
+
function ArgumentCommandNode:toString()
|
|
426
|
+
return `<argument {self.name}:{self.argumentType}>`
|
|
427
|
+
end
|
|
428
|
+
function ArgumentCommandNode:__tostring()
|
|
429
|
+
return self:toString()
|
|
430
|
+
end
|
|
431
|
+
end
|
|
432
|
+
local ArgumentBuilder
|
|
433
|
+
do
|
|
434
|
+
ArgumentBuilder = {}
|
|
435
|
+
function ArgumentBuilder:constructor()
|
|
436
|
+
self.args = RootCommandNode.new()
|
|
437
|
+
self.requirement = always
|
|
438
|
+
self.forks = false
|
|
439
|
+
end
|
|
440
|
+
ArgumentBuilder["then"] = function(self, argument)
|
|
441
|
+
if self.target ~= nil then
|
|
442
|
+
error(IllegalStateException.new("Cannot add children to a redirected node"))
|
|
443
|
+
end
|
|
444
|
+
self.args:addChild(if TS.instanceof(argument, CommandNode) then argument else argument:build())
|
|
445
|
+
return self
|
|
446
|
+
end
|
|
447
|
+
function ArgumentBuilder:getArguments()
|
|
448
|
+
return self.args:getChildren()
|
|
449
|
+
end
|
|
450
|
+
function ArgumentBuilder:executes(command)
|
|
451
|
+
self.command = command
|
|
452
|
+
return self
|
|
453
|
+
end
|
|
454
|
+
function ArgumentBuilder:getCommand()
|
|
455
|
+
return self.command
|
|
456
|
+
end
|
|
457
|
+
function ArgumentBuilder:requires(requirement)
|
|
458
|
+
self.requirement = requirement
|
|
459
|
+
return self
|
|
460
|
+
end
|
|
461
|
+
function ArgumentBuilder:getRequirement()
|
|
462
|
+
return self.requirement
|
|
463
|
+
end
|
|
464
|
+
function ArgumentBuilder:redirect(target, modifier)
|
|
465
|
+
if modifier == nil then
|
|
466
|
+
return self:forward(target, nil, false)
|
|
467
|
+
end
|
|
468
|
+
return self:forward(target, function(context)
|
|
469
|
+
return { modifier(context) }
|
|
470
|
+
end, false)
|
|
471
|
+
end
|
|
472
|
+
function ArgumentBuilder:fork(target, modifier)
|
|
473
|
+
return self:forward(target, modifier, true)
|
|
474
|
+
end
|
|
475
|
+
function ArgumentBuilder:forward(target, modifier, fork)
|
|
476
|
+
if #self.args:getChildren() > 0 then
|
|
477
|
+
error(IllegalStateException.new("Cannot forward a node with children"))
|
|
478
|
+
end
|
|
479
|
+
self.target = target
|
|
480
|
+
self.modifier = modifier
|
|
481
|
+
self.forks = fork
|
|
482
|
+
return self
|
|
483
|
+
end
|
|
484
|
+
function ArgumentBuilder:getRedirect()
|
|
485
|
+
return self.target
|
|
486
|
+
end
|
|
487
|
+
function ArgumentBuilder:getRedirectModifier()
|
|
488
|
+
return self.modifier
|
|
489
|
+
end
|
|
490
|
+
function ArgumentBuilder:isFork()
|
|
491
|
+
return self.forks
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
local LiteralArgumentBuilder
|
|
495
|
+
do
|
|
496
|
+
local super = ArgumentBuilder
|
|
497
|
+
LiteralArgumentBuilder = setmetatable({}, {
|
|
498
|
+
__tostring = function()
|
|
499
|
+
return "LiteralArgumentBuilder"
|
|
500
|
+
end,
|
|
501
|
+
__index = super,
|
|
502
|
+
})
|
|
503
|
+
LiteralArgumentBuilder.__index = LiteralArgumentBuilder
|
|
504
|
+
function LiteralArgumentBuilder.new(...)
|
|
505
|
+
local self = setmetatable({}, LiteralArgumentBuilder)
|
|
506
|
+
return self:constructor(...) or self
|
|
507
|
+
end
|
|
508
|
+
function LiteralArgumentBuilder:constructor(literal)
|
|
509
|
+
super.constructor(self)
|
|
510
|
+
self.literal = literal
|
|
511
|
+
end
|
|
512
|
+
function LiteralArgumentBuilder:getLiteral()
|
|
513
|
+
return self.literal
|
|
514
|
+
end
|
|
515
|
+
function LiteralArgumentBuilder:build()
|
|
516
|
+
local result = LiteralCommandNode.new(self.literal, self:getCommand(), self:getRequirement(), self:getRedirect(), self:getRedirectModifier(), self:isFork())
|
|
517
|
+
for _, child in self:getArguments() do
|
|
518
|
+
result:addChild(child)
|
|
519
|
+
end
|
|
520
|
+
return result
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
function literal(name)
|
|
524
|
+
return LiteralArgumentBuilder.new(name)
|
|
525
|
+
end
|
|
526
|
+
local RequiredArgumentBuilder
|
|
527
|
+
do
|
|
528
|
+
local super = ArgumentBuilder
|
|
529
|
+
RequiredArgumentBuilder = setmetatable({}, {
|
|
530
|
+
__tostring = function()
|
|
531
|
+
return "RequiredArgumentBuilder"
|
|
532
|
+
end,
|
|
533
|
+
__index = super,
|
|
534
|
+
})
|
|
535
|
+
RequiredArgumentBuilder.__index = RequiredArgumentBuilder
|
|
536
|
+
function RequiredArgumentBuilder.new(...)
|
|
537
|
+
local self = setmetatable({}, RequiredArgumentBuilder)
|
|
538
|
+
return self:constructor(...) or self
|
|
539
|
+
end
|
|
540
|
+
function RequiredArgumentBuilder:constructor(name, argumentType)
|
|
541
|
+
super.constructor(self)
|
|
542
|
+
self.name = name
|
|
543
|
+
self.argumentType = argumentType
|
|
544
|
+
end
|
|
545
|
+
function RequiredArgumentBuilder:suggests(provider)
|
|
546
|
+
self.suggestionsProvider = provider
|
|
547
|
+
return self
|
|
548
|
+
end
|
|
549
|
+
function RequiredArgumentBuilder:getSuggestionsProvider()
|
|
550
|
+
return self.suggestionsProvider
|
|
551
|
+
end
|
|
552
|
+
function RequiredArgumentBuilder:getType()
|
|
553
|
+
return self.argumentType
|
|
554
|
+
end
|
|
555
|
+
function RequiredArgumentBuilder:getName()
|
|
556
|
+
return self.name
|
|
557
|
+
end
|
|
558
|
+
function RequiredArgumentBuilder:build()
|
|
559
|
+
local result = ArgumentCommandNode.new(self.name, self.argumentType, self:getCommand(), self:getRequirement(), self:getRedirect(), self:getRedirectModifier(), self:isFork(), self:getSuggestionsProvider())
|
|
560
|
+
for _, child in self:getArguments() do
|
|
561
|
+
result:addChild(child)
|
|
562
|
+
end
|
|
563
|
+
return result
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
function argument(name, argumentType)
|
|
567
|
+
return RequiredArgumentBuilder.new(name, argumentType)
|
|
568
|
+
end
|
|
569
|
+
return {
|
|
570
|
+
literal = literal,
|
|
571
|
+
argument = argument,
|
|
572
|
+
CommandNode = CommandNode,
|
|
573
|
+
RootCommandNode = RootCommandNode,
|
|
574
|
+
LiteralCommandNode = LiteralCommandNode,
|
|
575
|
+
ArgumentCommandNode = ArgumentCommandNode,
|
|
576
|
+
ArgumentBuilder = ArgumentBuilder,
|
|
577
|
+
LiteralArgumentBuilder = LiteralArgumentBuilder,
|
|
578
|
+
RequiredArgumentBuilder = RequiredArgumentBuilder,
|
|
579
|
+
}
|