private void processClusteredShortOptions()

in log4j-core/src/main/java/org/apache/logging/log4j/core/tools/picocli/CommandLine.java [2357:2437]


        private void processClusteredShortOptions(
                final Collection<Field> required,
                final Set<Field> initialized,
                final String arg,
                final Stack<String> args)
                throws Exception {
            final String prefix = arg.substring(0, 1);
            String cluster = arg.substring(1);
            boolean paramAttachedToOption = true;
            do {
                if (cluster.length() > 0 && singleCharOption2Field.containsKey(cluster.charAt(0))) {
                    final Field field = singleCharOption2Field.get(cluster.charAt(0));
                    Range arity = Range.optionArity(field);
                    final String argDescription = "option " + prefix + cluster.charAt(0);
                    if (tracer.isDebug()) {
                        tracer.debug(
                                "Found option '%s%s' in %s: field %s, arity=%s%n",
                                prefix, cluster.charAt(0), arg, field, arity);
                    }
                    required.remove(field);
                    cluster = cluster.length() > 0 ? cluster.substring(1) : "";
                    paramAttachedToOption = cluster.length() > 0;
                    if (cluster.startsWith(separator)) { // attached with separator, like -f=FILE or -v=true
                        cluster = cluster.substring(separator.length());
                        arity = arity.min(Math.max(1, arity.min)); // if key=value, minimum arity is at least 1
                    }
                    if (arity.min > 0 && !empty(cluster)) {
                        if (tracer.isDebug()) {
                            tracer.debug("Trying to process '%s' as option parameter%n", cluster);
                        }
                    }
                    // arity may be >= 1, or
                    // arity <= 0 && !cluster.startsWith(separator)
                    // e.g., boolean @Option("-v", arity=0, varargs=true); arg "-rvTRUE", remainder cluster="TRUE"
                    if (!empty(cluster)) {
                        args.push(cluster); // interpret remainder as option parameter
                    }
                    final int consumed = applyOption(
                            field, Option.class, arity, paramAttachedToOption, args, initialized, argDescription);
                    // only return if cluster (and maybe more) was consumed, otherwise continue do-while loop
                    if (empty(cluster) || consumed > 0 || args.isEmpty()) {
                        return;
                    }
                    cluster = args.pop();
                } else { // cluster is empty || cluster.charAt(0) is not a short option key
                    if (cluster.length() == 0) { // we finished parsing a group of short options like -rxv
                        return; // return normally and parse the next arg
                    }
                    // We get here when the remainder of the cluster group is neither an option,
                    // nor a parameter that the last option could consume.
                    if (arg.endsWith(cluster)) {
                        args.push(paramAttachedToOption ? prefix + cluster : cluster);
                        if (args.peek().equals(arg)) { // #149 be consistent between unmatched short and long options
                            if (tracer.isDebug()) {
                                tracer.debug(
                                        "Could not match any short options in %s, deciding whether to treat as unmatched option or positional parameter...%n",
                                        arg);
                            }
                            if (resemblesOption(arg)) {
                                handleUnmatchedArguments(args.pop());
                                return;
                            } // #149
                            processPositionalParameter(required, initialized, args);
                            return;
                        }
                        // remainder was part of a clustered group that could not be completely parsed
                        if (tracer.isDebug()) {
                            tracer.debug("No option found for %s in %s%n", cluster, arg);
                        }
                        handleUnmatchedArguments(args.pop());
                    } else {
                        args.push(cluster);
                        if (tracer.isDebug()) {
                            tracer.debug("%s is not an option parameter for %s%n", cluster, arg);
                        }
                        processPositionalParameter(required, initialized, args);
                    }
                    return;
                }
            } while (true);
        }