Explorar el Código

refactor(keybinding): Refine Canonical Key Representation (B.2)

Bernardo Magri hace 1 mes
padre
commit
45acea6152
Se han modificado 2 ficheros con 136 adiciones y 31 borrados
  1. 29 7
      include/lumacs/keybinding.hpp
  2. 107 24
      src/keybinding.cpp

+ 29 - 7
include/lumacs/keybinding.hpp

@@ -12,21 +12,43 @@ namespace lumacs {
 
 namespace lumacs {
 
+/// @brief Represents the base key (without modifiers).
+enum class BaseKey : uint16_t {
+    Unknown = 0,
+    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
+    D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, // Digits
+    F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, // Function keys
+    Space, Return, Tab, Escape, Backspace, Delete,
+    ArrowUp, ArrowDown, ArrowLeft, ArrowRight,
+    Home, End, PageUp, PageDown, Insert,
+    Semicolon, Equal, Comma, Minus, Period, Slash, Backtick,
+    LeftBracket, Backslash, RightBracket, Quote,
+    NumLock, ScrollLock, PrintScreen, Pause,
+    // Add more as needed
+};
+
+/// @brief Represents key modifiers as a bitmask.
+enum class Modifier : uint16_t {
+    None = 0,
+    Control = 1 << 0,
+    Meta = 1 << 1, // Alt key, Option key
+    Shift = 1 << 2,
+};
+
 /// @brief Represents a single key in a key sequence.
 struct Key {
-    std::string name;           ///< Key name (e.g., "a", "Return", "F1").
-    bool ctrl = false;          ///< Ctrl modifier active.
-    bool meta = false;          ///< Meta/Alt modifier active.
-    bool shift = false;         ///< Shift modifier active.
+    BaseKey base_key = BaseKey::Unknown;
+    Modifier modifiers = Modifier::None;
     
     Key() = default;
-    explicit Key(const std::string& key_name);
+    explicit Key(BaseKey bk, Modifier mods = Modifier::None) : base_key(bk), modifiers(mods) {}
+    explicit Key(const std::string& key_name); // To be implemented in .cpp
     
     /// @brief Parse a key string like "C-x" or "M-S-a" into a Key structure.
-    static Key parse(const std::string& key_str);
+    static Key parse(const std::string& key_str); // To be implemented in .cpp
     
     /// @brief Convert Key back to canonical string representation.
-    std::string to_string() const;
+    std::string to_string() const; // To be implemented in .cpp
     
     bool operator==(const Key& other) const;
     bool operator<(const Key& other) const;

+ 107 - 24
src/keybinding.cpp

@@ -10,37 +10,125 @@ namespace lumacs {
 // Key Implementation
 // ============================================================================
 
-Key::Key(const std::string& key_name) {
-    *this = parse(key_name);
+namespace {
+    // Helper to convert string to BaseKey
+    BaseKey string_to_base_key(const std::string& s) {
+        if (s.length() == 1) {
+            char c = s[0];
+            if (c >= 'a' && c <= 'z') return static_cast<BaseKey>(static_cast<int>(BaseKey::A) + (c - 'a'));
+            if (c >= 'A' && c <= 'Z') return static_cast<BaseKey>(static_cast<int>(BaseKey::A) + (c - 'A'));
+            if (c >= '0' && c <= '9') return static_cast<BaseKey>(static_cast<int>(BaseKey::D0) + (c - '0'));
+        }
+        if (s == "Space") return BaseKey::Space;
+        if (s == "Return") return BaseKey::Return;
+        if (s == "Tab") return BaseKey::Tab;
+        if (s == "Escape") return BaseKey::Escape;
+        if (s == "Backspace") return BaseKey::Backspace;
+        if (s == "Delete") return BaseKey::Delete;
+        if (s == "ArrowUp") return BaseKey::ArrowUp;
+        if (s == "ArrowDown") return BaseKey::ArrowDown;
+        if (s == "ArrowLeft") return BaseKey::ArrowLeft;
+        if (s == "ArrowRight") return BaseKey::ArrowRight;
+        if (s == "Home") return BaseKey::Home;
+        if (s == "End") return BaseKey::End;
+        if (s == "PageUp") return BaseKey::PageUp;
+        if (s == "PageDown") return BaseKey::PageDown;
+        if (s == "Insert") return BaseKey::Insert;
+        if (s == ";") return BaseKey::Semicolon;
+        if (s == "=") return BaseKey::Equal;
+        if (s == ",") return BaseKey::Comma;
+        if (s == "-") return BaseKey::Minus;
+        if (s == ".") return BaseKey::Period;
+        if (s == "/") return BaseKey::Slash;
+        if (s == "`") return BaseKey::Backtick;
+        if (s == "[") return BaseKey::LeftBracket;
+        if (s == "\\") return BaseKey::Backslash;
+        if (s == "]") return BaseKey::RightBracket;
+        if (s == "'") return BaseKey::Quote;
+        // Add more keys as needed
+        return BaseKey::Unknown;
+    }
+
+    // Helper to convert BaseKey to string
+    std::string base_key_to_string(BaseKey bk) {
+        if (bk >= BaseKey::A && bk <= BaseKey::Z) return std::string(1, static_cast<char>(static_cast<int>(bk) - static_cast<int>(BaseKey::A) + 'a'));
+        if (bk >= BaseKey::D0 && bk <= BaseKey::D9) return std::string(1, static_cast<char>(static_cast<int>(bk) - static_cast<int>(BaseKey::D0) + '0'));
+        
+        switch (bk) {
+            case BaseKey::Space: return "Space";
+            case BaseKey::Return: return "Return";
+            case BaseKey::Tab: return "Tab";
+            case BaseKey::Escape: return "Escape";
+            case BaseKey::Backspace: return "Backspace";
+            case BaseKey::Delete: return "Delete";
+            case BaseKey::ArrowUp: return "ArrowUp";
+            case BaseKey::ArrowDown: return "ArrowDown";
+            case BaseKey::ArrowLeft: return "ArrowLeft";
+            case BaseKey::ArrowRight: return "ArrowRight";
+            case BaseKey::Home: return "Home";
+            case BaseKey::End: return "End";
+            case BaseKey::PageUp: return "PageUp";
+            case BaseKey::PageDown: return "PageDown";
+            case BaseKey::Insert: return "Insert";
+            case BaseKey::F1: return "F1"; // Handle F keys properly
+            case BaseKey::F2: return "F2";
+            case BaseKey::F3: return "F3";
+            case BaseKey::F4: return "F4";
+            case BaseKey::F5: return "F5";
+            case BaseKey::F6: return "F6";
+            case BaseKey::F7: return "F7";
+            case BaseKey::F8: return "F8";
+            case BaseKey::F9: return "F9";
+            case BaseKey::F10: return "F10";
+            case BaseKey::F11: return "F11";
+            case BaseKey::F12: return "F12";
+            case BaseKey::Semicolon: return ";";
+            case BaseKey::Equal: return "=";
+            case BaseKey::Comma: return ",";
+            case BaseKey::Minus: return "-";
+            case BaseKey::Period: return ".";
+            case BaseKey::Slash: return "/";
+            case BaseKey::Backtick: return "`";
+            case BaseKey::LeftBracket: return "[";
+            case BaseKey::Backslash: return "\\";
+            case BaseKey::RightBracket: return "]";
+            case BaseKey::Quote: return "'";
+            default: return "Unknown";
+        }
+    }
+} // anonymous namespace
+
+
+Key::Key(const std::string& key_name_str) {
+    *this = parse(key_name_str);
 }
 
 Key Key::parse(const std::string& key_str) {
     Key key;
-    
-    if (key_str.empty()) {
-        return key;
-    }
-    
     std::string remaining = key_str;
     
     // Parse modifiers
     while (true) {
         if (remaining.length() >= 2 && remaining.substr(0, 2) == "C-") {
-            key.ctrl = true;
+            key.modifiers = static_cast<Modifier>(static_cast<uint16_t>(key.modifiers) | static_cast<uint16_t>(Modifier::Control));
             remaining = remaining.substr(2);
         } else if (remaining.length() >= 2 && (remaining.substr(0, 2) == "M-" || remaining.substr(0, 2) == "A-")) {
-            key.meta = true;
+            key.modifiers = static_cast<Modifier>(static_cast<uint16_t>(key.modifiers) | static_cast<uint16_t>(Modifier::Meta));
             remaining = remaining.substr(2);
         } else if (remaining.length() >= 2 && remaining.substr(0, 2) == "S-") {
-            key.shift = true;
+            key.modifiers = static_cast<Modifier>(static_cast<uint16_t>(key.modifiers) | static_cast<uint16_t>(Modifier::Shift));
             remaining = remaining.substr(2);
         } else {
             break;
         }
     }
     
-    // The rest is the key name
-    key.name = remaining;
+    key.base_key = string_to_base_key(remaining);
+    
+    // If Shift is pressed and the base key is a letter, convert base_key to uppercase if necessary,
+    // but the BaseKey enum already handles 'a' through 'z' as lowercase by default for simplicity
+    // If the original input was 'S-a', string_to_base_key("a") gives BaseKey::A.
+    // So the explicit shift modifier should be enough.
     
     return key;
 }
@@ -48,27 +136,22 @@ Key Key::parse(const std::string& key_str) {
 std::string Key::to_string() const {
     std::string result;
     
-    if (ctrl) result += "C-";
-    if (meta) result += "M-";
-    if (shift) result += "S-";
+    if (static_cast<uint16_t>(modifiers) & static_cast<uint16_t>(Modifier::Control)) result += "C-";
+    if (static_cast<uint16_t>(modifiers) & static_cast<uint16_t>(Modifier::Meta)) result += "M-";
+    if (static_cast<uint16_t>(modifiers) & static_cast<uint16_t>(Modifier::Shift)) result += "S-";
     
-    result += name;
+    result += base_key_to_string(base_key);
     
     return result;
 }
 
 bool Key::operator==(const Key& other) const {
-    return name == other.name && 
-           ctrl == other.ctrl && 
-           meta == other.meta && 
-           shift == other.shift;
+    return base_key == other.base_key && modifiers == other.modifiers;
 }
 
 bool Key::operator<(const Key& other) const {
-    if (name != other.name) return name < other.name;
-    if (ctrl != other.ctrl) return ctrl < other.ctrl;
-    if (meta != other.meta) return meta < other.meta;
-    return shift < other.shift;
+    if (base_key != other.base_key) return base_key < other.base_key;
+    return modifiers < other.modifiers;
 }
 
 // ============================================================================