#pragma once #include #include #include #include #include #include #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& args) : target_(target), minibuffer_manager_(minibuffer_manager), args_(args) {} // Corrected initializer list order /// @brief Get argument at index as string. std::optional get_string_arg(size_t index) const; /// @brief Get argument at index as integer. std::optional 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 read_string(const std::string& prompt); /// @brief Prompts the user for a file path. std::optional 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& get_args() const { return args_; } private: ICommandTarget& target_; // Declared first MinibufferManager& minibuffer_manager_; // Declared second std::vector args_; // Declared third }; /// @brief Type for command functions. /// Commands take a CommandContext reference and return a CommandResult. using CommandFunction = std::function; /// @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 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 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 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& args); /// @brief Get a list of all registered command names. std::vector get_command_names() const; /// @brief Get documentation for a specific command. std::optional get_command_doc_string(const std::string& name) const; /// @brief Get the interactive spec for a specific command. std::optional 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); /// @brief Access the EditorCore instance. EditorCore& core() const { return core_; } private: EditorCore& core_; // Reference to EditorCore MinibufferManager& minibuffer_manager_; // Reference to MinibufferManager std::unordered_map commands_; std::unordered_map alias_map_; // Maps alias to canonical command name // State for interactive command execution std::optional current_interactive_command_; size_t current_interactive_spec_index_ = 0; std::vector gathered_interactive_args_; CommandResult process_next_interactive_argument(); }; } // namespace lumacs