Exemplo n.º 1
0
 // Here we set default commands, they do nothing since we quit with them
 // Quitting behaviour is hardcoded in readLine()
 Console::Console(std::string const& greeting)
     : pimpl_{ new Impl{ greeting } }
 {
     // Init readline basics
     rl_attempted_completion_function = &Console::getCommandCompletions;
     // These are other two hardcoded commands, but they are more readable
     // here rather than in the initialization list.
     // Help command lists available commands.
     pimpl_->commands_["help"] = [this](const std::vector<std::string>&){
         auto commands = getRegisteredCommands();
         std::cout << "Available commands are:\n";
         for ( auto & command : commands ) std::cout << "\t" << command << "\n";
         return 0;
     };
     // Run command executes all commands in an external file.
     pimpl_->commands_["run"] =  [this](const std::vector<std::string>& input) {
         if ( input.size() < 2 ) { std::cout << "Usage: " << input[0] << " script_filename\n"; return 1; }
         return executeFile(input[1]);
     };
 }
Exemplo n.º 2
0
/*
 * Execute is the main entry point for the framework.  It parses the user's input, matches it
 * to the appropriate CommandSpec/Feature and then runs the feature, returning the Result from
 * the feature.
 */
cli::framework::ResultBase* cli::framework::Framework::execute(int argCount, const char* args[])
{
	Trace trace(__FILE__, __FUNCTION__, __LINE__);
	ResultBase *pResult = NULL;
	if (argCount > 0)
	{
		logger << "Executing: " << tokenArrayToString(argCount, args) << std::endl;

		// add help and output options
		CommandSpecList commands = getRegisteredCommands();
		logger << "Commands to consider: " << commands.size() << std::endl;

		// convert user input into recognized tokens.  Command List is needed because
		// it is used to know what verbs, targets, and properties are supported
		TokenList tokens = tokenize(argCount, args, commands);
		logger << "Tokenized input is: " << tokenArrayToString(tokens) << std::endl;

		SyntaxErrorResult *pError = NULL;
		// The parser will convert the list of tokens into a parsed command.  It validates that the tokens
		// are in the proper order and will assign values to options, targets, and properties.
		Parser parser;
		pError = parser.parse(tokens);
		ParsedCommand parsedCommand = parser.getParsedCommand();

		// The filter will take the parsedCommand and filter the possible commands, hopefully
		// leaving only one left to execute.
		UnknownProperty unknownProperty = parser.getUnknownProperty();
		CommandFilter commandFilter(parsedCommand, unknownProperty);
		commandFilter.filter(commands);

		if (pError != NULL)
		{
			pResult = pError;
			if (parser.includePotentialCommandsIsRequested())
			{
				pError->setPotentialCommands(commandFilter.getLastErasedCommands());
			}
		}
		else
		{
			if (commands.size() == 1) // success ... 1 command to run
			{
				CommandVerify verify;
				pResult = verify.verify(parsedCommand, commands[0]);

				if (pResult == NULL)
				{
					// All good ... go, fight, win!!
					FeatureBase *pFeature = NULL;
					if (parsedCommand.options.find(OPTION_HELP.name) != parsedCommand.options.end())
					{
						// Intercept feature if asking for help
						pFeature = new HelpFeature(commands[0]);
					}
					else
					{
						pFeature = getCommandFeature(commands[0]);
					}

					logger << "Executing: " << commands[0].asStr() << std::endl;
					pResult = pFeature->run(commands[0].id, parsedCommand);
				}
			}
			else if (commands.empty())
			{
				logger << "No commands left. Setting potential commands with " <<
					commandFilter.getLastErasedCommands().size() << " commands" << std::endl;

				pError = new ParseErrorResult();
				pError->setPotentialCommands(commandFilter.getLastErasedCommands());
				pResult = pError;
			}
			else if (commands.size() > 1)
			{
				// this only happens if there are two CommandSpecs with the same syntax
				pResult = new ErrorResult(ErrorResult::ERRORCODE_UNKNOWN,
					"The command list had more than one after filtering. This means that there might be more than one CommandSpec with the same required syntax.");
				logger << "The conflicting commands are: ";
				CommandSpecList::const_iterator iter = commands.begin();
				for (; iter != commands.end(); iter++)
				{
					logger << "\"" + iter->asStr() << "\" ";
				}
				logger << std::endl;
			}
		}

		if (pResult != NULL)
		{
			pResult->setOutputOption(parser.getParsedCommand().options);
		}
	}
	else
	{
		pResult = HelpFeature().run(HelpFeature::HELP, (ParsedCommand){VERB_HELP});
	}
	return pResult;
}