<commit_before>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author <NAME>
////////////////////////////////////////////////////////////////////////////////

#include "ProgramOptions.h"
#include "ApplicationFeatures/ShellColorsFeature.h"
#include "Basics/files.h"
#include "Basics/levenshtein.h"
#include "Basics/terminal-utils.h"
#include "ProgramOptions/Option.h"
#include "ProgramOptions/Section.h"
#include "ProgramOptions/Translator.h"

#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>

#include <algorithm>
#include <iostream>
#ifdef TRI_HAVE_UNISTD_H
#include <unistd.h>
#endif

#define ARANGODB_PROGRAM_OPTIONS_PROGNAME "#progname#"

using namespace arangodb::options;

ProgramOptions::ProgramOptions(char const* progname, std::string const& usage,
                               std::string const& more, char const* binaryPath)
    : _progname(progname),
      _usage(usage),
      _more(more),
      _similarity(TRI_Levenshtein),
      _processingResult(),
      _sealed(false),
      _overrideOptions(false),
      _binaryPath(binaryPath) {
  // find progname wildcard in string
  size_t const pos = _usage.find(ARANGODB_PROGRAM_OPTIONS_PROGNAME);

  if (pos != std::string::npos) {
    // and replace it with actual program name
    _usage = usage.substr(0, pos) + _progname +
             _usage.substr(pos + strlen(ARANGODB_PROGRAM_OPTIONS_PROGNAME));
  }

  _translator = EnvironmentTranslator;
}

// sets a value translator
void ProgramOptions::setTranslator(
    std::function<std::string(std::string const&, char const*)> const& translator) {
  _translator = translator;
}

// prints usage information
void ProgramOptions::printUsage() const {
  std::cout << _usage << std::endl << std::endl;
}

// prints a help for all options, or the options of a section
// the special search string "*" will show help for all sections
// the special search string "." will show help for all sections, even if
// hidden
void ProgramOptions::printHelp(std::string const& search) const {
  bool const colors = (isatty(STDOUT_FILENO) != 0);
  printUsage();

  TRI_TerminalSize ts = TRI_DefaultTerminalSize();
  size_t const tw = ts.columns;
  size_t const ow = optionsWidth();

  for (auto const& it : _sections) {
    if (search == "*" || search == "." || search == it.second.name) {
      it.second.printHelp(search, tw, ow, colors);
    }
  }

  if (search == "*") {
    printSectionsHelp();
  }
}

// prints the names for all section help options
void ProgramOptions::printSectionsHelp() const {
  char const* colorStart = "";
  char const* colorEnd = "";

  if (isatty(STDOUT_FILENO)) {
    colorStart = ShellColorsFeature::SHELL_COLOR_BRIGHT;
    colorEnd = ShellColorsFeature::SHELL_COLOR_RESET;
  }

  // print names of sections
  std::cout << _more;
  for (auto const& it : _sections) {
    if (!it.second.name.empty() && it.second.hasOptions()) {
      std::cout << "  " << colorStart << "--help-" << it.second.name << colorEnd;
    }
  }
  std::cout << std::endl;
}

