| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- #pragma once
- #include <string>
- #include <vector>
- #include <functional>
- #include <unordered_map>
- #include <optional>
- #include <variant>
- #include "lumacs/i_command_target.hpp" // New include for ICommandTarget
- // #include "lumacs/editor_core.hpp" // Required for EditorCore definition - moved to .cpp
- namespace lumacs {
- class EditorCore; // Forward declaration
- class MinibufferManager; // Forward declare MinibufferManager for interactive args
- /// @brief Defines the status of a command execution.
- enum class CommandStatus {
- Success,
- Failure,
- PendingInput // Indicates the command is waiting for user input
- };
- /// @brief Represents the result of a command execution.
- struct CommandResult {
- CommandStatus status;
- std::string message;
- // Potentially add more fields, like return value, error code, etc.
- };
- /// @brief Context object passed to command functions for argument access and interaction.
- class CommandContext {
- public:
- CommandContext(ICommandTarget& target, MinibufferManager& minibuffer_manager, const std::vector<std::string>& args)
- : target_(target), minibuffer_manager_(minibuffer_manager), args_(args) {} // Corrected initializer list order
- /// @brief Get argument at index as string.
- std::optional<std::string> get_string_arg(size_t index) const;
- /// @brief Get argument at index as integer.
- std::optional<int> get_int_arg(size_t index) const;
- // TODO: Add more typed accessors as needed (bool, double, etc.)
- /// @brief Prompts the user for a string argument.
- std::optional<std::string> read_string(const std::string& prompt);
- /// @brief Prompts the user for a file path.
- std::optional<std::string> read_file_path(const std::string& prompt);
- // Access to core components for command logic
- ICommandTarget& target() { return target_; }
- /// @brief Get all gathered arguments.
- [[nodiscard]] const std::vector<std::string>& get_args() const { return args_; }
- private:
- ICommandTarget& target_; // Declared first
- MinibufferManager& minibuffer_manager_; // Declared second
- std::vector<std::string> args_; // Declared third
- };
- /// @brief Type for command functions.
- /// Commands take a CommandContext reference and return a CommandResult.
- using CommandFunction = std::function<CommandResult(CommandContext&)>;
- /// @brief Represents a single command.
- struct Command {
- std::string name;
- CommandFunction function;
- std::string doc_string; // Documentation for the command
- bool interactive; // Whether the command can be called interactively (e.g., via M-x)
- std::string interactive_spec; // Emacs-like interactive spec for argument gathering
- std::vector<std::string> aliases; // New: list of alias names for this command
- Command(std::string name, CommandFunction func, std::string doc = "", bool interactive = false, std::string i_spec = "", std::vector<std::string> aliases = {})
- : name(std::move(name)), function(std::move(func)), doc_string(std::move(doc)), interactive(interactive), interactive_spec(std::move(i_spec)), aliases(std::move(aliases)) {}
- };
- /// @brief Manages the registration and execution of editor commands.
- class CommandSystem {
- public:
- explicit CommandSystem(EditorCore& core, MinibufferManager& minibuffer_manager);
- /// @brief Registers a command with the system.
- void register_command(const std::string& name, CommandFunction function,
- const std::string& doc_string = "", bool interactive = false,
- std::string interactive_spec = "", std::vector<std::string> aliases = {});
- /// @brief Clears all registered commands and aliases.
- void clear_commands();
- /// @brief Executes a command by name with given arguments.
- /// @param name The name of the command to execute.
- /// @param args Arguments for the command.
- /// @return CommandResult indicating success/failure and a message.
- CommandResult execute(const std::string& name, const std::vector<std::string>& args);
- /// @brief Get a list of all registered command names.
- std::vector<std::string> get_command_names() const;
- /// @brief Get documentation for a specific command.
- std::optional<std::string> get_command_doc_string(const std::string& name) const;
- /// @brief Get the interactive spec for a specific command.
- std::optional<std::string> get_command_interactive_spec(const std::string& name) const;
- /// @brief Executes a command interactively, prompting the user for arguments if needed.
- /// @param name The name of the command to execute.
- /// @return CommandResult indicating success/failure and a message, or a pending state.
- CommandResult execute_interactive(const std::string& name);
- private:
- EditorCore& core_; // Reference to EditorCore
- MinibufferManager& minibuffer_manager_; // Reference to MinibufferManager
- std::unordered_map<std::string, Command> commands_;
- std::unordered_map<std::string, std::string> alias_map_; // Maps alias to canonical command name
- // State for interactive command execution
- std::optional<Command> current_interactive_command_;
- size_t current_interactive_spec_index_ = 0;
- std::vector<std::string> gathered_interactive_args_;
- CommandResult process_next_interactive_argument();
- };
- } // namespace lumacs
|