soffes / HotKey

Simple global shortcuts in macOS
MIT License
921 stars 82 forks source link

Add a constructor to create a HotKey from string #30

Open AlexGustafsson opened 3 years ago

AlexGustafsson commented 3 years ago

To help aid hotkeys configurable by the user, it would be helpful to have a way of creating a HotKey (or KeyCombo) from a string such as option+command+t.

I have done some limited research, but I was unable to find any existing solution for getting the key and modifiers from a string such as the above.

AlexGustafsson commented 3 years ago

This code works.

import AppKit
import HotKey

extension HotKey {
    public convenience init?(keys: String, keyDownHandler: Handler? = nil, keyUpHandler: Handler? = nil) {
        guard let keyCombo = KeyCombo(keys: keys) else {
      return nil
    }
        self.init(keyCombo: keyCombo, keyDownHandler: keyDownHandler, keyUpHandler: keyUpHandler)
    }
}

extension KeyCombo {
  public init?(keys: String) {
    var chosenKey: Key? = nil
    var chosenModifiers: NSEvent.ModifierFlags = []
    for key in keys.split(separator: "+") {
      guard let parsedKey = Key(string: String(key)) else {
        // Parse failed
        return nil
      }

      switch parsedKey {
      case .command: chosenModifiers = chosenModifiers.union(.command)
      case .rightCommand: chosenModifiers = chosenModifiers.union(.command)
      case .option: chosenModifiers = chosenModifiers.union(.option)
      case .rightOption: chosenModifiers = chosenModifiers.union(.option)
      case .control: chosenModifiers = chosenModifiers.union(.control)
      case .rightControl: chosenModifiers = chosenModifiers.union(.control)
      case .shift: chosenModifiers = chosenModifiers.union(.shift)
      case .rightShift: chosenModifiers = chosenModifiers.union(.shift)
      case .function: chosenModifiers = chosenModifiers.union(.function)
      case .capsLock: chosenModifiers = chosenModifiers.union(.capsLock)
      default:
          chosenKey = parsedKey
      }
    }

    if chosenKey == nil {
      return nil
    }
    self.init(carbonKeyCode: chosenKey!.carbonKeyCode, carbonModifiers: chosenModifiers.carbonFlags)
    }
}

The conversion from Key to carbonModifiers leaves some to be desired. Perhaps one could add a modifier: NSEvent.ModifierFlags or something to the Key class.

If this is something you'd like to support, I'd happily open a PR.