@rbxts/centurion-ui 1.0.0-dev-ecb0e98 → 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
+ }
@@ -1,35 +1,29 @@
1
1
  -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
- local splitString = TS.import(script, TS.getModule(script, "@rbxts", "centurion").out.shared.util.string).splitString
4
3
  local subscribe = TS.import(script, TS.getModule(script, "@rbxts", "charm").src).subscribe
5
4
  local UserInputService = TS.import(script, TS.getModule(script, "@rbxts", "services")).UserInputService
6
5
  local _vide = TS.import(script, TS.getModule(script, "@rbxts", "vide").src)
7
6
  local Vide = _vide
8
7
  local cleanup = _vide.cleanup
9
- local effect = _vide.effect
10
8
  local source = _vide.source
11
- local useAtom = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-atom").useAtom
12
- local useClient = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-client").useClient
13
- local useEvent = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-event").useEvent
14
- local px = TS.import(script, script.Parent.Parent.Parent, "hooks", "use-px").px
15
- local _store = TS.import(script, script.Parent.Parent.Parent, "store")
16
- 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")
17
14
  local currentCommandPath = _store.currentCommandPath
18
15
  local currentSuggestion = _store.currentSuggestion
19
- local currentTextPart = _store.currentTextPart
20
16
  local interfaceOptions = _store.interfaceOptions
21
17
  local interfaceVisible = _store.interfaceVisible
22
- local terminalArgIndex = _store.terminalArgIndex
23
- local terminalText = _store.terminalText
24
- local terminalTextParts = _store.terminalTextParts
25
18
  local terminalTextValid = _store.terminalTextValid
26
- local Frame = TS.import(script, script.Parent.Parent, "ui", "frame").Frame
27
- local Padding = TS.import(script, script.Parent.Parent, "ui", "padding").Padding
28
- local Text = TS.import(script, script.Parent.Parent, "ui", "text").Text
29
- local TextField = TS.import(script, script.Parent.Parent, "ui", "text-field").TextField
30
- local _command = TS.import(script, script.Parent, "command")
31
- local formatPartsAsPath = _command.formatPartsAsPath
32
- 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
33
27
  local TEXT_SIZE = 22
34
28
  local function TerminalTextField(_param)
35
29
  local anchor = _param.anchor
@@ -40,7 +34,6 @@ local function TerminalTextField(_param)
40
34
  local onSubmit = _param.onSubmit
41
35
  local client = useClient()
42
36
  local options = useAtom(interfaceOptions)
43
- local visible = useAtom(interfaceVisible)
44
37
  local valid = useAtom(terminalTextValid)
45
38
  local ref = source()
46
39
  local commandHistory = source({})
@@ -48,8 +41,8 @@ local function TerminalTextField(_param)
48
41
  local suggestionText = source("")
49
42
  local currentTextValue = ""
50
43
  -- Focus text field when terminal becomes visible
