[vcpkg] Begin refactor to use CommandStructure to represent command parsing
MODIFY
include/vcpkg/install.h
include/vcpkg/install.h
@@ -65,5 +65,7 @@ namespace vcpkg::Install
const VcpkgPaths& paths,
StatusParagraphs& status_db);
+ extern const CommandStructure INSTALL_COMMAND_STRUCTURE;
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet);
}

MODIFY
include/vcpkg/remove.h
include/vcpkg/remove.h
@@ -19,6 +19,8 @@ namespace vcpkg::Remove
const Purge purge,
StatusParagraphs& status_db);
+ extern const CommandStructure REMOVE_COMMAND_STRUCTURE;
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet);
void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db);
}

MODIFY
include/vcpkg/vcpkgcmdarguments.h
include/vcpkg/vcpkgcmdarguments.h
#pragma once
+#include <vcpkg/base/cstringview.h>
#include <vcpkg/base/optional.h>
+#include <vcpkg/base/span.h>
#include <memory>
#include <unordered_map>
@@ -47,4 +49,19 @@ namespace vcpkg
private:
std::unordered_map<std::string, Optional<std::string>> optional_command_arguments;
};
+
+ struct VcpkgPaths;
+
+ struct CommandStructure
+ {
+ CStringView example_text;
+
+ size_t minimum_arity;
+ size_t maximum_arity;
+
+ Span<const std::string> switches;
+ Span<const std::string> settings;
+
+ std::vector<std::string> (*valid_arguments)(const VcpkgPaths& paths);
+ };
}

MODIFY
src/vcpkg/commands.autocomplete.cpp
src/vcpkg/commands.autocomplete.cpp
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
+#include <vcpkg/install.h>
#include <vcpkg/metrics.h>
#include <vcpkg/paragraphs.h>
+#include <vcpkg/remove.h>
#include <vcpkg/vcpkglib.h>
namespace vcpkg::Commands::Autocomplete
@@ -47,6 +49,7 @@ namespace vcpkg::Commands::Autocomplete
{
const SortedVector<std::string> sorted_results(results);
System::println(Strings::join("\n", sorted_results));
+
Checks::exit_success(line_info);
}
@@ -63,7 +66,8 @@ namespace vcpkg::Commands::Autocomplete
{
const std::string requested_command = match[1].str();
- std::vector<std::string> valid_commands = {"install",
+ std::vector<std::string> valid_commands = {
+ "install",
"search",
"remove",
"list",
@@ -77,7 +81,8 @@ namespace vcpkg::Commands::Autocomplete
"owns",
"cache",
"version",
- "contact"};
+ "contact",
+ };
Util::unstable_keep_if(valid_commands, [&](const std::string& s) {
return Strings::case_insensitive_ascii_starts_with(s, requested_command);
@@ -86,22 +91,36 @@ namespace vcpkg::Commands::Autocomplete
output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(valid_commands));
}
- // Handles vcpkg install <package>
- if (std::regex_match(to_autocomplete, match, std::regex{R"###(^install.* (\S*)$)###"}))
+ struct CommandEntry
+ {
+ CStringView regex;
+ const CommandStructure& structure;
+ };
+ static constexpr CommandEntry commands[] = {
+ {R"###(^install\s(.*\s|)(\S*)$)###", Install::INSTALL_COMMAND_STRUCTURE},
+ {R"###(^remove\s(.*\s|)(\S*)$)###", Remove::REMOVE_COMMAND_STRUCTURE},
+ };
+
+ for (auto&& command : commands)
+ {
+ if (std::regex_match(to_autocomplete, match, std::regex{command.regex.c_str()}))
{
- const std::string start_with = match[1].str();
- auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
- auto& source_paragraphs = sources_and_errors.paragraphs;
- output_sorted_results_and_exit(VCPKG_LINE_INFO, autocomplete_install(source_paragraphs, start_with));
+ auto prefix = match[2].str();
+ std::vector<std::string> v;
+ if (Strings::case_insensitive_ascii_starts_with(prefix, "-"))
+ {
+ v = Util::fmap(command.structure.switches, [](auto&& s) -> std::string { return s; });
}
-
- // Handles vcpkg remove <package>
- if (std::regex_match(to_autocomplete, match, std::regex{R"###(^remove.* (\S*)$)###"}))
+ else
{
- const std::string start_with = match[1].str();
- const StatusParagraphs status_db = database_load_check(paths);
- const std::vector<StatusParagraph*> installed_packages = get_installed_ports(status_db);
- output_sorted_results_and_exit(VCPKG_LINE_INFO, autocomplete_remove(installed_packages, start_with));
+ v = command.structure.valid_arguments(paths);
+ }
+
+ Util::unstable_keep_if(
+ v, [&](const std::string& s) { return Strings::case_insensitive_ascii_starts_with(s, prefix); });
+
+ output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(v));
+ }
}
Checks::exit_success(VCPKG_LINE_INFO);

