winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Command.h (7480B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 #pragma once
      4 #include "Argument.h"
      5 #include "ExecutionContext.h"
      6 #include "Invocation.h"
      7 #include "Resources.h"
      8 #include <winget/UserSettings.h>
      9 #include <winget/ExperimentalFeature.h>
     10 #include <winget/GroupPolicy.h>
     11 
     12 #include <initializer_list>
     13 #include <memory>
     14 #include <optional>
     15 #include <ostream>
     16 #include <string>
     17 #include <string_view>
     18 #include <type_traits>
     19 #include <vector>
     20 
     21 namespace AppInstaller::CLI
     22 {
     23     struct CommandException
     24     {
     25         CommandException(Resource::LocString message) : m_message(std::move(message)) {}
     26         const Utility::LocIndString Message() const { return m_message; }
     27 
     28     private:
     29         Resource::LocString m_message;
     30     };
     31 
     32     // Flags to control the behavior of the command output.
     33     enum class CommandOutputFlags : int
     34     {
     35         None = 0x0,
     36         IgnoreSettingsWarnings = 0x1,
     37     };
     38 
     39     DEFINE_ENUM_FLAG_OPERATORS(CommandOutputFlags);
     40 
     41     struct Command
     42     {
     43         // Controls the visibility of the field.
     44         enum class Visibility
     45         {
     46             // Shown in help.
     47             Show,
     48             // Not shown in help.
     49             Hidden,
     50         };
     51 
     52         Command(std::string_view name, std::string_view parent) :
     53             Command(name, {}, parent) {}
     54         Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent) :
     55             Command(name, aliases, parent, Settings::ExperimentalFeature::Feature::None) {}
     56         Command(std::string_view name, std::string_view parent, CommandOutputFlags outputFlags) :
     57             Command(name, {}, parent, Command::Visibility::Show, Settings::ExperimentalFeature::Feature::None, Settings::TogglePolicy::Policy::None, outputFlags) {}
     58         Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility) :
     59             Command(name, aliases, parent, visibility, Settings::ExperimentalFeature::Feature::None) {}
     60         Command(std::string_view name, std::string_view parent, Settings::ExperimentalFeature::Feature feature) :
     61             Command(name, {}, parent, Command::Visibility::Show, feature) {}
     62         Command(std::string_view name, std::string_view parent, Settings::ExperimentalFeature::Feature feature, CommandOutputFlags outputFlags) :
     63             Command(name, {}, parent, Command::Visibility::Show, feature, Settings::TogglePolicy::Policy::None, outputFlags) {}
     64         Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Settings::ExperimentalFeature::Feature feature) :
     65             Command(name, aliases, parent, Command::Visibility::Show, feature) {}
     66         Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Settings::TogglePolicy::Policy groupPolicy) :
     67             Command(name, aliases, parent, Command::Visibility::Show, Settings::ExperimentalFeature::Feature::None, groupPolicy, CommandOutputFlags::None) {}
     68         Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility, Settings::ExperimentalFeature::Feature feature) :
     69             Command(name, aliases, parent, visibility, feature, Settings::TogglePolicy::Policy::None, CommandOutputFlags::None) {}
     70         Command(std::string_view name, std::vector<std::string_view> aliases, std::string_view parent, Command::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy) :
     71             Command(name, aliases, parent, visibility, Settings::ExperimentalFeature::Feature::None, groupPolicy, CommandOutputFlags::None) {}
     72 
     73         Command(std::string_view name,
     74             std::vector<std::string_view> aliases,
     75             std::string_view parent,
     76             Command::Visibility visibility,
     77             Settings::ExperimentalFeature::Feature feature,
     78             Settings::TogglePolicy::Policy groupPolicy,
     79             CommandOutputFlags outputFlags);
     80 
     81         virtual ~Command() = default;
     82 
     83         Command(const Command&) = default;
     84         Command& operator=(const Command&) = default;
     85 
     86         Command(Command&&) = default;
     87         Command& operator=(Command&&) = default;
     88 
     89         // The character used to split between commands and their parents in FullName.
     90         constexpr static char ParentSplitChar = ':';
     91 
     92         std::string_view Name() const { return m_name; }
     93         const std::vector<std::string_view>& Aliases() const& { return m_aliases; }
     94         const std::string& FullName() const { return m_fullName; }
     95         Command::Visibility GetVisibility() const;
     96         Settings::ExperimentalFeature::Feature Feature() const { return m_feature; }
     97         Settings::TogglePolicy::Policy GroupPolicy() const { return m_groupPolicy; }
     98         CommandOutputFlags GetOutputFlags() const { return m_outputFlags; }
     99 
    100         virtual std::vector<std::unique_ptr<Command>> GetCommands() const { return {}; }
    101         virtual std::vector<Argument> GetArguments() const { return {}; }
    102         std::vector<std::unique_ptr<Command>> GetVisibleCommands() const;
    103         std::vector<Argument> GetVisibleArguments() const;
    104 
    105         virtual Resource::LocString ShortDescription() const = 0;
    106         virtual Resource::LocString LongDescription() const = 0;
    107 
    108         virtual void OutputIntroHeader(Execution::Reporter& reporter) const;
    109         virtual void OutputHelp(Execution::Reporter& reporter, const CommandException* exception = nullptr) const;
    110         virtual Utility::LocIndView HelpLink() const { return {}; }
    111 
    112         virtual std::unique_ptr<Command> FindSubCommand(Invocation& inv) const;
    113         virtual void ParseArguments(Invocation& inv, Execution::Args& execArgs) const;
    114         virtual void ValidateArguments(Execution::Args& execArgs) const;
    115 
    116         virtual void Complete(Execution::Context& context) const;
    117         virtual void Complete(Execution::Context& context, Execution::Args::Type valueType) const;
    118 
    119         virtual void Execute(Execution::Context& context) const;
    120 
    121         virtual void Resume(Execution::Context& context) const;
    122 
    123     protected:
    124         void SelectCurrentCommandIfUnrecognizedSubcommandFound(bool value);
    125 
    126         virtual void ValidateArgumentsInternal(Execution::Args& execArgs) const;
    127         virtual void ExecuteInternal(Execution::Context& context) const;
    128 
    129     private:
    130         std::string_view m_name;
    131         std::string m_fullName;
    132         std::vector<std::string_view> m_aliases;
    133         Command::Visibility m_visibility;
    134         Settings::ExperimentalFeature::Feature m_feature;
    135         Settings::TogglePolicy::Policy m_groupPolicy;
    136         CommandOutputFlags m_outputFlags;
    137         bool m_selectCurrentCommandIfUnrecognizedSubcommandFound = false;
    138         std::string m_commandArguments;
    139     };
    140 
    141     template <typename Container>
    142     Container InitializeFromMoveOnly(std::initializer_list<typename Container::value_type> il)
    143     {
    144         using Value = typename Container::value_type;
    145         Container result;
    146 
    147         for (const auto& v : il)
    148         {
    149             result.emplace_back(std::move(*const_cast<Value*>(&v)));
    150         }
    151 
    152         return result;
    153     }
    154 
    155     void ExecuteWithoutLoggingSuccess(Execution::Context& context, Command* command);
    156 
    157     int Execute(Execution::Context& context, std::unique_ptr<Command>& command);
    158 }