51
- effect(function()
52
- if visible() then
44
+ local visibleConnection = subscribe(interfaceVisible, function(visible)
45
+ if visible then
53
46
  local _result = ref()
54
47
  if _result ~= nil then
55
48
  _result:CaptureFocus()
@@ -61,6 +54,16 @@ local function TerminalTextField(_param)
61
54
  end
62
55
  end
63
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
64
67
  local traverseHistory = function(up)
65
68
  local history = commandHistory()
66
69
  if #history == 0 then
@@ -76,8 +79,7 @@ local function TerminalTextField(_param)
76
79
  end
77
80
  local lastIndex = #history - 1
78
81
  if not up and historyIndex == lastIndex then
79
- textBox.Text = ""
80
- suggestionText("")
82
+ setText("")
81
83
  commandHistoryIndex(nil)
82
84
  return nil
83
85
  end
@@ -86,63 +88,20 @@ local function TerminalTextField(_param)
86
88
  _condition = #history
87
89
  end
88
90
  local newIndex = math.clamp(_condition + (if up then -1 else 1), 0, lastIndex)
89
- local newText = history[newIndex + 1]
90
- textBox.Text = newText
91
- textBox.CursorPosition = #newText + 1
92
- suggestionText("")
91
+ setText(history[newIndex + 1])
93
92
  commandHistoryIndex(newIndex)
94
93
  end
95
94
  local suggestionConnection = subscribe(currentSuggestion, function(suggestion)
96
- if suggestion == nil then
97
- suggestionText("")
98
- return nil
99
- end
100
- local atNextPart = string.sub(terminalText(), -1) == " "
101
- local textParts = terminalTextParts()
102
- if #textParts == 0 then
103
- suggestionText(suggestion.title)
104
- return nil
105
- end
106
- local _currentText = ref()
107
- if _currentText ~= nil then
108
- _currentText = _currentText.Text
95
+ local _exp = client.registry
96
+ local _result = ref()
97
+ if _result ~= nil then
98
+ _result = _result.Text
109
99
  end
110
- local currentText = _currentText
111
- if currentText == nil then
112
- return nil
113
- end
114
- -- Command suggestions
115
- if suggestion.type == "command" then
116
- local suggestionStartIndex = (if not atNextPart then #textParts[#textParts] else 0) + 1
117
- suggestionText(currentText .. string.sub(suggestion.title, suggestionStartIndex))
118
- return nil
119
- end
120
- -- Argument suggestions
121
- local command = currentCommandPath()
122
- local argIndex = terminalArgIndex()
123
- if suggestion.type ~= "argument" or command == nil or argIndex == nil then
124
- return nil
125
- end
126
- local newText = currentText
127
- if atNextPart and argIndex == commandArgIndex() then
128
- newText ..= suggestion.title
129
- elseif not (#suggestion.others == 0) then
130
- local _exp = suggestion.others[1]
131
- local _result = currentTextPart()
132
- if _result ~= nil then
133
- _result = #_result
134
- end
135
- local _condition = _result
136
- if _condition == nil then
137
- _condition = 0
138
- end
139
- newText ..= string.sub(_exp, _condition + 1)
140
- end
141
- local argNames = getArgumentNames(client.registry, command)
142
- for i = argIndex + 1, #argNames - 1 do
143
- newText = `{newText} {argNames[i + 1]}`
100
+ local _condition = _result
101
+ if _condition == nil then
102
+ _condition = ""
144
103
  end
145
- suggestionText(newText)
104
+ suggestionText(getSuggestedText(_exp, _condition, suggestion))
146
105
  end)
147
106
  cleanup(suggestionConnection)
148
107
  useEvent(UserInputService.InputBegan, function(input)
@@ -158,6 +117,7 @@ local function TerminalTextField(_param)
158
117
  if _condition then
159
118
  return nil
160
119
  end
120
+ -- Handle history traversal
161
121
  if input.KeyCode == Enum.KeyCode.Up then
162
122
  traverseHistory(true)
163
123
  elseif input.KeyCode == Enum.KeyCode.Down then
@@ -166,109 +126,38 @@ local function TerminalTextField(_param)
166
126
  if input.KeyCode ~= Enum.KeyCode.Tab then
167
127
  return nil
168
128
  end
169
- -- Command suggestions
129
+ -- Handle autocompletion
170
130
  local commandPath = currentCommandPath()
171
131
  local suggestion = currentSuggestion()
172
132
  if suggestion == nil then
173
133
  return nil
174
134
  end
175
135
  local currentText = textBox.Text
176
- local textParts = terminalTextParts()
177
- local atNextPart = string.sub(currentText, -1) == " "
178
- local lastPart = if not atNextPart then textParts[#textParts] else nil
179
136
  if commandPath == nil then
180
- local suggestionTitle = suggestion.title
181
- if #textParts == 0 then
182
- return nil
183
- end
184
- local _array = {}
185
- local _length = #_array
186
- table.move(textParts, 1, #textParts, _length + 1, _array)
187
- local pathParts = _array
188
- local newText = currentText
189
- if atNextPart then
190
- newText ..= suggestionTitle
191
- table.insert(pathParts, suggestionTitle)
192
- elseif lastPart ~= nil then
193
- local _newText = newText
194
- local _arg1 = #newText - #lastPart
195
- newText = string.sub(_newText, 0, _arg1) .. suggestionTitle
196
- local _arg0 = #textParts - 1
197
- table.remove(pathParts, _arg0 + 1)
198
- table.insert(pathParts, suggestionTitle)
199
- end
200
- local _nextCommand = client.registry:getCommandByString(formatPartsAsPath(pathParts))
201
- if _nextCommand ~= nil then
202
- _nextCommand = _nextCommand.options
203
- end
204
- local nextCommand = _nextCommand
205
- local _condition_1 = nextCommand == nil
206
- if not _condition_1 then
207
- local _result = nextCommand.arguments
208
- if _result ~= nil then
209
- _result = #_result == 0
210
- end
211
- local _condition_2 = _result
212
- if _condition_2 == nil then
213
- _condition_2 = true
214
- end
215
- _condition_1 = not _condition_2
216
- end
217
- if _condition_1 then
218
- newText ..= " "
219
- end
220
- suggestionText("")
221
- textBox.Text = newText
222
- textBox.CursorPosition = #newText + 1
137
+ setText(completeCommand(client.registry, textBox.Text, suggestion.title))
223
138
  return nil
224
139
  end
225
- local _commandArgs = client.registry:getCommand(commandPath)
226
- if _commandArgs ~= nil then
227
- _commandArgs = _commandArgs.options.arguments
228
- end
229
- local commandArgs = _commandArgs
230
- local _condition_1 = suggestion.type == "command" and not atNextPart
231
- if _condition_1 then
232
- local _result = commandArgs
140
+ local _result = client.registry:getCommand(commandPath)
141
+ if _result ~= nil then
142
+ _result = _result.options.arguments
233
143
  if _result ~= nil then
234
- _result = #_result == 0
235
- end
236
- local _condition_2 = _result
237
- if _condition_2 == nil then
238
- _condition_2 = true
144
+ _result = #_result
239
145
  end
240
- _condition_1 = not _condition_2
241
146
  end
242
- if _condition_1 then
243
- suggestionText("")
244
- local newText = `{currentText} `
245
- textBox.Text = newText
246
- textBox.CursorPosition = #newText + 1
247
- return nil
147
+ local _condition_1 = _result
148
+ if _condition_1 == nil then
149
+ _condition_1 = 0
248
150
  end
249
- -- Argument suggestions
250
- if #suggestion.others == 0 then
151
+ local argCount = _condition_1
152
+ if suggestion.type == "command" and argCount ~= 0 then
153
+ setText(`{currentText} `)
251
154
  return nil
252
155
  end
253
- local argIndex = terminalArgIndex()
254
- if argIndex == nil or commandArgs == nil then
156
+ if #suggestion.others == 0 then
157
+ setText(currentText)
255
158
  return nil
256
159
  end
257
- local newText = currentText
258
- local parts = splitString(newText, " ", true)
259
- local currentPart = parts[#parts]
260
- local currentPartSize = if currentTextPart() ~= nil then #currentPart else 0
261
- local _newText = newText
262
- local _arg1 = #newText - currentPartSize
263
- newText = string.sub(_newText, 0, _arg1)
264
- local otherSuggestion = suggestion.others[1]
265
- newText ..= if #{ string.match(otherSuggestion, "%s") } == 0 then otherSuggestion else `"{otherSuggestion}"`
266
- if argIndex < #commandArgs - 1 then
267
- newText ..= " "
268
- end
269
- suggestionText("")
270
- textBox.Text = newText
271
- textBox.CursorPosition = #newText + 1
160
+ setText(completeArgument(currentText, suggestion.others[1], argCount))
272
161
  end)
273
162
  return Vide.jsx(Frame, {
274
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-ecb0e98",
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-ecb0e98",
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
  }