| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- #pragma once
- #include <string>
- #include <functional>
- #include <memory>
- #include <vector>
- #include <unordered_map>
- #include <filesystem>
- namespace lumacs {
- class EditorCore; // Forward declaration
- /// @brief Result of command execution.
- struct CommandResult {
- bool success;
- std::string message;
-
- CommandResult(bool s = true, std::string msg = "")
- : success(s), message(std::move(msg)) {}
- };
- /// @brief Function signature for executable commands.
- /// Takes a vector of string arguments and returns a CommandResult.
- using CommandFunction = std::function<CommandResult(const std::vector<std::string>&)>;
- /// @brief Metadata and implementation of a named command.
- struct Command {
- std::string name; ///< Unique command name (e.g., "find-file").
- std::string description; ///< Human-readable help text.
- CommandFunction function; ///< The implementation function.
- std::vector<std::string> aliases; ///< Alternative names.
- bool interactive; ///< Whether this command can be called interactively (M-x).
-
- Command(std::string n, std::string desc, CommandFunction func,
- std::vector<std::string> alias = {}, bool inter = true)
- : name(std::move(n)), description(std::move(desc)),
- function(std::move(func)), aliases(std::move(alias)), interactive(inter) {}
- };
- /// @brief A possible completion match for user input.
- struct CompletionCandidate {
- std::string text; ///< The completion text.
- int score; ///< Matching score (higher is better).
- std::string description;///< Extra info (e.g., file type, command desc).
-
- CompletionCandidate(std::string t, int s = 0, std::string desc = "")
- : text(std::move(t)), score(s), description(std::move(desc)) {}
-
- bool operator<(const CompletionCandidate& other) const {
- if (score != other.score) return score > other.score; // Higher score first
- return text < other.text; // Alphabetical for same score
- }
- };
- /// @brief Provider function for generating completions.
- using CompletionProvider = std::function<std::vector<CompletionCandidate>(const std::string& input)>;
- /// @brief Utility class for filesystem completions.
- class FileSystemCompletionProvider {
- public:
- /// @brief Complete paths (files and directories) relative to CWD or absolute.
- std::vector<CompletionCandidate> complete_path(const std::string& input) const;
-
- /// @brief Complete directory paths only.
- std::vector<CompletionCandidate> complete_directory(const std::string& input) const;
-
- /// @brief Complete files, optionally filtered by extension.
- std::vector<CompletionCandidate> complete_file(const std::string& input, const std::vector<std::string>& extensions = {}) const;
-
- private:
- bool is_absolute_path(const std::string& path) const;
- std::string normalize_path(const std::string& path) const;
- int calculate_path_score(const std::string& candidate, const std::string& input) const;
- };
- /// @brief Central registry for commands and completion logic.
- ///
- /// The CommandSystem manages:
- /// - Registration of named commands.
- /// - Execution of commands by name.
- /// - Parsing of command strings.
- /// - Autocompletion providers for different contexts (M-x, Find File, etc.).
- class CommandSystem {
- public:
- explicit CommandSystem(EditorCore& core);
- ~CommandSystem() = default;
- // === Command Registration ===
- /// @brief Register a command object.
- void register_command(std::unique_ptr<Command> command);
- /// @brief Helper to register a command.
- void register_command(const std::string& name, const std::string& description,
- CommandFunction function, const std::vector<std::string>& aliases = {},
- bool interactive = true);
-
- // === Command Execution ===
- /// @brief Execute a named command with arguments.
- /// @return Result indicating success/failure and message.
- CommandResult execute(const std::string& command_name, const std::vector<std::string>& args = {});
- /// @brief Parse and execute a raw command string (e.g., "find-file src/main.cpp").
- CommandResult execute_string(const std::string& command_string);
-
- // === Command Lookup ===
- /// @brief Check if a command exists.
- bool has_command(const std::string& name) const;
- /// @brief Get a command by name.
- std::shared_ptr<Command> get_command(const std::string& name) const;
- /// @brief Get names of all registered commands.
- std::vector<std::string> get_all_command_names() const;
- /// @brief Get names of commands marked as interactive.
- std::vector<std::string> get_interactive_command_names() const;
-
- // === Completion System ===
- /// @brief Get completions for command names (M-x).
- std::vector<CompletionCandidate> complete_command(const std::string& input) const;
- /// @brief Get completions for buffer names (C-x b).
- std::vector<CompletionCandidate> complete_buffer_name(const std::string& input) const;
- /// @brief Get completions for file paths (C-x C-f).
- std::vector<CompletionCandidate> complete_file_path(const std::string& input) const;
- /// @brief Get completions for theme names.
- std::vector<CompletionCandidate> complete_theme_name(const std::string& input) const;
-
- /// @brief Register a custom completion provider for a command argument.
- void register_completion_provider(const std::string& command_name, CompletionProvider provider);
- /// @brief Get completions for a specific command's arguments.
- std::vector<CompletionCandidate> get_completions(const std::string& command_name, const std::string& input) const;
-
- // === Utilities ===
- /// @brief Calculate fuzzy match score between candidate and input.
- static int fuzzy_match_score(const std::string& candidate, const std::string& input);
- /// @brief Check if candidate matches input fuzzily.
- static bool fuzzy_match(const std::string& candidate, const std::string& input);
-
- private:
- EditorCore& core_;
- std::unordered_map<std::string, std::shared_ptr<Command>> commands_;
- std::unordered_map<std::string, CompletionProvider> completion_providers_;
- FileSystemCompletionProvider fs_provider_;
-
- void register_builtin_commands();
- std::vector<std::string> parse_command_string(const std::string& command_string) const;
- };
- } // namespace lumacs
|