@rbxts/centurion-ui 1.0.0-dev-a7b773c → 1.0.0-dev-84057f1

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.
@@ -1,6 +1,7 @@
1
1
  import { ClientAPI } from "@rbxts/centurion";
2
2
  import { InterfaceOptions } from "../types";
3
3
  export declare namespace CenturionUI {
4
+ function setVisible(visible: boolean): void;
4
5
  function updateOptions(options: Partial<InterfaceOptions>): void;
5
6
  function create(options?: Partial<InterfaceOptions>): (api: ClientAPI) => void;
6
7
  }
package/out/app/init.lua CHANGED
@@ -7,13 +7,19 @@ local Players = _services.Players
7
7
  local mount = TS.import(script, TS.getModule(script, "@rbxts", "vide").src).mount
8
8
  local DEFAULT_INTERFACE_OPTIONS = TS.import(script, script.Parent, "constants", "options").DEFAULT_INTERFACE_OPTIONS
9
9
  local DefaultPalette = TS.import(script, script.Parent, "palette").DefaultPalette
10
- local interfaceOptions = TS.import(script, script.Parent, "store").interfaceOptions
10
+ local _store = TS.import(script, script.Parent, "store")
11
+ local interfaceOptions = _store.interfaceOptions
12
+ local interfaceVisible = _store.interfaceVisible
11
13
  local CenturionApp = TS.import(script, script, "centurion-app").CenturionApp
12
14
  local CenturionUI = {}
13
15
  do
14
16
  local _container = CenturionUI
15
17
  local MAX_PRELOAD_ATTEMPTS = 3
16
18
  local PRELOAD_ATTEMPT_INTERVAL = 3
19
+ local function setVisible(visible)
20
+ interfaceVisible(visible)
21
+ end
22
+ _container.setVisible = setVisible
17
23
  local function updateOptions(options)
18
24
  interfaceOptions(function(prev)
19
25
  local _object = table.clone(prev)
@@ -25,33 +31,13 @@ do
25
31
  end)
26
32
  end
27
33
  _container.updateOptions = updateOptions
28
- local function registerCommands(registry)
29
- registry:registerCommand({
30
- name = "theme",
31
- description = "Change the terminal's theme",
32
- arguments = { {
33
- name = "name",
34
- description = "The name of the theme",
35
- type = CenturionType.String,
36
- suggestions = { "mocha", "macchiato", "frappe", "latte" },
37
- } },
38
- }, function(ctx, theme)
39
- if not (DefaultPalette[theme] ~= nil) then
40
- ctx:error("Invalid theme")
41
- return nil
42
- end
43
- updateOptions({
44
- palette = DefaultPalette[theme],
45
- })
46
- ctx:reply(`Set theme to '{theme}'`)
47
- end, { "centurion" })
48
- end
34
+ local registerCommands
49
35
  local function create(options)
50
36
  if options == nil then
51
37
  options = {}
52
38
  end
53
39
  return function(api)
54
- if api.options.registerBuiltInCommands then
40
+ if api.config.registerBuiltInCommands then
55
41
  registerCommands(api.registry)
56
42
  end
57
43
  updateOptions(options)
@@ -87,6 +73,27 @@ do
87
73
  end
88
74
  end
89
75
  _container.create = create
76
+ function registerCommands(registry)
77
+ registry:registerCommand({
78
+ name = "theme",
79
+ description = "Change the terminal's theme",
80
+ arguments = { {
81
+ name = "name",
82
+ description = "The name of the theme",
83
+ type = CenturionType.String,
84
+ suggestions = { "mocha", "macchiato", "frappe", "latte" },
85
+ } },
86
+ }, function(ctx, theme)
87
+ if not (DefaultPalette[theme] ~= nil) then
88
+ ctx:error("Invalid theme")
89
+ return nil
90
+ end
91
+ updateOptions({
92
+ palette = DefaultPalette[theme],
93
+ })
94
+ ctx:reply(`Set theme to '{theme}'`)
95
+ end, { "centurion" })
96
+ end
90
97
  end
91
98
  return {
92
99
  CenturionUI = CenturionUI,
@@ -1,7 +1,9 @@
1
1
  -- Compiled with roblox-ts v2.3.0-dev-26ec859
2
2
  local TS = _G[script]
3
+ local ArrayUtil = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.data).ArrayUtil
3
4
  local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
4
5
  local Vide = _vide
6
+ local derive = _vide.derive
5
7
  local For = _vide.For
6
8
  local read = _vide.read
7
9
  local SUGGESTION_TEXT_SIZE = TS.import(script, script.Parent.Parent.Parent, "constants", "text").SUGGESTION_TEXT_SIZE
@@ -15,11 +17,23 @@ local Group = TS.import(script, script.Parent.Parent, "ui", "group").Group
15
17
  local Padding = TS.import(script, script.Parent.Parent, "ui", "padding").Padding
16
18
  local Text = TS.import(script, script.Parent.Parent, "ui", "text").Text
17
19
  local highlightMatching = TS.import(script, script.Parent, "util").highlightMatching
20
+ local MAX_SUGGESTIONS = 3
18
21
  local function SuggestionList(_param)
19
22
  local suggestion = _param.suggestion
20
23
  local currentText = _param.currentText
21
24
  local size = _param.size
22
25
  local options = useAtom(interfaceOptions)
