local z=game:GetService("\080\108\097\121\101\114\115")local s=z.LocalPlayer return function(z)local B=z.Util local o=require(script:WaitForChild("\087\105\110\100\111\119"))o.Cmdr=z local X=(require(script:WaitForChild("\065\117\116\111\067\111\109\112\108\101\116\101")))(z)o.AutoComplete=X function o.ProcessEntry(X)X=B.TrimString(X)if#X==0 then return end o:AddLine(o:GetLabel()..(" "..X),Color3.fromRGB(255,223,93))o:AddLine(z.Dispatcher:EvaluateAndRun(X,s,{IsHuman=true}))end function o.OnTextChanged(G)local Y=z.Dispatcher:Evaluate(G,s,true)local r=B.SplitString(G)local O=table.remove(r,1)local i=false if Y then r=B.MashExcessArguments(r,#Y.Object.Args)i=#r==#Y.Object.Args end local W=O and#r>0 if(G:sub(#G,#G)):match("\037\115")and not i then W=true r[#r+1]=""end if Y and W then local z,s=Y:Validate()o:SetIsValidInput(z,("\086\097\108\105\100\097\116\105\111\110 \101\114\114\111\114\115\058 \037\115"):format(s or""))local B={}local O=Y:GetArgument(#r)if O then local z=O.TextSegmentInProgress local W=false if O.RawSegmentsAreAutocomplete then for z,s in ipairs(O.RawSegments)do B[z]={s,s}end else local s,o=O:GetAutocomplete()o=o or{}W=o.IsPartial or false for s,o in pairs(s)do B[s]={z,o}end end local P=true if#z>0 then P,s=O:Validate()end if not i and P then o:HideInvalidState()end return X:Show(B,{at=i and(#G-#z)+((G:sub(#G,#G)):match("\037\115")and-1 or 0),prefix=#O.RawSegments==1 and O.Prefix or"",isLast=#Y.Arguments==#Y.ArgumentDefinitions and#z>0,numArgs=#r;command=Y;arg=O,name=O.Name..(O.Required and""or"\063"),type=O.Type.DisplayName,description=P==false and s or O.Object.Description;invalid=not P;isPartial=W})end elseif O and#r==0 then o:SetIsValidInput(true)local s=z.Registry:GetCommand(O)local B if s then B={s.Name,s.Name,options={name=s.Name;description=s.Description}}local z=s.Args and s.Args[1]if type(z)=="\102\117\110\099\116\105\111\110"then z=z(Y)end if z and(not z.Optional and z.Default==nil)then o:SetIsValidInput(false,"\084\104\105\115 \099\111\109\109\097\110\100 \104\097\115 \114\101\113\117\105\114\101\100 \097\114\103\117\109\101\110\116\115\046")o:HideInvalidState()end else o:SetIsValidInput(false,("\037\113 \105\115 \110\111\116 \097 \118\097\108\105\100 \099\111\109\109\097\110\100 \110\097\109\101\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"):format(O))end local G={B}for s,o in pairs(z.Registry:GetCommandNames())do if O:lower()==(o:lower()):sub(1,#O)and(B==nil or B[1]~=O)then local s=z.Registry:GetCommand(o)G[#G+1]={O,o;options={name=s.Name;description=s.Description}}end end return X:Show(G)end o:SetIsValidInput(false,"\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")X:Hide()end o:UpdateLabel()o:UpdateWindowHeight()return{Window=o;AutoComplete=X}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.TextSegmentInProgress

				local isPartial = false
				if lastArgument.RawSegmentsAreAutocomplete then
					for i, segment in ipairs(lastArgument.RawSegments) do
						acItems[i] = { segment, segment }
					end
				else
					local items, options = lastArgument:GetAutocomplete()
					options = options or {}
					isPartial = options.IsPartial or false

					for i, item in pairs(items) do
						acItems[i] = { typedText, item }
					end
				end

				local valid = true

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

				if not atEnd and valid then
					Window:HideInvalidState()
				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,
					isPartial = isPartial,
				})
			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,
					},
				}

				local arg = exactCommand.Args and exactCommand.Args[1]

				if type(arg) == "function" then
					arg = arg(command)
				end

				if arg and (not arg.Optional and arg.Default == nil) then
					Window:SetIsValidInput(false, "This command has required arguments.")
					Window:HideInvalidState()
				end
			else
				Window:SetIsValidInput(
					false,
					("%q is not a valid command name. Use the help command to see all available commands."):format(
						commandText
					)
				)
			end

			local acItems = { exactMatch }
			for _, cmd in pairs(Cmdr.Registry:GetCommandNames()) 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, "Use the help command to see all available commands.")
		AutoComplete:Hide()
	end

	Window:UpdateLabel()
	Window:UpdateWindowHeight()

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