parseArgsImpl is the underlying implementation of [parseArgs] that is called recursively and takes most of what [parseArgs] does, plus the current command state, and returns most of what [parseArgs] does, plus the args state.
(cfg T, baseArgs []string, baseCmd string, cmds ...*Cmd[T])
| 212 | // recursively and takes most of what [parseArgs] does, plus the current command state, |
| 213 | // and returns most of what [parseArgs] does, plus the args state. |
| 214 | func parseArgsImpl[T any](cfg T, baseArgs []string, baseCmd string, cmds ...*Cmd[T]) (args []string, cmd string, err error) { |
| 215 | // we start with our base args and command |
| 216 | args = baseArgs |
| 217 | cmd = baseCmd |
| 218 | |
| 219 | // if we have no additional args, we have nothing to do |
| 220 | if len(args) == 0 { |
| 221 | return |
| 222 | } |
| 223 | |
| 224 | // we only care about one arg at a time (everything else is handled recursively) |
| 225 | arg := args[0] |
| 226 | // get all of the (sub)commands in our base command |
| 227 | baseCmdStrs := strings.Fields(baseCmd) |
| 228 | for _, c := range cmds { |
| 229 | // get all of the (sub)commands in this command |
| 230 | cmdStrs := strings.Fields(c.Name) |
| 231 | // find the (sub)commands that our base command shares with the command we are checking |
| 232 | gotTo := 0 |
| 233 | hasMismatch := false |
| 234 | for i, cstr := range cmdStrs { |
| 235 | // if we have no more (sub)commands on our base, mark our location and break |
| 236 | if i >= len(baseCmdStrs) { |
| 237 | gotTo = i |
| 238 | break |
| 239 | } |
| 240 | // if we have a different thing than our base, it is a mismatch |
| 241 | if baseCmdStrs[i] != cstr { |
| 242 | hasMismatch = true |
| 243 | break |
| 244 | } |
| 245 | } |
| 246 | // if we have a different sub(command) for something, this isn't the right command |
| 247 | if hasMismatch { |
| 248 | continue |
| 249 | } |
| 250 | // if the thing after we ran out of (sub)commands on our base isn't our next arg, this isn't the right command |
| 251 | if gotTo >= len(cmdStrs) || arg != cmdStrs[gotTo] { |
| 252 | continue |
| 253 | } |
| 254 | // otherwise, it is the right command, and our new command is our base plus our next arg |
| 255 | cmd = arg |
| 256 | if baseCmd != "" { |
| 257 | cmd = baseCmd + " " + arg |
| 258 | } |
| 259 | // we have consumed our next arg, so we get rid of it |
| 260 | args = args[1:] |
| 261 | // then, we recursively parse again with our new command as context |
| 262 | oargs, ocmd, err := parseArgsImpl(cfg, args, cmd, cmds...) |
| 263 | if err != nil { |
| 264 | return nil, "", err |
| 265 | } |
| 266 | // our new args and command are now whatever the recursive call returned, building upon what we passed it |
| 267 | args = oargs |
| 268 | cmd = ocmd |
| 269 | // we got the command we wanted, so we can break |
| 270 | break |
| 271 | } |