26
+ local suggestions = derive(function()
27
+ local _result = read(suggestion)
28
+ if _result ~= nil then
29
+ _result = _result.others
30
+ end
31
+ local _condition = _result
32
+ if _condition == nil then
33
+ _condition = {}
34
+ end
35
+ return ArrayUtil.slice(_condition, 0, MAX_SUGGESTIONS)
36
+ end)
23
37
  return Vide.jsx(Group, {
24
38
  size = size,
25
39
  mouseEnter = function()
@@ -34,17 +48,7 @@ local function SuggestionList(_param)
34
48
  return UDim.new(0, px(8))
35
49
  end,
36
50
  }), Vide.jsx(For, {
37
- each = function()
38
- local _result = read(suggestion)
39
- if _result ~= nil then
40
- _result = _result.others
41
- end
42
- local _condition = _result
43
- if _condition == nil then
44
- _condition = {}
45
- end
46
- return _condition
47
- end,
51
+ each = suggestions,
48
52
  }, function(name, i)
49
53
  return Vide.jsx(Frame, {
50
54
  size = function()
@@ -64,6 +68,7 @@ local function SuggestionList(_param)
64
68
  return UDim.new(0, px(8))
65
69
  end,
66
70
  clipsDescendants = true,
71
+ layoutOrder = i,
67
72
  }, Vide.jsx(Padding, {
68
73
  all = function()
69
74
  return UDim.new(0, px(4))
@@ -0,0 +1,5 @@
1
+ import { BaseRegistry, ImmutableRegistryPath, RegistryPath } from "@rbxts/centurion";
2
+ import { BaseCommand } from "@rbxts/centurion/out/shared/core/command";
3
+ export declare function getValidPath(registry: BaseRegistry, text: string[]): ImmutableRegistryPath | undefined;
4
+ export declare function getArgumentNames(registry: BaseRegistry, path: RegistryPath): string[];
5
+ export declare function getMissingArgs(command: BaseCommand, text: string[]): string[];
@@ -0,0 +1,71 @@
1
+ -- Compiled with roblox-ts v2.3.0-dev-26ec859
2
+ local TS = _G[script]
3
+ local _centurion = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out)
4
+ local ImmutableRegistryPath = _centurion.ImmutableRegistryPath
5
+ local RegistryPath = _centurion.RegistryPath
6
+ local formatPartsAsPath = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.string).formatPartsAsPath
7
+ local IS_EDIT = TS.import(script, script.Parent.Parent.Parent, "constants", "util").IS_EDIT
8
+ local function getValidPath(registry, text)
9
+ if #text == 0 then
10
+ return nil
11
+ end
12
+ local textPath = formatPartsAsPath(text)
13
+ if registry:getCommandByString(textPath) ~= nil or registry:getGroupByString(textPath) ~= nil then
14
+ return ImmutableRegistryPath:fromString(textPath)
15
+ end
16
+ local path = RegistryPath:empty()
17
+ for _, part in text do
18
+ path:append(part)
19
+ if registry:getCommand(path) == nil and registry:getGroup(path) == nil and #registry:getChildPaths(path) == 0 then
20
+ path:remove(path:size() - 1)
21
+ break
22
+ end
23
+ end
24
+ if registry:getCommand(path) ~= nil or registry:getGroup(path) ~= nil then
25
+ return ImmutableRegistryPath:fromPath(path)
26
+ end
27
+ end
28
+ local function getArgumentNames(registry, path)
29
+ if IS_EDIT then
30
+ return {}
31
+ end
32
+ local command = registry:getCommand(path)
33
+ if command == nil or command.options.arguments == nil then
34
+ return {}
35
+ end
36
+ local _exp = command.options.arguments
37
+ -- ▼ ReadonlyArray.map ▼
38
+ local _newValue = table.create(#_exp)
39
+ local _callback = function(arg)
40
+ return arg.name
41
+ end
42
+ for _k, _v in _exp do
43
+ _newValue[_k] = _callback(_v, _k - 1, _exp)
44
+ end
45
+ -- ▲ ReadonlyArray.map ▲
46
+ return _newValue
47
+ end
48
+ local function getMissingArgs(command, text)
49
+ if command.options.arguments == nil or #command.options.arguments == 0 then
50
+ return {}
51
+ end
52
+ local lastPartIndex = #text - command:getPath():size() - 1
53
+ local missingArgs = {}
54
+ local index = 0
55
+ for _, arg in command.options.arguments do
56
+ if arg.optional then
57
+ break
58
+ end
59
+ if index > lastPartIndex then
60
+ local _name = arg.name
61
+ table.insert(missingArgs, _name)
62
+ end
63
+ index += 1
64
+ end
65
+ return missingArgs
66
+ end
67
+ return {
68
+ getValidPath = getValidPath,
69
+ getArgumentNames = getArgumentNames,
70
+ getMissingArgs = getMissingArgs,
71
+ }
@@ -0,0 +1,26 @@
1
+ import { ArgumentOptions, BaseRegistry, ListArgumentType, RegistryPath, SingleArgumentType } from "@rbxts/centurion";
2
+ import { ReadonlyDeep } from "@rbxts/centurion/out/shared/util/data";
3
+ import { CommandSuggestion } from "../../types";
4
+ export interface SingleArgument {
5
+ kind: "single";
6
+ options: ReadonlyDeep<ArgumentOptions>;
7
+ type: SingleArgumentType<unknown>;
8
+ input?: string;
9
+ }
10
+ export interface ListArgument {
11
+ kind: "list";
12
+ options: ReadonlyDeep<ArgumentOptions>;
13
+ type: ListArgumentType<unknown>;
14
+ input: string[];
15
+ }
16
+ export type Argument = SingleArgument | ListArgument;
17
+ export declare function getArgumentSuggestion(arg: Argument, textPart?: string): {
18
+ type: "argument";
19
+ title: string;
20
+ others: string[];
21
+ description: string;
22
+ dataType: string;
23
+ optional: boolean;
24
+ error: string | undefined;
25
+ };
26
+ export declare function getCommandSuggestion(registry: BaseRegistry, parentPath?: RegistryPath, text?: string): CommandSuggestion | undefined;
@@ -0,0 +1,187 @@
1
+ -- Compiled with roblox-ts v2.3.0-dev-26ec859
2
+ local TS = _G[script]
3
+ local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players
4
+ local MAX_OTHER_SUGGESTIONS = 3
5
+ local function getMatches(strings, text)
6
+ if text == nil then
7
+ table.sort(strings)
8
+ -- ▼ ReadonlyArray.map ▼
9
+ local _newValue = table.create(#strings)
10
+ local _callback = function(str, i)
11
+ return { i, str, #str }
12
+ end
13
+ for _k, _v in strings do
14
+ _newValue[_k] = _callback(_v, _k - 1, strings)
15
+ end
16
+ -- ▲ ReadonlyArray.map ▲
17
+ return _newValue
18
+ end
19
+ local textLower = string.lower(text)
20
+ local textEndIndex = #text
21
+ -- ▼ ReadonlyArray.mapFiltered ▼
22
+ local _newValue = {}
23
+ local _callback = function(str, i)
24
+ local part = string.sub(string.lower(str), 0, textEndIndex)
25
+ if part == textLower then
26
+ return { i, str, #str }
27
+ end
28
+ end
29
+ local _length = 0
30
+ for _k, _v in strings do
31
+ local _result = _callback(_v, _k - 1, strings)
32
+ if _result ~= nil then
33
+ _length += 1
34
+ _newValue[_length] = _result
35
+ end
36
+ end
37
+ -- ▲ ReadonlyArray.mapFiltered ▲
38
+ table.sort(_newValue, function(a, b)
39
+ return a[2] < b[2]
40
+ end)
41
+ return _newValue
42
+ end
43
+ local function getArgumentSuggestion(arg, textPart)
44
+ local _array = {}
45
+ local _length = #_array
46
+ local _array_1 = (arg.options.suggestions or {})
47
+ table.move(_array_1, 1, #_array_1, _length + 1, _array)
48
+ local suggestions = _array
49
+ local singleArg = arg.kind == "single"
50
+ local _result
51
+ if singleArg then
52
+ local _result_1 = arg.type.suggestions
53
+ if _result_1 ~= nil then
54
+ local _condition = arg.input
55
+ if _condition == nil then
56
+ _condition = ""
57
+ end
58
+ _result_1 = _result_1(_condition, Players.LocalPlayer)
59
+ end
60
+ _result = _result_1
61
+ else
62
+ local _result_1 = arg.type.suggestions
63
+ if _result_1 ~= nil then
64
+ _result_1 = _result_1(arg.input, Players.LocalPlayer)
65
+ end
66
+ _result = _result_1
67
+ end
68
+ local typeSuggestions = _result
69
+ if typeSuggestions ~= nil then
70
+ for _, text in typeSuggestions do
71
+ table.insert(suggestions, text)
72
+ end
73
+ end
74
+ local errorText
75
+ if not arg.type.expensive then
76
+ local success, err = pcall(function()
77
+ local _result_1
78
+ if singleArg then
79
+ local _type = arg.type
80
+ local _condition = arg.input
81
+ if _condition == nil then
82
+ _condition = ""
83
+ end
84
+ _result_1 = _type.transform(_condition, Players.LocalPlayer)
85
+ else
86
+ _result_1 = arg.type.transform(arg.input, Players.LocalPlayer)
87
+ end
88
+ local transformResult = _result_1
89
+ if transformResult.ok then
90
+ return nil
91
+ end
92
+ errorText = transformResult.value
93
+ end)
94
+ if not success then
95
+ errorText = "Failed to transform argument"
96
+ warn(err)
97
+ end
98
+ end
99
+ local _object = {
100
+ type = "argument",
101
+ title = arg.options.name,
102
+ }
103
+ local _left = "others"
104
+ local _exp = getMatches(suggestions, textPart)
105
+ -- ▼ ReadonlyArray.map ▼
106
+ local _newValue = table.create(#_exp)
107
+ local _callback = function(_param)
108
+ local str = _param[2]
109
+ return str
110
+ end
111
+ for _k, _v in _exp do
112
+ _newValue[_k] = _callback(_v, _k - 1, _exp)
113
+ end
114
+ -- ▲ ReadonlyArray.map ▲
115
+ _object[_left] = _newValue
116
+ _object.description = arg.options.description
117
+ _object.dataType = arg.type.name
118
+ local _left_1 = "optional"
119
+ local _condition = arg.options.optional
120
+ if _condition == nil then
121
+ _condition = false
122
+ end
123
+ _object[_left_1] = _condition
124
+ _object.error = errorText
125
+ return _object
126
+ end
127
+ local function getCommandSuggestion(registry, parentPath, text)
128
+ local paths = if parentPath ~= nil then registry:getChildPaths(parentPath) else registry:getRootPaths()
129
+ if #paths == 0 then
130
+ return nil
131
+ end
132
+ -- ▼ ReadonlyArray.map ▼
133
+ local _newValue = table.create(#paths)
134
+ local _callback = function(path)
135
+ return path:tail()
136
+ end
137
+ for _k, _v in paths do
138
+ _newValue[_k] = _callback(_v, _k - 1, paths)
139
+ end
140
+ -- ▲ ReadonlyArray.map ▲
141
+ local pathNames = _newValue
142
+ local sortedPaths = getMatches(pathNames, text)
143
+ local firstMatch = table.remove(sortedPaths, 1)
144
+ if firstMatch == nil then
145
+ return nil
146
+ end
147
+ local firstPath = paths[firstMatch[1] + 1]
148
+ local _result = registry:getCommand(firstPath)
149
+ if _result ~= nil then
150
+ _result = _result.options
151
+ end
152
+ local _condition = _result
153
+ if _condition == nil then
154
+ local _result_1 = registry:getGroup(firstPath)
155
+ if _result_1 ~= nil then
156
+ _result_1 = _result_1.options
157
+ end
158
+ _condition = _result_1
159
+ end
160
+ local mainData = _condition
161
+ if mainData == nil then
162
+ return nil
163
+ end
164
+ local _object = {
165
+ type = "command",
166
+ title = firstPath:tail(),
167
+ }
168
+ local _left = "others"
169
+ -- ▼ ReadonlyArray.map ▼
170
+ local _newValue_1 = table.create(#sortedPaths)
171
+ local _callback_1 = function(_param)
172
+ local str = _param[2]
173
+ return str
174
+ end
175
+ for _k, _v in sortedPaths do
176
+ _newValue_1[_k] = _callback_1(_v, _k - 1, sortedPaths)
177
+ end
178
+ -- ▲ ReadonlyArray.map ▲
179
+ _object[_left] = _newValue_1
180
+ _object.description = mainData.description
181
+ _object.shortcuts = mainData.shortcuts
182
+ return _object
183
+ end
184
+ return {
185
+ getArgumentSuggestion = getArgumentSuggestion,
186
+ getCommandSuggestion = getCommandSuggestion,
187
+ }
@@ -15,19 +15,21 @@ local useAtom = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-ato
15
15
  local useEvent = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-event").useEvent
16
16
  local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
17
17
  local _store = TS.import(script, script.Parent.Parent.Parent, "store")
18
- local currentArgIndex = _store.currentArgIndex
18
+ local commandArgIndex = _store.commandArgIndex
19
19
  local currentCommandPath = _store.currentCommandPath
20
20
  local currentSuggestion = _store.currentSuggestion
21
+ local currentTextPart = _store.currentTextPart
21
22
  local interfaceOptions = _store.interfaceOptions
22
23
  local interfaceVisible = _store.interfaceVisible
24
+ local terminalArgIndex = _store.terminalArgIndex
23
25
  local terminalText = _store.terminalText
24
26
  local terminalTextParts = _store.terminalTextParts
25
27
  local terminalTextValid = _store.terminalTextValid
26
- local getArgumentNames = TS.import(script, script.Parent.Parent.Parent, "util", "argument").getArgumentNames
27
28
  local Frame = TS.import(script, script.Parent.Parent, "ui", "frame").Frame
28
29
  local Padding = TS.import(script, script.Parent.Parent, "ui", "padding").Padding
29
30
  local Text = TS.import(script, script.Parent.Parent, "ui", "text").Text
30
31
  local TextField = TS.import(script, script.Parent.Parent, "ui", "text-field").TextField
32
+ local getArgumentNames = TS.import(script, script.Parent, "command").getArgumentNames
31
33
  local TEXT_SIZE = 22
32
34
  local function TerminalTextField(_param)
33
35
  local anchorPoint = _param.anchorPoint
@@ -96,27 +98,40 @@ local function TerminalTextField(_param)
96
98
  end
97
99
  local atNextPart = endsWithSpace(terminalText())
98
100
  local textParts = terminalTextParts()
99
- local suggestionStartIndex = if #textParts > 0 then (if not atNextPart then #textParts[#textParts] else 0) + 1 else -1
100
- if suggestion.type == "command" and suggestionStartIndex > -1 then
101
+ if #textParts == 0 then
102
+ suggestionText(suggestion.title)
103
+ return nil
104
+ end
105
+ -- Command suggestions
106
+ if suggestion.type == "command" then
107
+ local suggestionStartIndex = (if not atNextPart then #textParts[#textParts] else 0) + 1
101
108
  suggestionText(text() .. string.sub(suggestion.title, suggestionStartIndex))
102
109
  return nil
103
110
  end
111
+ -- Argument suggestions
104
112
  local command = currentCommandPath()
105
- local argIndex = currentArgIndex()
113
+ local argIndex = terminalArgIndex()
106
114
  if suggestion.type ~= "argument" or command == nil or argIndex == nil then
107
115
  return nil
108
116
  end
109
117
  local newText = text()
110
- local argNames = getArgumentNames(api.registry, command)
111
- for i = argIndex, #argNames - 1 do
112
- if i == argIndex and not atNextPart then
113
- if not (#suggestion.others == 0) then
114
- newText ..= string.sub(suggestion.others[1], suggestionStartIndex)
115
- end
116
- newText ..= " "
117
- continue
118
+ if atNextPart and argIndex == commandArgIndex() then
119
+ newText ..= suggestion.title
120
+ elseif not (#suggestion.others == 0) then
121
+ local _exp = suggestion.others[1]
122
+ local _result = currentTextPart()
123
+ if _result ~= nil then
124
+ _result = #_result
125
+ end
126
+ local _condition = _result
127
+ if _condition == nil then
128
+ _condition = 0
118
129
  end
119
- newText = `{newText}{argNames[i + 1]} `
130
+ newText ..= string.sub(_exp, _condition + 1)
131
+ end
132
+ local argNames = getArgumentNames(api.registry, command)
133
+ for i = argIndex + 1, #argNames - 1 do
134
+ newText = `{newText} {argNames[i + 1]}`
120
135
  end
121
136
  suggestionText(newText)
122
137
  end)
@@ -142,30 +157,37 @@ local function TerminalTextField(_param)
142
157
  if input.KeyCode ~= Enum.KeyCode.Tab then
143
158
  return nil
144
159
  end
145
- -- Handle command suggestions
160
+ -- Command suggestions
146
161
  local commandPath = currentCommandPath()
147
162
  local suggestion = currentSuggestion()
163
+ if suggestion == nil then
164
+ return nil
165
+ end
148
166
  if commandPath == nil then
149
- local _suggestionTitle = suggestion
150
- if _suggestionTitle ~= nil then
151
- _suggestionTitle = _suggestionTitle.title
152
- end
153
- local suggestionTitle = _suggestionTitle
154
- if suggestionTitle == nil then
155
- return nil
156
- end
167
+ local suggestionTitle = suggestion.title
157
168
  local currentText = text()
158
169
  local textParts = terminalTextParts()
159
- local newText = ""
170
+ if #textParts == 0 then
171
+ return nil
172
+ end
173
+ local _array = {}
174
+ local _length = #_array
175
+ table.move(textParts, 1, #textParts, _length + 1, _array)
176
+ local pathParts = _array
177
+ local newText = currentText
160
178
  if endsWithSpace(currentText) then
161
- newText = currentText .. suggestionTitle
179
+ newText ..= suggestionTitle
180
+ table.insert(pathParts, suggestionTitle)
162
181
  elseif not (#textParts == 0) then
163
- local textPartSize = #textParts[#textParts]
164
- local _arg1 = #currentText - textPartSize
165
- newText = string.sub(currentText, 0, _arg1) .. suggestionTitle
182
+ local lastPartSize = textParts[#textParts]
183
+ local _newText = newText
184
+ local _arg1 = #newText - #lastPartSize
185
+ newText = string.sub(_newText, 0, _arg1) .. suggestionTitle
186
+ local _arg0 = #textParts - 1
187
+ table.remove(pathParts, _arg0 + 1)
188
+ table.insert(pathParts, suggestionTitle)
166
189
  end
167
- local suggestionTextParts = string.split((string.gsub(suggestionText(), "%s+", " ")), " ")
168
- local _nextCommand = api.registry:getCommandByString(formatPartsAsPath(suggestionTextParts))
190
+ local _nextCommand = api.registry:getCommandByString(formatPartsAsPath(pathParts))
169
191
  if _nextCommand ~= nil then
170
192
  _nextCommand = _nextCommand.options
171
193
  end
@@ -174,13 +196,13 @@ local function TerminalTextField(_param)
174
196
  if not _condition_1 then
175
197
  local _result = nextCommand.arguments
176
198
  if _result ~= nil then
177
- _result = #_result
199
+ _result = #_result == 0
178
200
  end
179
201
  local _condition_2 = _result
180
202
  if _condition_2 == nil then
181
- _condition_2 = 0
203
+ _condition_2 = true
182
204
  end
183
- _condition_1 = _condition_2 > 0
205
+ _condition_1 = not _condition_2
184
206
  end
185
207
  if _condition_1 then
186
208
  newText ..= " "
@@ -190,11 +212,11 @@ local function TerminalTextField(_param)
190
212
  textBox.CursorPosition = #newText + 1
191
213
  return nil
192
214
  end
193
- -- Handle argument suggestions
215
+ -- Argument suggestions
194
216
  if commandPath == nil or suggestion == nil or #suggestion.others == 0 then
195
217
  return nil
196
218
  end
197
- local argIndex = currentArgIndex()
219
+ local argIndex = terminalArgIndex()
198
220
  local _commandArgs = api.registry:getCommand(commandPath)
199
221
  if _commandArgs ~= nil then
200
222
  _commandArgs = _commandArgs.options.arguments
@@ -204,17 +226,20 @@ local function TerminalTextField(_param)
204
226
  return nil
205
227
  end
206
228
  local newText = text()
207
- local parts = terminalTextParts()
208
- if not endsWithSpace(newText) and not (#parts == 0) then
209
- local _newText = newText
210
- local _arg1 = #newText - #parts[#parts]
211
- newText = string.sub(_newText, 0, _arg1)
212
- end
213
229
  local otherSuggestion = suggestion.others[1]
214
230
  if (string.match(otherSuggestion, "%s")) ~= nil then
215
231
  otherSuggestion = `"{otherSuggestion}"`
216
232
  end
217
- newText ..= otherSuggestion
233
+ local _otherSuggestion = otherSuggestion
234
+ local _result = currentTextPart()
235
+ if _result ~= nil then
236
+ _result = #_result
237
+ end
238
+ local _condition_1 = _result
239
+ if _condition_1 == nil then
240
+ _condition_1 = 0
241
+ end
242
+ newText ..= string.sub(_otherSuggestion, _condition_1 + 1)
218
243
  if argIndex < #commandArgs - 1 then
219
244
  newText ..= " "
220
245
  end
@@ -1,12 +1,9 @@
1
1
  -- Compiled with roblox-ts v2.3.0-dev-26ec859
2
2
  local TS = _G[script]
3
- local _centurion = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out)
4
- local ImmutableRegistryPath = _centurion.ImmutableRegistryPath
5
- local RegistryPath = _centurion.RegistryPath
6
3
  local ArrayUtil = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.data).ArrayUtil
7
4
  local _string = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.string)
8
5
  local endsWithSpace = _string.endsWithSpace
9
- local formatPartsAsPath = _string.formatPartsAsPath
6
+ local splitString = _string.splitString
10
7
  local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
11
8
  local Vide = _vide
12
9
  local effect = _vide.effect
@@ -18,21 +15,25 @@ local useHistory = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-
18
15
  local useMotion = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-motion").useMotion
19
16
  local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
20
17
  local _store = TS.import(script, script.Parent.Parent.Parent, "store")
21
- local currentArgIndex = _store.currentArgIndex
18
+ local commandArgIndex = _store.commandArgIndex
22
19
  local currentCommandPath = _store.currentCommandPath
23
20
  local currentSuggestion = _store.currentSuggestion
21
+ local currentTextPart = _store.currentTextPart
24
22
  local interfaceOptions = _store.interfaceOptions
25
23
  local mouseOverInterface = _store.mouseOverInterface
24
+ local terminalArgIndex = _store.terminalArgIndex
26
25
  local terminalText = _store.terminalText
27
26
  local terminalTextParts = _store.terminalTextParts
28
27
  local terminalTextValid = _store.terminalTextValid
29
- local getMissingArgs = TS.import(script, script.Parent.Parent.Parent, "util", "argument").getMissingArgs
30
- local _suggestion = TS.import(script, script.Parent.Parent.Parent, "util", "suggestion")
31
- local getArgumentSuggestion = _suggestion.getArgumentSuggestion
32
- local getCommandSuggestion = _suggestion.getCommandSuggestion
33
28
  local HistoryList = TS.import(script, script.Parent.Parent, "history").HistoryList
34
29
  local Frame = TS.import(script, script.Parent.Parent, "ui", "frame").Frame
35
30
  local Padding = TS.import(script, script.Parent.Parent, "ui", "padding").Padding
31
+ local _command = TS.import(script, script.Parent, "command")
32
+ local getMissingArgs = _command.getMissingArgs
33
+ local getValidPath = _command.getValidPath
34
+ local _suggestion = TS.import(script, script.Parent, "suggestion")
35
+ local getArgumentSuggestion = _suggestion.getArgumentSuggestion
36
+ local getCommandSuggestion = _suggestion.getCommandSuggestion
36
37
  local TerminalTextField = TS.import(script, script.Parent, "terminal-text-field").TerminalTextField
37
38
  local MAX_HEIGHT = HISTORY_TEXT_SIZE * 10
38
39
  local TEXT_FIELD_HEIGHT = 40
@@ -103,112 +104,141 @@ local function Terminal()
103
104
  onTextChange = function(text)
104
105
  terminalText(text)
105
106
  terminalTextValid(false)
107
+ missingArgs({})
106
108
  local parts = terminalTextParts()
107
109
  if #parts == 0 then
108
110
  currentCommandPath(nil)
109
111
  currentSuggestion(nil)
110
- currentArgIndex(nil)
112
+ terminalArgIndex(nil)
111
113
  return nil
112
114
  end
113
115
  -- If the text ends in a space, we want to count that as having traversed
114
- -- to the next "part" of the text. This means we should include the previous
115
- -- text part as part of the parent path.
116
+ -- to the next "part" of the text.
116
117
  local atNextPart = endsWithSpace(text)
117
- local commandPath = currentCommandPath()
118
- local atCommand = false
119
- if commandPath ~= nil and formatPartsAsPath(ArrayUtil.slice(parts, 0, commandPath:size())) == commandPath:toString() then
120
- -- The current path still leads to the command, so it's valid
121
- atCommand = true
122
- elseif api.registry:getCommandByString(formatPartsAsPath(parts)) ~= nil then
123
- atCommand = true
124
- commandPath = ImmutableRegistryPath.new(parts)
125
- else
126
- local currentPath = RegistryPath:empty()
127
- for _, part in parts do
128
- currentPath:append(part)
129
- if api.registry:getCommand(currentPath) ~= nil then
130
- atCommand = true
131
- break
132
- end
133
- if #api.registry:getChildPaths(currentPath) == 0 then
134
- atCommand = false
135
- break
136
- end
118
+ local path = getValidPath(api.registry, parts)
119
+ local command = if path ~= nil then api.registry:getCommand(path) else nil
120
+ if command ~= nil then
121
+ -- Check for missing arguments
122
+ local missing = getMissingArgs(command, parts)
123
+ local _result = command.options.arguments
124
+ if _result ~= nil then
125
+ _result = #_result == 0
137
126
  end
138
- commandPath = ImmutableRegistryPath:fromPath(currentPath)
139
- end
140
- local currentPath = currentCommandPath()
141
- if not atCommand and currentPath ~= nil then
142
- currentCommandPath(nil)
143
- elseif atCommand and commandPath ~= currentPath then
144
- currentCommandPath(commandPath)
145
- end
146
- local _result
147
- if commandPath ~= nil then
148
- local _result_1 = api.registry:getCommand(commandPath)
149
- if _result_1 ~= nil then
150
- _result_1 = _result_1.options
151
- end
152
- _result = _result_1
153
- else
154
- _result = nil
155
- end
156
- local command = _result
157
- if commandPath ~= nil and command ~= nil then
158
- local missing = getMissingArgs(api.registry, commandPath, parts)
159
- missingArgs(missing)
160
- local _result_1 = command.arguments
161
- if _result_1 ~= nil then
162
- _result_1 = #_result_1 == 0
163
- end
164
- local _condition = _result_1
127
+ local _condition = _result
165
128
  if _condition == nil then
166
129
  _condition = true
167
130
  end
168
131
  local noArgs = _condition
132
+ currentCommandPath(path)
133
+ missingArgs(missing)
169
134
  terminalTextValid(noArgs or #missing == 0 or (atNextPart and #missing == 1))
170
135
  else
171
136
  terminalTextValid(false)
172
137
  end
173
- -- Update suggestions
174
- local showArgs = atCommand and (atNextPart or (commandPath ~= nil and #parts > commandPath:size()))
175
- local _result_1
176
- if showArgs and command ~= nil then
177
- local _result_2 = command.arguments
178
- if _result_2 ~= nil then
179
- _result_2 = #_result_2
138
+ local textPart = if not atNextPart then parts[#parts] else nil
139
+ local argIndex = if path ~= nil then #parts - path:size() - (if atNextPart then 0 else 1) else -1
140
+ terminalArgIndex(argIndex)
141
+ if command == nil or argIndex == -1 then
142
+ -- Get command suggestions
143
+ local index = #parts - (if atNextPart then 1 else 2)
144
+ local _parentPath = path
145
+ if _parentPath ~= nil then
146
+ _parentPath = _parentPath:slice(0, index)
147
+ end
148
+ local parentPath = _parentPath
149
+ local _exp = api.registry
150
+ local _result = parentPath
151
+ if _result ~= nil then
152
+ _result = _result:isEmpty()
153
+ end
154
+ currentSuggestion(getCommandSuggestion(_exp, if not _result then parentPath else nil, textPart))
155
+ currentTextPart(textPart)
156
+ return nil
157
+ end
158
+ -- Handle arguments
159
+ local args = command.options.arguments
160
+ if args == nil then
161
+ currentSuggestion(nil)
162
+ currentTextPart(nil)
163
+ commandArgIndex(nil)
164
+ return nil
165
+ end
166
+ local index = -1
167
+ local currentArg
168
+ local endIndex = -1
169
+ for i = 0, argIndex do
170
+ if endIndex == nil or i <= endIndex then
171
+ continue
180
172
  end
181
- local _condition = _result_2
173
+ index += 1
174
+ if index >= #args then
175
+ currentArg = nil
176
+ break
177
+ end
178
+ currentArg = args[index + 1]
179
+ local _condition = currentArg.numArgs
182
180
  if _condition == nil then
183
- _condition = 0
181
+ _condition = 1
184
182
  end
185
- _result_1 = _condition
186
- else
187
- _result_1 = 0
183
+ local numArgs = _condition
184
+ endIndex = if numArgs ~= "rest" then i + (numArgs - 1) else nil
185
+ end
186
+ local _registry = api.registry
187
+ local _result = currentArg
188
+ if _result ~= nil then
189
+ _result = _result.type
190
+ end
191
+ local _condition = _result
192
+ if _condition == nil then
193
+ _condition = ""
188
194
  end
189
- local argCount = _result_1
190
- local currentTextPart = if not atNextPart then parts[#parts] else nil
195
+ local argType = _registry:getType(_condition)
196
+ if currentArg == nil or argType == nil then
197
+ currentSuggestion(nil)
198
+ currentTextPart(nil)
199
+ terminalArgIndex(nil)
200
+ commandArgIndex(nil)
201
+ return nil
202
+ end
203
+ commandArgIndex(index)
204
+ local argTextPart
191
205
  local suggestion
192
- if argCount == 0 then
193
- local parentPath = if atNextPart then commandPath elseif commandPath:size() ~= 1 then commandPath:parent() else nil
194
- suggestion = getCommandSuggestion(api.registry, parentPath, currentTextPart)
195
- elseif commandPath ~= nil then
196
- -- Handle argument suggestions
197
- local argIndex = #parts - commandPath:size() - (if atNextPart then 0 else 1)
198
- if argIndex >= argCount then
199
- return nil
200
- end
201
- currentArgIndex(argIndex)
202
- suggestion = getArgumentSuggestion(api.registry, commandPath, argIndex, currentTextPart)
203
- local _result_2 = suggestion
204
- if _result_2 ~= nil then
205
- _result_2 = _result_2.error
206
+ if argType.kind == "single" then
207
+ argTextPart = textPart
208
+ suggestion = getArgumentSuggestion({
209
+ kind = "single",
210
+ options = currentArg,
211
+ type = argType,
212
+ input = textPart,
213
+ }, textPart)
214
+ else
215
+ local _condition_1 = textPart
216
+ if _condition_1 == nil then
217
+ _condition_1 = ""
206
218
  end
207
- if _result_2 ~= nil then
208
- terminalTextValid(false)
219
+ local textParts = splitString(_condition_1, ",")
220
+ local lastPart = if not (#textParts == 0) then textParts[#textParts] else nil
221
+ local _result_1 = textPart
222
+ if _result_1 ~= nil then
223
+ _result_1 = string.sub(_result_1, -1)
209
224
  end
225
+ argTextPart = if _result_1 ~= "," then lastPart else nil
226
+ suggestion = getArgumentSuggestion({
227
+ kind = "list",
228
+ options = currentArg,
229
+ type = argType,
230
+ input = textParts,
231
+ }, argTextPart)
210
232
  end
233
+ currentTextPart(argTextPart)
211
234
  currentSuggestion(suggestion)
235
+ local _result_1 = suggestion
236
+ if _result_1 ~= nil then
237
+ _result_1 = _result_1.error
238
+ end
239
+ if _result_1 ~= nil then
240
+ terminalTextValid(false)
241
+ end
212
242
  end,
213
243
  onSubmit = function()
214
244
  local commandPath = currentCommandPath()
@@ -45,7 +45,8 @@ local px = setmetatable({
45
45
  ]]
46
46
  local function usePx()
47
47
  local camera = Workspace.CurrentCamera
48
- assert(camera, "CurrentCamera is not set")
48
+ local _arg0 = camera ~= nil
49
+ assert(_arg0, "CurrentCamera is not set")
49
50
  local updateScale = debounce(function()
50
51
  local viewport = camera.ViewportSize
51
52
  local width = math.log(viewport.X / BASE_RESOLUTION.X, 2)
package/out/store.d.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { ImmutableRegistryPath } from "@rbxts/centurion";
2
- import { InterfaceOptions, Suggestion } from "./types";
2
+ import { Suggestion } from "./types";
3
3
  export declare const interfaceVisible: import("@rbxts/charm").Atom<boolean>;
4
- export declare const interfaceOptions: import("@rbxts/charm").Atom<InterfaceOptions>;
4
+ export declare const interfaceOptions: import("@rbxts/charm").Atom<import("./types").InterfaceOptions>;
5
5
  export declare const mouseOverInterface: import("@rbxts/charm").Atom<boolean>;
6
6
  export declare const currentCommandPath: import("@rbxts/charm").Atom<ImmutableRegistryPath | undefined>;
7
- export declare const currentArgIndex: import("@rbxts/charm").Atom<number | undefined>;
7
+ export declare const commandArgIndex: import("@rbxts/charm").Atom<number | undefined>;
8
+ export declare const terminalArgIndex: import("@rbxts/charm").Atom<number | undefined>;
8
9
  export declare const currentSuggestion: import("@rbxts/charm").Atom<Suggestion | undefined>;
9
10
  export declare const terminalText: import("@rbxts/charm").Atom<string>;
10
11
  export declare const terminalTextParts: import("@rbxts/charm").Molecule<string[]>;
11
- export declare const currentTextPart: import("@rbxts/charm").Molecule<string | undefined>;
12
12
  export declare const terminalTextValid: import("@rbxts/charm").Atom<boolean>;
13
+ export declare const currentTextPart: import("@rbxts/charm").Atom<string | undefined>;
package/out/store.lua CHANGED
@@ -9,32 +9,25 @@ local interfaceVisible = atom(false)
9
9
  local interfaceOptions = atom(DEFAULT_INTERFACE_OPTIONS)
10
10
  local mouseOverInterface = atom(false)
11
11
  local currentCommandPath = atom(nil)
12
- local currentArgIndex = atom(nil)
12
+ local commandArgIndex = atom(nil)
13
+ local terminalArgIndex = atom(nil)
13
14
  local currentSuggestion = atom(nil)
14
15
  local terminalText = atom("")
15
16
  local terminalTextParts = computed(function()
16
17
  return splitString(terminalText(), " ")
17
18
  end)
18
- local currentTextPart = computed(function()
19
- local text = terminalText()
20
- local textParts = terminalTextParts()
21
- local endsWithSpace = #textParts > 0 and #{ string.match(text, "%s$") } > 0
22
- local index = if endsWithSpace then #textParts else #textParts - 1
23
- if index == -1 or index >= #textParts then
24
- return nil
25
- end
26
- return textParts[index + 1]
27
- end)
28
19
  local terminalTextValid = atom(false)
20
+ local currentTextPart = atom(nil)
29
21
  return {
30
22
  interfaceVisible = interfaceVisible,
31
23
  interfaceOptions = interfaceOptions,
32
24
  mouseOverInterface = mouseOverInterface,
33
25
  currentCommandPath = currentCommandPath,
34
- currentArgIndex = currentArgIndex,
26
+ commandArgIndex = commandArgIndex,
27
+ terminalArgIndex = terminalArgIndex,
35
28
  currentSuggestion = currentSuggestion,
36
29
  terminalText = terminalText,
37
30
  terminalTextParts = terminalTextParts,
38
- currentTextPart = currentTextPart,
39
31
  terminalTextValid = terminalTextValid,
32
+ currentTextPart = currentTextPart,
40
33
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rbxts/centurion-ui",
3
3
  "description": "Terminal UI for the Centurion command framework",
4
- "version": "1.0.0-dev-a7b773c",
4
+ "version": "1.0.0-dev-84057f1",
5
5
  "author": "paradoxuum",
6
6
  "license": "MIT",
7
7
  "main": "out/init.lua",
@@ -32,22 +32,22 @@
32
32
  "dev": "shx rm -rf out && rbxtsc -w"
33
33
  },
34
34
  "devDependencies": {
35
- "@rbxts/centurion": "^1.0.0-dev-a7b773c",
35
+ "@rbxts/centurion": "^1.0.0-dev-84057f1",
36
36
  "@rbxts/compiler-types": "2.3.0-types.1",
37
- "@rbxts/types": "^1.0.790",
37
+ "@rbxts/types": "^1.0.794",
38
38
  "roblox-ts": "2.3.0-dev-26ec859",
39
39
  "shx": "^0.3.4",
40
- "typescript": "~5.5.3"
40
+ "typescript": "~5.5.4"
41
41
  },
42
42
  "dependencies": {
43
43
  "@rbxts/charm": "^0.5.2",
44
44
  "@rbxts/ripple": "^0.8.2",
45
45
  "@rbxts/services": "^1.5.4",
46
46
  "@rbxts/set-timeout": "^1.1.2",
47
- "@rbxts/vide": "^0.4.1"
47
+ "@rbxts/vide": "^0.4.2"
48
48
  },
49
49
  "peerDependencies": {
50
- "@rbxts/centurion": "^1.0.0-dev-a7b773c"
50
+ "@rbxts/centurion": "*"
51
51
  },
52
52
  "stableVersion": "1.0.0"
53
53
  }
@@ -1,3 +0,0 @@
1
- import { BaseRegistry, ImmutableRegistryPath, RegistryPath } from "@rbxts/centurion";
2
- export declare function getArgumentNames(registry: BaseRegistry, path: RegistryPath): string[];
3
- export declare function getMissingArgs(registry: BaseRegistry, path: ImmutableRegistryPath, text: string[]): string[];
@@ -1,51 +0,0 @@
1
- -- Compiled with roblox-ts v2.3.0-dev-26ec859
2
- local TS = _G[script]
3
- local IS_EDIT = TS.import(script, script.Parent.Parent, "constants", "util").IS_EDIT
4
- local function getArgumentNames(registry, path)
5
- if IS_EDIT then
6
- return {}
7
- end
8
- local command = registry:getCommand(path)
9
- if command == nil or command.options.arguments == nil then
10
- return {}
11
- end
12
- local _exp = command.options.arguments
13
- -- ▼ ReadonlyArray.map ▼
14
- local _newValue = table.create(#_exp)
15
- local _callback = function(arg)
16
- return arg.name
17
- end
18
- for _k, _v in _exp do
19
- _newValue[_k] = _callback(_v, _k - 1, _exp)
20
- end
21
- -- ▲ ReadonlyArray.map ▲
22
- return _newValue
23
- end
24
- local function getMissingArgs(registry, path, text)
25
- local _commandOptions = registry:getCommand(path)
26
- if _commandOptions ~= nil then
27
- _commandOptions = _commandOptions.options
28
- end
29
- local commandOptions = _commandOptions
30
- if commandOptions == nil or commandOptions.arguments == nil or #commandOptions.arguments == 0 then
31
- return {}
32
- end
33
- local lastPartIndex = #text - path:size() - 1
34
- local missingArgs = {}
35
- local index = 0
36
- for _, arg in commandOptions.arguments do
37
- if arg.optional then
38
- break
39
- end
40
- if index > lastPartIndex then
41
- local _name = arg.name
42
- table.insert(missingArgs, _name)
43
- end
44
- index += 1
45
- end
46
- return missingArgs
47
- end
48
- return {
49
- getArgumentNames = getArgumentNames,
50
- getMissingArgs = getMissingArgs,
51
- }
@@ -1,4 +0,0 @@
1
- import { BaseRegistry, RegistryPath } from "@rbxts/centurion";
2
- import { ArgumentSuggestion, Suggestion } from "../types";
3
- export declare function getArgumentSuggestion(registry: BaseRegistry, path: RegistryPath, index: number, text?: string): ArgumentSuggestion | undefined;
4
- export declare function getCommandSuggestion(registry: BaseRegistry, parentPath?: RegistryPath, text?: string): Suggestion | undefined;
@@ -1,203 +0,0 @@
1
- -- Compiled with roblox-ts v2.3.0-dev-26ec859
2
- local TS = _G[script]
3
- local ArrayUtil = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.data).ArrayUtil
4
- local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players
5
- local MAX_OTHER_SUGGESTIONS = 3
6
- local function getSortedIndices(max, strings, text)
7
- -- If no text is provided, sort alphabetically
8
- if text == nil then
9
- local _array = {}
10
- local _length = #_array
11
- table.move(strings, 1, #strings, _length + 1, _array)
12
- table.sort(_array)
13
- -- ▼ ReadonlyArray.map ▼
14
- local _newValue = table.create(#_array)
15
- local _callback = function(_, index)
16
- return index
17
- end
18
- for _k, _v in _array do
19
- _newValue[_k] = _callback(_v, _k - 1, _array)
20
- end
21
- -- ▲ ReadonlyArray.map ▲
22
- local sorted = _newValue
23
- return ArrayUtil.slice(sorted, 0, math.min(#sorted, max))
24
- end
25
- -- Otherwise, sort by the closest match
26
- local textLower = string.lower(text)
27
- local textEndIndex = #text
28
- local results = {}
29
- for i = 0, #strings - 1 do
30
- local part = string.sub(string.lower(strings[i + 1]), 0, textEndIndex)
31
- if part == textLower then
32
- local _arg0 = { #part, i }
33
- table.insert(results, _arg0)
34
- end
35
- end
36
- table.sort(results, function(a, b)
37
- if a[1] == b[1] then
38
- return strings[a[2] + 1] < strings[b[2] + 1]
39
- end
40
- return a[1] < b[1]
41
- end)
42
- local _exp = ArrayUtil.slice(results, 0, math.min(#results, max))
43
- -- ▼ ReadonlyArray.map ▼
44
- local _newValue = table.create(#_exp)
45
- local _callback = function(val)
46
- return val[2]
47
- end
48
- for _k, _v in _exp do
49
- _newValue[_k] = _callback(_v, _k - 1, _exp)
50
- end
51
- -- ▲ ReadonlyArray.map ▲
52
- return _newValue
53
- end
54
- local function getArgumentSuggestion(registry, path, index, text)
55
- local command = registry:getCommand(path)
56
- if command == nil then
57
- return nil
58
- end
59
- local args = command.options.arguments
60
- if args == nil or #args == 0 then
61
- return nil
62
- end
63
- if index < 0 or index >= #args then
64
- return nil
65
- end
66
- local arg = args[index + 1]
67
- local typeObject = registry:getType(arg.type)
68
- if typeObject == nil then
69
- return nil
70
- end
71
- local _result
72
- if arg.suggestions ~= nil then
73
- local _array = {}
74
- local _length = #_array
75
- local _array_1 = arg.suggestions
76
- table.move(_array_1, 1, #_array_1, _length + 1, _array)
77
- _result = _array
78
- else
79
- _result = {}
80
- end
81
- local argSuggestions = _result
82
- if typeObject.suggestions ~= nil then
83
- local _condition = text
84
- if _condition == nil then
85
- _condition = ""
86
- end
87
- for _, suggestion in typeObject.suggestions(_condition, Players.LocalPlayer) do
88
- table.insert(argSuggestions, suggestion)
89
- end
90
- end
91
- -- If the type is not marked as "expensive", transform the text into the type
92
- -- If the transformation fails, include the error message in the suggestion
93
- local errorText
94
- local success, err = pcall(function()
95
- if typeObject.expensive then
96
- return nil
97
- end
98
- local _condition = text
99
- if _condition == nil then
100
- _condition = ""
101
- end
102
- local transformResult = typeObject.transform(_condition, Players.LocalPlayer)
103
- if transformResult.ok then
104
- return nil
105
- end
106
- errorText = transformResult.value
107
- end)
108
- if not success then
109
- errorText = "Failed to transform argument"
110
- warn(err)
111
- end
112
- local _exp = getSortedIndices(MAX_OTHER_SUGGESTIONS, argSuggestions, text)
113
- -- ▼ ReadonlyArray.map ▼
114
- local _newValue = table.create(#_exp)
115
- local _callback = function(index)
116
- return argSuggestions[index + 1]
117
- end
118
- for _k, _v in _exp do
119
- _newValue[_k] = _callback(_v, _k - 1, _exp)
120
- end
121
- -- ▲ ReadonlyArray.map ▲
122
- local otherSuggestions = _newValue
123
- local _object = {
124
- type = "argument",
125
- title = arg.name,
126
- others = otherSuggestions,
127
- description = arg.description,
128
- dataType = typeObject.name,
129
- }
130
- local _left = "optional"
131
- local _condition = arg.optional
132
- if _condition == nil then
133
- _condition = false
134
- end
135
- _object[_left] = _condition
136
- _object.error = errorText
137
- return _object
138
- end
139
- local function getCommandSuggestion(registry, parentPath, text)
140
- local paths = if parentPath ~= nil then registry:getChildPaths(parentPath) else registry:getRootPaths()
141
- if #paths == 0 then
142
- return nil
143
- end
144
- -- ▼ ReadonlyArray.map ▼
145
- local _newValue = table.create(#paths)
146
- local _callback = function(path)
147
- return path:tail()
148
- end
149
- for _k, _v in paths do
150
- _newValue[_k] = _callback(_v, _k - 1, paths)
151
- end
152
- -- ▲ ReadonlyArray.map ▲
153
- local pathNames = _newValue
154
- local sortedPaths = getSortedIndices(MAX_OTHER_SUGGESTIONS + 1, pathNames, text)
155
- if #sortedPaths == 0 then
156
- return nil
157
- end
158
- local firstPath = paths[sortedPaths[1] + 1]
159
- local _result = registry:getCommand(firstPath)
160
- if _result ~= nil then
161
- _result = _result.options
162
- end
163
- local _condition = _result
164
- if _condition == nil then
165
- local _result_1 = registry:getGroup(firstPath)
166
- if _result_1 ~= nil then
167
- _result_1 = _result_1.options
168
- end
169
- _condition = _result_1
170
- end
171
- local mainData = _condition
172
- if mainData == nil then
173
- return nil
174
- end
175
- local _result_1
176
- if #sortedPaths > 1 then
177
- local _exp = ArrayUtil.slice(sortedPaths, 1)
178
- -- ▼ ReadonlyArray.map ▼
179
- local _newValue_1 = table.create(#_exp)
180
- local _callback_1 = function(index)
181
- return pathNames[index + 1]
182
- end
183
- for _k, _v in _exp do
184
- _newValue_1[_k] = _callback_1(_v, _k - 1, _exp)
185
- end
186
- -- ▲ ReadonlyArray.map ▲
187
- _result_1 = _newValue_1
188
- else
189
- _result_1 = {}
190
- end
191
- local otherNames = _result_1
192
- return {
193
- type = "command",
194
- title = firstPath:tail(),
195
- others = otherNames,
196
- description = mainData.description,
197
- shortcuts = mainData.shortcuts,
198
- }
199
- end
200
- return {
201
- getArgumentSuggestion = getArgumentSuggestion,
202
- getCommandSuggestion = getCommandSuggestion,
203
- }