cronokirby/alchemy

Cogs: support quoted arguments

Closed this issue · 8 comments

My command works like this:

!cmd add "some long text"

Presently, I have to manually extract "some long text" from message.content or use Cogs.set_parser but I think is a very common case that should be addressed in Cogs itself. E.g. I should be able to add another argument to my command function, and It should hold the entire quoted string, not just "some.

Sorry for the late reply :P

So, if I get you right, you want to change the default parser, so that it splits on whitespace, but leaves quoted sections intact?
so that would make it so that

!foo "bar baz" bar "bar baz"

would represent 3 args.
For a single argument, this would just be

Cogs.set_parser(:foo, &List.wrap/1)

but, for larger argument commands, this becomes a bit tedious to write.

This is actually a better default parser tbh, a lot more versatile than just whitespace. I'm planning to add a lot more configurability to a lot of things, so I think what I'll do is make this new parser the default,
but also add the option to configure what it would be, for people who don't use this feature.

Probably gonna work on this after voice is sorted out, matter of a day or 2, in the mean time, feel free to work on a PR if you want.

I can work on this for sure. I'll have a PR today or tomorrow.

Another issue I was thinking about is a command like

!foo x bar bar

Where bar bar is a single argument. The reason for this is that I think its easier to type in commands without quotes.

One way to support this to check the cogs defined for the command and if the parsed arguments total more than the highest arity cog for the command, we combine as many args into the last argument and choose the highest arity cog.

This feels unclean to me though, so I want to know what you think.

The current behaviour of dropping arguments is somewhat intentional

!add 1 3 and the rest doesn't parse

We could make some kind of :parser_drop flag, in the config again, which would make extra text either be dropped off, or agglomerated into one command.

I feel like this and other things would be alleviated by a macro that generates a parser based on a function spec:

Cogs.gen_parser(:add, [:int, :int])
Cogs.def add(a, b), do: Cogs.say "#{a + b}"

Cogs.gen_parser(:foo, [:string, [:string]]

Syntax to be determined, maybe try and get it so that it'd work with anything that defines a protocol allowing it to be read as well. Definitely something to look into...

For my PR, I'll keep it simple and implement not splitting spaces in quotes.

https://github.com/cronokirby/alchemy/blob/master/lib/Cogs/command_handler.ex#L56

You'll want to change this here; you'll probably need a regex here, or a custom splitter. Something like

"1 2 \"3 3 3\" 4 \"5 5\" "

should be

["1", "2", "3 3 3", "4", "5 5"]

which isn't feasable with a "normal" split

https://github.com/cronokirby/alchemy/blob/master/lib/cogs.ex#L515
oh and, you'll need to match it here, if you don't want to break grouped cogs

I'm going to write a function to first split on quotes. Then I'll split every even indexed element on spaces because all the odd indexed elements would be quoted elements. Then I have to make sure everything is ordered right.

Also, why is the name for that function cOGS_COMMANDS_GROUPER? shouldn't it be all lowercase?

it's to avoid people overwriting it :P,
the way grouped cogs work is kinda magic...