Beispiel #1
0
bool CLICommand::ParseCommand(int argc, char **argv, po::options_description& visibleDesc,
    po::options_description& hiddenDesc,
    po::positional_options_description& positionalDesc,
    po::variables_map& vm, String& cmdname, CLICommand::Ptr& command, bool autocomplete)
{
	boost::mutex::scoped_lock lock(GetRegistryMutex());

	typedef std::map<std::vector<String>, CLICommand::Ptr>::value_type CLIKeyValue;

	std::vector<String> best_match;
	int arg_end = 1;

	BOOST_FOREACH(const CLIKeyValue& kv, GetRegistry()) {
		const std::vector<String>& vname = kv.first;

		for (int i = 0, k = 1; i < vname.size() && k < argc; i++, k++) {
			if (strcmp(argv[k], "--no-stack-rlimit") == 0 || strcmp(argv[k], "--autocomplete") == 0 || strcmp(argv[k], "--scm") == 0) {
				i--;
				continue;
			}

			if (vname[i] != argv[k])
				break;

			if (i >= best_match.size())
				best_match.push_back(vname[i]);

			if (i == vname.size() - 1) {
				cmdname = boost::algorithm::join(vname, " ");
				command = kv.second;
				arg_end = k;
				goto found_command;
			}
		}
	}

found_command:
	lock.unlock();

	po::options_description vdesc("Command options");

	if (command)
		command->InitParameters(vdesc, hiddenDesc);

	visibleDesc.add(vdesc);

	if (autocomplete)
		return true;

	po::options_description adesc;
	adesc.add(visibleDesc);
	adesc.add(hiddenDesc);

	po::store(po::command_line_parser(argc - arg_end, argv + arg_end).options(adesc).positional(positionalDesc).run(), vm);
	po::notify(vm);

	return true;
}
Beispiel #2
0
void CLICommand::ShowCommands(int argc, char **argv, po::options_description *visibleDesc,
    po::options_description *hiddenDesc,
    ArgumentCompletionCallback globalArgCompletionCallback,
    bool autocomplete, int autoindex)
{
	boost::mutex::scoped_lock lock(GetRegistryMutex());

	typedef std::map<std::vector<String>, CLICommand::Ptr>::value_type CLIKeyValue;

	std::vector<String> best_match;
	int arg_begin = 0;
	CLICommand::Ptr command;

	BOOST_FOREACH(const CLIKeyValue& kv, GetRegistry()) {
		const std::vector<String>& vname = kv.first;

		arg_begin = 0;

		for (int i = 0, k = 1; i < vname.size() && k < argc; i++, k++) {
			if (strcmp(argv[k], "--no-stack-rlimit") == 0 || strcmp(argv[k], "--autocomplete") == 0 || strcmp(argv[k], "--scm") == 0) {
				i--;
				arg_begin++;
				continue;
			}

			if (autocomplete && i >= autoindex - 1)
				break;

			if (vname[i] != argv[k])
				break;

			if (i >= best_match.size()) {
				best_match.push_back(vname[i]);
			}

			if (i == vname.size() - 1) {
				command = kv.second;
				break;
			}
		}
	}

	String aword;

	if (autocomplete) {
		if (autoindex < argc)
			aword = argv[autoindex];

		if (autoindex - 1 > best_match.size() && !command)
			return;
	} else
		std::cout << "Supported commands: " << std::endl;

	BOOST_FOREACH(const CLIKeyValue& kv, GetRegistry()) {
		const std::vector<String>& vname = kv.first;

		if (vname.size() < best_match.size() || kv.second->IsHidden())
			continue;

		bool match = true;

		for (int i = 0; i < best_match.size(); i++) {
			if (vname[i] != best_match[i]) {
				match = false;
				break;
			}
		}

		if (!match)
			continue;

		if (autocomplete) {
			String cname;

			if (autoindex - 1 < vname.size()) {
				cname = vname[autoindex - 1];

				if (cname.Find(aword) == 0)
					std::cout << cname << "\n";
			}
		} else
			std::cout << "  * " << boost::algorithm::join(vname, " ") << " (" << kv.second->GetShortDescription() << ")" << std::endl;
	}

	if (!autocomplete)
		std::cout << std::endl;

	if (command && autocomplete) {
		String aname, prefix, pword;
		const po::option_description *odesc;

		if (autoindex - 2 >= 0 && strcmp(argv[autoindex - 1], "=") == 0 && strstr(argv[autoindex - 2], "--") == argv[autoindex - 2]) {
			aname = argv[autoindex - 2] + 2;
			pword = aword;
		} else if (autoindex - 1 >= 0 && argv[autoindex - 1][0] == '-' && argv[autoindex - 1][1] == '-') {
			aname = argv[autoindex - 1] + 2;
			pword = aword;

			if (pword == "=")
				pword = "";
		} else if (autoindex - 1 >= 0 && argv[autoindex - 1][0] == '-' && argv[autoindex - 1][1] != '-') {
			aname = argv[autoindex - 1];
			pword = aword;
			
			if (pword == "=")
				pword = "";
		} else if (aword.GetLength() > 1 && aword[0] == '-' && aword[1] != '-') {
			aname = aword.SubStr(0, 2);
			prefix = aname;
			pword = aword.SubStr(2);
		} else {
			goto complete_option;
		}

		odesc = visibleDesc->find_nothrow(aname, false);

		if (!odesc)
			return;

		if (odesc->semantic()->min_tokens() == 0)
			goto complete_option;

		BOOST_FOREACH(const String& suggestion, globalArgCompletionCallback(odesc->long_name(), pword)) {
			std::cout << prefix << suggestion << "\n";
		}

		BOOST_FOREACH(const String& suggestion, command->GetArgumentSuggestions(odesc->long_name(), pword)) {
			std::cout << prefix << suggestion << "\n";
		}
		
		return;

complete_option:
		BOOST_FOREACH(const boost::shared_ptr<po::option_description>& odesc, visibleDesc->options()) {
			String cname = "--" + odesc->long_name();

			if (cname.Find(aword) == 0)
				std::cout << cname << "\n";
		}

		BOOST_FOREACH(const String& suggestion, command->GetPositionalSuggestions(aword)) {
			std::cout << suggestion << "\n";
		}
	}
Beispiel #3
0
bool CLICommand::ParseCommand(int argc, char **argv, po::options_description& visibleDesc,
	po::options_description& hiddenDesc,
	po::positional_options_description& positionalDesc,
	po::variables_map& vm, String& cmdname, CLICommand::Ptr& command, bool autocomplete)
{
	boost::mutex::scoped_lock lock(GetRegistryMutex());

	typedef std::map<std::vector<String>, CLICommand::Ptr>::value_type CLIKeyValue;

	std::vector<String> best_match;
	int arg_end = 0;
	bool tried_command = false;

	for (const CLIKeyValue& kv : GetRegistry()) {
		const std::vector<String>& vname = kv.first;

		std::vector<String>::size_type i;
		int k;
		for (i = 0, k = 1; i < vname.size() && k < argc; i++, k++) {
			if (strncmp(argv[k], "-", 1) == 0 || strncmp(argv[k], "--", 2) == 0) {
				i--;
				continue;
			}

			tried_command = true;

			if (vname[i] != argv[k])
				break;

			if (i >= best_match.size())
				best_match.push_back(vname[i]);

			if (i == vname.size() - 1) {
				cmdname = boost::algorithm::join(vname, " ");
				command = kv.second;
				arg_end = k;
				goto found_command;
			}
		}
	}

found_command:
	lock.unlock();

	if (command) {
		po::options_description vdesc("Command options");
		command->InitParameters(vdesc, hiddenDesc);
		visibleDesc.add(vdesc);
	}

	if (autocomplete || (tried_command && !command))
		return true;

	po::options_description adesc;
	adesc.add(visibleDesc);
	adesc.add(hiddenDesc);

	if (command && command->IsDeprecated()) {
		std::cerr << ConsoleColorTag(Console_ForegroundRed | Console_Bold)
			<< "Warning: CLI command '" << cmdname << "' is DEPRECATED! Please read the Changelog."
			<< ConsoleColorTag(Console_Normal) << std::endl << std::endl;
	}

	po::store(po::command_line_parser(argc - arg_end, argv + arg_end).options(adesc).positional(positionalDesc).run(), vm);
	po::notify(vm);

	return true;
}