Arguments w/ Chat Commands

Hiya! This may seem like the same topic posted hundreds of times ago, but I hope that I’ve made it different. I’ve been trying to search the DevForum and on the Wiki for a method on getting things outside of a string.

For example, this is how the command works:

How it works:
/ban (Player) (Time) (Appealable; Bool Value) (Reason)

Example:
/ban HarleySummersDev “20d” true “Crashed into my car. xd”

I’m trying to make it so where I can grab it as 4 total arguments. (Excluding the prefix + command).

args[1] = HarleySummersDev
args[2] = 20d / 20 days
args[3] true (bool value)
args[4] Crashed into my car. xd

If someone could help me achieve this, please let me know! I’ve tried the following:

  • string.split
  • string.sub
  • string.gsub

I’d like the best outcome possible instead of lazy methods.

My old method:

/ban (Player) ; (Reason)
string.split method.

Result:
string.split(msg, ";")[1] = /ban (Player)
string.split(msg, ";")[2] = (Reason)

2 Likes

Use string.split(msg, " ") seeming as the common pattern is a blank character.

  • args[1] could be a command
  • args[2] will be name
  • args[3] time string
  • args[4] boolean value
  • args[5] You can use this to determine the cut off point of the first letter and extract it from the message.
1 Like

I’ve already used string.split, but I’m making the Time String & Reason be a full sentence.

string.split(msg, " ") will split every single time it finds a space.

args[1] = HarleySummersDev
args[2] = 20
args[3] = days
args[4] = true
args[5] = Crashed
args[6] = into
etc…

Hence, that’s why I have “” quotation marks to have the string joined together as one.

Hence why I said you can use args[5] to determine the cut off point. :smile:

  • Using string.len you can determine the size of args1, args2, args3, args4 with an additional +4 added to the sum.
  • Seeming as we know args[5] is the final one and its our reason, we wont include it in our addition.
  • Use string.sub(msg, [value we calculated])

e.g.

local args = string.split(msg, " ")
local command = args[1]
local name = args[2]
local date = args[3]
local appeal = args[4]

local length = string.len(command) + string.len(name) + string.len(args) + string.len(args) +4
local reason = string.sub(msg, length)

Should then return your reason.

Even better (not tested but should work):

local args = string.split(msg, " ")
local command = args[1]
local name = args[2]
local date = args[3]
local appeal = args[4]
local searchValue = args[5]
local point = string.find(msg, searchValue) -- this then returns the index number of where it is and you can use that in string.sub
1 Like

Alright, thanks for your input! :smile: :grin: I was actually hoping if someone could actually help me get the string inside the quotation marks for both the Date and the Reason, but this seems reasonable for now, thanks! :heart:

If anyone else wants to share, I’m still willing to hear some more answers! The more answers, the better that I can improve on it! :stuck_out_tongue:

Isn’t date just a single word string?

Also I can do that but it will look messy :laughing:

Edit: Does the “” always exist?

Dates can be like:

  • 20d
  • 20 days
  • 20 days and 5 hours
  • 03/18/2020
  • February 18, 2020

Of course, I’ll handle that, but I just need to extract it from the quotation marks.

So the quotation marks always exist?

If they don’t we’re going to have some serious regex problems

Yes, it acts like a separator to say “Hey! Inside this quotation mark field is another string, put this in a separate group!”

... "Date Here" true "Reason here"
“Date Here” would shows as: Date Here in args[#]
“Reason Here” would shows as: Reason Here in args[#]

If you’d want to conversate more about this, we can talk in Discord DMs?
Bit#4930

Theoretically, if you use args = string.split(msg, ‘“‘) first then you could get four components and yes that’s a speech marks inside a quotation marks.

You could then do string.split(args[1], “ “) for your command and name, args[2] will be your date, string.gsub(args[3], “ “, “”) will be your appeal boolean and args[4] will be your reason.

big inhale of effort.

args = string.split(msg, ‘“‘)

command, name, date, appeal, reason = string.split(args[1], “ “), args[2], string.gsub(args[3], “ “, “”), args[4]

You could use gmatch.

local s = [[/ban HarleySummersDev “20d” true “Crashed into my car. xd”]]
local tokens = {}
for k in s:gmatch("[%S]+") do
	table.insert(tokens, k)
end
for k, v in ipairs(tokens) do
	print(k..": "..v)
end

output:

1: /ban
2: HarleySummersDev
3: “20d”
4: true
5: “Crashed
6: into
7: my
8: car.
9: xd”

From there you would execute the command based on what the first argument was.

local cmd = tokens[1]:lower()
if (cmd == "/ban") then
	local user = game.Players:FindFirstChild(tokens[2])
	local length = tonumber(tokens[3]:match("%d+"))
	local appealable = (tokens[4] == "true")
	local reason = ""
	for i = 5, #tokens do
		reason = reason..tokens[i].." "
	end
	print("Banned "..tostring(user).." for "..tostring(length).." days, can "..(appealable and "" or "NOT ").."appeal, reason: "..reason)
end

Output:

Banned nil for 20 days, can appeal, reason: “Crashed into my car. xd” 

(the nil is just because ‘HarleySummersDev’ wasn’t in the game.)

Using command bar, and this worked pretty well, awesome! Thank you so much! :heart: :grin: :grin: :grin:
Although, I’d have to get the Bool Value out another way, because it does this:

As I was explaining earlier, I was trying to have the quotation marks join together.
Input: /ban HarleySummersDev "20d" true "Crashed into my car"
So the output would be:

1: /ban
2: HarleySummersDev
3: 20d
4: true
5: Crashed into my car

Sorry. :frowning:

Edit: I seem to believe that your gmatch function is the same as string.split

In command prompt you typed in the wrong things, hence why it didn’t work. I’d honestly use my format for extraction, it’s easy and clean.

I don’t think you have grasped the requirements of the problem.

If she wanted to match arguments then she’d do it but the arguments are different each time. Respectfully, your solution has over complicated the matter as well as it’s turning a relatively simple task into a long task.

local s = [[/ban HarleySummersDev "20d" true "Crashed into my car. xd"]]

-- Match alphanumeric followed by '/'
local cmd = s:match("/%w*")
-- Remove so it doesn't get matched later
s = s:gsub("/%w*", "")

-- Match any alphanumeric that may also contain an underscore
local name = s:match("%w*_%w*") or s:match("%w+") 

-- Match anything in double quotes containing a number
local length = s:match('"%d+%P*"')
s = s:gsub('"%d+%P*"', "")

-- Literally just search for a "true" and return false if otherwise
local bool = s:match("true") and true or false

-- Match anything in quotes as the last argument.
local reason = s:match('".*"')

print("cmd: "..tostring(cmd))
print("name: "..tostring(name))
print("length: "..tostring(length))
print("bool: "..tostring(bool))
print("reason: "..tostring(reason))

My output:

cmd: /ban
name: HarleySummersDev
length: "20d"
bool: true
reason: "Crashed into my car. xd"
4 Likes

Thank you so much! You too, @6Clu!
I’ll try to add both of your examples, and I’m super glad that you both helped me out.

Thank you so much for the effort, cheers! :heart: :tada: