local G=game:GetService("\080\108\097\121\101\114\115")local M=G.LocalPlayer return function(G)local t=G.Util local m=require(script:WaitForChild("\087\105\110\100\111\119"))m.Cmdr=G local D=(require(script:WaitForChild("\065\117\116\111\067\111\109\112\108\101\116\101")))(G)m.AutoComplete=D function m.ProcessEntry(D)D=t.TrimString(D)if#D==0 then return end m:AddLine(m:GetLabel()..(" "..D),Color3.fromRGB(255,223,93))m:AddLine(G.Dispatcher:EvaluateAndRun(D,M,{IsHuman=true}))end function m.OnTextChanged(n)local E=G.Dispatcher:Evaluate(n,M,true)local P=t.SplitString(n)local q=table.remove(P,1)local c=false if E then P=t.MashExcessArguments(P,#E.Object.Args)c=#P==#E.Object.Args end local x=q and#P>0 if(n:sub(#n,#n)):match("\037\115")and not c then x=true P[#P+1]=""end if E and x then local G,M=E:Validate()m:SetIsValidInput(G,("\086\097\108\105\100\097\116\105\111\110 \101\114\114\111\114\115\058 \037\115"):format(M or""))local t={}local q=E:GetArgument(#P)if q then local G=q.RawSegments[#q.RawSegments]local m=q:GetAutocomplete()for M,m in pairs(m)do t[M]={G,m}end local x=true if#G>0 then x,M=q:Validate()end return D:Show(t,{at=c and(#n-#G)+((n:sub(#n,#n)):match("\037\115")and-1 or 0);prefix=#q.RawSegments==1 and q.Prefix or"",isLast=#E.Arguments==#E.ArgumentDefinitions and#G>0,numArgs=#P;command=E;arg=q,name=q.Name..(q.Required and""or"\063"),type=q.Type.DisplayName;description=x==false and M or q.Object.Description;invalid=not x})end elseif q and#P==0 then m:SetIsValidInput(true)local M=G.Registry:GetCommand(q)local t if M then t={M.Name;M.Name,options={name=M.Name,description=M.Description}}end local n={t}for M,m in pairs(G.Registry:GetCommandsAsStrings())do if q:lower()==(m:lower()):sub(1,#q)and(t==nil or t[1]~=q)then local M=G.Registry:GetCommand(m)n[#n+1]={q,m;options={name=M.Name;description=M.Description}}end end return D:Show(n)end m:SetIsValidInput(false,"\073\110\118\097\108\105\100 \099\111\109\109\097\110\100\046 \085\115\101 \116\104\101 \104\101\108\112 \099\111\109\109\097\110\100 \116\111 \115\101\101 \097\108\108 \097\118\097\105\108\097\098\108\101 \099\111\109\109\097\110\100\115\046")D:Hide()end m:UpdateLabel()m:UpdateWindowHeight()return{Window=m;AutoComplete=D}end
-- Here be dragons

local Players = game:GetService("Players")
local Player = Players.LocalPlayer

return function(Cmdr)
	local Util = Cmdr.Util

	local Window = require(script:WaitForChild("Window"))
	Window.Cmdr = Cmdr

	local AutoComplete = require(script:WaitForChild("AutoComplete"))(Cmdr)
	Window.AutoComplete = AutoComplete

	-- Sets the Window.ProcessEntry callback so that we can dispatch our commands out
	function Window.ProcessEntry(text)
		text = Util.TrimString(text)

		if #text == 0 then
			return
		end

		Window:AddLine(Window:GetLabel() .. " " .. text, Color3.fromRGB(255, 223, 93))

		Window:AddLine(Cmdr.Dispatcher:EvaluateAndRun(text, Player, {
			IsHuman = true,
		}))
	end

	-- Sets the Window.OnTextChanged callback so we can update the auto complete
	function Window.OnTextChanged(text)
		local command = Cmdr.Dispatcher:Evaluate(text, Player, true)
		local arguments = Util.SplitString(text)
		local commandText = table.remove(arguments, 1)
		local atEnd = false
		if command then
			arguments = Util.MashExcessArguments(arguments, #command.Object.Args)

			atEnd = #arguments == #command.Object.Args
		end

		local entryComplete = commandText and #arguments > 0

		if text:sub(#text, #text):match("%s") and not atEnd then
			entryComplete = true
			arguments[#arguments + 1] = ""
		end

		if command and entryComplete then
			local commandValid, errorText = command:Validate()

			Window:SetIsValidInput(commandValid, ("Validation errors: %s"):format(errorText or ""))

			local acItems = {}

			local lastArgument = command:GetArgument(#arguments)
			if lastArgument then
				local typedText = lastArgument.RawSegments[#lastArgument.RawSegments]
				local items = lastArgument:GetAutocomplete()
				for i, item in pairs(items) do
					acItems[i] = { typedText, item }
				end

				local valid = true

				if #typedText > 0 then
					valid, errorText = lastArgument:Validate()
				end

				return AutoComplete:Show(acItems, {
					at = atEnd and #text - #typedText + (text:sub(#text, #text):match("%s") and -1 or 0),
					prefix = #lastArgument.RawSegments == 1 and lastArgument.Prefix or "",
					isLast = #command.Arguments == #command.ArgumentDefinitions and #typedText > 0,
					numArgs = #arguments,
					command = command,
					arg = lastArgument,
					name = lastArgument.Name .. (lastArgument.Required and "" or "?"),
					type = lastArgument.Type.DisplayName,
					description = (valid == false and errorText) or lastArgument.Object.Description,
					invalid = not valid,
				})
			end
		elseif commandText and #arguments == 0 then
			Window:SetIsValidInput(true)
			local exactCommand = Cmdr.Registry:GetCommand(commandText)
			local exactMatch
			if exactCommand then
				exactMatch = {
					exactCommand.Name,
					exactCommand.Name,
					options = {
						name = exactCommand.Name,
						description = exactCommand.Description,
					},
				}
			end

			local acItems = { exactMatch }
			for _, cmd in pairs(Cmdr.Registry:GetCommandsAsStrings()) do
				if
					commandText:lower() == cmd:lower():sub(1, #commandText)
					and (exactMatch == nil or exactMatch[1] ~= commandText)
				then
					local commandObject = Cmdr.Registry:GetCommand(cmd)
					acItems[#acItems + 1] = {
						commandText,
						cmd,
						options = {
							name = commandObject.Name,
							description = commandObject.Description,
						},
					}
				end
			end

			return AutoComplete:Show(acItems)
		end

		Window:SetIsValidInput(false, "Invalid command. Use the help command to see all available commands.")
		AutoComplete:Hide()
	end

	Window:UpdateLabel()
	Window:UpdateWindowHeight()

	return {
		Window = Window,
		AutoComplete = AutoComplete,
	}
end
