bool CommandObject::ParseOptions ( Args& args, CommandReturnObject &result ) { // See if the subclass has options? Options *options = GetOptions(); if (options != NULL) { Error error; options->NotifyOptionParsingStarting(); // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1, // so we need to push a dummy value into position zero. args.Unshift("dummy_string"); error = args.ParseOptions (*options); // The "dummy_string" will have already been removed by ParseOptions, // so no need to remove it. if (error.Success()) error = options->NotifyOptionParsingFinished(); if (error.Success()) { if (options->VerifyOptions (result)) return true; } else { const char *error_cstr = error.AsCString(); if (error_cstr) { // We got an error string, lets use that result.AppendError(error_cstr); } else { // No error string, output the usage information into result options->GenerateOptionUsage (result.GetErrorStream(), this); } } result.SetStatus (eReturnStatusFailed); return false; } return true; }
void CommandInterpreter::BuildAliasCommandArgs ( CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args, CommandReturnObject &result ) { OptionArgVectorSP option_arg_vector_sp = GetAliasOptions (alias_name); if (option_arg_vector_sp.get()) { // Make sure that the alias name is the 0th element in cmd_args std::string alias_name_str = alias_name; if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) cmd_args.Unshift (alias_name); Args new_args (alias_cmd_obj->GetCommandName()); if (new_args.GetArgumentCount() == 2) new_args.Shift(); OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); int old_size = cmd_args.GetArgumentCount(); int *used = (int *) malloc ((old_size + 1) * sizeof (int)); memset (used, 0, (old_size + 1) * sizeof (int)); used[0] = 1; for (int i = 0; i < option_arg_vector->size(); ++i) { OptionArgPair option_pair = (*option_arg_vector)[i]; std::string option = option_pair.first; std::string value = option_pair.second; if (option.compare ("<argument>") == 0) new_args.AppendArgument (value.c_str()); else { new_args.AppendArgument (option.c_str()); if (value.compare ("<no-argument>") != 0) { int index = GetOptionArgumentPosition (value.c_str()); if (index == 0) // value was NOT a positional argument; must be a real value new_args.AppendArgument (value.c_str()); else if (index >= cmd_args.GetArgumentCount()) { result.AppendErrorWithFormat ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", index); result.SetStatus (eReturnStatusFailed); return; } else { new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); used[index] = 1; } } } } for (int j = 0; j < cmd_args.GetArgumentCount(); ++j) { if (!used[j]) new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); } cmd_args.Clear(); cmd_args.SetArguments (new_args.GetArgumentCount(), (const char **) new_args.GetArgumentVector()); } else { result.SetStatus (eReturnStatusSuccessFinishNoResult); // This alias was not created with any options; nothing further needs to be done. return; } result.SetStatus (eReturnStatusSuccessFinishNoResult); return; }
int CommandObject::HandleCompletion ( Args &input, int &cursor_index, int &cursor_char_position, int match_start_point, int max_return_elements, bool &word_complete, StringList &matches ) { // Default implmentation of WantsCompletion() is !WantsRawCommandString(). // Subclasses who want raw command string but desire, for example, // argument completion should override WantsCompletion() to return true, // instead. if (WantsRawCommandString() && !WantsCompletion()) { // FIXME: Abstract telling the completion to insert the completion character. matches.Clear(); return -1; } else { // Can we do anything generic with the options? Options *cur_options = GetOptions(); CommandReturnObject result; OptionElementVector opt_element_vector; if (cur_options != NULL) { // Re-insert the dummy command name string which will have been // stripped off: input.Unshift ("dummy-string"); cursor_index++; // I stick an element on the end of the input, because if the last element is // option that requires an argument, getopt_long will freak out. input.AppendArgument ("<FAKE-VALUE>"); input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index); input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1); bool handled_by_options; handled_by_options = cur_options->HandleOptionCompletion (input, opt_element_vector, cursor_index, cursor_char_position, match_start_point, max_return_elements, word_complete, matches); if (handled_by_options) return matches.GetSize(); } // If we got here, the last word is not an option or an option argument. return HandleArgumentCompletion (input, cursor_index, cursor_char_position, opt_element_vector, match_start_point, max_return_elements, word_complete, matches); } }