// returns a VPack representation of the option values, with optional
// filters applied to filter out specific options. 
// the filter function is expected to return true
// for any options that should become part of the result
VPackBuilder ProgramOptions::toVPack(bool onlyTouched, bool detailed,
                                     std::function<bool(std::string const&)> const& filter) const {
  VPackBuilder builder;
  builder.openObject();

  walk(
      [this, &builder, &filter, &detailed](Section const& section, Option const& option) {
        std::string full(option.fullName());
        
        if (!filter(full)) {
          return;
        }

        // add key
        builder.add(VPackValue(full));

        // add value
        if (detailed) {
          builder.openObject();
          builder.add("section", VPackValue(option.section));
          builder.add("description", VPackValue(option.description));
          builder.add("category", VPackValue(option.hasFlag(arangodb::options::Flags::Command)
                                                 ? "command"
                                                 : "option"));
          builder.add("hidden", VPackValue(option.hasFlag(arangodb::options::Flags::Hidden)));
          builder.add("type", VPackValue(option.parameter->name()));
          builder.add("obsolete",
                      VPackValue(option.hasFlag(arangodb::options::Flags::Obsolete)));
          builder.add("enterpriseOnly",
                      VPackValue(section.enterpriseOnly ||
                                 option.hasFlag(arangodb::options::Flags::Enterprise)));
          builder.add("requiresValue", VPackValue(option.parameter->requiresValue()));
         
          // OS support
          builder.add("os", VPackValue(VPackValueType::Array));
          if (option.hasFlag(arangodb::options::Flags::OsLinux)) {
            builder.add(VPackValue("linux"));
          }
          if (option.hasFlag(arangodb::options::Flags::OsMac)) {
            builder.add(VPackValue("macos"));
          }
          if (option.hasFlag(arangodb::options::Flags::OsWindows)) {
            builder.add(VPackValue("windows"));
          }
          builder.close();
          
          // component support
          std::cout << "PROG: " << _progname << std::endl;
          if (_progname == "arangod") {
            builder.add("component", VPackValue(VPackValueType::Array));
            if (option.hasFlag(arangodb::options::Flags::OnCoordinator)) {<commit_msg>fix outputting of "component" in --dump-options<commit_after>////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
///     http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author <NAME>
////////////////////////////////////////////////////////////////////////////////

#include "ProgramOptions.h"
#include "ApplicationFeatures/ShellColorsFeature.h"
#include "Basics/files.h"
#include "Basics/levenshtein.h"
#include "Basics/terminal-utils.h"
#include "ProgramOptions/Option.h"
#include "ProgramOptions/Section.h"
#include "ProgramOptions/Translator.h"

#include <velocypack/Builder.h>
#include <velocypack/velocypack-aliases.h>

#include <algorithm>
#include <iostream>
#ifdef TRI_HAVE_UNISTD_H
#include <unistd.h>
#endif

#define ARANGODB_PROGRAM_OPTIONS_PROGNAME "#progname#"

using namespace arangodb::options;

ProgramOptions::ProgramOptions(char const* progname, std::string const& usage,
                               std::string const& more, char const* binaryPath)
    : _progname(progname),
      _usage(usage),
      _more(more),
      _similarity(TRI_Levenshtein),
      _processingResult(),
      _sealed(false),
      _overrideOptions(false),
      _binaryPath(binaryPath) {
  // find progname wildcard in string
  size_t const pos = _usage.find(ARANGODB_PROGRAM_OPTIONS_PROGNAME);

  if (pos != std::string::npos) {
    // and replace it with actual program name
    _usage = usage.substr(0, pos) + _progname +
             _usage.substr(pos + strlen(ARANGODB_PROGRAM_OPTIONS_PROGNAME));
  }

  _translator = EnvironmentTranslator;
}

// sets a value translator
void ProgramOptions::setTranslator(
    std::function<std::string(std::string const&, char const*)> const& translator) {
  _translator = translator;
}

// prints usage information
void ProgramOptions::printUsage() const {
  std::cout << _usage << std::endl << std::endl;
}

// prints a help for all options, or the options of a section
// the special search string "*" will show help for all sections
// the special search string "." will show help for all sections, even if
// hidden
void ProgramOptions::printHelp(std::string const& search) const {
  bool const colors = (isatty(STDOUT_FILENO) != 0);
  printUsage();

  TRI_TerminalSize ts = TRI_DefaultTerminalSize();
  size_t const tw = ts.columns;
  size_t const ow = optionsWidth();

  for (auto const& it : _sections) {
    if (search == "*" || search == "." || search == it.second.name) {
      it.second.printHelp(search, tw, ow, colors);
    }
  }

  if (search == "*") {
    printSectionsHelp();
  }
}

// prints the names for all section help options
void ProgramOptions::printSectionsHelp() const {
  char const* colorStart = "";
  char const* colorEnd = "";

  if (isatty(STDOUT_FILENO)) {
    colorStart = ShellColorsFeature::SHELL_COLOR_BRIGHT;
    colorEnd = ShellColorsFeature::SHELL_COLOR_RESET;
  }

  // print names of sections
  std::cout << _more;
  for (auto const& it : _sections) {
    if (!it.second.name.empty() && it.second.hasOptions()) {
      std::cout << "  " << colorStart << "--help-" << it.second.name << colorEnd;
    }
  }
  std::cout << std::endl;
}

// returns a VPack representation of the option values, with optional
// filters applied to filter out specific options. 
// the filter function is expected to return true
// for any options that should become part of the result
VPackBuilder ProgramOptions::toVPack(bool onlyTouched, bool detailed,
                                     std::function<bool(std::string const&)> const& filter) const {
  VPackBuilder builder;
  builder.openObject();

  walk(
      [this, &builder, &filter, &detailed](Section const& section, Option const& option) {
        std::string full(option.fullName());
        
        if (!filter(full)) {
          return;
        }

        // add key
        builder.add(VPackValue(full));

        // add value
        if (detailed) {
          builder.openObject();
          builder.add("section", VPackValue(option.section));
          builder.add("description", VPackValue(option.description));
          builder.add("category", VPackValue(option.hasFlag(arangodb::options::Flags::Command)
                                                 ? "command"
                                                 : "option"));
          builder.add("hidden", VPackValue(option.hasFlag(arangodb::options::Flags::Hidden)));
          builder.add("type", VPackValue(option.parameter->name()));
          builder.add("obsolete",
                      VPackValue(option.hasFlag(arangodb::options::Flags::Obsolete)));
          builder.add("enterpriseOnly",
                      VPackValue(section.enterpriseOnly ||
                                 option.hasFlag(arangodb::options::Flags::Enterprise)));
          builder.add("requiresValue", VPackValue(option.parameter->requiresValue()));
         
          // OS support
          builder.add("os", VPackValue(VPackValueType::Array));
          if (option.hasFlag(arangodb::options::Flags::OsLinux)) {
            builder.add(VPackValue("linux"));
          }
          if (option.hasFlag(arangodb::options::Flags::OsMac)) {
            builder.add(VPackValue("macos"));
          }
          if (option.hasFlag(arangodb::options::Flags::OsWindows)) {
            builder.add(VPackValue("windows"));
          }
          builder.close();
          
          // component support
          char const* arangod = "arangod";
          if (_progname.size() >= strlen(arangod) &&
              _progname.compare(_progname.size() - strlen(arangod), strlen(arangod), arangod) == 0) {
            builder.add("component", VPackValue(VPackValueType::Array));
            if (option.hasFlag(arangodb::options::Flags::OnCoordinator)) {
{'fraction_non_alphanumeric': 0.1535542025776864, 'fraction_numerical': 0.0016604728394085553, 'mean_word_length': 2.655491329479769, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5434208', 'n_tokens_mistral': 3642, 'n_tokens_neox': 3507, 'n_words': 882}