diff options
Diffstat (limited to 'extern/libmv/third_party/gflags/gflags_completions.cc')
-rw-r--r-- | extern/libmv/third_party/gflags/gflags_completions.cc | 769 |
1 files changed, 0 insertions, 769 deletions
diff --git a/extern/libmv/third_party/gflags/gflags_completions.cc b/extern/libmv/third_party/gflags/gflags_completions.cc deleted file mode 100644 index 3a476230ff9..00000000000 --- a/extern/libmv/third_party/gflags/gflags_completions.cc +++ /dev/null @@ -1,769 +0,0 @@ -// Copyright (c) 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// --- - -// Bash-style command line flag completion for C++ binaries -// -// This module implements bash-style completions. It achieves this -// goal in the following broad chunks: -// -// 1) Take a to-be-completed word, and examine it for search hints -// 2) Identify all potentially matching flags -// 2a) If there are no matching flags, do nothing. -// 2b) If all matching flags share a common prefix longer than the -// completion word, output just that matching prefix -// 3) Categorize those flags to produce a rough ordering of relevence. -// 4) Potentially trim the set of flags returned to a smaller number -// that bash is happier with -// 5) Output the matching flags in groups ordered by relevence. -// 5a) Force bash to place most-relevent groups at the top of the list -// 5b) Trim most flag's descriptions to fit on a single terminal line - - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> // for strlen - -#include <set> -#include <string> -#include <utility> -#include <vector> - -#include "gflags.h" -#include "util.h" - -using std::set; -using std::string; -using std::vector; - - -DEFINE_string(tab_completion_word, "", - "If non-empty, HandleCommandLineCompletions() will hijack the " - "process and attempt to do bash-style command line flag " - "completion on this value."); -DEFINE_int32(tab_completion_columns, 80, - "Number of columns to use in output for tab completion"); - - -namespace GFLAGS_NAMESPACE { - - -namespace { -// Function prototypes and Type forward declarations. Code may be -// more easily understood if it is roughly ordered according to -// control flow, rather than by C's "declare before use" ordering -struct CompletionOptions; -struct NotableFlags; - -// The entry point if flag completion is to be used. -static void PrintFlagCompletionInfo(void); - - -// 1) Examine search word -static void CanonicalizeCursorWordAndSearchOptions( - const string &cursor_word, - string *canonical_search_token, - CompletionOptions *options); - -static bool RemoveTrailingChar(string *str, char c); - - -// 2) Find all matches -static void FindMatchingFlags( - const vector<CommandLineFlagInfo> &all_flags, - const CompletionOptions &options, - const string &match_token, - set<const CommandLineFlagInfo *> *all_matches, - string *longest_common_prefix); - -static bool DoesSingleFlagMatch( - const CommandLineFlagInfo &flag, - const CompletionOptions &options, - const string &match_token); - - -// 3) Categorize matches -static void CategorizeAllMatchingFlags( - const set<const CommandLineFlagInfo *> &all_matches, - const string &search_token, - const string &module, - const string &package_dir, - NotableFlags *notable_flags); - -static void TryFindModuleAndPackageDir( - const vector<CommandLineFlagInfo> all_flags, - string *module, - string *package_dir); - - -// 4) Decide which flags to use -static void FinalizeCompletionOutput( - const set<const CommandLineFlagInfo *> &matching_flags, - CompletionOptions *options, - NotableFlags *notable_flags, - vector<string> *completions); - -static void RetrieveUnusedFlags( - const set<const CommandLineFlagInfo *> &matching_flags, - const NotableFlags ¬able_flags, - set<const CommandLineFlagInfo *> *unused_flags); - - -// 5) Output matches -static void OutputSingleGroupWithLimit( - const set<const CommandLineFlagInfo *> &group, - const string &line_indentation, - const string &header, - const string &footer, - bool long_output_format, - int *remaining_line_limit, - size_t *completion_elements_added, - vector<string> *completions); - -// (helpers for #5) -static string GetShortFlagLine( - const string &line_indentation, - const CommandLineFlagInfo &info); - -static string GetLongFlagLine( - const string &line_indentation, - const CommandLineFlagInfo &info); - - -// -// Useful types - -// Try to deduce the intentions behind this completion attempt. Return the -// canonical search term in 'canonical_search_token'. Binary search options -// are returned in the various booleans, which should all have intuitive -// semantics, possibly except: -// - return_all_matching_flags: Generally, we'll trim the number of -// returned candidates to some small number, showing those that are -// most likely to be useful first. If this is set, however, the user -// really does want us to return every single flag as an option. -// - force_no_update: Any time we output lines, all of which share a -// common prefix, bash will 'helpfully' not even bother to show the -// output, instead changing the current word to be that common prefix. -// If it's clear this shouldn't happen, we'll set this boolean -struct CompletionOptions { - bool flag_name_substring_search; - bool flag_location_substring_search; - bool flag_description_substring_search; - bool return_all_matching_flags; - bool force_no_update; -}; - -// Notable flags are flags that are special or preferred for some -// reason. For example, flags that are defined in the binary's module -// are expected to be much more relevent than flags defined in some -// other random location. These sets are specified roughly in precedence -// order. Once a flag is placed in one of these 'higher' sets, it won't -// be placed in any of the 'lower' sets. -struct NotableFlags { - typedef set<const CommandLineFlagInfo *> FlagSet; - FlagSet perfect_match_flag; - FlagSet module_flags; // Found in module file - FlagSet package_flags; // Found in same directory as module file - FlagSet most_common_flags; // One of the XXX most commonly supplied flags - FlagSet subpackage_flags; // Found in subdirectories of package -}; - - -// -// Tab completion implementation - entry point -static void PrintFlagCompletionInfo(void) { - string cursor_word = FLAGS_tab_completion_word; - string canonical_token; - CompletionOptions options = { }; - CanonicalizeCursorWordAndSearchOptions( - cursor_word, - &canonical_token, - &options); - - DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'"; - - vector<CommandLineFlagInfo> all_flags; - set<const CommandLineFlagInfo *> matching_flags; - GetAllFlags(&all_flags); - DVLOG(2) << "Found " << all_flags.size() << " flags overall"; - - string longest_common_prefix; - FindMatchingFlags( - all_flags, - options, - canonical_token, - &matching_flags, - &longest_common_prefix); - DVLOG(1) << "Identified " << matching_flags.size() << " matching flags"; - DVLOG(1) << "Identified " << longest_common_prefix - << " as longest common prefix."; - if (longest_common_prefix.size() > canonical_token.size()) { - // There's actually a shared common prefix to all matching flags, - // so may as well output that and quit quickly. - DVLOG(1) << "The common prefix '" << longest_common_prefix - << "' was longer than the token '" << canonical_token - << "'. Returning just this prefix for completion."; - fprintf(stdout, "--%s", longest_common_prefix.c_str()); - return; - } - if (matching_flags.empty()) { - VLOG(1) << "There were no matching flags, returning nothing."; - return; - } - - string module; - string package_dir; - TryFindModuleAndPackageDir(all_flags, &module, &package_dir); - DVLOG(1) << "Identified module: '" << module << "'"; - DVLOG(1) << "Identified package_dir: '" << package_dir << "'"; - - NotableFlags notable_flags; - CategorizeAllMatchingFlags( - matching_flags, - canonical_token, - module, - package_dir, - ¬able_flags); - DVLOG(2) << "Categorized matching flags:"; - DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size(); - DVLOG(2) << " module: " << notable_flags.module_flags.size(); - DVLOG(2) << " package: " << notable_flags.package_flags.size(); - DVLOG(2) << " most common: " << notable_flags.most_common_flags.size(); - DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size(); - - vector<string> completions; - FinalizeCompletionOutput( - matching_flags, - &options, - ¬able_flags, - &completions); - - if (options.force_no_update) - completions.push_back("~"); - - DVLOG(1) << "Finalized with " << completions.size() - << " chosen completions"; - - for (vector<string>::const_iterator it = completions.begin(); - it != completions.end(); - ++it) { - DVLOG(9) << " Completion entry: '" << *it << "'"; - fprintf(stdout, "%s\n", it->c_str()); - } -} - - -// 1) Examine search word (and helper method) -static void CanonicalizeCursorWordAndSearchOptions( - const string &cursor_word, - string *canonical_search_token, - CompletionOptions *options) { - *canonical_search_token = cursor_word; - if (canonical_search_token->empty()) return; - - // Get rid of leading quotes and dashes in the search term - if ((*canonical_search_token)[0] == '"') - *canonical_search_token = canonical_search_token->substr(1); - while ((*canonical_search_token)[0] == '-') - *canonical_search_token = canonical_search_token->substr(1); - - options->flag_name_substring_search = false; - options->flag_location_substring_search = false; - options->flag_description_substring_search = false; - options->return_all_matching_flags = false; - options->force_no_update = false; - - // Look for all search options we can deduce now. Do this by walking - // backwards through the term, looking for up to three '?' and up to - // one '+' as suffixed characters. Consume them if found, and remove - // them from the canonical search token. - int found_question_marks = 0; - int found_plusses = 0; - while (true) { - if (found_question_marks < 3 && - RemoveTrailingChar(canonical_search_token, '?')) { - ++found_question_marks; - continue; - } - if (found_plusses < 1 && - RemoveTrailingChar(canonical_search_token, '+')) { - ++found_plusses; - continue; - } - break; - } - - switch (found_question_marks) { // all fallthroughs - case 3: options->flag_description_substring_search = true; - case 2: options->flag_location_substring_search = true; - case 1: options->flag_name_substring_search = true; - }; - - options->return_all_matching_flags = (found_plusses > 0); -} - -// Returns true if a char was removed -static bool RemoveTrailingChar(string *str, char c) { - if (str->empty()) return false; - if ((*str)[str->size() - 1] == c) { - *str = str->substr(0, str->size() - 1); - return true; - } - return false; -} - - -// 2) Find all matches (and helper methods) -static void FindMatchingFlags( - const vector<CommandLineFlagInfo> &all_flags, - const CompletionOptions &options, - const string &match_token, - set<const CommandLineFlagInfo *> *all_matches, - string *longest_common_prefix) { - all_matches->clear(); - bool first_match = true; - for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin(); - it != all_flags.end(); - ++it) { - if (DoesSingleFlagMatch(*it, options, match_token)) { - all_matches->insert(&*it); - if (first_match) { - first_match = false; - *longest_common_prefix = it->name; - } else { - if (longest_common_prefix->empty() || it->name.empty()) { - longest_common_prefix->clear(); - continue; - } - string::size_type pos = 0; - while (pos < longest_common_prefix->size() && - pos < it->name.size() && - (*longest_common_prefix)[pos] == it->name[pos]) - ++pos; - longest_common_prefix->erase(pos); - } - } - } -} - -// Given the set of all flags, the parsed match options, and the -// canonical search token, produce the set of all candidate matching -// flags for subsequent analysis or filtering. -static bool DoesSingleFlagMatch( - const CommandLineFlagInfo &flag, - const CompletionOptions &options, - const string &match_token) { - // Is there a prefix match? - string::size_type pos = flag.name.find(match_token); - if (pos == 0) return true; - - // Is there a substring match if we want it? - if (options.flag_name_substring_search && - pos != string::npos) - return true; - - // Is there a location match if we want it? - if (options.flag_location_substring_search && - flag.filename.find(match_token) != string::npos) - return true; - - // TODO(user): All searches should probably be case-insensitive - // (especially this one...) - if (options.flag_description_substring_search && - flag.description.find(match_token) != string::npos) - return true; - - return false; -} - -// 3) Categorize matches (and helper method) - -// Given a set of matching flags, categorize them by -// likely relevence to this specific binary -static void CategorizeAllMatchingFlags( - const set<const CommandLineFlagInfo *> &all_matches, - const string &search_token, - const string &module, // empty if we couldn't find any - const string &package_dir, // empty if we couldn't find any - NotableFlags *notable_flags) { - notable_flags->perfect_match_flag.clear(); - notable_flags->module_flags.clear(); - notable_flags->package_flags.clear(); - notable_flags->most_common_flags.clear(); - notable_flags->subpackage_flags.clear(); - - for (set<const CommandLineFlagInfo *>::const_iterator it = - all_matches.begin(); - it != all_matches.end(); - ++it) { - DVLOG(2) << "Examining match '" << (*it)->name << "'"; - DVLOG(7) << " filename: '" << (*it)->filename << "'"; - string::size_type pos = string::npos; - if (!package_dir.empty()) - pos = (*it)->filename.find(package_dir); - string::size_type slash = string::npos; - if (pos != string::npos) // candidate for package or subpackage match - slash = (*it)->filename.find( - PATH_SEPARATOR, - pos + package_dir.size() + 1); - - if ((*it)->name == search_token) { - // Exact match on some flag's name - notable_flags->perfect_match_flag.insert(*it); - DVLOG(3) << "Result: perfect match"; - } else if (!module.empty() && (*it)->filename == module) { - // Exact match on module filename - notable_flags->module_flags.insert(*it); - DVLOG(3) << "Result: module match"; - } else if (!package_dir.empty() && - pos != string::npos && slash == string::npos) { - // In the package, since there was no slash after the package portion - notable_flags->package_flags.insert(*it); - DVLOG(3) << "Result: package match"; - } else if (false) { - // In the list of the XXX most commonly supplied flags overall - // TODO(user): Compile this list. - DVLOG(3) << "Result: most-common match"; - } else if (!package_dir.empty() && - pos != string::npos && slash != string::npos) { - // In a subdirectory of the package - notable_flags->subpackage_flags.insert(*it); - DVLOG(3) << "Result: subpackage match"; - } - - DVLOG(3) << "Result: not special match"; - } -} - -static void PushNameWithSuffix(vector<string>* suffixes, const char* suffix) { - suffixes->push_back( - StringPrintf("/%s%s", ProgramInvocationShortName(), suffix)); -} - -static void TryFindModuleAndPackageDir( - const vector<CommandLineFlagInfo> all_flags, - string *module, - string *package_dir) { - module->clear(); - package_dir->clear(); - - vector<string> suffixes; - // TODO(user): There's some inherant ambiguity here - multiple directories - // could share the same trailing folder and file structure (and even worse, - // same file names), causing us to be unsure as to which of the two is the - // actual package for this binary. In this case, we'll arbitrarily choose. - PushNameWithSuffix(&suffixes, "."); - PushNameWithSuffix(&suffixes, "-main."); - PushNameWithSuffix(&suffixes, "_main."); - // These four are new but probably merited? - PushNameWithSuffix(&suffixes, "-test."); - PushNameWithSuffix(&suffixes, "_test."); - PushNameWithSuffix(&suffixes, "-unittest."); - PushNameWithSuffix(&suffixes, "_unittest."); - - for (vector<CommandLineFlagInfo>::const_iterator it = all_flags.begin(); - it != all_flags.end(); - ++it) { - for (vector<string>::const_iterator suffix = suffixes.begin(); - suffix != suffixes.end(); - ++suffix) { - // TODO(user): Make sure the match is near the end of the string - if (it->filename.find(*suffix) != string::npos) { - *module = it->filename; - string::size_type sep = it->filename.rfind(PATH_SEPARATOR); - *package_dir = it->filename.substr(0, (sep == string::npos) ? 0 : sep); - return; - } - } - } -} - -// Can't specialize template type on a locally defined type. Silly C++... -struct DisplayInfoGroup { - const char* header; - const char* footer; - set<const CommandLineFlagInfo *> *group; - - int SizeInLines() const { - int size_in_lines = static_cast<int>(group->size()) + 1; - if (strlen(header) > 0) { - size_in_lines++; - } - if (strlen(footer) > 0) { - size_in_lines++; - } - return size_in_lines; - } -}; - -// 4) Finalize and trim output flag set -static void FinalizeCompletionOutput( - const set<const CommandLineFlagInfo *> &matching_flags, - CompletionOptions *options, - NotableFlags *notable_flags, - vector<string> *completions) { - - // We want to output lines in groups. Each group needs to be indented - // the same to keep its lines together. Unless otherwise required, - // only 99 lines should be output to prevent bash from harassing the - // user. - - // First, figure out which output groups we'll actually use. For each - // nonempty group, there will be ~3 lines of header & footer, plus all - // output lines themselves. - int max_desired_lines = // "999999 flags should be enough for anyone. -dave" - (options->return_all_matching_flags ? 999999 : 98); - int lines_so_far = 0; - - vector<DisplayInfoGroup> output_groups; - bool perfect_match_found = false; - if (lines_so_far < max_desired_lines && - !notable_flags->perfect_match_flag.empty()) { - perfect_match_found = true; - DisplayInfoGroup group = - { "", - "==========", - ¬able_flags->perfect_match_flag }; - lines_so_far += group.SizeInLines(); - output_groups.push_back(group); - } - if (lines_so_far < max_desired_lines && - !notable_flags->module_flags.empty()) { - DisplayInfoGroup group = { - "-* Matching module flags *-", - "===========================", - ¬able_flags->module_flags }; - lines_so_far += group.SizeInLines(); - output_groups.push_back(group); - } - if (lines_so_far < max_desired_lines && - !notable_flags->package_flags.empty()) { - DisplayInfoGroup group = { - "-* Matching package flags *-", - "============================", - ¬able_flags->package_flags }; - lines_so_far += group.SizeInLines(); - output_groups.push_back(group); - } - if (lines_so_far < max_desired_lines && - !notable_flags->most_common_flags.empty()) { - DisplayInfoGroup group = { - "-* Commonly used flags *-", - "=========================", - ¬able_flags->most_common_flags }; - lines_so_far += group.SizeInLines(); - output_groups.push_back(group); - } - if (lines_so_far < max_desired_lines && - !notable_flags->subpackage_flags.empty()) { - DisplayInfoGroup group = { - "-* Matching sub-package flags *-", - "================================", - ¬able_flags->subpackage_flags }; - lines_so_far += group.SizeInLines(); - output_groups.push_back(group); - } - - set<const CommandLineFlagInfo *> obscure_flags; // flags not notable - if (lines_so_far < max_desired_lines) { - RetrieveUnusedFlags(matching_flags, *notable_flags, &obscure_flags); - if (!obscure_flags.empty()) { - DisplayInfoGroup group = { - "-* Other flags *-", - "", - &obscure_flags }; - lines_so_far += group.SizeInLines(); - output_groups.push_back(group); - } - } - - // Second, go through each of the chosen output groups and output - // as many of those flags as we can, while remaining below our limit - int remaining_lines = max_desired_lines; - size_t completions_output = 0; - int indent = static_cast<int>(output_groups.size()) - 1; - for (vector<DisplayInfoGroup>::const_iterator it = - output_groups.begin(); - it != output_groups.end(); - ++it, --indent) { - OutputSingleGroupWithLimit( - *it->group, // group - string(indent, ' '), // line indentation - string(it->header), // header - string(it->footer), // footer - perfect_match_found, // long format - &remaining_lines, // line limit - reduces this by number printed - &completions_output, // completions (not lines) added - completions); // produced completions - perfect_match_found = false; - } - - if (completions_output != matching_flags.size()) { - options->force_no_update = false; - completions->push_back("~ (Remaining flags hidden) ~"); - } else { - options->force_no_update = true; - } -} - -static void RetrieveUnusedFlags( - const set<const CommandLineFlagInfo *> &matching_flags, - const NotableFlags ¬able_flags, - set<const CommandLineFlagInfo *> *unused_flags) { - // Remove from 'matching_flags' set all members of the sets of - // flags we've already printed (specifically, those in notable_flags) - for (set<const CommandLineFlagInfo *>::const_iterator it = - matching_flags.begin(); - it != matching_flags.end(); - ++it) { - if (notable_flags.perfect_match_flag.count(*it) || - notable_flags.module_flags.count(*it) || - notable_flags.package_flags.count(*it) || - notable_flags.most_common_flags.count(*it) || - notable_flags.subpackage_flags.count(*it)) - continue; - unused_flags->insert(*it); - } -} - -// 5) Output matches (and helper methods) - -static void OutputSingleGroupWithLimit( - const set<const CommandLineFlagInfo *> &group, - const string &line_indentation, - const string &header, - const string &footer, - bool long_output_format, - int *remaining_line_limit, - size_t *completion_elements_output, - vector<string> *completions) { - if (group.empty()) return; - if (!header.empty()) { - if (*remaining_line_limit < 2) return; - *remaining_line_limit -= 2; - completions->push_back(line_indentation + header); - completions->push_back(line_indentation + string(header.size(), '-')); - } - for (set<const CommandLineFlagInfo *>::const_iterator it = group.begin(); - it != group.end() && *remaining_line_limit > 0; - ++it) { - --*remaining_line_limit; - ++*completion_elements_output; - completions->push_back( - (long_output_format - ? GetLongFlagLine(line_indentation, **it) - : GetShortFlagLine(line_indentation, **it))); - } - if (!footer.empty()) { - if (*remaining_line_limit < 1) return; - --*remaining_line_limit; - completions->push_back(line_indentation + footer); - } -} - -static string GetShortFlagLine( - const string &line_indentation, - const CommandLineFlagInfo &info) { - string prefix; - bool is_string = (info.type == "string"); - SStringPrintf(&prefix, "%s--%s [%s%s%s] ", - line_indentation.c_str(), - info.name.c_str(), - (is_string ? "'" : ""), - info.default_value.c_str(), - (is_string ? "'" : "")); - int remainder = - FLAGS_tab_completion_columns - static_cast<int>(prefix.size()); - string suffix; - if (remainder > 0) - suffix = - (static_cast<int>(info.description.size()) > remainder ? - (info.description.substr(0, remainder - 3) + "...").c_str() : - info.description.c_str()); - return prefix + suffix; -} - -static string GetLongFlagLine( - const string &line_indentation, - const CommandLineFlagInfo &info) { - - string output = DescribeOneFlag(info); - - // Replace '-' with '--', and remove trailing newline before appending - // the module definition location. - string old_flagname = "-" + info.name; - output.replace( - output.find(old_flagname), - old_flagname.size(), - "-" + old_flagname); - // Stick a newline and indentation in front of the type and default - // portions of DescribeOneFlag()s description - static const char kNewlineWithIndent[] = "\n "; - output.replace(output.find(" type:"), 1, string(kNewlineWithIndent)); - output.replace(output.find(" default:"), 1, string(kNewlineWithIndent)); - output = StringPrintf("%s Details for '--%s':\n" - "%s defined: %s", - line_indentation.c_str(), - info.name.c_str(), - output.c_str(), - info.filename.c_str()); - - // Eliminate any doubled newlines that crept in. Specifically, if - // DescribeOneFlag() decided to break the line just before "type" - // or "default", we don't want to introduce an extra blank line - static const string line_of_spaces(FLAGS_tab_completion_columns, ' '); - static const char kDoubledNewlines[] = "\n \n"; - for (string::size_type newlines = output.find(kDoubledNewlines); - newlines != string::npos; - newlines = output.find(kDoubledNewlines)) - // Replace each 'doubled newline' with a single newline - output.replace(newlines, sizeof(kDoubledNewlines) - 1, string("\n")); - - for (string::size_type newline = output.find('\n'); - newline != string::npos; - newline = output.find('\n')) { - int newline_pos = static_cast<int>(newline) % FLAGS_tab_completion_columns; - int missing_spaces = FLAGS_tab_completion_columns - newline_pos; - output.replace(newline, 1, line_of_spaces, 1, missing_spaces); - } - return output; -} -} // anonymous - -void HandleCommandLineCompletions(void) { - if (FLAGS_tab_completion_word.empty()) return; - PrintFlagCompletionInfo(); - gflags_exitfunc(0); -} - - -} // namespace GFLAGS_NAMESPACE |