diff --git a/Sources/SendKeysLib/Commands/Command.swift b/Sources/SendKeysLib/Commands/Command.swift index bcaa675..7db2fb1 100644 --- a/Sources/SendKeysLib/Commands/Command.swift +++ b/Sources/SendKeysLib/Commands/Command.swift @@ -1,4 +1,7 @@ +import Foundation + public enum CommandType { + case undefined case keyPress case keyDown case keyUp @@ -11,20 +14,49 @@ public enum CommandType { case continuation } -public struct Command: Equatable { - let type: CommandType - let arguments: [String?] +public protocol CommandProtocol { + static var commandType: CommandType { get } + static var expression: NSRegularExpression { get } + + init(arguments: [String?]) + func execute() throws + func equals(_ comparison: Command) -> Bool +} - public init(_ type: CommandType, _ arguments: [String?]) { - self.type = type - self.arguments = arguments +public class Command: Equatable, CustomStringConvertible { + public class var commandType: CommandType { return .undefined } + + private static let _expression = try! NSRegularExpression(pattern: ".") + public class var expression: NSRegularExpression { return _expression } + + init() {} + + required public init(arguments: [String?]) { } - public init(_ type: CommandType) { - self.init(type, []) + public func execute() throws { } - + + public func equals(_ comparison: Command) -> Bool { + return type(of: self) == type(of: comparison) + } + public static func == (lhs: Command, rhs: Command) -> Bool { - return lhs.type == rhs.type && lhs.arguments == rhs.arguments; + return lhs.equals(rhs) && rhs.equals(lhs) + } + + public var description: String { + let output = "\(type(of: self)): \(type(of: self).commandType)" + let members = describeMembers() + + if !members.isEmpty { + return "\(output) (\(members))" + } + + return output + } + + func describeMembers() -> String { + return "" } } diff --git a/Sources/SendKeysLib/Commands/CommandExecutor.swift b/Sources/SendKeysLib/Commands/CommandExecutor.swift index 601f8a3..5da4eed 100644 --- a/Sources/SendKeysLib/Commands/CommandExecutor.swift +++ b/Sources/SendKeysLib/Commands/CommandExecutor.swift @@ -5,121 +5,7 @@ public protocol CommandExecutorProtocol { } public class CommandExecutor: CommandExecutorProtocol { - private let keyPresser = KeyPresser() - private let mouseController = MouseController() - public func execute(_ command: Command) { - switch command.type { - case .keyPress, .keyDown, .keyUp: - executeKeyPress(command) - case .pause, .stickyPause: - executePause(command) - case .mouseMove: - executeMouseMove(command) - case .mouseClick: - executeMouseClick(command) - case .mouseDrag: - executeMouseDrag(command) - case .mouseScroll: - executeMouseScroll(command) - case .continuation: - return - } - } - - private func executeKeyPress(_ command: Command) { - var modifiers: [String] = [] - - if command.arguments.count > 1 { - modifiers = command.arguments[1]!.components(separatedBy: ",") - } - - switch command.type { - case .keyPress: - try! keyPresser.keyPress(key: command.arguments[0]!, modifiers: modifiers) - case .keyDown: - let _ = try! keyPresser.keyDown(key: command.arguments[0]!, modifiers: modifiers) - case .keyUp: - let _ = try! keyPresser.keyUp(key: command.arguments[0]!, modifiers: modifiers) - default: - return - } - } - - private func executePause(_ command: Command) { - Sleeper.sleep(seconds: Double(command.arguments[0]!)!) - } - - private func executeMouseMove(_ command: Command) { - let x1 = Double(command.arguments[0]!)! - let y1 = Double(command.arguments[1]!)! - let x2 = Double(command.arguments[2]!)! - let y2 = Double(command.arguments[3]!)! - let duration: TimeInterval = Double(command.arguments[4]!)! - let modifiers = command.arguments[5] - - mouseController.move( - start: CGPoint(x: x1, y: y1), - end: CGPoint(x: x2, y: y2), - duration: duration, - flags: modifiers != nil ? try! KeyPresser.getModifierFlags(modifiers!.components(separatedBy: ",")) : [] - ) - } - - private func executeMouseClick(_ command: Command) { - let button = command.arguments[0]! - let modifiers = command.arguments[1] - let clicks = Int(command.arguments[2]!)! - - try! mouseController.click( - CGPoint(x: -1, y: -1), - button: getMouseButton(button: button), - flags: modifiers != nil ? try! KeyPresser.getModifierFlags(modifiers!.components(separatedBy: ",")) : [], - clickCount: clicks - ) - } - - private func executeMouseScroll(_ command: Command) { - let x = Int(command.arguments[0]!) ?? 0 - let y = Int(command.arguments[1]!) ?? 0 - let duration = Double(command.arguments[2] ?? "0") ?? 0 - let modifiers = command.arguments[3] - - mouseController.scroll( - CGPoint(x: x, y: y), - duration, - flags: modifiers != nil ? try! KeyPresser.getModifierFlags(modifiers!.components(separatedBy: ",")) : [] - ) - } - - private func executeMouseDrag(_ command: Command) { - let x1 = Double(command.arguments[0]!)! - let y1 = Double(command.arguments[1]!)! - let x2 = Double(command.arguments[2]!)! - let y2 = Double(command.arguments[3]!)! - let duration: TimeInterval = Double(command.arguments[4]!)! - let button = command.arguments[5]! - let modifiers = command.arguments[6] - - try! mouseController.drag( - start: CGPoint(x: x1, y: y1), - end: CGPoint(x: x2, y: y2), - duration: duration, - button: getMouseButton(button: button), - flags: modifiers != nil ? try! KeyPresser.getModifierFlags(modifiers!.components(separatedBy: ",")) : [] - ) - } - - private func getMouseButton(button: String) throws -> CGMouseButton { - switch button { - case "left": - return CGMouseButton.left - case "center": - return CGMouseButton.center - case "right": - return CGMouseButton.right - default: - throw RuntimeError("Unknown mouse button: \(button)") - } + try! command.execute() } } diff --git a/Sources/SendKeysLib/Commands/CommandFactory.swift b/Sources/SendKeysLib/Commands/CommandFactory.swift new file mode 100644 index 0000000..321bb3e --- /dev/null +++ b/Sources/SendKeysLib/Commands/CommandFactory.swift @@ -0,0 +1,20 @@ +public class CommandFactory { + public static let commands: [Command.Type] = [ + KeyPressCommand.self, + KeyDownCommand.self, + KeyUpCommand.self, + StickyPauseCommand.self, + PauseCommand.self, + ContinuationCommand.self, + NewlineCommand.self, + MouseMoveCommand.self, + MouseClickCommand.self, + MouseDragCommand.self, + MouseScrollCommand.self, + DefaultCommand.self + ] + + public static func create(_ commandType: Command.Type, arguments: [String?]) -> Command { + return commandType.init(arguments: arguments) + } +} diff --git a/Sources/SendKeysLib/Commands/CommandMatcher.swift b/Sources/SendKeysLib/Commands/CommandMatcher.swift deleted file mode 100644 index f5f49a3..0000000 --- a/Sources/SendKeysLib/Commands/CommandMatcher.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation - -public class CommandMatcher { - let expression: NSRegularExpression - - public func createCommand(_ arguments: [String?]) -> Command { - fatalError("Not implemented\n") - } - - public init(_ expression: NSRegularExpression) { - self.expression = expression - } -} diff --git a/Sources/SendKeysLib/Commands/CommandsIterator.swift b/Sources/SendKeysLib/Commands/CommandsIterator.swift index 5281b1b..6c5f0d2 100644 --- a/Sources/SendKeysLib/Commands/CommandsIterator.swift +++ b/Sources/SendKeysLib/Commands/CommandsIterator.swift @@ -3,21 +3,6 @@ import Foundation public class CommandsIterator: IteratorProtocol { public typealias Element = Command - private let commandMatchers: [CommandMatcher] = [ - KeyPressCommandMatcher(), - KeyDownCommandMatcher(), - KeyUpCommandMatcher(), - StickyPauseCommandMatcher(), - PauseCommandMatcher(), - ContinuationCommandMatcher(), - NewlineCommandMatcher(), - MouseMoveCommandMatcher(), - MouseClickCommandMatcher(), - MouseDragCommandMatcher(), - MouseScrollCommandMatcher(), - DefaultCommandMatcher() - ] - let commandString: String var index = 0; @@ -29,14 +14,13 @@ public class CommandsIterator: IteratorProtocol { let length = commandString.utf16.count if index < length { var matchResult: NSTextCheckingResult?; - let matcher = commandMatchers.first { (matcher: CommandMatcher) -> Bool in - matchResult = matcher.expression.firstMatch(in: commandString, options: .anchored, range: NSMakeRange(index, length - index)) - return matchResult != nil - } - - if matcher != nil { + if let commandType = CommandFactory.commands.first(where: { (commandType: Command.Type) -> Bool in + matchResult = commandType.expression.firstMatch(in: commandString, options: .anchored, range: NSMakeRange(index, length - index)) + return matchResult != nil + } + ) { let args = getArguments(commandString, matchResult!) - let command = matcher!.createCommand(args) + let command = CommandFactory.create(commandType, arguments: args) if matchResult != nil { let range = Range(matchResult!.range, in: commandString) diff --git a/Sources/SendKeysLib/Commands/CommandsProcessor.swift b/Sources/SendKeysLib/Commands/CommandsProcessor.swift index 25c4545..e85ee32 100644 --- a/Sources/SendKeysLib/Commands/CommandsProcessor.swift +++ b/Sources/SendKeysLib/Commands/CommandsProcessor.swift @@ -1,9 +1,10 @@ import Foundation public class CommandsProcessor { - var defaultPause: Double - let commandExecutor: CommandExecutorProtocol + var defaultPause: TimeInterval + let numberFormatter = NumberFormatter() + let commandExecutor: CommandExecutorProtocol public init(defaultPause: Double, commandExecutor: CommandExecutorProtocol? = nil) { self.defaultPause = defaultPause @@ -15,7 +16,7 @@ public class CommandsProcessor { } private func getDefaultPauseCommand() -> Command { - return Command(.pause, [numberFormatter.string(from: NSNumber(value: defaultPause))!]) + return PauseCommand(duration: defaultPause) } public func process(_ commandString: String) { @@ -29,28 +30,24 @@ public class CommandsProcessor { continue } - if command.type == .continuation { + if command is ContinuationCommand { shouldIgnoreNextCommand = true continue } - - if command.type == .pause { + + if command is StickyPauseCommand { shouldDefaultPause = false - } else if command.type == .stickyPause { + defaultPause = (command as! StickyPauseCommand).duration + } else if command is PauseCommand { shouldDefaultPause = false - defaultPause = Double(command.arguments[0]!)! } else if shouldDefaultPause { - executeCommand(getDefaultPauseCommand()) + commandExecutor.execute(getDefaultPauseCommand()) shouldDefaultPause = true } else { shouldDefaultPause = true } - - executeCommand(command) + + commandExecutor.execute(command) } } - - func executeCommand(_ command: Command) { - commandExecutor.execute(command) - } } diff --git a/Sources/SendKeysLib/Commands/ContinuationCommand.swift b/Sources/SendKeysLib/Commands/ContinuationCommand.swift new file mode 100644 index 0000000..653cf98 --- /dev/null +++ b/Sources/SendKeysLib/Commands/ContinuationCommand.swift @@ -0,0 +1,16 @@ +import Foundation + +public class ContinuationCommand: Command { + public override class var commandType: CommandType { return .continuation } + + private static let _expression = try! NSRegularExpression(pattern: "\\<\\\\\\>") + public override class var expression: NSRegularExpression { return _expression } + + public override init () { + super.init() + } + + required public init(arguments: [String?]) { + super.init(arguments: arguments) + } +} diff --git a/Sources/SendKeysLib/Commands/ContinuationCommandMatcher.swift b/Sources/SendKeysLib/Commands/ContinuationCommandMatcher.swift deleted file mode 100644 index 05751eb..0000000 --- a/Sources/SendKeysLib/Commands/ContinuationCommandMatcher.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -public class ContinuationCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\<\\\\\\>")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - return Command(.continuation, []) - } -} diff --git a/Sources/SendKeysLib/Commands/DefaultCommand.swift b/Sources/SendKeysLib/Commands/DefaultCommand.swift new file mode 100644 index 0000000..751e107 --- /dev/null +++ b/Sources/SendKeysLib/Commands/DefaultCommand.swift @@ -0,0 +1,17 @@ +import Foundation + +public class DefaultCommand: KeyPressCommand { + private static let _expression = try! NSRegularExpression(pattern: ".") + public override class var expression: NSRegularExpression { return _expression } + + public init(key: String) { + super.init() + + self.key = key + } + + required public init(arguments: [String?]) { + super.init() + self.key = arguments[0]! + } +} diff --git a/Sources/SendKeysLib/Commands/DefaultCommandMatcher.swift b/Sources/SendKeysLib/Commands/DefaultCommandMatcher.swift deleted file mode 100644 index 5ee1bac..0000000 --- a/Sources/SendKeysLib/Commands/DefaultCommandMatcher.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -public class DefaultCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: ".")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - return Command(.keyPress, [arguments[0]!]) - } -} diff --git a/Sources/SendKeysLib/Commands/KeyDownCommand.swift b/Sources/SendKeysLib/Commands/KeyDownCommand.swift new file mode 100644 index 0000000..0b34b87 --- /dev/null +++ b/Sources/SendKeysLib/Commands/KeyDownCommand.swift @@ -0,0 +1,20 @@ +import Foundation + +public class KeyDownCommand: KeyPressCommand { + public override class var commandType: CommandType { return .keyDown } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } + + public override init (key: String, modifiers: [String]) { + super.init(key: key, modifiers: modifiers) + } + + required public init(arguments: [String?]) { + super.init(arguments: arguments) + } + + public override func execute() throws { + let _ = try! keyPresser.keyDown(key: key!, modifiers: modifiers) + } +} diff --git a/Sources/SendKeysLib/Commands/KeyDownCommandMatcher.swift b/Sources/SendKeysLib/Commands/KeyDownCommandMatcher.swift deleted file mode 100644 index 1184f25..0000000 --- a/Sources/SendKeysLib/Commands/KeyDownCommandMatcher.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - -public class KeyDownCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - var args = [arguments[1]!] - if arguments[3] != nil { - args.append(arguments[3]!) - } - return Command(.keyDown, args) - } -} diff --git a/Sources/SendKeysLib/Commands/KeyPressCommand.swift b/Sources/SendKeysLib/Commands/KeyPressCommand.swift new file mode 100644 index 0000000..6fc99f0 --- /dev/null +++ b/Sources/SendKeysLib/Commands/KeyPressCommand.swift @@ -0,0 +1,49 @@ +import Foundation + +public class KeyPressCommand: Command { + public override class var commandType: CommandType { return .keyPress } + + private static let _expression = try! NSRegularExpression(pattern: "\\<[ck]:(.|[\\w]+)(:([,\\w⌘^⌥⇧]+))?\\>") + public override class var expression: NSRegularExpression { return _expression } + + var key: String? + var modifiers: [String] = [] + + let keyPresser = KeyPresser() + + override init() { + super.init() + } + + public init (key: String, modifiers: [String]) { + super.init() + + self.key = key + self.modifiers = modifiers + } + + required public init(arguments: [String?]) { + super.init() + + self.key = arguments[1]! + self.modifiers = arguments[3]?.components(separatedBy: ",").filter({ !$0.isEmpty }) ?? [] + } + + public override func execute() throws { + try! keyPresser.keyPress(key: key!, modifiers: modifiers) + } + + public override func equals(_ comparison: Command) -> Bool { + return super.equals(comparison) && { + if let command = comparison as? KeyPressCommand { + return key == command.key + && modifiers == command.modifiers + } + return false + }() + } + + public override func describeMembers() -> String { + return "key: \(key ?? "''")), modifiers: \(modifiers)" + } +} diff --git a/Sources/SendKeysLib/Commands/KeyPressCommandMatcher.swift b/Sources/SendKeysLib/Commands/KeyPressCommandMatcher.swift deleted file mode 100644 index 7987a9f..0000000 --- a/Sources/SendKeysLib/Commands/KeyPressCommandMatcher.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - -public class KeyPressCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\<[ck]:(.|[\\w]+)(:([,\\w⌘^⌥⇧]+))?\\>")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - var args = [arguments[1]!] - if arguments[3] != nil { - args.append(arguments[3]!) - } - return Command(.keyPress, args) - } -} diff --git a/Sources/SendKeysLib/Commands/KeyUpCommand.swift b/Sources/SendKeysLib/Commands/KeyUpCommand.swift new file mode 100644 index 0000000..c3bfc0d --- /dev/null +++ b/Sources/SendKeysLib/Commands/KeyUpCommand.swift @@ -0,0 +1,20 @@ +import Foundation + +public class KeyUpCommand: KeyPressCommand { + public override class var commandType: CommandType { return .keyUp } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } + + public override init (key: String, modifiers: [String]) { + super.init(key: key, modifiers: modifiers) + } + + required public init(arguments: [String?]) { + super.init(arguments: arguments) + } + + public override func execute() throws { + let _ = try! keyPresser.keyUp(key: key!, modifiers: modifiers) + } +} diff --git a/Sources/SendKeysLib/Commands/KeyUpCommandMatcher.swift b/Sources/SendKeysLib/Commands/KeyUpCommandMatcher.swift deleted file mode 100644 index 4a796db..0000000 --- a/Sources/SendKeysLib/Commands/KeyUpCommandMatcher.swift +++ /dev/null @@ -1,15 +0,0 @@ -import Foundation - -public class KeyUpCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - var args = [arguments[1]!] - if arguments[3] != nil { - args.append(arguments[3]!) - } - return Command(.keyUp, args) - } -} diff --git a/Sources/SendKeysLib/Commands/MouseClickCommand.swift b/Sources/SendKeysLib/Commands/MouseClickCommand.swift new file mode 100644 index 0000000..1a6b5e3 --- /dev/null +++ b/Sources/SendKeysLib/Commands/MouseClickCommand.swift @@ -0,0 +1,71 @@ +import Foundation + +public class MouseClickCommand: Command { + public override class var commandType: CommandType { return .mouseClick } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } + + var button: String? + var modifiers: [String] = [] + var clicks: Int = 1 + + let mouseController = MouseController() + + override init() { + super.init() + } + + public init(button: String?, modifiers: [String], clicks: Int) { + super.init() + + self.button = button + self.modifiers = modifiers + self.clicks = clicks + } + + required public init(arguments: [String?]) { + super.init() + + self.button = arguments[1]! + self.modifiers = arguments[3]?.components(separatedBy: ",").filter({ !$0.isEmpty }) ?? [] + self.clicks = Int(arguments[5] ?? "1")! + } + + public override func execute() throws { + try! mouseController.click( + nil, + button: getMouseButton(button: button!), + flags: try! KeyPresser.getModifierFlags(modifiers), + clickCount: clicks + ) + } + + public override func equals(_ comparison: Command) -> Bool { + return super.equals(comparison) && { + if let command = comparison as? MouseClickCommand { + return button == command.button + && modifiers == command.modifiers + && clicks == command.clicks + } + return false + }() + } + + public override func describeMembers() -> String { + return "button: \(button ?? "''")), modifiers: \(modifiers), clicks: \(clicks)" + } + + func getMouseButton(button: String) throws -> CGMouseButton { + switch button { + case "left": + return CGMouseButton.left + case "center": + return CGMouseButton.center + case "right": + return CGMouseButton.right + default: + throw RuntimeError("Unknown mouse button: \(button)") + } + } +} diff --git a/Sources/SendKeysLib/Commands/MouseClickCommandMatcher.swift b/Sources/SendKeysLib/Commands/MouseClickCommandMatcher.swift deleted file mode 100644 index ff553f7..0000000 --- a/Sources/SendKeysLib/Commands/MouseClickCommandMatcher.swift +++ /dev/null @@ -1,19 +0,0 @@ -import Foundation - -public class MouseClickCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - let button = arguments[1] - let modifiers = arguments[3] - let clicks = arguments[5] - - return Command(.mouseClick, [ - button!, - modifiers, - clicks ?? "1" - ]) - } -} diff --git a/Sources/SendKeysLib/Commands/MouseDragCommand.swift b/Sources/SendKeysLib/Commands/MouseDragCommand.swift new file mode 100644 index 0000000..1106b05 --- /dev/null +++ b/Sources/SendKeysLib/Commands/MouseDragCommand.swift @@ -0,0 +1,45 @@ +import Foundation + +public class MouseDragCommand: MouseMoveCommand { + public override class var commandType: CommandType { return .mouseDrag } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } + + public init(x1: Int?, y1: Int?, x2: Int, y2: Int, duration: TimeInterval, button: String?, modifiers: [String]) { + super.init() + + self.x1 = x1 + self.y1 = y1 + self.x2 = x2 + self.y2 = y2 + self.duration = duration + self.button = button + self.modifiers = modifiers + } + + required public init(arguments: [String?]) { + super.init() + self.x1 = Int(arguments[2] ?? "") + self.y1 = Int(arguments[3] ?? "") + self.x2 = Int(arguments[4]!)! + self.y2 = Int(arguments[5]!)! + self.duration = TimeInterval(arguments[7] ?? "0")! + self.button = arguments[9] ?? "left" + self.modifiers = arguments[11]?.components(separatedBy: ",").filter({ !$0.isEmpty }) ?? [] + } + + public override func describeMembers() -> String { + return "x1: \(x1?.description ?? "nil")), y1: \(y1?.description ?? "nil"), x2: \(x2), y2: \(y2), duration: \(duration), button: \(button ?? "''")), modifiers: \(modifiers)" + } + + public override func execute() throws { + try! mouseController.drag( + start: x1 == nil || y1 == nil ? nil : CGPoint(x: x1!, y: y1!), + end: CGPoint(x: x2, y: y2), + duration: duration, + button: getMouseButton(button: button!), + flags: try! KeyPresser.getModifierFlags(modifiers) + ) + } +} diff --git a/Sources/SendKeysLib/Commands/MouseDragCommandMatcher.swift b/Sources/SendKeysLib/Commands/MouseDragCommandMatcher.swift deleted file mode 100644 index 26cc1b3..0000000 --- a/Sources/SendKeysLib/Commands/MouseDragCommandMatcher.swift +++ /dev/null @@ -1,27 +0,0 @@ -import Foundation - -public class MouseDragCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - let x1 = arguments[2] - let y1 = arguments[3] - let x2 = arguments[4] - let y2 = arguments[5] - let duration = arguments[7] - let button = arguments[9] - let modifiers = arguments[11] - - return Command(.mouseDrag, [ - x1 ?? "-1", - y1 ?? "-1", - x2!, - y2!, - duration ?? "0", - button ?? "left", - modifiers - ]) - } -} diff --git a/Sources/SendKeysLib/Commands/MouseMoveCommand.swift b/Sources/SendKeysLib/Commands/MouseMoveCommand.swift new file mode 100644 index 0000000..75b9334 --- /dev/null +++ b/Sources/SendKeysLib/Commands/MouseMoveCommand.swift @@ -0,0 +1,65 @@ +import Foundation + +public class MouseMoveCommand: MouseClickCommand { + public override class var commandType: CommandType { return .mouseMove } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } + + var x1: Int? + var y1: Int? + var x2: Int = 0 + var y2: Int = 0 + var duration: TimeInterval = 0 + + override init() { + super.init() + } + + public init(x1: Int?, y1: Int?, x2: Int, y2: Int, duration: TimeInterval, modifiers: [String]) { + super.init() + + self.x1 = x1 + self.y1 = y1 + self.x2 = x2 + self.y2 = y2 + self.duration = duration + self.modifiers = modifiers + } + + required public init(arguments: [String?]) { + super.init() + self.x1 = Int(arguments[2] ?? "") + self.y1 = Int(arguments[3] ?? "") + self.x2 = Int(arguments[4]!)! + self.y2 = Int(arguments[5]!)! + self.duration = TimeInterval(arguments[7] ?? "0")! + self.modifiers = arguments[9]?.components(separatedBy: ",").filter({ !$0.isEmpty }) ?? [] + } + + public override func execute() throws { + mouseController.move( + start: x1 == nil || y1 == nil ? nil : CGPoint(x: x1!, y: y1!), + end: CGPoint(x: x2, y: y2), + duration: duration, + flags: try! KeyPresser.getModifierFlags(modifiers) + ) + } + + public override func equals(_ comparison: Command) -> Bool { + return super.equals(comparison) && { + if let command = comparison as? MouseMoveCommand { + return x1 == command.x1 + && y1 == command.y1 + && x2 == command.x2 + && y2 == command.y2 + && duration == command.duration + } + return false + }() + } + + public override func describeMembers() -> String { + return "x1: \(x1?.description ?? "nil")), y1: \(y1?.description ?? "nil"), x2: \(x2), y2: \(y2), duration: \(duration)" + } +} diff --git a/Sources/SendKeysLib/Commands/MouseMoveCommandMatcher.swift b/Sources/SendKeysLib/Commands/MouseMoveCommandMatcher.swift deleted file mode 100644 index 8e8f5f5..0000000 --- a/Sources/SendKeysLib/Commands/MouseMoveCommandMatcher.swift +++ /dev/null @@ -1,25 +0,0 @@ -import Foundation - -public class MouseMoveCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - let x1 = arguments[2] - let y1 = arguments[3] - let x2 = arguments[4] - let y2 = arguments[5] - let duration = arguments[7] - let modifiers = arguments[9] - - return Command(.mouseMove, [ - x1 ?? "-1", - y1 ?? "-1", - x2!, - y2!, - duration ?? "0", - modifiers - ]) - } -} diff --git a/Sources/SendKeysLib/Commands/MouseScrollCommand.swift b/Sources/SendKeysLib/Commands/MouseScrollCommand.swift new file mode 100644 index 0000000..3bf5e30 --- /dev/null +++ b/Sources/SendKeysLib/Commands/MouseScrollCommand.swift @@ -0,0 +1,53 @@ +import Foundation + +public class MouseScrollCommand: MouseClickCommand { + public override class var commandType: CommandType { return .mouseScroll } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } + + var x: Int + var y: Int + var duration: TimeInterval + + public init(x: Int, y: Int, duration: TimeInterval, modifiers: [String]) { + self.x = x + self.y = y + self.duration = duration + + super.init() + self.modifiers = modifiers + } + + required public init(arguments: [String?]) { + self.x = Int(arguments[1]!)! + self.y = Int(arguments[2]!)! + self.duration = TimeInterval(arguments[4] ?? "0")! + + super.init() + self.modifiers = arguments[6]?.components(separatedBy: ",").filter({ !$0.isEmpty }) ?? [] + } + + public override func execute() throws { + mouseController.scroll( + CGPoint(x: x, y: y), + duration, + flags: try! KeyPresser.getModifierFlags(modifiers) + ) + } + + public override func describeMembers() -> String { + return "x: \(x), y: \(y), duration: \(duration), modifiers: \(modifiers)" + } + + public override func equals(_ comparison: Command) -> Bool { + return super.equals(comparison) && { + if let command = comparison as? MouseScrollCommand { + return x == command.x + && y == command.y + && duration == command.duration + } + return false + }() + } +} diff --git a/Sources/SendKeysLib/Commands/MouseScrollCommandMatcher.swift b/Sources/SendKeysLib/Commands/MouseScrollCommandMatcher.swift deleted file mode 100644 index 46e3609..0000000 --- a/Sources/SendKeysLib/Commands/MouseScrollCommandMatcher.swift +++ /dev/null @@ -1,21 +0,0 @@ -import Foundation - -public class MouseScrollCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - let x = arguments[1] - let y = arguments[2] - let duration = arguments[4] - let modifiers = arguments[6] - - return Command(.mouseScroll, [ - x, - y, - duration, - modifiers - ]) - } -} diff --git a/Sources/SendKeysLib/Commands/NewlineCommand.swift b/Sources/SendKeysLib/Commands/NewlineCommand.swift new file mode 100644 index 0000000..ec84dda --- /dev/null +++ b/Sources/SendKeysLib/Commands/NewlineCommand.swift @@ -0,0 +1,15 @@ +import Foundation + +public class NewlineCommand: KeyPressCommand { + private static let _expression = try! NSRegularExpression(pattern: "\\r?\\n") + public override class var expression: NSRegularExpression { return _expression } + + public override init() { + super.init() + self.key = "return" + } + + required public convenience init(arguments: [String?]) { + self.init() + } +} diff --git a/Sources/SendKeysLib/Commands/NewlineCommandMatcher.swift b/Sources/SendKeysLib/Commands/NewlineCommandMatcher.swift deleted file mode 100644 index 58c6550..0000000 --- a/Sources/SendKeysLib/Commands/NewlineCommandMatcher.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -public class NewlineCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\r?\\n")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - return Command(.keyPress, ["return"]) - } -} diff --git a/Sources/SendKeysLib/Commands/PauseCommand.swift b/Sources/SendKeysLib/Commands/PauseCommand.swift new file mode 100644 index 0000000..f31db70 --- /dev/null +++ b/Sources/SendKeysLib/Commands/PauseCommand.swift @@ -0,0 +1,39 @@ +import Foundation + +public class PauseCommand: Command { + public override class var commandType: CommandType { return .pause } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } + + var duration: TimeInterval = 0 + + init(duration: TimeInterval) { + super.init() + + self.duration = duration + } + + required public init(arguments: [String?]) { + super.init() + + self.duration = TimeInterval(arguments[1]!)! + } + + public override func execute() throws { + Sleeper.sleep(seconds: duration) + } + + public override func equals(_ comparison: Command) -> Bool { + return super.equals(comparison) && { + if let command = comparison as? PauseCommand { + return duration == command.duration + } + return false + }() + } + + public override func describeMembers() -> String { + return "duration: \(duration)" + } +} diff --git a/Sources/SendKeysLib/Commands/PauseCommandMatcher.swift b/Sources/SendKeysLib/Commands/PauseCommandMatcher.swift deleted file mode 100644 index d46bce2..0000000 --- a/Sources/SendKeysLib/Commands/PauseCommandMatcher.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -public class PauseCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - return Command(.pause, [arguments[1]!]) - } -} diff --git a/Sources/SendKeysLib/Commands/StickyPauseCommand.swift b/Sources/SendKeysLib/Commands/StickyPauseCommand.swift new file mode 100644 index 0000000..a0a9d81 --- /dev/null +++ b/Sources/SendKeysLib/Commands/StickyPauseCommand.swift @@ -0,0 +1,8 @@ +import Foundation + +public class StickyPauseCommand: PauseCommand { + public override class var commandType: CommandType { return .stickyPause } + + private static let _expression = try! NSRegularExpression(pattern: "\\") + public override class var expression: NSRegularExpression { return _expression } +} diff --git a/Sources/SendKeysLib/Commands/StickyPauseCommandMatcher.swift b/Sources/SendKeysLib/Commands/StickyPauseCommandMatcher.swift deleted file mode 100644 index f7cfc24..0000000 --- a/Sources/SendKeysLib/Commands/StickyPauseCommandMatcher.swift +++ /dev/null @@ -1,11 +0,0 @@ -import Foundation - -public class StickyPauseCommandMatcher: CommandMatcher { - public init() { - super.init(try! NSRegularExpression(pattern: "\\")) - } - - override public func createCommand(_ arguments: [String?]) -> Command { - return Command(.stickyPause, [arguments[1]!]) - } -} diff --git a/Sources/SendKeysLib/MouseController.swift b/Sources/SendKeysLib/MouseController.swift index e8c4616..d0eacc8 100644 --- a/Sources/SendKeysLib/MouseController.swift +++ b/Sources/SendKeysLib/MouseController.swift @@ -9,8 +9,8 @@ class MouseController { let animationRefreshInterval: TimeInterval = 0.01 let keyPresser = KeyPresser() - func move(start: CGPoint, end: CGPoint, duration: TimeInterval, flags: CGEventFlags) { - let resolvedStart = resolveLocation(start) + func move(start: CGPoint?, end: CGPoint, duration: TimeInterval, flags: CGEventFlags) { + let resolvedStart = start ?? getLocation()! let eventSource = CGEventSource(event: nil) let animator = Animator(duration, animationRefreshInterval, { progress in @@ -24,8 +24,8 @@ class MouseController { animator.animate() } - func click(_ location: CGPoint, button: CGMouseButton, flags: CGEventFlags, clickCount: Int) { - let resolvedLocation = resolveLocation(location) + func click(_ location: CGPoint?, button: CGMouseButton, flags: CGEventFlags, clickCount: Int) { + let resolvedLocation = location ?? getLocation()! var downMouseType = CGEventType.leftMouseDown var upMouseType = CGEventType.leftMouseUp @@ -48,8 +48,8 @@ class MouseController { upEvent?.post(tap: CGEventTapLocation.cghidEventTap) } - func drag(start: CGPoint, end: CGPoint, duration: TimeInterval, button: CGMouseButton, flags: CGEventFlags) { - let resolvedStart = resolveLocation(start) + func drag(start: CGPoint?, end: CGPoint, duration: TimeInterval, button: CGMouseButton, flags: CGEventFlags) { + let resolvedStart = start ?? getLocation()! var eventSource: CGEventSource? var downMouseType = CGEventType.leftMouseDown diff --git a/Tests/SendKeysTests/CommandIteratorTests.swift b/Tests/SendKeysTests/CommandIteratorTests.swift index 0e5bc53..7070de2 100644 --- a/Tests/SendKeysTests/CommandIteratorTests.swift +++ b/Tests/SendKeysTests/CommandIteratorTests.swift @@ -8,9 +8,9 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["a"]), - Command(CommandType.keyPress, ["b"]), - Command(CommandType.keyPress, ["c"]) + DefaultCommand(key: "a"), + DefaultCommand(key: "b"), + DefaultCommand(key: "c") ]) } @@ -19,7 +19,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["a"]) + KeyPressCommand(key: "a", modifiers: []) ]) } @@ -28,7 +28,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["delete"]) + KeyPressCommand(key: "delete", modifiers: []) ]) } @@ -37,7 +37,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["a", "command"]) + KeyPressCommand(key: "a", modifiers: ["command"]) ]) } @@ -46,7 +46,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["a", "command,shift"]) + KeyPressCommand(key: "a", modifiers: ["command", "shift"]) ]) } @@ -55,7 +55,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["a"]) + KeyPressCommand(key: "a", modifiers: []) ]) } @@ -64,7 +64,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyDown, ["a"]) + KeyDownCommand(key: "a", modifiers: []) ]) } @@ -73,7 +73,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyDown, ["a", "shift"]) + KeyDownCommand(key: "a", modifiers: ["shift"]) ]) } @@ -82,7 +82,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyDown, ["shift"]) + KeyDownCommand(key: "shift", modifiers: []) ]) } @@ -91,7 +91,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyUp, ["a"]) + KeyUpCommand(key: "a", modifiers: []) ]) } @@ -100,7 +100,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyUp, ["a", "shift"]) + KeyUpCommand(key: "a", modifiers: ["shift"]) ]) } @@ -109,7 +109,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyUp, ["shift"]) + KeyUpCommand(key: "shift", modifiers: []) ]) } @@ -118,9 +118,9 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["return"]), - Command(CommandType.keyPress, ["return"]), - Command(CommandType.keyPress, ["return"]) + NewlineCommand(), + NewlineCommand(), + NewlineCommand() ]) } @@ -129,9 +129,9 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["return"]), - Command(CommandType.keyPress, ["return"]), - Command(CommandType.keyPress, ["return"]) + NewlineCommand(), + NewlineCommand(), + NewlineCommand() ]) } @@ -140,8 +140,8 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.keyPress, ["a", "command"]), - Command(CommandType.keyPress, ["c", "command"]) + KeyPressCommand(key: "a", modifiers: ["command"]), + KeyPressCommand(key: "c", modifiers: ["command"]) ]) } @@ -150,7 +150,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.continuation, []) + ContinuationCommand() ]) } @@ -159,7 +159,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.pause, ["0.2"]) + PauseCommand(duration: 0.2) ]) } @@ -168,7 +168,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.stickyPause, ["0.2"]) + StickyPauseCommand(duration: 0.2) ]) } @@ -177,7 +177,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseMove, ["1", "2", "3", "4", "0", nil]) + MouseMoveCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0, modifiers: []) ]) } @@ -186,7 +186,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseMove, ["1", "2", "3", "4", "0", "command"]) + MouseMoveCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0, modifiers: ["command"]) ]) } @@ -195,7 +195,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseMove, ["1", "2", "3", "4", "0.1", nil]) + MouseMoveCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0.1, modifiers: []) ]) } @@ -204,7 +204,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseMove, ["1", "2", "3", "4", "0.1", "shift,command"]) + MouseMoveCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0.1, modifiers: ["shift", "command"]) ]) } @@ -213,7 +213,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseMove, ["-1", "-1", "3", "4", "0", nil]) + MouseMoveCommand(x1: nil, y1: nil, x2: 3, y2: 4, duration: 0, modifiers: []) ]) } @@ -222,7 +222,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseMove, ["-1", "-1", "3", "4", "2", nil]) + MouseMoveCommand(x1: nil, y1: nil, x2: 3, y2: 4, duration: 2, modifiers: []) ]) } @@ -231,7 +231,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseClick, ["left", nil, "1"]) + MouseClickCommand(button: "left", modifiers: [], clicks: 1) ]) } @@ -240,7 +240,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseClick, ["left", "shift,command", "1"]) + MouseClickCommand(button: "left", modifiers: ["shift", "command"], clicks: 1) ]) } @@ -249,7 +249,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseClick, ["right", nil, "2"]) + MouseClickCommand(button: "right", modifiers: [], clicks: 2) ]) } @@ -258,7 +258,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseClick, ["right", "command", "2"]) + MouseClickCommand(button: "right", modifiers: ["command"], clicks: 2) ]) } @@ -267,7 +267,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["1", "2", "3", "4", "0", "left", nil]) + MouseDragCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0, button: "left", modifiers: []) ]) } @@ -276,7 +276,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["1", "2", "3", "4", "0", "right", nil]) + MouseDragCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0, button: "right", modifiers: []) ]) } @@ -285,7 +285,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["1", "2", "3", "4", "0", "right", "command,shift"]) + MouseDragCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0, button: "right", modifiers: ["command", "shift"]) ]) } @@ -294,7 +294,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["1", "2", "3", "4", "0.1", "left", nil]) + MouseDragCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0.1, button: "left", modifiers: []) ]) } @@ -303,7 +303,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["1", "2", "3", "4", "0.1", "right", nil]) + MouseDragCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0.1, button: "right", modifiers: []) ]) } @@ -312,7 +312,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["1", "2", "3", "4", "0.1", "right", "command"]) + MouseDragCommand(x1: 1, y1: 2, x2: 3, y2: 4, duration: 0.1, button: "right", modifiers: ["command"]) ]) } @@ -321,7 +321,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["-1", "-1", "3", "4", "0", "left", nil]) + MouseDragCommand(x1: nil, y1: nil, x2: 3, y2: 4, duration: 0, button: "left", modifiers: []) ]) } @@ -330,7 +330,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["-1", "-1", "3", "4", "2", "left", nil]) + MouseDragCommand(x1: nil, y1: nil, x2: 3, y2: 4, duration: 2, button: "left", modifiers: []) ]) } @@ -339,7 +339,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseDrag, ["-1", "-1", "3", "4", "2", "center", nil]) + MouseDragCommand(x1: nil, y1: nil, x2: 3, y2: 4, duration: 2, button: "center", modifiers: []) ]) } @@ -348,7 +348,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseScroll, ["0", "10", nil, nil]) + MouseScrollCommand(x: 0, y: 10, duration: 0, modifiers: []) ]) } @@ -357,7 +357,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseScroll, ["-100", "10", nil, nil]) + MouseScrollCommand(x: -100, y: 10, duration: 0, modifiers: []) ]) } @@ -366,7 +366,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseScroll, ["0", "10", "0.5", nil]) + MouseScrollCommand(x: 0, y: 10, duration: 0.5, modifiers: []) ]) } @@ -375,7 +375,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseScroll, ["0", "10", "0.5", "shift"]) + MouseScrollCommand(x: 0, y: 10, duration: 0.5, modifiers: ["shift"]) ]) } @@ -384,7 +384,7 @@ final class CommandIteratorTests: XCTestCase { XCTAssertEqual( commands, [ - Command(CommandType.mouseScroll, ["0", "-10", "0.5", nil]) + MouseScrollCommand(x: 0, y: -10, duration: 0.5, modifiers: []) ]) } diff --git a/Tests/SendKeysTests/CommandsProcessorTests.swift b/Tests/SendKeysTests/CommandsProcessorTests.swift index 77ade50..7e47c4e 100644 --- a/Tests/SendKeysTests/CommandsProcessorTests.swift +++ b/Tests/SendKeysTests/CommandsProcessorTests.swift @@ -4,7 +4,7 @@ import XCTest class CommandExecutorSpy: CommandExecutorProtocol { var commands: [Command] = [] - + func execute(_ command: Command) { commands.append(command) } @@ -13,124 +13,124 @@ class CommandExecutorSpy: CommandExecutorProtocol { final class CommandProcessorTests: XCTestCase { var commandExecutor: CommandExecutorSpy? var commandsProcessor: CommandsProcessor? - + override func setUp() { commandExecutor = CommandExecutorSpy() commandsProcessor = CommandsProcessor(defaultPause: 0.1, commandExecutor: commandExecutor) } - + func testExecutesSingleKeyPress() { commandsProcessor!.process("a") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["a"]) + DefaultCommand(key: "a") ]) } - + func testExecutesSpecialKeyPress() { commandsProcessor!.process("") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["tab"]) + KeyPressCommand(key: "tab", modifiers: []) ]) } - + func testExecutesSpecialKeyPressWithModifier() { commandsProcessor!.process("") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["tab", "shift"]) + KeyPressCommand(key: "tab", modifiers: ["shift"]) ]) } func testExecutesMultipleKeyPressWithDelay() { commandsProcessor!.process("hello") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["h"]), - Command(.pause, ["0.1"]), - Command(.keyPress, ["e"]), - Command(.pause, ["0.1"]), - Command(.keyPress, ["l"]), - Command(.pause, ["0.1"]), - Command(.keyPress, ["l"]), - Command(.pause, ["0.1"]), - Command(.keyPress, ["o"]) + DefaultCommand(key: "h"), + PauseCommand(duration: 0.1), + DefaultCommand(key: "e"), + PauseCommand(duration: 0.1), + DefaultCommand(key: "l"), + PauseCommand(duration: 0.1), + DefaultCommand(key: "l"), + PauseCommand(duration: 0.1), + DefaultCommand(key: "o") ]) } - + func testExecutesMultipleKeyPressWithExplicitPause() { commandsProcessor!.process("a") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["a"]), - Command(.pause, ["10"]), - Command(.keyPress, ["a", "command"]) + DefaultCommand(key: "a"), + PauseCommand(duration: 10), + KeyPressCommand(key: "a", modifiers: ["command"]) ]) } - + func testExecutesMultipleKeyPressWithStickyPause() { commandsProcessor!.process("abcd") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["a"]), - Command(.pause, ["0.1"]), - Command(.keyPress, ["b"]), - Command(.stickyPause, ["10"]), - Command(.keyPress, ["c"]), - Command(.pause, ["10"]), - Command(.keyPress, ["d"]) + DefaultCommand(key: "a"), + PauseCommand(duration: 0.1), + DefaultCommand(key: "b"), + StickyPauseCommand(duration: 10), + DefaultCommand(key: "c"), + PauseCommand(duration: 10), + DefaultCommand(key: "d") ]) } - + func testIgnoreContinuation() { commandsProcessor!.process("<\\>") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, []) } - + func testIgnoreConsecutiveContinuations() { commandsProcessor!.process("<\\><\\>") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, []) } - + func testNegateConsecutiveContinuations() { commandsProcessor!.process("<\\><\\>a") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["a"]) + DefaultCommand(key: "a") ]) } func testExecutesMultipleKeyPressWithContinuation() { commandsProcessor!.process("a<\\>b") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.keyPress, ["a"]) + DefaultCommand(key: "a") ]) } func testExecutesMultipleMouseCommands() { commandsProcessor!.process("") let commands = commandExecutor!.commands - + XCTAssertEqual(commands, [ - Command(.mouseMove, ["-1", "-1", "20", "20", "1", nil]), - Command(.pause, ["0.1"]), - Command(.mouseMove, ["-1", "-1", "200", "200", "1", nil]), - Command(.pause, ["0.1"]), - Command(.mouseClick, ["left", nil, "1"]), + MouseMoveCommand(x1: nil, y1: nil, x2: 20, y2: 20, duration: 1, modifiers: []), + PauseCommand(duration: 0.1), + MouseMoveCommand(x1: nil, y1: nil, x2: 200, y2: 200, duration: 1, modifiers: []), + PauseCommand(duration: 0.1), + MouseClickCommand(button: "left", modifiers: [], clicks: 1), ]) } }