Skip to main content

Parse Flags

This code snippet provides a reusable template which you can add to your custom commands.
It separates predefined flags from positional arguments within input, for example:

-command -m 123 positional arg -f might be parsed into:

positional:
- positional
- arg
flags:
m: '123'
f: true

Licensed under the terms of the Unlicense.

Code

{{/*
Separates predefined flags from positional arguments within input.
See <https://yagpdb-cc.github.io/code-snippets/parse-flags> for more information.

Licensed under the terms of the Unlicense.
Author: jo3-l <https://github.com/jo3-l>
*/}}

{{define "parseFlags"}}
{{.Set "Out" (sdict
"Positional" (cslice)
"Flags" (dict)
"Switches" (dict)
)}}

{{$curFlag := ""}}
{{$lastIdx := sub (len .Args) 1}}
{{range $i, $arg := .Args}}
{{- if $curFlag}}
{{- $.Out.Flags.Set $curFlag $arg}}
{{- $curFlag = ""}}
{{- else if and ($id := $.Flags.Get $arg) (ne $i $lastIdx)}}
{{- $curFlag = $id}}
{{- else if $id := $.Switches.Get $arg}}
{{- $.Out.Switches.Set $id true}}
{{- else}}
{{- $.Out.Set "Positional" ($.Out.Positional.Append $arg)}}
{{- end -}}
{{end}}
{{end}}

Usage

First, copy the above snippet to the top of your code.
To use it, you will need to construct a map holding the flags, switches, and input argument slice to parse.

In this example, we will be parsing a command similar in structure to the rolemenu create built-in command.

{{/* code snippet goes here */}}
{{$query := dict
"Flags" (dict
"-m" "MessageID"
"-msg" "MessageID"

"-skip" "Skip"
"-s" "Skip"
)

"Switches" (dict
"-nodm" "NoDM"
"-rr" "RemoveRole"
)

"Args" .CmdArgs
}}
tip

Flags take on the value that is after them, while switches are simple on-off switches (hence the name).

Now, let's run the template, passing our query as the data:

{{/* code snippet goes here */}}
{{$query := dict
"Flags" (dict
"-m" "MessageID"
"-msg" "MessageID"

"-skip" "Skip"
"-s" "Skip"
)

"Switches" (dict
"-nodm" "NoDM"
"-rr" "RemoveRole"
)

"Args" .CmdArgs
}}
{{template "parseFlags" $query}}

Running the template causes our input map to be filled with the parsed data, which we can access via $query.Out.

Flags

Access flags by their ID (the value in the map supplied to parseFlags). The value will be nil if the user did not supply that flag; otherwise it will be the argument directly after the flag. For example, $msgID would have the value "1" if the input was "-m 1".

Example: {{$msgID := $query.Out.Flags.MessageID}}

Switches

Same thing for switches. In this case, the value will be nil if the user did not supply that switch; otherwise it will be 'true'.

Example: {{$nodm := $query.Out.Switches.NoDM}}

Positional arguments

Finally, we can access any excess arguments that are neither flags nor switches by indexing into the Positional slice. In this case, $first would have the value "a" if the input was "a -nodm -m 123".

Example: {{$first := index $query.Out.Positional 0}}

Author

This code snippet was written by @jo3-l.