@rbxts/centurion-ui 1.0.0-dev-dd918ea → 1.0.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.
@@ -2,10 +2,9 @@
2
2
  local TS = _G[script]
3
3
  local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
4
4
  local Vide = _vide
5
- local effect = _vide.effect
5
+ local derive = _vide.derive
6
6
  local For = _vide.For
7
7
  local read = _vide.read
8
- local source = _vide.source
9
8
  local useAtom = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-atom").useAtom
10
9
  local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
11
10
  local interfaceOptions = TS.import(script, script.Parent.Parent.Parent, "store").interfaceOptions
@@ -17,29 +16,30 @@ local function HistoryList(_param)
17
16
  local position = _param.position
18
17
  local maxHeight = _param.maxHeight
19
18
  local options = useAtom(interfaceOptions)
20
- local scrollingEnabled = source(false)
21
- local canvasSize = source(UDim2.new())
22
- local canvasPos = source(Vector2.new())
23
- effect(function()
24
- local height = read(data).height - px(8)
25
- canvasSize(UDim2.new(0, 0, 0, height))
26
- canvasPos(Vector2.new(0, height))
27
- if maxHeight ~= nil then
28
- scrollingEnabled(height > read(maxHeight))
29
- end
19
+ local height = derive(function()
20
+ return read(data).height - px(8)
21
+ end)
22
+ local exceedsMaxHeight = derive(function()
23
+ return maxHeight ~= nil and height() > read(maxHeight)
30
24
  end)
31
25
  return Vide.jsx(ScrollingFrame, {
32
26
  size = size,
33
27
  position = position,
34
- canvasSize = canvasSize,
35
- canvasPosition = canvasPos,
28
+ canvasSize = function()
29
+ return UDim2.fromOffset(0, height())
30
+ end,
31
+ canvasPosition = function()
32
+ return Vector2.new(0, height())
33
+ end,
36
34
  scrollBarColor = function()
37
35
  return options().palette.subtext
38
36
  end,
39
37
  scrollBarThickness = function()
40
- return if scrollingEnabled() then 10 else 0
38
+ return if exceedsMaxHeight() then 10 else 0
39
+ end,
40
+ scrollingEnabled = function()
41
+ return exceedsMaxHeight()
41
42
  end,
42
- scrollingEnabled = scrollingEnabled,
43
43
  }, Vide.jsx(For, {
44
44
  each = function()
45
45
  return read(data).lines
@@ -5,7 +5,7 @@ local ImmutableRegistryPath = _centurion.ImmutableRegistryPath
5
5
  local RegistryPath = _centurion.RegistryPath
6
6
  local IS_EDIT = TS.import(script, script.Parent.Parent.Parent, "constants", "util").IS_EDIT
7
7
  local function formatPartsAsPath(parts)
8
- return table.concat(parts, "/")
8
+ return string.lower(table.concat(parts, "/"))
9
9
  end
10
10
  local function getValidPath(registry, text)
11
11
  if #text == 0 then
@@ -17,7 +17,7 @@ local function getValidPath(registry, text)
17
17
  end
18
18
  local path = RegistryPath:empty()
19
19
  for _, part in text do
20
- path:append(part)
20
+ path:append(string.lower(part))
21
21
  if registry:getCommand(path) == nil and registry:getGroup(path) == nil and #registry:getChildPaths(path) == 0 then
22
22
  path:remove(path:size() - 1)
23
23
  break
@@ -2,6 +2,9 @@
2
2
  local TS = _G[script]
3
3
  local Players = TS.import(script, TS.getModule(script, "@rbxts", "services")).Players
4
4
  local MAX_OTHER_SUGGESTIONS = 3
5
+ local function formatText(text)
6
+ return if #{ string.match(text, "%s") } == 0 then text else `"{text}"`
7
+ end
5
8
  local function getMatches(strings, text)
6
9
  if text == nil then
7
10
  table.sort(strings)
@@ -41,51 +44,61 @@ local function getMatches(strings, text)
41
44
  return _newValue
42
45
  end
43
46
  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
47
  local _result
48
+ if arg.options.suggestions ~= nil then
49
+ local _exp = arg.options.suggestions
50
+ -- ▼ ReadonlyArray.map ▼
51
+ local _newValue = table.create(#_exp)
52
+ for _k, _v in _exp do
53
+ _newValue[_k] = formatText(_v, _k - 1, _exp)
54
+ end
55
+ -- ▲ ReadonlyArray.map ▲
56
+ _result = _newValue
57
+ else
58
+ _result = {}
59
+ end
60
+ local suggestions = _result
61
+ local singleArg = arg.kind == "single"
62
+ local _result_1
51
63
  if singleArg then
52
- local _result_1 = arg.type.suggestions
53
- if _result_1 ~= nil then
64
+ local _result_2 = arg.type.suggestions
65
+ if _result_2 ~= nil then
54
66
  local _condition = arg.input
55
67
  if _condition == nil then
56
68
  _condition = ""
57
69
  end
58
- _result_1 = _result_1(_condition, Players.LocalPlayer)
70
+ _result_2 = _result_2(_condition, Players.LocalPlayer)
59
71
  end
60
- _result = _result_1
72
+ _result_1 = _result_2
61
73
  else
62
- local _result_1 = arg.type.suggestions
63
- if _result_1 ~= nil then
64
- _result_1 = _result_1(arg.input, Players.LocalPlayer)
74
+ local _result_2 = arg.type.suggestions
75
+ if _result_2 ~= nil then
76
+ _result_2 = _result_2(arg.input, Players.LocalPlayer)
65
77
  end
66
- _result = _result_1
78
+ _result_1 = _result_2
67
79
  end
68
- local typeSuggestions = _result
80
+ local typeSuggestions = _result_1
69
81
  if typeSuggestions ~= nil then
70
82
  for _, text in typeSuggestions do
71
- table.insert(suggestions, text)
83
+ local _arg0 = formatText(text)
84
+ table.insert(suggestions, _arg0)
72
85
  end
73
86
  end
74
87
  local errorText
75
88
  if not arg.type.expensive then
76
89
  local success, err = pcall(function()
77
- local _result_1
90
+ local _result_2
78
91
  if singleArg then
79
92
  local _type = arg.type
80
93
  local _condition = arg.input
81
94
  if _condition == nil then
82
95
  _condition = ""
83
96
  end
84
- _result_1 = _type.transform(_condition, Players.LocalPlayer)
97
+ _result_2 = _type.transform(_condition, Players.LocalPlayer)
85
98
  else
86
- _result_1 = arg.type.transform(arg.input, Players.LocalPlayer)
99
+ _result_2 = arg.type.transform(arg.input, Players.LocalPlayer)
87
100
  end
88
- local transformResult = _result_1
101
+ local transformResult = _result_2
89
102
  if transformResult.ok then
90
103
  return nil
91
104
  end
@@ -170,7 +183,7 @@ local function getCommandSuggestion(registry, parentPath, text)
170
183
  local _newValue_1 = table.create(#sortedPaths)
171
184
  local _callback_1 = function(_param)
172
185
  local str = _param[2]
173
- return str
186
+ return formatText(str)
174
187
  end
175
188
  for _k, _v in sortedPaths do
176
189
  _newValue_1[_k] = _callback_1(_v, _k - 1, sortedPaths)
@@ -0,0 +1 @@
1
+ export * from "./terminal-text-field";
@@ -0,0 +1,7 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local exports = {}
4
+ for _k, _v in TS.import(script, script, "terminal-text-field") or {} do
5
+ exports[_k] = _v
6
+ end
7
+ return exports
@@ -0,0 +1,5 @@
1
+ import { BaseRegistry } from "@rbxts/centurion";
2
+ import { Suggestion } from "../../../types";
3
+ export declare function completeCommand(registry: BaseRegistry, text: string, suggestion: string): string;
4
+ export declare function completeArgument(text: string, suggestion: string, commandArgCount: number): string;
5
+ export declare function getSuggestedText(registry: BaseRegistry, text: string, suggestion?: Suggestion): string;
@@ -0,0 +1,128 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local _store = TS.import(script, script.Parent.Parent.Parent.Parent, "store")
4
+ local commandArgIndex = _store.commandArgIndex
5
+ local currentCommandPath = _store.currentCommandPath
6
+ local currentTextPart = _store.currentTextPart
7
+ local terminalArgIndex = _store.terminalArgIndex
8
+ local terminalTextParts = _store.terminalTextParts
9
+ local _command = TS.import(script, script.Parent.Parent, "command")
10
+ local formatPartsAsPath = _command.formatPartsAsPath
11
+ local getArgumentNames = _command.getArgumentNames
12
+ local function replaceTextPart(text, ...)
13
+ local suggestions = { ... }
14
+ local currentPart = currentTextPart()
15
+ local _result = currentPart
16
+ if _result ~= nil then
17
+ _result = #_result
18
+ end
19
+ local _condition = _result
20
+ if _condition == nil then
21
+ _condition = 0
22
+ end
23
+ local currentPartSize = _condition
24
+ local _text = text
25
+ local _arg1 = #text - currentPartSize
26
+ local result = string.sub(_text, 0, _arg1)
27
+ result ..= table.concat(suggestions, " ")
28
+ return result
29
+ end
30
+ local function completeCommand(registry, text, suggestion)
31
+ local textParts = terminalTextParts()
32
+ local atNextPart = string.sub(text, -1) == " "
33
+ local _array = {}
34
+ local _length = #_array
35
+ table.move(textParts, 1, #textParts, _length + 1, _array)
36
+ local pathParts = _array
37
+ if not atNextPart then
38
+ local _arg0 = #textParts - 1
39
+ table.remove(pathParts, _arg0 + 1)
40
+ end
41
+ local _suggestion = suggestion
42
+ table.insert(pathParts, _suggestion)
43
+ local _command_1 = registry:getCommandByString(formatPartsAsPath(pathParts))
44
+ if _command_1 ~= nil then
45
+ _command_1 = _command_1.options
46
+ end
47
+ local command = _command_1
48
+ local result = replaceTextPart(text, suggestion)
49
+ -- Add a space if this path isn't a command (meaning it's a group) or is a command with arguments
50
+ local _condition = command == nil
51
+ if not _condition then
52
+ local _result = command.arguments
53
+ if _result ~= nil then
54
+ _result = #_result == 0
55
+ end
56
+ local _condition_1 = _result
57
+ if _condition_1 == nil then
58
+ _condition_1 = true
59
+ end
60
+ _condition = not _condition_1
61
+ end
62
+ if _condition then
63
+ result ..= " "
64
+ end
65
+ return result
66
+ end
67
+ local function completeArgument(text, suggestion, commandArgCount)
68
+ local argIndex = terminalArgIndex()
69
+ if argIndex == nil or commandArgCount == 0 then
70
+ return text
71
+ end
72
+ local result = replaceTextPart(text, suggestion)
73
+ if argIndex < commandArgCount - 1 then
74
+ result ..= " "
75
+ end
76
+ return result
77
+ end
78
+ local function getSuggestedText(registry, text, suggestion)
79
+ if suggestion == nil then
80
+ return text
81
+ end
82
+ local suggestionText
83
+ local parts = terminalTextParts()
84
+ if #parts == 0 or suggestion.type == "command" then
85
+ suggestionText = suggestion.title
86
+ else
87
+ local command = currentCommandPath()
88
+ local argIndex = terminalArgIndex()
89
+ if command == nil or argIndex == nil then
90
+ return text
91
+ end
92
+ local atNextPart = string.sub(text, -1) == " "
93
+ if atNextPart and argIndex == commandArgIndex() then
94
+ suggestionText = suggestion.title
95
+ elseif not (#suggestion.others == 0) then
96
+ suggestionText = suggestion.others[1]
97
+ else
98
+ local _condition = currentTextPart()
99
+ if _condition == nil then
100
+ _condition = ""
101
+ end
102
+ suggestionText = _condition
103
+ end
104
+ local argNames = getArgumentNames(registry, command)
105
+ for i = argIndex + 1, #argNames - 1 do
106
+ suggestionText ..= ` {argNames[i + 1]}`
107
+ end
108
+ end
109
+ local _result = currentTextPart()
110
+ if _result ~= nil then
111
+ _result = #_result
112
+ end
113
+ local _condition = _result
114
+ if _condition == nil then
115
+ _condition = 0
116
+ end
117
+ local partSize = _condition
118
+ local result = text
119
+ local _suggestionText = suggestionText
120
+ local _arg0 = partSize + 1
121
+ result ..= string.sub(_suggestionText, _arg0)
122
+ return result
123
+ end
124
+ return {
125
+ completeCommand = completeCommand,
126
+ completeArgument = completeArgument,
127
+ getSuggestedText = getSuggestedText,
128
+ }
@@ -5,30 +5,25 @@ local UserInputService = TS.import(script, TS.getModule(script, "@rbxts", "servi
5
5
  local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
6
6
  local Vide = _vide
7
7
  local cleanup = _vide.cleanup
8
- local effect = _vide.effect
9
8
  local source = _vide.source
10
- local useAtom = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-atom").useAtom
11
- local useClient = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-client").useClient
12
- local useEvent = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-event").useEvent
13
- local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
14
- local _store = TS.import(script, script.Parent.Parent.Parent, "store")
15
- local commandArgIndex = _store.commandArgIndex
9
+ local useAtom = TS.import(script, script.Parent.Parent.Parent.Parent, "hooks", "use-atom").useAtom
10
+ local useClient = TS.import(script, script.Parent.Parent.Parent.Parent, "hooks", "use-client").useClient
11
+ local useEvent = TS.import(script, script.Parent.Parent.Parent.Parent, "hooks", "use-event").useEvent
12
+ local px = TS.import(script, script.Parent.Parent.Parent.Parent, "hooks", "use-px").px
13
+ local _store = TS.import(script, script.Parent.Parent.Parent.Parent, "store")
16
14
  local currentCommandPath = _store.currentCommandPath
17
15
  local currentSuggestion = _store.currentSuggestion
18
- local currentTextPart = _store.currentTextPart
19
16
  local interfaceOptions = _store.interfaceOptions
20
17
  local interfaceVisible = _store.interfaceVisible
21
- local terminalArgIndex = _store.terminalArgIndex
22
- local terminalText = _store.terminalText
23
- local terminalTextParts = _store.terminalTextParts
24
18
  local terminalTextValid = _store.terminalTextValid
25
- local Frame = TS.import(script, script.Parent.Parent, "ui", "frame").Frame
26
- local Padding = TS.import(script, script.Parent.Parent, "ui", "padding").Padding
27
- local Text = TS.import(script, script.Parent.Parent, "ui", "text").Text
28
- local TextField = TS.import(script, script.Parent.Parent, "ui", "text-field").TextField
29
- local _command = TS.import(script, script.Parent, "command")
30
- local formatPartsAsPath = _command.formatPartsAsPath
31
- local getArgumentNames = _command.getArgumentNames
19
+ local Frame = TS.import(script, script.Parent.Parent.Parent, "ui", "frame").Frame
20
+ local Padding = TS.import(script, script.Parent.Parent.Parent, "ui", "padding").Padding
21
+ local Text = TS.import(script, script.Parent.Parent.Parent, "ui", "text").Text
22
+ local TextField = TS.import(script, script.Parent.Parent.Parent, "ui", "text-field").TextField
23
+ local _suggestion = TS.import(script, script.Parent, "suggestion")
24
+ local completeArgument = _suggestion.completeArgument
25
+ local completeCommand = _suggestion.completeCommand
26
+ local getSuggestedText = _suggestion.getSuggestedText
32
27
  local TEXT_SIZE = 22
33
28
  local function TerminalTextField(_param)
34
29
  local anchor = _param.anchor
@@ -39,7 +34,6 @@ local function TerminalTextField(_param)
39
34
  local onSubmit = _param.onSubmit
40
35
  local client = useClient()
41
36
  local options = useAtom(interfaceOptions)
42
- local visible = useAtom(interfaceVisible)
43
37
  local valid = useAtom(terminalTextValid)
44
38
  local ref = source()
45
39
  local commandHistory = source({})
@@ -47,8 +41,8 @@ local function TerminalTextField(_param)
47
41
  local suggestionText = source("")
48
42
  local currentTextValue = ""
49
43
  -- Focus text field when terminal becomes visible
50
- effect(function()
51
- if visible() then
44
+ local visibleConnection = subscribe(interfaceVisible, function(visible)
45
+ if visible then
52
46
  local _result = ref()
53
47
  if _result ~= nil then
54
48
  _result:CaptureFocus()
@@ -60,6 +54,16 @@ local function TerminalTextField(_param)
60
54
  end
61
55
  end
62
56
  end)
57
+ cleanup(visibleConnection)
58
+ local setText = function(text)
59
+ local textBox = ref()
60
+ if textBox == nil then
61
+ return nil
62
+ end
63
+ textBox.Text = text
64
+ textBox.CursorPosition = #text + 1
65
+ suggestionText(text)
66
+ end
63
67
  local traverseHistory = function(up)
64
68
  local history = commandHistory()
65
69
  if #history == 0 then
@@ -75,8 +79,7 @@ local function TerminalTextField(_param)
75
79
  end
76
80
  local lastIndex = #history - 1
77
81
  if not up and historyIndex == lastIndex then
78
- textBox.Text = ""
79
- suggestionText("")
82
+ setText("")
80
83
  commandHistoryIndex(nil)
81
84
  return nil
82
85
  end
@@ -85,63 +88,20 @@ local function TerminalTextField(_param)
85
88
  _condition = #history
86
89
  end
87
90
  local newIndex = math.clamp(_condition + (if up then -1 else 1), 0, lastIndex)
88
- local newText = history[newIndex + 1]
89
- textBox.Text = newText
90
- textBox.CursorPosition = #newText + 1
91
- suggestionText("")
91
+ setText(history[newIndex + 1])
92
92
  commandHistoryIndex(newIndex)
93
93
  end
94
94
  local suggestionConnection = subscribe(currentSuggestion, function(suggestion)
95
- if suggestion == nil then
96
- suggestionText("")
97
- return nil
98
- end
99
- local atNextPart = string.sub(terminalText(), -1) == " "
100
- local textParts = terminalTextParts()
101
- if #textParts == 0 then
102
- suggestionText(suggestion.title)
103
- return nil
104
- end
105
- local _currentText = ref()
106
- if _currentText ~= nil then
107
- _currentText = _currentText.Text
108
- end
109
- local currentText = _currentText
110
- if currentText == nil then
111
- return nil
112
- end
113
- -- Command suggestions
114
- if suggestion.type == "command" then
115
- local suggestionStartIndex = (if not atNextPart then #textParts[#textParts] else 0) + 1
116
- suggestionText(currentText .. string.sub(suggestion.title, suggestionStartIndex))
117
- return nil
118
- end
119
- -- Argument suggestions
120
- local command = currentCommandPath()
121
- local argIndex = terminalArgIndex()
122
- if suggestion.type ~= "argument" or command == nil or argIndex == nil then
123
- return nil
124
- end
125
- local newText = currentText
126
- if atNextPart and argIndex == commandArgIndex() then
127
- newText ..= suggestion.title
128
- elseif not (#suggestion.others == 0) then
129
- local _exp = suggestion.others[1]
130
- local _result = currentTextPart()
131
- if _result ~= nil then
132
- _result = #_result
133
- end
134
- local _condition = _result
135
- if _condition == nil then
136
- _condition = 0
137
- end
138
- newText ..= string.sub(_exp, _condition + 1)
95
+ local _exp = client.registry
96
+ local _result = ref()
97
+ if _result ~= nil then
98
+ _result = _result.Text
139
99
  end
140
- local argNames = getArgumentNames(client.registry, command)
141
- for i = argIndex + 1, #argNames - 1 do
142
- newText = `{newText} {argNames[i + 1]}`
100
+ local _condition = _result
101
+ if _condition == nil then
102
+ _condition = ""
143
103
  end
144
- suggestionText(newText)
104
+ suggestionText(getSuggestedText(_exp, _condition, suggestion))
145
105
  end)
146
106
  cleanup(suggestionConnection)
147
107
  useEvent(UserInputService.InputBegan, function(input)
@@ -157,6 +117,7 @@ local function TerminalTextField(_param)
157
117
  if _condition then
158
118
  return nil
159
119
  end
120
+ -- Handle history traversal
160
121
  if input.KeyCode == Enum.KeyCode.Up then
161
122
  traverseHistory(true)
162
123
  elseif input.KeyCode == Enum.KeyCode.Down then
@@ -165,120 +126,38 @@ local function TerminalTextField(_param)
165
126
  if input.KeyCode ~= Enum.KeyCode.Tab then
166
127
  return nil
167
128
  end
168
- -- Command suggestions
129
+ -- Handle autocompletion
169
130
  local commandPath = currentCommandPath()
170
131
  local suggestion = currentSuggestion()
171
132
  if suggestion == nil then
172
133
  return nil
173
134
  end
174
135
  local currentText = textBox.Text
175
- local textParts = terminalTextParts()
176
- local lastPart = textParts[#textParts]
177
- local atNextPart = string.sub(currentText, -1) == " "
178
136
  if commandPath == nil then
179
- local suggestionTitle = suggestion.title
180
- if #textParts == 0 then
181
- return nil
182
- end
183
- local _array = {}
184
- local _length = #_array
185
- table.move(textParts, 1, #textParts, _length + 1, _array)
186
- local pathParts = _array
187
- local newText = currentText
188
- if atNextPart then
189
- newText ..= suggestionTitle
190
- table.insert(pathParts, suggestionTitle)
191
- elseif not (#textParts == 0) then
192
- local _newText = newText
193
- local _arg1 = #newText - #lastPart
194
- newText = string.sub(_newText, 0, _arg1) .. suggestionTitle
195
- local _arg0 = #textParts - 1
196
- table.remove(pathParts, _arg0 + 1)
197
- table.insert(pathParts, suggestionTitle)
198
- end
199
- local _nextCommand = client.registry:getCommandByString(formatPartsAsPath(pathParts))
200
- if _nextCommand ~= nil then
201
- _nextCommand = _nextCommand.options
202
- end
203
- local nextCommand = _nextCommand
204
- local _condition_1 = nextCommand == nil
205
- if not _condition_1 then
206
- local _result = nextCommand.arguments
207
- if _result ~= nil then
208
- _result = #_result == 0
209
- end
210
- local _condition_2 = _result
211
- if _condition_2 == nil then
212
- _condition_2 = true
213
- end
214
- _condition_1 = not _condition_2
215
- end
216
- if _condition_1 then
217
- newText ..= " "
218
- end
219
- suggestionText("")
220
- textBox.Text = newText
221
- textBox.CursorPosition = #newText + 1
137
+ setText(completeCommand(client.registry, textBox.Text, suggestion.title))
222
138
  return nil
223
139
  end
224
- local _commandArgs = client.registry:getCommand(commandPath)
225
- if _commandArgs ~= nil then
226
- _commandArgs = _commandArgs.options.arguments
227
- end
228
- local commandArgs = _commandArgs
229
- local _condition_1 = suggestion.type == "command" and not atNextPart
230
- if _condition_1 then
231
- local _result = commandArgs
140
+ local _result = client.registry:getCommand(commandPath)
141
+ if _result ~= nil then
142
+ _result = _result.options.arguments
232
143
  if _result ~= nil then
233
- _result = #_result == 0
234
- end
235
- local _condition_2 = _result
236
- if _condition_2 == nil then
237
- _condition_2 = true
144
+ _result = #_result
238
145
  end
239
- _condition_1 = not _condition_2
240
146
  end
241
- if _condition_1 then
242
- suggestionText("")
243
- local newText = `{currentText} `
244
- textBox.Text = newText
245
- textBox.CursorPosition = #newText + 1
246
- return nil
147
+ local _condition_1 = _result
148
+ if _condition_1 == nil then
149
+ _condition_1 = 0
247
150
  end
248
- -- Argument suggestions
249
- if #suggestion.others == 0 then
151
+ local argCount = _condition_1
152
+ if suggestion.type == "command" and argCount ~= 0 then
153
+ setText(`{currentText} `)
250
154
  return nil
251
155
  end
252
- local argIndex = terminalArgIndex()
253
- if argIndex == nil or commandArgs == nil then
156
+ if #suggestion.others == 0 then
157
+ setText(currentText)
254
158
  return nil
255
159
  end
256
- local newText = currentText
257
- local otherSuggestion = suggestion.others[1]
258
- local trailingSpaces = (string.match(newText, "(%s+)$"))
259
- local _newText = newText
260
- local _exp = #newText
261
- local _condition_2 = #lastPart
262
- if _condition_2 == nil then
263
- _condition_2 = 0
264
- end
265
- local _exp_1 = _exp - _condition_2
266
- local _result = trailingSpaces
267
- if _result ~= nil then
268
- _result = #_result
269
- end
270
- local _condition_3 = _result
271
- if _condition_3 == nil then
272
- _condition_3 = 0
273
- end
274
- newText = string.sub(_newText, 0, _exp_1 - _condition_3)
275
- newText ..= if #{ string.match(otherSuggestion, "%s") } == 0 then otherSuggestion else `"{otherSuggestion}"`
276
- if argIndex < #commandArgs - 1 then
277
- newText ..= " "
278
- end
279
- suggestionText("")
280
- textBox.Text = newText
281
- textBox.CursorPosition = #newText + 1
160
+ setText(completeArgument(currentText, suggestion.others[1], argCount))
282
161
  end)
283
162
  return Vide.jsx(Frame, {
284
163
  anchor = anchor,
@@ -36,6 +36,8 @@ local getCommandSuggestion = _suggestion.getCommandSuggestion
36
36
  local TerminalTextField = TS.import(script, script.Parent, "terminal-text-field").TerminalTextField
37
37
  local MAX_HEIGHT = HISTORY_TEXT_SIZE * 10
38
38
  local TEXT_FIELD_HEIGHT = 40
39
+ local START_QUOTE_PATTERN = `^(['"])`
40
+ local TRAILING_SPACE_PATTERN = "(%s+)$"
39
41
  local function Terminal()
40
42
  local client = useClient()
41
43
  local options = useAtom(interfaceOptions)
@@ -136,38 +138,41 @@ local function Terminal()
136
138
  currentCommandPath(nil)
137
139
  terminalTextValid(false)
138
140
  end
139
- local lastPart = parts[#parts]
140
- local textPart = nil
141
- if string.sub(lastPart, 0, 1) == '"' then
142
- textPart = string.sub(lastPart, 2)
143
- elseif not atNextPart then
144
- textPart = lastPart
141
+ local textPart = parts[#parts]
142
+ local _result = textPart
143
+ if _result ~= nil then
144
+ _result = string.match(_result, START_QUOTE_PATTERN)
145
145
  end
146
- if textPart ~= nil then
147
- local trailingSpaces = (string.match(text, "(%s+)$"))
148
- if trailingSpaces ~= nil then
149
- textPart ..= tostring(trailingSpaces)
146
+ local quoted = _result ~= nil
147
+ if atNextPart and not quoted then
148
+ textPart = nil
149
+ elseif textPart ~= nil then
150
+ local _condition = (string.match(text, TRAILING_SPACE_PATTERN))
151
+ if _condition == nil then
152
+ _condition = ""
150
153
  end
154
+ local spaces = _condition
155
+ textPart ..= tostring(spaces)
151
156
  end
152
157
  local argIndex = if path ~= nil then #parts - path:size() - (if atNextPart then 0 else 1) else -1
153
158
  terminalArgIndex(argIndex)
154
159
  if command == nil or argIndex == -1 then
155
160
  -- Get command suggestions
156
161
  local parentPath = if not (#parts == 0) then RegistryPath.new(ArrayUtil.slice(parts, 0, #parts - (if atNextPart then 0 else 1))) else nil
162
+ currentTextPart(textPart)
157
163
  local _exp = client.registry
158
- local _result = parentPath
159
- if _result ~= nil then
160
- _result = _result:isEmpty()
164
+ local _result_1 = parentPath
165
+ if _result_1 ~= nil then
166
+ _result_1 = _result_1:isEmpty()
161
167
  end
162
- currentSuggestion(getCommandSuggestion(_exp, if not _result then parentPath else nil, textPart))
163
- currentTextPart(textPart)
168
+ currentSuggestion(getCommandSuggestion(_exp, if not _result_1 then parentPath else nil, textPart))
164
169
  return nil
165
170
  end
166
171
  -- Handle arguments
167
172
  local args = command.options.arguments
168
173
  if args == nil then
169
- currentSuggestion(nil)
170
174
  currentTextPart(nil)
175
+ currentSuggestion(nil)
171
176
  commandArgIndex(nil)
172
177
  return nil
173
178
  end
@@ -192,11 +197,11 @@ local function Terminal()
192
197
  endIndex = if numArgs ~= "rest" then i + (numArgs - 1) else nil
193
198
  end
194
199
  local _registry = client.registry
195
- local _result = currentArg
196
- if _result ~= nil then
197
- _result = _result.type
200
+ local _result_1 = currentArg
201
+ if _result_1 ~= nil then
202
+ _result_1 = _result_1.type
198
203
  end
199
- local _condition = _result
204
+ local _condition = _result_1
200
205
  if _condition == nil then
201
206
  _condition = ""
202
207
  end
@@ -217,20 +222,20 @@ local function Terminal()
217
222
  kind = "single",
218
223
  options = currentArg,
219
224
  type = argType,
220
- input = textPart,
221
- }, textPart)
225
+ input = argTextPart,
226
+ }, argTextPart)
222
227
  else
223
228
  local _condition_1 = textPart
224
229
  if _condition_1 == nil then
225
230
  _condition_1 = ""
226
231
  end
227
- local textParts = splitString(_condition_1, ",")
228
- local lastPart = if not (#textParts == 0) then textParts[#textParts] else nil
229
- local _result_1 = textPart
230
- if _result_1 ~= nil then
231
- _result_1 = string.sub(_result_1, -1)
232
+ local textParts = splitString(_condition_1, ",", true)
233
+ local lastText = if not (#textParts == 0) then textParts[#textParts] else nil
234
+ local _result_2 = textPart
235
+ if _result_2 ~= nil then
236
+ _result_2 = string.sub(_result_2, -1)
232
237
  end
233
- argTextPart = if _result_1 ~= "," then lastPart else nil
238
+ argTextPart = if _result_2 ~= "," then lastText else nil
234
239
  suggestion = getArgumentSuggestion({
235
240
  kind = "list",
236
241
  options = currentArg,
@@ -240,11 +245,11 @@ local function Terminal()
240
245
  end
241
246
  currentTextPart(argTextPart)
242
247
  currentSuggestion(suggestion)
243
- local _result_1 = suggestion
244
- if _result_1 ~= nil then
245
- _result_1 = _result_1.error
248
+ local _result_2 = suggestion
249
+ if _result_2 ~= nil then
250
+ _result_2 = _result_2.error
246
251
  end
247
- if _result_1 ~= nil then
252
+ if _result_2 ~= nil then
248
253
  terminalTextValid(false)
249
254
  end
250
255
  end,
package/out/store.luau CHANGED
@@ -14,7 +14,7 @@ local terminalArgIndex = atom(nil)
14
14
  local currentSuggestion = atom(nil)
15
15
  local terminalText = atom("")
16
16
  local terminalTextParts = computed(function()
17
- return splitString(terminalText(), " ")
17
+ return splitString(terminalText(), " ", true)
18
18
  end)
19
19
  local terminalTextValid = atom(false)
20
20
  local currentTextPart = atom(nil)
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-dd918ea",
4
+ "version": "1.0.0",
5
5
  "author": "paradoxuum",
6
6
  "license": "MIT",
7
7
  "main": "out/init.lua",
@@ -32,21 +32,20 @@
32
32
  "dev": "shx rm -rf out && rbxtsc -w"
33
33
  },
34
34
  "devDependencies": {
35
- "@rbxts/centurion": "^1.0.0-dev-dd918ea",
35
+ "@rbxts/centurion": "^1.0.0",
36
36
  "@rbxts/compiler-types": "3.0.0-types.0",
37
- "@rbxts/types": "^1.0.799",
37
+ "@rbxts/types": "^1.0.809",
38
38
  "roblox-ts": "3.0.0",
39
39
  "shx": "^0.3.4",
40
- "typescript": "~5.5.4"
40
+ "typescript": "=5.5.3"
41
41
  },
42
42
  "dependencies": {
43
- "@rbxts/charm": "^0.6.0",
44
- "@rbxts/services": "^1.5.4",
43
+ "@rbxts/charm": "^0.7.5",
44
+ "@rbxts/services": "^1.5.5",
45
45
  "@rbxts/set-timeout": "^1.1.2",
46
- "@rbxts/vide": "^0.4.4"
46
+ "@rbxts/vide": "^0.4.6"
47
47
  },
48
48
  "peerDependencies": {
49
- "@rbxts/centurion": "*"
50
- },
51
- "stableVersion": "1.0.0"
49
+ "@rbxts/centurion": "^1.0.0"
50
+ }
52
51
  }