@trioforge/brigadier 0.0.0-stage → 0.1.0

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.
@@ -0,0 +1,271 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local CommandSyntaxException = TS.import(script, script.Parent, "exceptions").CommandSyntaxException
4
+ local _java = TS.import(script, script.Parent, "java")
5
+ local charAt = _java.charAt
6
+ local substring = _java.substring
7
+ local toFloat = _java.toFloat
8
+ local SYNTAX_ESCAPE = "\\"
9
+ local SYNTAX_DOUBLE_QUOTE = '"'
10
+ local SYNTAX_SINGLE_QUOTE = "'"
11
+ local INT_MIN = -2147483648
12
+ local INT_MAX = 2147483647
13
+ -- Character.isWhitespace for the one-byte characters it accepts.
14
+ local function isWhitespace(c)
15
+ local code = string.byte(c)
16
+ return code ~= nil and ((code >= 9 and code <= 13) or (code >= 28 and code <= 32))
17
+ end
18
+ -- Integer.parseInt and Long.parseLong: an optional sign, then decimal digits that fit the type.
19
+ local function parseWholeNumber(text, minDigits, maxDigits)
20
+ local sign, digits = string.match(text, "^([+-]?)(%d+)$")
21
+ if not (type(digits) == "string") then
22
+ return nil
23
+ end
24
+ local significant = (string.match(digits, "^0*(%d-)$"))
25
+ local limit = if sign == "-" then minDigits else maxDigits
26
+ if #significant > #limit or (#significant == #limit and significant > limit) then
27
+ return nil
28
+ end
29
+ -- Adding zero turns "-0" into 0, which is what an int holds.
30
+ return tonumber(text) + 0
31
+ end
32
+ local function parseInt(text)
33
+ local value = parseWholeNumber(text, "2147483648", "2147483647")
34
+ if value == nil or value < INT_MIN or value > INT_MAX then
35
+ return nil
36
+ end
37
+ return value
38
+ end
39
+ local function parseLong(text)
40
+ return parseWholeNumber(text, "9223372036854775808", "9223372036854775807")
41
+ end
42
+ -- Double.parseDouble for what isAllowedNumber lets through: an optional minus, then digits with at most one point.
43
+ local function parseDouble(text)
44
+ local body = string.match(text, "^%-?([%d%.]+)$")
45
+ if not (type(body) == "string") or (string.find(body, "%d")) == nil then
46
+ return nil
47
+ end
48
+ local _, points = string.gsub(body, "%.", "")
49
+ if points > 1 then
50
+ return nil
51
+ end
52
+ return tonumber(text)
53
+ end
54
+ -- Float.parseFloat rounds the decimal straight to a float. Rounding through a double first differs only for
55
+ -- decimals within half a double ulp of the midpoint between two floats.
56
+ local function parseFloat(text)
57
+ local value = parseDouble(text)
58
+ return if value == nil then nil else toFloat(value)
59
+ end
60
+ local StringReader
61
+ do
62
+ StringReader = setmetatable({}, {
63
+ __tostring = function()
64
+ return "StringReader"
65
+ end,
66
+ })
67
+ StringReader.__index = StringReader
68
+ function StringReader.new(...)
69
+ local self = setmetatable({}, StringReader)
70
+ return self:constructor(...) or self
71
+ end
72
+ function StringReader:constructor(other)
73
+ local _other = other
74
+ if type(_other) == "string" then
75
+ self.text = other
76
+ self.cursor = 0
77
+ else
78
+ self.text = other.text
79
+ self.cursor = other.cursor
80
+ end
81
+ end
82
+ function StringReader:isAllowedNumber(c)
83
+ return (c >= "0" and c <= "9") or c == "." or c == "-"
84
+ end
85
+ function StringReader:isQuotedStringStart(c)
86
+ return c == SYNTAX_DOUBLE_QUOTE or c == SYNTAX_SINGLE_QUOTE
87
+ end
88
+ function StringReader:isAllowedInUnquotedString(c)
89
+ return (c >= "0" and c <= "9") or (c >= "A" and c <= "Z") or (c >= "a" and c <= "z") or c == "_" or c == "-" or c == "." or c == "+"
90
+ end
91
+ function StringReader:getString()
92
+ return self.text
93
+ end
94
+ function StringReader:setCursor(cursor)
95
+ self.cursor = cursor
96
+ end
97
+ function StringReader:getRemainingLength()
98
+ return #self.text - self.cursor
99
+ end
100
+ function StringReader:getTotalLength()
101
+ return #self.text
102
+ end
103
+ function StringReader:getCursor()
104
+ return self.cursor
105
+ end
106
+ function StringReader:getRead()
107
+ return substring(self.text, 0, self.cursor)
108
+ end
109
+ function StringReader:getRemaining()
110
+ return substring(self.text, self.cursor)
111
+ end
112
+ function StringReader:canRead(length)
113
+ if length == nil then
114
+ length = 1
115
+ end
116
+ return self.cursor + length <= #self.text
117
+ end
118
+ function StringReader:peek(offset)
119
+ if offset == nil then
120
+ offset = 0
121
+ end
122
+ return charAt(self.text, self.cursor + offset)
123
+ end
124
+ function StringReader:read()
125
+ local c = charAt(self.text, self.cursor)
126
+ self.cursor += 1
127
+ return c
128
+ end
129
+ function StringReader:skip()
130
+ self.cursor += 1
131
+ end
132
+ function StringReader:skipWhitespace()
133
+ while self:canRead() and isWhitespace(self:peek()) do
134
+ self:skip()
135
+ end
136
+ end
137
+ function StringReader:readNumber()
138
+ local start = self.cursor
139
+ while self:canRead() and StringReader:isAllowedNumber(self:peek()) do
140
+ self:skip()
141
+ end
142
+ return substring(self.text, start, self.cursor)
143
+ end
144
+ function StringReader:readInt()
145
+ local start = self.cursor
146
+ local text = self:readNumber()
147
+ if text == "" then
148
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedInt():createWithContext(self))
149
+ end
150
+ local value = parseInt(text)
151
+ if value == nil then
152
+ self.cursor = start
153
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerInvalidInt():createWithContext(self, text))
154
+ end
155
+ return value
156
+ end
157
+ function StringReader:readLong()
158
+ local start = self.cursor
159
+ local text = self:readNumber()
160
+ if text == "" then
161
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedLong():createWithContext(self))
162
+ end
163
+ local value = parseLong(text)
164
+ if value == nil then
165
+ self.cursor = start
166
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerInvalidLong():createWithContext(self, text))
167
+ end
168
+ return value
169
+ end
170
+ function StringReader:readDouble()
171
+ local start = self.cursor
172
+ local text = self:readNumber()
173
+ if text == "" then
174
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedDouble():createWithContext(self))
175
+ end
176
+ local value = parseDouble(text)
177
+ if value == nil then
178
+ self.cursor = start
179
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerInvalidDouble():createWithContext(self, text))
180
+ end
181
+ return value
182
+ end
183
+ function StringReader:readFloat()
184
+ local start = self.cursor
185
+ local text = self:readNumber()
186
+ if text == "" then
187
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedFloat():createWithContext(self))
188
+ end
189
+ local value = parseFloat(text)
190
+ if value == nil then
191
+ self.cursor = start
192
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerInvalidFloat():createWithContext(self, text))
193
+ end
194
+ return value
195
+ end
196
+ function StringReader:readUnquotedString()
197
+ local start = self.cursor
198
+ while self:canRead() and StringReader:isAllowedInUnquotedString(self:peek()) do
199
+ self:skip()
200
+ end
201
+ return substring(self.text, start, self.cursor)
202
+ end
203
+ function StringReader:readQuotedString()
204
+ if not self:canRead() then
205
+ return ""
206
+ end
207
+ local nextChar = self:peek()
208
+ if not StringReader:isQuotedStringStart(nextChar) then
209
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedStartOfQuote():createWithContext(self))
210
+ end
211
+ self:skip()
212
+ return self:readStringUntil(nextChar)
213
+ end
214
+ function StringReader:readStringUntil(terminator)
215
+ local result = {}
216
+ local escaped = false
217
+ while self:canRead() do
218
+ local c = self:read()
219
+ if escaped then
220
+ if c == terminator or c == SYNTAX_ESCAPE then
221
+ table.insert(result, c)
222
+ escaped = false
223
+ else
224
+ self:setCursor(self:getCursor() - 1)
225
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerInvalidEscape():createWithContext(self, c))
226
+ end
227
+ elseif c == SYNTAX_ESCAPE then
228
+ escaped = true
229
+ elseif c == terminator then
230
+ return table.concat(result, "")
231
+ else
232
+ table.insert(result, c)
233
+ end
234
+ end
235
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedEndOfQuote():createWithContext(self))
236
+ end
237
+ function StringReader:readString()
238
+ if not self:canRead() then
239
+ return ""
240
+ end
241
+ local nextChar = self:peek()
242
+ if StringReader:isQuotedStringStart(nextChar) then
243
+ self:skip()
244
+ return self:readStringUntil(nextChar)
245
+ end
246
+ return self:readUnquotedString()
247
+ end
248
+ function StringReader:readBoolean()
249
+ local start = self.cursor
250
+ local value = self:readString()
251
+ if value == "" then
252
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedBool():createWithContext(self))
253
+ end
254
+ if value == "true" then
255
+ return true
256
+ elseif value == "false" then
257
+ return false
258
+ end
259
+ self.cursor = start
260
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerInvalidBool():createWithContext(self, value))
261
+ end
262
+ function StringReader:expect(c)
263
+ if not self:canRead() or self:peek() ~= c then
264
+ error(CommandSyntaxException.BUILT_IN_EXCEPTIONS:readerExpectedSymbol():createWithContext(self, c))
265
+ end
266
+ self:skip()
267
+ end
268
+ end
269
+ return {
270
+ StringReader = StringReader,
271
+ }
@@ -0,0 +1,60 @@
1
+ import { StringRange } from "./context";
2
+ import type { Message } from "./literal-message";
3
+ export declare class Suggestion {
4
+ protected readonly range: StringRange;
5
+ protected readonly text: string;
6
+ protected readonly tooltip?: Message | undefined;
7
+ constructor(range: StringRange, text: string, tooltip?: Message | undefined);
8
+ getRange(): StringRange;
9
+ getText(): string;
10
+ getTooltip(): Message | undefined;
11
+ apply(input: string): string;
12
+ equals(other: unknown): boolean;
13
+ toString(): string;
14
+ compareTo(other: Suggestion): number;
15
+ compareToIgnoreCase(other: Suggestion): number;
16
+ expand(command: string, range: StringRange): Suggestion;
17
+ }
18
+ export declare class IntegerSuggestion extends Suggestion {
19
+ private readonly value;
20
+ constructor(range: StringRange, value: number, tooltip?: Message);
21
+ getValue(): number;
22
+ equals(other: unknown): boolean;
23
+ toString(): string;
24
+ compareTo(other: Suggestion): number;
25
+ compareToIgnoreCase(other: Suggestion): number;
26
+ }
27
+ export declare class Suggestions {
28
+ private readonly range;
29
+ private readonly suggestions;
30
+ private static readonly EMPTY;
31
+ constructor(range: StringRange, suggestions: readonly Suggestion[]);
32
+ static empty(): Promise<Suggestions>;
33
+ static merge(command: string, input: readonly Suggestions[]): Suggestions;
34
+ static create(command: string, suggestions: readonly Suggestion[]): Suggestions;
35
+ getRange(): StringRange;
36
+ getList(): readonly Suggestion[];
37
+ isEmpty(): boolean;
38
+ equals(other: unknown): boolean;
39
+ toString(): string;
40
+ }
41
+ export declare class SuggestionsBuilder {
42
+ private readonly input;
43
+ private readonly inputLowerCase;
44
+ private readonly start;
45
+ private readonly remaining;
46
+ private readonly remainingLowerCase;
47
+ private readonly result;
48
+ constructor(input: string, start: number);
49
+ constructor(input: string, inputLowerCase: string, start: number);
50
+ getInput(): string;
51
+ getStart(): number;
52
+ getRemaining(): string;
53
+ getRemainingLowerCase(): string;
54
+ build(): Suggestions;
55
+ buildFuture(): Promise<Suggestions>;
56
+ suggest(textOrValue: string | number, tooltip?: Message): this;
57
+ add(other: SuggestionsBuilder): this;
58
+ createOffset(start: number): SuggestionsBuilder;
59
+ restart(): SuggestionsBuilder;
60
+ }
@@ -0,0 +1,340 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local StringRange = TS.import(script, script.Parent, "context").StringRange
4
+ local _java = TS.import(script, script.Parent, "java")
5
+ local compareStrings = _java.compareStrings
6
+ local formatInteger = _java.formatInteger
7
+ local objectsEquals = _java.objectsEquals
8
+ local stableSort = _java.stableSort
9
+ local substring = _java.substring
10
+ local toLowerCase = _java.toLowerCase
11
+ local function describeTooltip(tooltip)
12
+ return if tooltip == nil then "null" else tostring(tooltip)
13
+ end
14
+ local Suggestion
15
+ do
16
+ Suggestion = setmetatable({}, {
17
+ __tostring = function()
18
+ return "Suggestion"
19
+ end,
20
+ })
21
+ Suggestion.__index = Suggestion
22
+ function Suggestion.new(...)
23
+ local self = setmetatable({}, Suggestion)
24
+ return self:constructor(...) or self
25
+ end
26
+ function Suggestion:constructor(range, text, tooltip)
27
+ self.range = range
28
+ self.text = text
29
+ self.tooltip = tooltip
30
+ end
31
+ function Suggestion:getRange()
32
+ return self.range
33
+ end
34
+ function Suggestion:getText()
35
+ return self.text
36
+ end
37
+ function Suggestion:getTooltip()
38
+ return self.tooltip
39
+ end
40
+ function Suggestion:apply(input)
41
+ if self.range:getStart() == 0 and self.range:getEnd() == #input then
42
+ return self.text
43
+ end
44
+ local result = ""
45
+ if self.range:getStart() > 0 then
46
+ result ..= substring(input, 0, self.range:getStart())
47
+ end
48
+ result ..= self.text
49
+ if self.range:getEnd() < #input then
50
+ result ..= substring(input, self.range:getEnd())
51
+ end
52
+ return result
53
+ end
54
+ function Suggestion:equals(other)
55
+ if rawequal(self, other) then
56
+ return true
57
+ end
58
+ if not (TS.instanceof(other, Suggestion)) then
59
+ return false
60
+ end
61
+ return objectsEquals(self.range, other.range) and objectsEquals(self.text, other.text) and objectsEquals(self.tooltip, other.tooltip)
62
+ end
63
+ function Suggestion:toString()
64
+ return `Suggestion\{range={self.range}, text='{self.text}', tooltip='{describeTooltip(self.tooltip)}'\}`
65
+ end
66
+ function Suggestion:compareTo(other)
67
+ return compareStrings(self.text, other:getText())
68
+ end
69
+ function Suggestion:compareToIgnoreCase(other)
70
+ return compareStrings(string.lower(self.text), string.lower(other:getText()))
71
+ end
72
+ function Suggestion:expand(command, range)
73
+ if range:equals(self.range) then
74
+ return self
75
+ end
76
+ local result = ""
77
+ if range:getStart() < self.range:getStart() then
78
+ result ..= substring(command, range:getStart(), self.range:getStart())
79
+ end
80
+ result ..= self.text
81
+ if range:getEnd() > self.range:getEnd() then
82
+ result ..= substring(command, self.range:getEnd(), range:getEnd())
83
+ end
84
+ return Suggestion.new(range, result, self.tooltip)
85
+ end
86
+ function Suggestion:__tostring()
87
+ return self:toString()
88
+ end
89
+ end
90
+ local IntegerSuggestion
91
+ do
92
+ local super = Suggestion
93
+ IntegerSuggestion = setmetatable({}, {
94
+ __tostring = function()
95
+ return "IntegerSuggestion"
96
+ end,
97
+ __index = super,
98
+ })
99
+ IntegerSuggestion.__index = IntegerSuggestion
100
+ function IntegerSuggestion.new(...)
101
+ local self = setmetatable({}, IntegerSuggestion)
102
+ return self:constructor(...) or self
103
+ end
104
+ function IntegerSuggestion:constructor(range, value, tooltip)
105
+ super.constructor(self, range, formatInteger(value), tooltip)
106
+ self.value = value
107
+ end
108
+ function IntegerSuggestion:getValue()
109
+ return self.value
110
+ end
111
+ function IntegerSuggestion:equals(other)
112
+ if rawequal(self, other) then
113
+ return true
114
+ end
115
+ if not (TS.instanceof(other, IntegerSuggestion)) then
116
+ return false
117
+ end
118
+ return self.value == other.value and super.equals(self, other)
119
+ end
120
+ function IntegerSuggestion:toString()
121
+ return `IntegerSuggestion\{value={formatInteger(self.value)}, range={self.range}, text='{self.text}', tooltip='{describeTooltip(self.tooltip)}'\}`
122
+ end
123
+ function IntegerSuggestion:compareTo(other)
124
+ if TS.instanceof(other, IntegerSuggestion) then
125
+ return if self.value < other.value then -1 elseif self.value == other.value then 0 else 1
126
+ end
127
+ return super.compareTo(self, other)
128
+ end
129
+ function IntegerSuggestion:compareToIgnoreCase(other)
130
+ return self:compareTo(other)
131
+ end
132
+ function IntegerSuggestion:__tostring()
133
+ return self:toString()
134
+ end
135
+ end
136
+ -- A HashSet<Suggestion> keeps the first of each group of equal suggestions. Equal suggestions share their range,
137
+ -- text and class, so those key the buckets that `equals` searches.
138
+ local function addToSet(set, buckets, suggestion)
139
+ local clazz = getmetatable(suggestion)
140
+ local byKey = buckets[clazz]
141
+ if byKey == nil then
142
+ byKey = {}
143
+ local _buckets = buckets
144
+ local _byKey = byKey
145
+ _buckets[clazz] = _byKey
146
+ end
147
+ local range = suggestion:getRange()
148
+ local key = `{range:getStart()}:{range:getEnd()}:{suggestion:getText()}`
149
+ local bucket = byKey[key]
150
+ if bucket == nil then
151
+ bucket = {}
152
+ local _byKey = byKey
153
+ local _bucket = bucket
154
+ _byKey[key] = _bucket
155
+ end
156
+ for _, existing in bucket do
157
+ if existing:equals(suggestion) then
158
+ return nil
159
+ end
160
+ end
161
+ local _bucket = bucket
162
+ local _suggestion = suggestion
163
+ table.insert(_bucket, _suggestion)
164
+ local _set = set
165
+ local _suggestion_1 = suggestion
166
+ table.insert(_set, _suggestion_1)
167
+ end
168
+ local Suggestions
169
+ do
170
+ Suggestions = setmetatable({}, {
171
+ __tostring = function()
172
+ return "Suggestions"
173
+ end,
174
+ })
175
+ Suggestions.__index = Suggestions
176
+ function Suggestions.new(...)
177
+ local self = setmetatable({}, Suggestions)
178
+ return self:constructor(...) or self
179
+ end
180
+ function Suggestions:constructor(range, suggestions)
181
+ self.range = range
182
+ self.suggestions = suggestions
183
+ end
184
+ function Suggestions:empty()
185
+ return TS.Promise.resolve(Suggestions.EMPTY)
186
+ end
187
+ function Suggestions:merge(command, input)
188
+ if #input == 0 then
189
+ return Suggestions.EMPTY
190
+ elseif #input == 1 then
191
+ return input[1]
192
+ end
193
+ local texts = {}
194
+ local buckets = {}
195
+ for _, suggestions in input do
196
+ for _1, suggestion in suggestions:getList() do
197
+ addToSet(texts, buckets, suggestion)
198
+ end
199
+ end
200
+ return Suggestions:create(command, texts)
201
+ end
202
+ function Suggestions:create(command, suggestions)
203
+ if #suggestions == 0 then
204
+ return Suggestions.EMPTY
205
+ end
206
+ local start = math.huge
207
+ local finish = -math.huge
208
+ for _, suggestion in suggestions do
209
+ start = math.min(suggestion:getRange():getStart(), start)
210
+ finish = math.max(suggestion:getRange():getEnd(), finish)
211
+ end
212
+ local range = StringRange.new(start, finish)
213
+ local texts = {}
214
+ local buckets = {}
215
+ for _, suggestion in suggestions do
216
+ addToSet(texts, buckets, suggestion:expand(command, range))
217
+ end
218
+ stableSort(texts, function(a, b)
219
+ return a:compareToIgnoreCase(b)
220
+ end)
221
+ return Suggestions.new(range, texts)
222
+ end
223
+ function Suggestions:getRange()
224
+ return self.range
225
+ end
226
+ function Suggestions:getList()
227
+ return self.suggestions
228
+ end
229
+ function Suggestions:isEmpty()
230
+ return #self.suggestions == 0
231
+ end
232
+ function Suggestions:equals(other)
233
+ if rawequal(self, other) then
234
+ return true
235
+ end
236
+ if not (TS.instanceof(other, Suggestions)) then
237
+ return false
238
+ end
239
+ return objectsEquals(self.range, other.range) and objectsEquals(self.suggestions, other.suggestions)
240
+ end
241
+ function Suggestions:toString()
242
+ local _exp = self.suggestions
243
+ -- ▼ ReadonlyArray.map ▼
244
+ local _newValue = table.create(#_exp)
245
+ local _callback = function(suggestion)
246
+ return tostring(suggestion)
247
+ end
248
+ for _k, _v in _exp do
249
+ _newValue[_k] = _callback(_v, _k - 1, _exp)
250
+ end
251
+ -- ▲ ReadonlyArray.map ▲
252
+ local parts = _newValue
253
+ return `Suggestions\{range={self.range}, suggestions=[{table.concat(parts, ", ")}]\}`
254
+ end
255
+ function Suggestions:__tostring()
256
+ return self:toString()
257
+ end
258
+ Suggestions.EMPTY = Suggestions.new(StringRange:at(0), {})
259
+ end
260
+ local SuggestionsBuilder
261
+ do
262
+ SuggestionsBuilder = setmetatable({}, {
263
+ __tostring = function()
264
+ return "SuggestionsBuilder"
265
+ end,
266
+ })
267
+ SuggestionsBuilder.__index = SuggestionsBuilder
268
+ function SuggestionsBuilder.new(...)
269
+ local self = setmetatable({}, SuggestionsBuilder)
270
+ return self:constructor(...) or self
271
+ end
272
+ function SuggestionsBuilder:constructor(input, inputLowerCaseOrStart, start)
273
+ self.input = input
274
+ self.result = {}
275
+ local _inputLowerCaseOrStart = inputLowerCaseOrStart
276
+ if type(_inputLowerCaseOrStart) == "number" then
277
+ self.inputLowerCase = toLowerCase(input)
278
+ self.start = inputLowerCaseOrStart
279
+ else
280
+ self.inputLowerCase = inputLowerCaseOrStart
281
+ self.start = start
282
+ end
283
+ self.remaining = substring(input, self.start)
284
+ self.remainingLowerCase = substring(self.inputLowerCase, self.start)
285
+ end
286
+ function SuggestionsBuilder:getInput()
287
+ return self.input
288
+ end
289
+ function SuggestionsBuilder:getStart()
290
+ return self.start
291
+ end
292
+ function SuggestionsBuilder:getRemaining()
293
+ return self.remaining
294
+ end
295
+ function SuggestionsBuilder:getRemainingLowerCase()
296
+ return self.remainingLowerCase
297
+ end
298
+ function SuggestionsBuilder:build()
299
+ return Suggestions:create(self.input, self.result)
300
+ end
301
+ function SuggestionsBuilder:buildFuture()
302
+ return TS.Promise.resolve(self:build())
303
+ end
304
+ function SuggestionsBuilder:suggest(textOrValue, tooltip)
305
+ local range = StringRange:between(self.start, #self.input)
306
+ local _textOrValue = textOrValue
307
+ if type(_textOrValue) == "number" then
308
+ local _result = self.result
309
+ local _integerSuggestion = IntegerSuggestion.new(range, textOrValue, tooltip)
310
+ table.insert(_result, _integerSuggestion)
311
+ return self
312
+ end
313
+ if textOrValue == self.remaining then
314
+ return self
315
+ end
316
+ local _result = self.result
317
+ local _suggestion = Suggestion.new(range, textOrValue, tooltip)
318
+ table.insert(_result, _suggestion)
319
+ return self
320
+ end
321
+ function SuggestionsBuilder:add(other)
322
+ for _, suggestion in other.result do
323
+ local _exp = self.result
324
+ table.insert(_exp, suggestion)
325
+ end
326
+ return self
327
+ end
328
+ function SuggestionsBuilder:createOffset(start)
329
+ return SuggestionsBuilder.new(self.input, self.inputLowerCase, start)
330
+ end
331
+ function SuggestionsBuilder:restart()
332
+ return self:createOffset(self.start)
333
+ end
334
+ end
335
+ return {
336
+ Suggestion = Suggestion,
337
+ IntegerSuggestion = IntegerSuggestion,
338
+ Suggestions = Suggestions,
339
+ SuggestionsBuilder = SuggestionsBuilder,
340
+ }