MODIFY
src/vcpkg/install.cpp
src/vcpkg/install.cpp
@@ -525,14 +525,40 @@ namespace vcpkg::Install
Checks::exit_success(VCPKG_LINE_INFO);
}
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
- {
static const std::string OPTION_DRY_RUN = "--dry-run";
static const std::string OPTION_USE_HEAD_VERSION = "--head";
static const std::string OPTION_NO_DOWNLOADS = "--no-downloads";
static const std::string OPTION_RECURSE = "--recurse";
static const std::string OPTION_KEEP_GOING = "--keep-going";
+ static const std::array<std::string, 5> INSTALL_SWITCHES = {
+ OPTION_DRY_RUN,
+ OPTION_USE_HEAD_VERSION,
+ OPTION_NO_DOWNLOADS,
+ OPTION_RECURSE,
+ OPTION_KEEP_GOING,
+ };
+ static const std::array<std::string, 0> INSTALL_SETTINGS;
+
+ static std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
+ {
+ auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
+
+ return Util::fmap(sources_and_errors.paragraphs,
+ [](auto&& pgh) -> std::string { return pgh->core_paragraph->name; });
+ }
+
+ const CommandStructure INSTALL_COMMAND_STRUCTURE = {
+ "install zlib zlib:x64-windows curl boost",
+ 1,
+ SIZE_MAX,
+ INSTALL_SWITCHES,
+ INSTALL_SETTINGS,
+ &valid_arguments,
+ };
+
+ void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
+ {
// input sanitization
static const std::string EXAMPLE = Help::create_example_string("install zlib zlib:x64-windows curl boost");
args.check_min_arg_count(1, EXAMPLE);

MODIFY
src/vcpkg/remove.cpp
src/vcpkg/remove.cpp
@@ -163,13 +163,40 @@ namespace vcpkg::Remove
}
}
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
- {
static const std::string OPTION_PURGE = "--purge";
static const std::string OPTION_NO_PURGE = "--no-purge";
static const std::string OPTION_RECURSE = "--recurse";
static const std::string OPTION_DRY_RUN = "--dry-run";
static const std::string OPTION_OUTDATED = "--outdated";
+
+ static const std::array<std::string, 5> REMOVE_SWITCHES = {
+ OPTION_PURGE,
+ OPTION_NO_PURGE,
+ OPTION_RECURSE,
+ OPTION_DRY_RUN,
+ OPTION_OUTDATED,
+ };
+ static const std::array<std::string, 0> REMOVE_SETTINGS;
+
+ static std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
+ {
+ const StatusParagraphs status_db = database_load_check(paths);
+ const std::vector<StatusParagraph*> installed_packages = get_installed_ports(status_db);
+
+ return Util::fmap(installed_packages, [](auto&& pgh) -> std::string { return pgh->package.spec.to_string(); });
+ }
+
+ const CommandStructure REMOVE_COMMAND_STRUCTURE = {
+ "remove zlib zlib:x64-windows curl boost",
+ 1,
+ SIZE_MAX,
+ REMOVE_SWITCHES,
+ REMOVE_SETTINGS,
+ &valid_arguments,
+ };
+
+ void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
+ {
static const std::string EXAMPLE = Help::create_example_string("remove zlib zlib:x64-windows curl boost");
const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments(
{OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED});

[vcpkg] Begin refactor to use CommandStructure to represent command parsing