Created
November 18, 2023 22:33
-
-
Save Samasaur1/71f246cd8797da05385f927220f6ef43 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Cocoa | |
let src = CGEventSource(stateID: .hidSystemState) | |
let down = CGEvent(keyboardEventSource: src, virtualKey: 0x12, keyDown: true)! | |
let up = CGEvent(keyboardEventSource: src, virtualKey: 0x12, keyDown: false)! | |
sleep(5) | |
////down?.post(tap: .cghidEventTap) | |
////up?.post(tap: .cghidEventTap) | |
////down?.flags = .maskCommand | |
// | |
//let cmd_d = CGEvent(keyboardEventSource: src, virtualKey: 0x37, keyDown: true)! | |
//let cmd_u = CGEvent(keyboardEventSource: src, virtualKey: 0x37, keyDown: false)! | |
//let a_d = CGEvent(keyboardEventSource: src, virtualKey: 0x00, keyDown: true)! | |
//let a_u = CGEvent(keyboardEventSource: src, virtualKey: 0x00, keyDown: false)! | |
//let delete_d = CGEvent(keyboardEventSource: src, virtualKey: 0x33, keyDown: true)! | |
//let delete_u = CGEvent(keyboardEventSource: src, virtualKey: 0x33, keyDown: false)! | |
// | |
//down.post(tap: .cghidEventTap) | |
//up.post(tap: .cghidEventTap) | |
//sleep(1) | |
////cmd_d.post(tap: .cghidEventTap) | |
//a_d.flags = .maskCommand | |
//a_u.flags = .maskCommand | |
//a_d.post(tap: .cghidEventTap) | |
//a_u.post(tap: .cghidEventTap) | |
////cmd_u.post(tap: .cghidEventTap) | |
//sleep(1) | |
//delete_d.post(tap: .cghidEventTap) | |
//delete_u.post(tap: .cghidEventTap) | |
enum KeyCode: UInt16 { | |
// https://gist.github.com/swillits/df648e87016772c7f7e5dbed2b345066 | |
// Layout-independent Keys | |
// eg.These key codes are always the same key on all layouts. | |
case returnKey = 0x24 | |
// case enter = 0x4C //0x24 | |
case tab = 0x30 | |
case space = 0x31 | |
case delete = 0x33 | |
case escape = 0x35 | |
case command = 0x37 | |
case shift = 0x38 | |
case capsLock = 0x39 | |
case option = 0x3A | |
case control = 0x3B | |
case rightShift = 0x3C | |
case rightOption = 0x3D | |
case rightControl = 0x3E | |
case leftArrow = 0x7B | |
case rightArrow = 0x7C | |
case downArrow = 0x7D | |
case upArrow = 0x7E | |
case volumeUp = 0x48 | |
case volumeDown = 0x49 | |
case mute = 0x4A | |
case help = 0x72 | |
case home = 0x73 | |
case pageUp = 0x74 | |
case forwardDelete = 0x75 | |
case end = 0x77 | |
case pageDown = 0x79 | |
case function = 0x3F | |
case f1 = 0x7A | |
case f2 = 0x78 | |
case f4 = 0x76 | |
case f5 = 0x60 | |
case f6 = 0x61 | |
case f7 = 0x62 | |
case f3 = 0x63 | |
case f8 = 0x64 | |
case f9 = 0x65 | |
case f10 = 0x6D | |
case f11 = 0x67 | |
case f12 = 0x6F | |
case f13 = 0x69 | |
case f14 = 0x6B | |
case f15 = 0x71 | |
case f16 = 0x6A | |
case f17 = 0x40 | |
case f18 = 0x4F | |
case f19 = 0x50 | |
case f20 = 0x5A | |
// US-ANSI Keyboard Positions | |
// eg. These key codes are for the physical key (in any keyboard layout) | |
// at the location of the named key in the US-ANSI layout. | |
case a = 0x00 | |
case b = 0x0B | |
case c = 0x08 | |
case d = 0x02 | |
case e = 0x0E | |
case f = 0x03 | |
case g = 0x05 | |
case h = 0x04 | |
case i = 0x22 | |
case j = 0x26 | |
case k = 0x28 | |
case l = 0x25 | |
case m = 0x2E | |
case n = 0x2D | |
case o = 0x1F | |
case p = 0x23 | |
case q = 0x0C | |
case r = 0x0F | |
case s = 0x01 | |
case t = 0x11 | |
case u = 0x20 | |
case v = 0x09 | |
case w = 0x0D | |
case x = 0x07 | |
case y = 0x10 | |
case z = 0x06 | |
case zero = 0x1D | |
case one = 0x12 | |
case two = 0x13 | |
case three = 0x14 | |
case four = 0x15 | |
case five = 0x17 | |
case six = 0x16 | |
case seven = 0x1A | |
case eight = 0x1C | |
case nine = 0x19 | |
case equals = 0x18 | |
case minus = 0x1B | |
case semicolon = 0x29 | |
case apostrophe = 0x27 | |
case comma = 0x2B | |
case period = 0x2F | |
case forwardSlash = 0x2C | |
case backslash = 0x2A | |
case grave = 0x32 | |
case leftBracket = 0x21 | |
case rightBracket = 0x1E | |
case keypadDecimal = 0x41 | |
case keypadMultiply = 0x43 | |
case keypadPlus = 0x45 | |
case keypadClear = 0x47 | |
case keypadDivide = 0x4B | |
case keypadEnter = 0x4C | |
case keypadMinus = 0x4E | |
case keypadEquals = 0x51 | |
case keypad0 = 0x52 | |
case keypad1 = 0x53 | |
case keypad2 = 0x54 | |
case keypad3 = 0x55 | |
case keypad4 = 0x56 | |
case keypad5 = 0x57 | |
case keypad6 = 0x58 | |
case keypad7 = 0x59 | |
case keypad8 = 0x5B | |
case keypad9 = 0x5C | |
} | |
func press(_ key: KeyCode, withModifiers modifiers: CGEventFlags = .init()) { | |
let down = CGEvent(keyboardEventSource: src, virtualKey: key.rawValue, keyDown: true)! | |
let up = CGEvent(keyboardEventSource: src, virtualKey: key.rawValue, keyDown: false)! | |
down.flags = modifiers | |
up.flags = modifiers | |
down.post(tap: .cghidEventTap) | |
up.post(tap: .cghidEventTap) | |
} | |
struct KeyPress { | |
let key: KeyCode | |
let modifiers: CGEventFlags | |
} | |
func press(_ key: KeyPress) { | |
press(key.key, withModifiers: key.modifiers) | |
} | |
/// An enum representing possible typing rates. | |
/// | |
/// - allAtOnce: All the text should be typed at once. | |
/// - consistent: The text should be typed at a reasonable speed, but with no variance in delay. | |
/// - natural: The text should be typed so that it appears natural. | |
/// - customConsistent: The text should be typed at a consistent speed, specified by the associated value. | |
/// - customVarying: The text should be typed around a given speed, with 5 possible ranges of variation. Both the base speed and the maximum variance are specified by associated values. | |
public enum Rate { | |
/// All the text should be typed at once. | |
case allAtOnce | |
/// The text should be typed at a reasonable speed, but with no variance in delay. | |
case consistent | |
/// The text should be typed so that it appears natural. | |
case natural | |
/// The text should be typed at a specified consistent speed. | |
/// - µsecondDelay: The delay between each key typed. | |
case customConsistent(µsecondDelay: UInt32) | |
/// The text should be typed around a specified given speed, with specified variation. The base delay should be the average delay time, and the max variance is the maximum distance from the average to the fastest/slowest possible delay. | |
/// - µsecondBaseDelay: The base delay between each key typed. | |
/// - maxVariance: The delay between each key typed. | |
case customVarying(µsecondBaseDelay: UInt32, maxVariance: UInt32) | |
} | |
func type(_ text: [KeyPress], typing: Rate = .natural) { | |
for character in text { | |
press(character) | |
switch typing { | |
case .allAtOnce: | |
usleep(0001000) | |
case .consistent: | |
usleep(0100000) | |
case .natural: | |
var sleepTime = UInt32.random(in: 0...4) | |
sleepTime *= 10000 | |
usleep(0080000 + sleepTime) | |
case .customConsistent(let µsecondDelay): | |
usleep(µsecondDelay) | |
case let .customVarying(µsecondBaseDelay, maxVariance): | |
var sleepTime = UInt32.random(in: 0...4) | |
let base = µsecondBaseDelay - maxVariance | |
sleepTime *= (maxVariance / 2) | |
let µsecondDelay = base + sleepTime | |
usleep(µsecondDelay) | |
} | |
} | |
} | |
let lowercaseCharMap: [Character: KeyCode] = [ | |
"a": .a, | |
"b": .b, | |
"c": .c, | |
"d": .d, | |
"e": .e, | |
"f": .f, | |
"g": .g, | |
"h": .h, | |
"i": .i, | |
"j": .j, | |
"k": .k, | |
"l": .l, | |
"m": .m, | |
"n": .n, | |
"o": .o, | |
"p": .p, | |
"q": .q, | |
"r": .r, | |
"s": .s, | |
"t": .t, | |
"u": .u, | |
"v": .v, | |
"w": .w, | |
"x": .x, | |
"y": .y, | |
"z": .z, | |
"0": .zero, | |
"1": .one, | |
"2": .two, | |
"3": .three, | |
"4": .four, | |
"5": .five, | |
"6": .six, | |
"7": .seven, | |
"8": .eight, | |
"9": .nine, | |
"=": .equals, | |
"-": .minus, | |
";": .semicolon, | |
"'": .apostrophe, | |
",": .comma, | |
".": .period, | |
"/": .forwardSlash, | |
"\\": .backslash, | |
"`": .grave, | |
"[": .leftBracket, | |
"]": .rightBracket, | |
" ": .space | |
] | |
let uppercaseCharMap: [Character: KeyCode] = [ | |
"A": .a, | |
"B": .b, | |
"C": .c, | |
"D": .d, | |
"E": .e, | |
"F": .f, | |
"G": .g, | |
"H": .h, | |
"I": .i, | |
"J": .j, | |
"K": .k, | |
"L": .l, | |
"M": .m, | |
"N": .n, | |
"O": .o, | |
"P": .p, | |
"Q": .q, | |
"R": .r, | |
"S": .s, | |
"T": .t, | |
"U": .u, | |
"V": .v, | |
"W": .w, | |
"X": .x, | |
"Y": .y, | |
"Z": .z, | |
")": .zero, | |
"!": .one, | |
"@": .two, | |
"#": .three, | |
"$": .four, | |
"%": .five, | |
"^": .six, | |
"&": .seven, | |
"*": .eight, | |
"(": .nine, | |
"+": .equals, | |
"_": .minus, | |
":": .semicolon, | |
"\"": .apostrophe, | |
"<": .comma, | |
">": .period, | |
"?": .forwardSlash, | |
"|": .backslash, | |
"~": .grave, | |
"{": .leftBracket, | |
"}": .rightBracket, | |
] | |
func type(_ text: String, typing: Rate = .natural) { | |
type(str_to_kparr(text), typing: typing) | |
} | |
type("Hello, there") | |
func str_to_kparr(_ str: String) -> [KeyPress] { | |
str.map { char -> KeyPress in | |
if let kc = lowercaseCharMap[char] { | |
return KeyPress(key: kc, modifiers: .init()) | |
} | |
if let kc = uppercaseCharMap[char] { | |
return KeyPress(key: kc, modifiers: .maskShift) | |
} | |
return KeyPress(key: .three, modifiers: .maskShift) | |
} | |
} | |
func +(lhs: String, rhs: [KeyPress]) -> [KeyPress] { | |
return str_to_kparr(lhs) + rhs | |
} | |
func +(lhs: [KeyPress], rhs: String) -> [KeyPress] { | |
return lhs + str_to_kparr(rhs) | |
} | |
type("! General Kenobi" + [.init(key: .a, modifiers: .maskCommand), .init(key: .delete, modifiers: .init()), .init(key: .space, modifiers: [.maskCommand])]) | |
extension KeyPress { | |
static let returnKey = KeyPress(key: .returnKey, modifiers: .init()) | |
static let enter = Self.returnKey | |
static let tab = KeyPress(key: .tab, modifiers: .init()) | |
static let space = KeyPress(key: .space, modifiers: .init()) | |
static let delete = KeyPress(key: .delete, modifiers: .init()) | |
static let escape = KeyPress(key: .escape, modifiers: .init()) | |
static let command = KeyPress(key: .command, modifiers: .init()) | |
static let shift = KeyPress(key: .shift, modifiers: .init()) | |
static let capsLock = KeyPress(key: .capsLock, modifiers: .init()) | |
static let option = KeyPress(key: .option, modifiers: .init()) | |
static let control = KeyPress(key: .control, modifiers: .init()) | |
static let rightShift = KeyPress(key: .rightShift, modifiers: .init()) | |
static let rightOption = KeyPress(key: .rightOption, modifiers: .init()) | |
static let rightControl = KeyPress(key: .rightControl, modifiers: .init()) | |
static let leftArrow = KeyPress(key: .leftArrow, modifiers: .init()) | |
static let rightArrow = KeyPress(key: .rightArrow, modifiers: .init()) | |
static let downArrow = KeyPress(key: .downArrow, modifiers: .init()) | |
static let upArrow = KeyPress(key: .upArrow, modifiers: .init()) | |
static let volumeUp = KeyPress(key: .volumeUp, modifiers: .init()) | |
static let volumeDown = KeyPress(key: .volumeDown, modifiers: .init()) | |
static let mute = KeyPress(key: .mute, modifiers: .init()) | |
static let help = KeyPress(key: .help, modifiers: .init()) | |
static let home = KeyPress(key: .home, modifiers: .init()) | |
static let pageUp = KeyPress(key: .pageUp, modifiers: .init()) | |
static let forwardDelete = KeyPress(key: .forwardDelete, modifiers: .init()) | |
static let end = KeyPress(key: .end, modifiers: .init()) | |
static let pageDown = KeyPress(key: .pageDown, modifiers: .init()) | |
static let function = KeyPress(key: .function, modifiers: .init()) | |
static let f1 = KeyPress(key: .f1, modifiers: .init()) | |
static let f2 = KeyPress(key: .f2, modifiers: .init()) | |
static let f4 = KeyPress(key: .f4, modifiers: .init()) | |
static let f5 = KeyPress(key: .f5, modifiers: .init()) | |
static let f6 = KeyPress(key: .f6, modifiers: .init()) | |
static let f7 = KeyPress(key: .f7, modifiers: .init()) | |
static let f3 = KeyPress(key: .f3, modifiers: .init()) | |
static let f8 = KeyPress(key: .f8, modifiers: .init()) | |
static let f9 = KeyPress(key: .f9, modifiers: .init()) | |
static let f10 = KeyPress(key: .f10, modifiers: .init()) | |
static let f11 = KeyPress(key: .f11, modifiers: .init()) | |
static let f12 = KeyPress(key: .f12, modifiers: .init()) | |
static let f13 = KeyPress(key: .f13, modifiers: .init()) | |
static let f14 = KeyPress(key: .f14, modifiers: .init()) | |
static let f15 = KeyPress(key: .f15, modifiers: .init()) | |
static let f16 = KeyPress(key: .f16, modifiers: .init()) | |
static let f17 = KeyPress(key: .f17, modifiers: .init()) | |
static let f18 = KeyPress(key: .f18, modifiers: .init()) | |
static let f19 = KeyPress(key: .f19, modifiers: .init()) | |
static let f20 = KeyPress(key: .f20, modifiers: .init()) | |
// US-ANSI Keyboard Positions | |
// eg. These key codes are for the physical key (in any keyboard layout) | |
// at the location of the named key in the US-ANSI layout. | |
static let a = KeyPress(key: .a, modifiers: .init()) | |
static let b = KeyPress(key: .b, modifiers: .init()) | |
static let c = KeyPress(key: .c, modifiers: .init()) | |
static let d = KeyPress(key: .d, modifiers: .init()) | |
static let e = KeyPress(key: .e, modifiers: .init()) | |
static let f = KeyPress(key: .f, modifiers: .init()) | |
static let g = KeyPress(key: .g, modifiers: .init()) | |
static let h = KeyPress(key: .h, modifiers: .init()) | |
static let i = KeyPress(key: .i, modifiers: .init()) | |
static let j = KeyPress(key: .j, modifiers: .init()) | |
static let k = KeyPress(key: .k, modifiers: .init()) | |
static let l = KeyPress(key: .l, modifiers: .init()) | |
static let m = KeyPress(key: .m, modifiers: .init()) | |
static let n = KeyPress(key: .n, modifiers: .init()) | |
static let o = KeyPress(key: .o, modifiers: .init()) | |
static let p = KeyPress(key: .p, modifiers: .init()) | |
static let q = KeyPress(key: .q, modifiers: .init()) | |
static let r = KeyPress(key: .r, modifiers: .init()) | |
static let s = KeyPress(key: .s, modifiers: .init()) | |
static let t = KeyPress(key: .t, modifiers: .init()) | |
static let u = KeyPress(key: .u, modifiers: .init()) | |
static let v = KeyPress(key: .v, modifiers: .init()) | |
static let w = KeyPress(key: .w, modifiers: .init()) | |
static let x = KeyPress(key: .x, modifiers: .init()) | |
static let y = KeyPress(key: .y, modifiers: .init()) | |
static let z = KeyPress(key: .z, modifiers: .init()) | |
static let A = KeyPress(key: .a, modifiers: .maskShift) | |
static let B = KeyPress(key: .b, modifiers: .maskShift) | |
static let C = KeyPress(key: .c, modifiers: .maskShift) | |
static let D = KeyPress(key: .d, modifiers: .maskShift) | |
static let E = KeyPress(key: .e, modifiers: .maskShift) | |
static let F = KeyPress(key: .f, modifiers: .maskShift) | |
static let G = KeyPress(key: .g, modifiers: .maskShift) | |
static let H = KeyPress(key: .h, modifiers: .maskShift) | |
static let I = KeyPress(key: .i, modifiers: .maskShift) | |
static let J = KeyPress(key: .j, modifiers: .maskShift) | |
static let K = KeyPress(key: .k, modifiers: .maskShift) | |
static let L = KeyPress(key: .l, modifiers: .maskShift) | |
static let M = KeyPress(key: .m, modifiers: .maskShift) | |
static let N = KeyPress(key: .n, modifiers: .maskShift) | |
static let O = KeyPress(key: .o, modifiers: .maskShift) | |
static let P = KeyPress(key: .p, modifiers: .maskShift) | |
static let Q = KeyPress(key: .q, modifiers: .maskShift) | |
static let R = KeyPress(key: .r, modifiers: .maskShift) | |
static let S = KeyPress(key: .s, modifiers: .maskShift) | |
static let T = KeyPress(key: .t, modifiers: .maskShift) | |
static let U = KeyPress(key: .u, modifiers: .maskShift) | |
static let V = KeyPress(key: .v, modifiers: .maskShift) | |
static let W = KeyPress(key: .w, modifiers: .maskShift) | |
static let X = KeyPress(key: .x, modifiers: .maskShift) | |
static let Y = KeyPress(key: .y, modifiers: .maskShift) | |
static let Z = KeyPress(key: .z, modifiers: .maskShift) | |
static let zero = KeyPress(key: .zero, modifiers: .init()) | |
static let one = KeyPress(key: .one, modifiers: .init()) | |
static let two = KeyPress(key: .two, modifiers: .init()) | |
static let three = KeyPress(key: .three, modifiers: .init()) | |
static let four = KeyPress(key: .four, modifiers: .init()) | |
static let five = KeyPress(key: .five, modifiers: .init()) | |
static let six = KeyPress(key: .six, modifiers: .init()) | |
static let seven = KeyPress(key: .seven, modifiers: .init()) | |
static let eight = KeyPress(key: .eight, modifiers: .init()) | |
static let nine = KeyPress(key: .nine, modifiers: .init()) | |
static let leftParenthesis = KeyPress(key: .zero, modifiers: .maskShift) | |
static let exclamationPoint = KeyPress(key: .one, modifiers: .maskShift) | |
static let atSign = KeyPress(key: .two, modifiers: .maskShift) | |
static let numberSign = KeyPress(key: .three, modifiers: .maskShift) | |
static let dollarSign = KeyPress(key: .four, modifiers: .maskShift) | |
static let percent = KeyPress(key: .five, modifiers: .maskShift) | |
static let caret = KeyPress(key: .six, modifiers: .maskShift) | |
static let ampersand = KeyPress(key: .seven, modifiers: .maskShift) | |
static let asterisk = KeyPress(key: .eight, modifiers: .maskShift) | |
static let rightParenthesis = KeyPress(key: .nine, modifiers: .maskShift) | |
static let equals = KeyPress(key: .equals, modifiers: .init()) | |
static let minus = KeyPress(key: .minus, modifiers: .init()) | |
static let semicolon = KeyPress(key: .semicolon, modifiers: .init()) | |
static let apostrophe = KeyPress(key: .apostrophe, modifiers: .init()) | |
static let comma = KeyPress(key: .comma, modifiers: .init()) | |
static let period = KeyPress(key: .period, modifiers: .init()) | |
static let forwardSlash = KeyPress(key: .forwardSlash, modifiers: .init()) | |
static let backslash = KeyPress(key: .backslash, modifiers: .init()) | |
static let grave = KeyPress(key: .grave, modifiers: .init()) | |
static let leftBracket = KeyPress(key: .leftBracket, modifiers: .init()) | |
static let rightBracket = KeyPress(key: .rightBracket, modifiers: .init()) | |
static let plus = KeyPress(key: .equals, modifiers: .maskShift) | |
static let underscore = KeyPress(key: .minus, modifiers: .maskShift) | |
static let colon = KeyPress(key: .semicolon, modifiers: .maskShift) | |
static let quotationMark = KeyPress(key: .apostrophe, modifiers: .maskShift) | |
static let lessThan = KeyPress(key: .comma, modifiers: .maskShift) | |
static let greaterThan = KeyPress(key: .period, modifiers: .maskShift) | |
static let questionMark = KeyPress(key: .forwardSlash, modifiers: .maskShift) | |
static let pipe = KeyPress(key: .backslash, modifiers: .maskShift) | |
static let tilde = KeyPress(key: .grave, modifiers: .maskShift) | |
static let leftBrace = KeyPress(key: .leftBracket, modifiers: .maskShift) | |
static let rightBrace = KeyPress(key: .rightBracket, modifiers: .maskShift) | |
static let keypadDecimal = KeyPress(key: .keypadDecimal, modifiers: .init()) | |
static let keypadMultiply = KeyPress(key: .keypadMultiply, modifiers: .init()) | |
static let keypadPlus = KeyPress(key: .keypadPlus, modifiers: .init()) | |
static let keypadClear = KeyPress(key: .keypadClear, modifiers: .init()) | |
static let keypadDivide = KeyPress(key: .keypadDivide, modifiers: .init()) | |
static let keypadEnter = KeyPress(key: .keypadEnter, modifiers: .init()) | |
static let keypadMinus = KeyPress(key: .keypadMinus, modifiers: .init()) | |
static let keypadEquals = KeyPress(key: .keypadEquals, modifiers: .init()) | |
static let keypad0 = KeyPress(key: .keypad0, modifiers: .init()) | |
static let keypad1 = KeyPress(key: .keypad1, modifiers: .init()) | |
static let keypad2 = KeyPress(key: .keypad2, modifiers: .init()) | |
static let keypad3 = KeyPress(key: .keypad3, modifiers: .init()) | |
static let keypad4 = KeyPress(key: .keypad4, modifiers: .init()) | |
static let keypad5 = KeyPress(key: .keypad5, modifiers: .init()) | |
static let keypad6 = KeyPress(key: .keypad6, modifiers: .init()) | |
static let keypad7 = KeyPress(key: .keypad7, modifiers: .init()) | |
static let keypad8 = KeyPress(key: .keypad8, modifiers: .init()) | |
static let keypad9 = KeyPress(key: .keypad9, modifiers: .init()) | |
} | |
extension KeyPress { | |
func withModifiers(_ modifiers: CGEventFlags) -> KeyPress { | |
return KeyPress(key: self.key, modifiers: modifiers) | |
} | |
func appendingModifiers(_ modifiers: CGEventFlags) -> KeyPress { | |
return self.withModifiers(self.modifiers.union(modifiers)) | |
} | |
} | |
sleep(2) | |
type([KeyPress.space.withModifiers([.maskCommand])] + "My name is Inigo Montoya. You killed my father. Prepare to die" + [KeyPress.space.withModifiers([.maskCommand]), KeyPress.tab.withModifiers(.maskCommand), .command]) | |
func +(lhs: String, rhs: KeyPress) -> [KeyPress] { | |
return lhs + [rhs] | |
} | |
func +(lhs: KeyPress, rhs: String) -> [KeyPress] { | |
return [lhs] + rhs | |
} | |
type([KeyPress.tab.withModifiers(.maskCommand), .command, KeyPress.space.withModifiers([.maskCommand])] + "") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment