command_system.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #pragma once
  2. #include <string>
  3. #include <functional>
  4. #include <memory>
  5. #include <vector>
  6. #include <unordered_map>
  7. #include <filesystem>
  8. #include "lumacs/completion_common.hpp" // For CompletionCandidate
  9. namespace lumacs {
  10. class EditorCore; // Forward declaration
  11. /// @brief Result of command execution.
  12. struct CommandResult {
  13. bool success;
  14. std::string message;
  15. CommandResult(bool s = true, std::string msg = "")
  16. : success(s), message(std::move(msg)) {}
  17. };
  18. /// @brief Function signature for executable commands.
  19. /// Takes a vector of string arguments and returns a CommandResult.
  20. using CommandFunction = std::function<CommandResult(const std::vector<std::string>&)>;
  21. /// @brief Metadata and implementation of a named command.
  22. struct Command {
  23. std::string name; ///< Unique command name (e.g., "find-file").
  24. std::string description; ///< Human-readable help text.
  25. CommandFunction function; ///< The implementation function.
  26. std::vector<std::string> aliases; ///< Alternative names.
  27. bool interactive; ///< Whether this command can be called interactively (M-x).
  28. Command(std::string n, std::string desc, CommandFunction func,
  29. std::vector<std::string> alias = {}, bool inter = true)
  30. : name(std::move(n)), description(std::move(desc)),
  31. function(std::move(func)), aliases(std::move(alias)), interactive(inter) {}
  32. };
  33. /// @brief Provider function for generating completions.
  34. using CompletionProvider = std::function<std::vector<CompletionCandidate>(const std::string& input)>;
  35. /// @brief Utility class for filesystem completions.
  36. class FileSystemCompletionProvider {
  37. public:
  38. /// @brief Complete paths (files and directories) relative to CWD or absolute.
  39. std::vector<CompletionCandidate> complete_path(const std::string& input) const;
  40. /// @brief Complete directory paths only.
  41. std::vector<CompletionCandidate> complete_directory(const std::string& input) const;
  42. /// @brief Complete files, optionally filtered by extension.
  43. std::vector<CompletionCandidate> complete_file(const std::string& input, const std::vector<std::string>& extensions = {}) const;
  44. private:
  45. bool is_absolute_path(const std::string& path) const;
  46. std::string normalize_path(const std::string& path) const;
  47. int calculate_path_score(const std::string& candidate, const std::string& input) const;
  48. };
  49. /// @brief Central registry for commands and completion logic.
  50. ///
  51. /// The CommandSystem manages:
  52. /// - Registration of named commands.
  53. /// - Execution of commands by name.
  54. /// - Parsing of command strings.
  55. /// - Autocompletion providers for different contexts (M-x, Find File, etc.).
  56. class CommandSystem {
  57. public:
  58. explicit CommandSystem(EditorCore& core);
  59. ~CommandSystem() = default;
  60. // === Command Registration ===
  61. /// @brief Register a command object.
  62. void register_command(std::unique_ptr<Command> command);
  63. /// @brief Helper to register a command.
  64. void register_command(const std::string& name, const std::string& description,
  65. CommandFunction function, const std::vector<std::string>& aliases = {},
  66. bool interactive = true);
  67. // === Command Execution ===
  68. /// @brief Execute a named command with arguments.
  69. /// @return Result indicating success/failure and message.
  70. CommandResult execute(const std::string& command_name, const std::vector<std::string>& args = {});
  71. /// @brief Parse and execute a raw command string (e.g., "find-file src/main.cpp").
  72. CommandResult execute_string(const std::string& command_string);
  73. // === Command Lookup ===
  74. /// @brief Check if a command exists.
  75. bool has_command(const std::string& name) const;
  76. /// @brief Get a command by name.
  77. std::shared_ptr<Command> get_command(const std::string& name) const;
  78. /// @brief Get names of all registered commands.
  79. std::vector<std::string> get_all_command_names() const;
  80. /// @brief Get names of commands marked as interactive.
  81. std::vector<std::string> get_interactive_command_names() const;
  82. // === Completion System ===
  83. /// @brief Get completions for command names (M-x).
  84. std::vector<CompletionCandidate> complete_command(const std::string& input) const;
  85. /// @brief Get completions for buffer names (C-x b).
  86. std::vector<CompletionCandidate> complete_buffer_name(const std::string& input) const;
  87. /// @brief Get completions for file paths (C-x C-f).
  88. std::vector<CompletionCandidate> complete_file_path(const std::string& input) const;
  89. /// @brief Get completions for theme names.
  90. std::vector<CompletionCandidate> complete_theme_name(const std::string& input) const;
  91. /// @brief Register a custom completion provider for a command argument.
  92. void register_completion_provider(const std::string& command_name, CompletionProvider provider);
  93. /// @brief Get completions for a specific command's arguments.
  94. std::vector<CompletionCandidate> get_completions(const std::string& command_name, const std::string& input) const;
  95. // === Utilities ===
  96. /// @brief Calculate fuzzy match score between candidate and input.
  97. static int fuzzy_match_score(const std::string& candidate, const std::string& input);
  98. /// @brief Check if candidate matches input fuzzily.
  99. static bool fuzzy_match(const std::string& candidate, const std::string& input);
  100. private:
  101. EditorCore& core_;
  102. std::unordered_map<std::string, std::shared_ptr<Command>> commands_;
  103. std::unordered_map<std::string, CompletionProvider> completion_providers_;
  104. FileSystemCompletionProvider fs_provider_;
  105. void register_builtin_commands();
  106. std::vector<std::string> parse_command_string(const std::string& command_string) const;
  107. };
  108. } // namespace lumacs