bool _parse_positional()

in fboss/cli/fboss2/CLI11/App.hpp [2451:2548]


    bool _parse_positional(std::vector<std::string> &args, bool haltOnSubcommand) {

        const std::string &positional = args.back();

        if(positionals_at_end_) {
            // deal with the case of required arguments at the end which should take precedence over other arguments
            auto arg_rem = args.size();
            auto remreq = _count_remaining_positionals(true);
            if(arg_rem <= remreq) {
                for(const Option_p &opt : options_) {
                    if(opt->get_positional() && opt->required_) {
                        if(static_cast<int>(opt->count()) < opt->get_items_expected_min()) {
                            if(validate_positionals_) {
                                std::string pos = positional;
                                pos = opt->_validate(pos, 0);
                                if(!pos.empty()) {
                                    continue;
                                }
                            }
                            opt->add_result(positional);
                            parse_order_.push_back(opt.get());
                            args.pop_back();
                            return true;
                        }
                    }
                }
            }
        }
        for(const Option_p &opt : options_) {
            // Eat options, one by one, until done
            if(opt->get_positional() &&
               (static_cast<int>(opt->count()) < opt->get_items_expected_min() || opt->get_allow_extra_args())) {
                if(validate_positionals_) {
                    std::string pos = positional;
                    pos = opt->_validate(pos, 0);
                    if(!pos.empty()) {
                        continue;
                    }
                }
                opt->add_result(positional);
                parse_order_.push_back(opt.get());
                args.pop_back();
                return true;
            }
        }

        for(auto &subc : subcommands_) {
            if((subc->name_.empty()) && (!subc->disabled_)) {
                if(subc->_parse_positional(args, false)) {
                    if(!subc->pre_parse_called_) {
                        subc->_trigger_pre_parse(args.size());
                    }
                    return true;
                }
            }
        }
        // let the parent deal with it if possible
        if(parent_ != nullptr && fallthrough_)
            return _get_fallthrough_parent()->_parse_positional(args, static_cast<bool>(parse_complete_callback_));

        /// Try to find a local subcommand that is repeated
        auto com = _find_subcommand(args.back(), true, false);
        if(com != nullptr && (require_subcommand_max_ == 0 || require_subcommand_max_ > parsed_subcommands_.size())) {
            if(haltOnSubcommand) {
                return false;
            }
            args.pop_back();
            com->_parse(args);
            return true;
        }
        /// now try one last gasp at subcommands that have been executed before, go to root app and try to find a
        /// subcommand in a broader way, if one exists let the parent deal with it
        auto parent_app = (parent_ != nullptr) ? _get_fallthrough_parent() : this;
        com = parent_app->_find_subcommand(args.back(), true, false);
        if(com != nullptr && (com->parent_->require_subcommand_max_ == 0 ||
                              com->parent_->require_subcommand_max_ > com->parent_->parsed_subcommands_.size())) {
            return false;
        }

        if(positionals_at_end_) {
            throw CLI::ExtrasError(name_, args);
        }
        /// If this is an option group don't deal with it
        if(parent_ != nullptr && name_.empty()) {
            return false;
        }
        /// We are out of other options this goes to missing
        _move_to_missing(detail::Classifier::NONE, positional);
        args.pop_back();
        if(prefix_command_) {
            while(!args.empty()) {
                _move_to_missing(detail::Classifier::NONE, args.back());
                args.pop_back();
            }
        }

        return true;
    }