From a06c1ca4f651b83ec1a6259f91bd39b2b746f6e1 Mon Sep 17 00:00:00 2001 From: Tae Won Ha Date: Sat, 16 Jul 2016 00:07:50 +0200 Subject: [PATCH] GH-215 Use one file for NeoVimView - This way we can use more `private` properties. --- SwiftNeoVim/NeoVimView.swift | 647 +++++++++++++++++++++++- SwiftNeoVim/NeoVimViewKeyEvents.swift | 219 -------- SwiftNeoVim/NeoVimViewMouseEvents.swift | 180 ------- SwiftNeoVim/NeoVimViewUiBridge.swift | 218 -------- VimR.xcodeproj/project.pbxproj | 12 - 5 files changed, 625 insertions(+), 651 deletions(-) delete mode 100644 SwiftNeoVim/NeoVimViewKeyEvents.swift delete mode 100644 SwiftNeoVim/NeoVimViewMouseEvents.swift delete mode 100644 SwiftNeoVim/NeoVimViewUiBridge.swift diff --git a/SwiftNeoVim/NeoVimView.swift b/SwiftNeoVim/NeoVimView.swift index 5373773a..ab40588f 100644 --- a/SwiftNeoVim/NeoVimView.swift +++ b/SwiftNeoVim/NeoVimView.swift @@ -22,30 +22,31 @@ public class NeoVimView: NSView { public let uuid = NSUUID().UUIDString public var delegate: NeoVimViewDelegate? - let agent: NeoVimAgent + private let agent: NeoVimAgent - let grid = Grid() + private let grid = Grid() + + private var markedText: String? - var markedText: String? /// We store the last marked text because Cocoa's text input system does the following: /// 하 -> hanja popup -> insertText(하) -> attributedSubstring...() -> setMarkedText(下) -> ... /// We want to return "하" in attributedSubstring...() - var lastMarkedText: String? + private var lastMarkedText: String? - var markedPosition = Position.null - var keyDownDone = true + private var markedPosition = Position.null + private var keyDownDone = true - var lastClickedCellPosition = Position.null + private var lastClickedCellPosition = Position.null - var xOffset = CGFloat(0) - var yOffset = CGFloat(0) - var cellSize = CGSize.zero - var descent = CGFloat(0) - var leading = CGFloat(0) + private var xOffset = CGFloat(0) + private var yOffset = CGFloat(0) + private var cellSize = CGSize.zero + private var descent = CGFloat(0) + private var leading = CGFloat(0) - var scrollGuardCounterX = 9 - var scrollGuardCounterY = 9 - let scrollGuardYield = 10 + private var scrollGuardCounterX = 9 + private var scrollGuardCounterY = 9 + private let scrollGuardYield = 10 private let drawer: TextDrawer private var font: NSFont { @@ -119,7 +120,7 @@ public class NeoVimView: NSView { self.resizeNeoVimUiTo(size: self.bounds.size) } - func resizeNeoVimUiTo(size size: CGSize) { + private func resizeNeoVimUiTo(size size: CGSize) { // NSLog("\(#function): \(size)") let discreteSize = Size(width: Int(floor(size.width / self.cellSize.width)), height: Int(floor(size.height / self.cellSize.height))) @@ -250,22 +251,22 @@ public class NeoVimView: NSView { return Region(top: rowStart, bottom: rowEnd, left: columnStart, right: columnEnd) } - func pointInViewFor(position position: Position) -> CGPoint { + private func pointInViewFor(position position: Position) -> CGPoint { return self.pointInViewFor(row: position.row, column: position.column) } - func pointInViewFor(row row: Int, column: Int) -> CGPoint { + private func pointInViewFor(row row: Int, column: Int) -> CGPoint { return CGPoint( x: CGFloat(column) * self.cellSize.width + self.xOffset, y: self.frame.size.height - CGFloat(row) * self.cellSize.height - self.cellSize.height - self.yOffset ) } - func cellRectFor(row row: Int, column: Int) -> CGRect { + private func cellRectFor(row row: Int, column: Int) -> CGRect { return CGRect(origin: self.pointInViewFor(row: row, column: column), size: self.cellSize) } - func regionRectFor(region region: Region) -> CGRect { + private func regionRectFor(region region: Region) -> CGRect { let top = CGFloat(region.top) let bottom = CGFloat(region.bottom) let left = CGFloat(region.left) @@ -282,11 +283,11 @@ public class NeoVimView: NSView { ) } - func wrapNamedKeys(string: String) -> String { + private func wrapNamedKeys(string: String) -> String { return "<\(string)>" } - func vimPlainString(string: String) -> String { + private func vimPlainString(string: String) -> String { return string.stringByReplacingOccurrencesOfString("<", withString: self.wrapNamedKeys("lt")) } @@ -294,3 +295,605 @@ public class NeoVimView: NSView { fatalError("init(coder:) has not been implemented") } } + +// MARK: - Key Events +extension NeoVimView: NSTextInputClient { + + override public func keyDown(event: NSEvent) { + self.keyDownDone = false + + let context = NSTextInputContext.currentInputContext()! + let cocoaHandledEvent = context.handleEvent(event) + if self.keyDownDone && cocoaHandledEvent { + return + } + +// NSLog("\(#function): \(event)") + + let modifierFlags = event.modifierFlags + let capslock = modifierFlags.contains(.AlphaShiftKeyMask) + let shift = modifierFlags.contains(.ShiftKeyMask) + let chars = event.characters! + let charsIgnoringModifiers = shift || capslock ? event.charactersIgnoringModifiers!.lowercaseString + : event.charactersIgnoringModifiers! + + if KeyUtils.isSpecial(key: charsIgnoringModifiers) { + if let vimModifiers = self.vimModifierFlags(modifierFlags) { + self.agent.vimInput(self.wrapNamedKeys(vimModifiers + KeyUtils.namedKeyFrom(key: charsIgnoringModifiers))) + } else { + self.agent.vimInput(self.wrapNamedKeys(KeyUtils.namedKeyFrom(key: charsIgnoringModifiers))) + } + } else { + if let vimModifiers = self.vimModifierFlags(modifierFlags) { + self.agent.vimInput(self.wrapNamedKeys(vimModifiers + charsIgnoringModifiers)) + } else { + self.agent.vimInput(self.vimPlainString(chars)) + } + } + + self.keyDownDone = true + } + + public func insertText(aString: AnyObject, replacementRange: NSRange) { +// NSLog("\(#function): \(replacementRange): '\(aString)'") + + switch aString { + case let string as String: + self.agent.vimInput(self.vimPlainString(string)) + case let attributedString as NSAttributedString: + self.agent.vimInput(self.vimPlainString(attributedString.string)) + default: + break; + } + + // unmarkText() + self.lastMarkedText = self.markedText + self.markedText = nil + self.markedPosition = Position.null + self.keyDownDone = true + } + + public override func doCommandBySelector(aSelector: Selector) { +// NSLog("\(#function): \(aSelector)"); + + // FIXME: handle when ㅎ -> delete + + if self.respondsToSelector(aSelector) { + Swift.print("\(#function): calling \(aSelector)") + self.performSelector(aSelector, withObject: self) + self.keyDownDone = true + return + } + +// NSLog("\(#function): "\(aSelector) not implemented, forwarding input to vim") + self.keyDownDone = false + } + + public func setMarkedText(aString: AnyObject, selectedRange: NSRange, replacementRange: NSRange) { + if self.markedText == nil { + self.markedPosition = self.grid.putPosition + } + + // eg 하 -> hanja popup, cf comment for self.lastMarkedText + if replacementRange.length > 0 { + self.agent.deleteCharacters(replacementRange.length) + } + + switch aString { + case let string as String: + self.markedText = string + case let attributedString as NSAttributedString: + self.markedText = attributedString.string + default: + self.markedText = String(aString) // should not occur + } + +// NSLog("\(#function): \(self.markedText), \(selectedRange), \(replacementRange)") + + self.agent.vimInputMarkedText(self.markedText!) + self.keyDownDone = true + } + + public func unmarkText() { +// NSLog("\(#function): ") + self.markedText = nil + self.markedPosition = Position.null + self.keyDownDone = true + + // TODO: necessary? + self.setNeedsDisplayInRect(self.cellRectFor(row: self.grid.putPosition.row, column: self.grid.putPosition.column)) + } + + /// Return the current selection (or the position of the cursor with empty-length range). For example when you enter + /// "Cmd-Ctrl-Return" you'll get the Emoji-popup at the rect by firstRectForCharacterRange(actualRange:) where the + /// first range is the result of this method. + public func selectedRange() -> NSRange { + // When the app starts and the Hangul input method is selected, this method gets called very early... + guard self.grid.hasData else { +// NSLog("\(#function): not found") + return NSRange(location: NSNotFound, length: 0) + } + + let result = NSRange(location: self.grid.singleIndexFrom(self.grid.putPosition), length: 0) +// NSLog("\(#function): \(result)") + return result + } + + public func markedRange() -> NSRange { + // FIXME: do we have to handle positions at the column borders? + if let markedText = self.markedText { + let result = NSRange(location: self.grid.singleIndexFrom(self.markedPosition), + length: markedText.characters.count) +// NSLog("\(#function): \(result)") + return result + } + + NSLog("\(#function): returning empty range") + return NSRange(location: NSNotFound, length: 0) + } + + public func hasMarkedText() -> Bool { +// NSLog("\(#function)") + return self.markedText != nil + } + + // FIXME: take into account the "return nil"-case + // FIXME: just fix me, PLEASE... + public func attributedSubstringForProposedRange(aRange: NSRange, actualRange: NSRangePointer) -> NSAttributedString? { +// NSLog("\(#function): \(aRange), \(actualRange[0])") + if aRange.location == NSNotFound { +// NSLog("\(#function): range not found: returning nil") + return nil + } + + guard let lastMarkedText = self.lastMarkedText else { +// NSLog("\(#function): no last marked text: returning nil") + return nil + } + + // we only support last marked text, thus fill dummy characters when Cocoa asks for more characters than marked... + let fillCount = aRange.length - lastMarkedText.characters.count + guard fillCount >= 0 else { + return nil + } + + let fillChars = Array(0.. [String] { + return [] + } + + public func firstRectForCharacterRange(aRange: NSRange, actualRange: NSRangePointer) -> NSRect { + let position = self.grid.positionFromSingleIndex(aRange.location) + +// NSLog("\(#function): \(aRange),\(actualRange[0]) -> \(position.row):\(position.column)") + + let resultInSelf = self.cellRectFor(row: position.row, column: position.column) + let result = self.window?.convertRectToScreen(self.convertRect(resultInSelf, toView: nil)) + + return result! + } + + public func characterIndexForPoint(aPoint: NSPoint) -> Int { +// NSLog("\(#function): \(aPoint)") + return 1 + } + + private func vimModifierFlags(modifierFlags: NSEventModifierFlags) -> String? { + var result = "" + + let control = modifierFlags.contains(.ControlKeyMask) + let option = modifierFlags.contains(.AlternateKeyMask) + let command = modifierFlags.contains(.CommandKeyMask) + + if control { + result += "C-" + } + + if option { + result += "M-" + } + + if command { + result += "D-" + } + + if result.characters.count > 0 { + return result + } + + return nil + } +} + +// MARK: - Mouse Events +extension NeoVimView { + + override public func mouseDown(event: NSEvent) { + self.mouse(event: event, vimName:"LeftMouse") + } + + override public func mouseUp(event: NSEvent) { + self.mouse(event: event, vimName:"LeftRelease") + } + + override public func mouseDragged(event: NSEvent) { + self.mouse(event: event, vimName:"LeftDrag") + } + + override public func scrollWheel(event: NSEvent) { + let (deltaX, deltaY) = (event.scrollingDeltaX, event.scrollingDeltaY) + if deltaX == 0 && deltaY == 0 { + return + } + + let cellPosition = self.cellPositionFor(event: event) + let (vimInputX, vimInputY) = self.vimScrollInputFor(deltaX: deltaX, deltaY: deltaY, + modifierFlags: event.modifierFlags, + cellPosition: cellPosition) + + let (absDeltaX, absDeltaY) = (abs(deltaX), abs(deltaY)) + + // The absolute delta values can get very very big when you use two finger scrolling on the trackpad: + // Cap them using heuristic values... + let numX = deltaX != 0 ? max(1, min(Int(absDeltaX / 20), 25)) : 0 + let numY = deltaY != 0 ? max(1, min(Int(absDeltaY / 20), 25)) : 0 + + for i in 0.. Position { + let location = self.convertPoint(event.locationInWindow, fromView: nil) + let cellPosition = Position( + row: min(Int(floor(location.x / self.cellSize.width)), self.grid.size.width - 1), + column: min(Int(floor((self.bounds.height - location.y) / self.cellSize.height)), self.grid.size.height - 1) + ) + + return cellPosition + } + + private func mouse(event event: NSEvent, vimName: String) { + let cellPosition = self.cellPositionFor(event: event) + guard self.shouldFireVimInputFor(event: event, newCellPosition: cellPosition) else { + return + } + + let vimMouseLocation = self.wrapNamedKeys("\(cellPosition.row),\(cellPosition.column)") + let vimClickCount = self.vimClickCountFrom(event: event) + + let result: String + if let vimModifiers = self.vimModifierFlags(event.modifierFlags) { + result = self.wrapNamedKeys("\(vimModifiers)\(vimClickCount)\(vimName)") + vimMouseLocation + } else { + result = self.wrapNamedKeys("\(vimClickCount)\(vimName)") + vimMouseLocation + } + +// NSLog("\(#function): \(result)") + self.agent.vimInput(result) + } + + private func shouldFireVimInputFor(event event:NSEvent, newCellPosition: Position) -> Bool { + let type = event.type + guard type == .LeftMouseDragged || type == .RightMouseDragged || type == .OtherMouseDragged else { + self.lastClickedCellPosition = newCellPosition + return true + } + + if self.lastClickedCellPosition == newCellPosition { + return false + } + + self.lastClickedCellPosition = newCellPosition + return true + } + + private func vimClickCountFrom(event event: NSEvent) -> String { + let clickCount = event.clickCount + + guard 2 <= clickCount && clickCount <= 4 else { + return "" + } + + switch event.type { + case .LeftMouseDown, .LeftMouseUp, .RightMouseDown, .RightMouseUp: + return "\(clickCount)-" + default: + return "" + } + } + + private func vimScrollEventNamesFor(deltaX deltaX: CGFloat, deltaY: CGFloat) -> (String, String) { + let typeY: String + if deltaY > 0 { + typeY = "ScrollWheelUp" + } else { + typeY = "ScrollWheelDown" + } + + let typeX: String + if deltaX < 0 { + typeX = "ScrollWheelRight" + } else { + typeX = "ScrollWheelLeft" + } + + return (typeX, typeY) + } + + private func vimScrollInputFor(deltaX deltaX: CGFloat, deltaY: CGFloat, + modifierFlags: NSEventModifierFlags, + cellPosition: Position) -> (String, String) + { + let vimMouseLocation = self.wrapNamedKeys("\(cellPosition.row),\(cellPosition.column)") + + let (typeX, typeY) = self.vimScrollEventNamesFor(deltaX: deltaX, deltaY: deltaY) + let resultX: String + let resultY: String + if let vimModifiers = self.vimModifierFlags(modifierFlags) { + resultX = self.wrapNamedKeys("\(vimModifiers)\(typeX)") + vimMouseLocation + resultY = self.wrapNamedKeys("\(vimModifiers)\(typeY)") + vimMouseLocation + } else { + resultX = self.wrapNamedKeys("\(typeX)") + vimMouseLocation + resultY = self.wrapNamedKeys("\(typeY)") + vimMouseLocation + } + + return (resultX, resultY) + } + + private func throttleScrollX(absDelta absDeltaX: CGFloat, vimInput: String) { + if absDeltaX == 0 { + self.scrollGuardCounterX = self.scrollGuardYield - 1 + } else if absDeltaX <= 2 { + // Poor man's throttle for scroll value = 1 or 2 + if self.scrollGuardCounterX % self.scrollGuardYield == 0 { + self.agent.vimInput(vimInput) + self.scrollGuardCounterX = 1 + } else { + self.scrollGuardCounterX += 1 + } + } else { + self.agent.vimInput(vimInput) + } + } + + private func throttleScrollY(absDelta absDeltaY: CGFloat, vimInput: String) { + if absDeltaY == 0 { + self.scrollGuardCounterY = self.scrollGuardYield - 1 + } else if absDeltaY <= 2 { + // Poor man's throttle for scroll value = 1 or 2 + if self.scrollGuardCounterY % self.scrollGuardYield == 0 { + self.agent.vimInput(vimInput) + self.scrollGuardCounterY = 1 + } else { + self.scrollGuardCounterY += 1 + } + } else { + self.agent.vimInput(vimInput) + } + } +} + +// MARK: - NeoVimUiBridgeProtocol +extension NeoVimView: NeoVimUiBridgeProtocol { + + public func neoVimUiIsReady() { + DispatchUtils.gui { + self.resizeNeoVimUiTo(size: self.frame.size) + } + } + + public func resizeToWidth(width: Int32, height: Int32) { + DispatchUtils.gui { + NSLog("\(#function): \(width):\(height)") + self.grid.resize(Size(width: Int(width), height: Int(height))) + self.needsDisplay = true + } + } + + public func clear() { + DispatchUtils.gui { + self.grid.clear() + self.needsDisplay = true + } + } + + public func eolClear() { + DispatchUtils.gui { + self.grid.eolClear() + + let origin = self.pointInViewFor(position: self.grid.putPosition) + let size = CGSize( + width: CGFloat(self.grid.region.right - self.grid.putPosition.column + 1) * self.cellSize.width, + height: self.cellSize.height + ) + let rect = CGRect(origin: origin, size: size) + self.setNeedsDisplayInRect(rect) + } + } + + public func gotoPosition(position: Position, screenCursor: Position) { + DispatchUtils.gui { +// NSLog("\(#function): \(position), \(screenCursor)") + + // Because neovim fills blank space with "Space" and when we enter "Space" we don't get the puts. + self.setNeedsDisplay(cellPosition: self.grid.putPosition) + self.setNeedsDisplay(cellPosition: self.grid.nextCellPosition(self.grid.putPosition)) + self.setNeedsDisplay(screenCursor: position) + + self.grid.goto(position) + self.grid.moveCursor(screenCursor) + } + } + + public func updateMenu() { + } + + public func busyStart() { + } + + public func busyStop() { + } + + public func mouseOn() { + } + + public func mouseOff() { + } + + public func modeChange(mode: Int32) { + } + + public func setScrollRegionToTop(top: Int32, bottom: Int32, left: Int32, right: Int32) { + DispatchUtils.gui { + let region = Region(top: Int(top), bottom: Int(bottom), left: Int(left), right: Int(right)) + self.grid.setScrollRegion(region) + self.setNeedsDisplay(region: region) + } + } + + public func scroll(count: Int32) { + DispatchUtils.gui { + self.grid.scroll(Int(count)) + self.setNeedsDisplay(region: self.grid.region) + } + } + + public func highlightSet(attrs: CellAttributes) { + DispatchUtils.gui { + self.grid.attrs = attrs + } + } + + public func put(string: String) { + DispatchUtils.gui { + let curPos = self.grid.putPosition +// NSLog("\(#function): \(curPos) -> \(string)") + self.grid.put(string) + self.setNeedsDisplay(cellPosition: curPos) + // When the cursor is in the command line, then we need this... + self.setNeedsDisplay(cellPosition: self.grid.nextCellPosition(curPos)) + + self.setNeedsDisplay(screenCursor: self.grid.screenCursor) + } + } + + public func putMarkedText(markedText: String) { + DispatchUtils.gui { + NSLog("\(#function): '\(markedText)'") + let curPos = self.grid.putPosition + self.grid.putMarkedText(markedText) + + self.setNeedsDisplay(position: curPos) + // When the cursor is in the command line, then we need this... + self.setNeedsDisplay(cellPosition: self.grid.nextCellPosition(curPos)) + if markedText.characters.count == 0 { + self.setNeedsDisplay(position: self.grid.previousCellPosition(curPos)) + } + self.setNeedsDisplay(screenCursor: self.grid.screenCursor) + } + } + + public func unmarkRow(row: Int32, column: Int32) { + DispatchUtils.gui { + let position = Position(row: Int(row), column: Int(column)) + + NSLog("\(#function): \(position)") + + self.grid.unmarkCell(position) + self.setNeedsDisplay(position: position) + + self.setNeedsDisplay(screenCursor: self.grid.screenCursor) + } + } + + public func bell() { + DispatchUtils.gui { + NSBeep() + } + } + + public func visualBell() { + } + + public func flush() { +// NSLog("\(#function)") + } + + public func updateForeground(fg: Int32) { + DispatchUtils.gui { + self.grid.foreground = UInt32(bitPattern: fg) + } + } + + public func updateBackground(bg: Int32) { + DispatchUtils.gui { + self.grid.background = UInt32(bitPattern: bg) + self.layer?.backgroundColor = ColorUtils.colorIgnoringAlpha(self.grid.background).CGColor + } + } + + public func updateSpecial(sp: Int32) { + DispatchUtils.gui { + self.grid.special = UInt32(bitPattern: sp) + } + } + + public func suspend() { + } + + public func setTitle(title: String) { + DispatchUtils.gui { + self.delegate?.setNeoVimTitle(title) + } + } + + public func setIcon(icon: String) { + } + + public func stop() { + } + + private func setNeedsDisplay(region region: Region) { + self.setNeedsDisplayInRect(self.regionRectFor(region: region)) + } + + private func setNeedsDisplay(cellPosition position: Position) { + self.setNeedsDisplay(position: position) + + if self.grid.isCellEmpty(position) { + self.setNeedsDisplay(position: self.grid.previousCellPosition(position)) + } + + if self.grid.isNextCellEmpty(position) { + self.setNeedsDisplay(position: self.grid.nextCellPosition(position)) + } + } + + private func setNeedsDisplay(position position: Position) { + self.setNeedsDisplay(row: position.row, column: position.column) + } + + private func setNeedsDisplay(row row: Int, column: Int) { +// Swift.print("\(#function): \(row):\(column)") + self.setNeedsDisplayInRect(self.cellRectFor(row: row, column: column)) + } + + private func setNeedsDisplay(screenCursor position: Position) { + self.setNeedsDisplay(position: position) + if self.grid.isNextCellEmpty(position) { + self.setNeedsDisplay(position: self.grid.nextCellPosition(position)) + } + } +} \ No newline at end of file diff --git a/SwiftNeoVim/NeoVimViewKeyEvents.swift b/SwiftNeoVim/NeoVimViewKeyEvents.swift deleted file mode 100644 index 6d3012fe..00000000 --- a/SwiftNeoVim/NeoVimViewKeyEvents.swift +++ /dev/null @@ -1,219 +0,0 @@ -/** - * Tae Won Ha - http://taewon.de - @hataewon - * See LICENSE - */ - -import Cocoa - -extension NeoVimView: NSTextInputClient { - - override public func keyDown(event: NSEvent) { - self.keyDownDone = false - - let context = NSTextInputContext.currentInputContext()! - let cocoaHandledEvent = context.handleEvent(event) - if self.keyDownDone && cocoaHandledEvent { - return - } - -// NSLog("\(#function): \(event)") - - let modifierFlags = event.modifierFlags - let capslock = modifierFlags.contains(.AlphaShiftKeyMask) - let shift = modifierFlags.contains(.ShiftKeyMask) - let chars = event.characters! - let charsIgnoringModifiers = shift || capslock ? event.charactersIgnoringModifiers!.lowercaseString - : event.charactersIgnoringModifiers! - - if KeyUtils.isSpecial(key: charsIgnoringModifiers) { - if let vimModifiers = self.vimModifierFlags(modifierFlags) { - self.agent.vimInput(self.wrapNamedKeys(vimModifiers + KeyUtils.namedKeyFrom(key: charsIgnoringModifiers))) - } else { - self.agent.vimInput(self.wrapNamedKeys(KeyUtils.namedKeyFrom(key: charsIgnoringModifiers))) - } - } else { - if let vimModifiers = self.vimModifierFlags(modifierFlags) { - self.agent.vimInput(self.wrapNamedKeys(vimModifiers + charsIgnoringModifiers)) - } else { - self.agent.vimInput(self.vimPlainString(chars)) - } - } - - self.keyDownDone = true - } - - public func insertText(aString: AnyObject, replacementRange: NSRange) { -// NSLog("\(#function): \(replacementRange): '\(aString)'") - - switch aString { - case let string as String: - self.agent.vimInput(self.vimPlainString(string)) - case let attributedString as NSAttributedString: - self.agent.vimInput(self.vimPlainString(attributedString.string)) - default: - break; - } - - // unmarkText() - self.lastMarkedText = self.markedText - self.markedText = nil - self.markedPosition = Position.null - self.keyDownDone = true - } - - public override func doCommandBySelector(aSelector: Selector) { -// NSLog("\(#function): \(aSelector)"); - - // FIXME: handle when ㅎ -> delete - - if self.respondsToSelector(aSelector) { - Swift.print("\(#function): calling \(aSelector)") - self.performSelector(aSelector, withObject: self) - self.keyDownDone = true - return - } - -// NSLog("\(#function): "\(aSelector) not implemented, forwarding input to vim") - self.keyDownDone = false - } - - public func setMarkedText(aString: AnyObject, selectedRange: NSRange, replacementRange: NSRange) { - if self.markedText == nil { - self.markedPosition = self.grid.putPosition - } - - // eg 하 -> hanja popup, cf comment for self.lastMarkedText - if replacementRange.length > 0 { - self.agent.deleteCharacters(replacementRange.length) - } - - switch aString { - case let string as String: - self.markedText = string - case let attributedString as NSAttributedString: - self.markedText = attributedString.string - default: - self.markedText = String(aString) // should not occur - } - -// NSLog("\(#function): \(self.markedText), \(selectedRange), \(replacementRange)") - - self.agent.vimInputMarkedText(self.markedText!) - self.keyDownDone = true - } - - public func unmarkText() { -// NSLog("\(#function): ") - self.markedText = nil - self.markedPosition = Position.null - self.keyDownDone = true - - // TODO: necessary? - self.setNeedsDisplayInRect(self.cellRectFor(row: self.grid.putPosition.row, column: self.grid.putPosition.column)) - } - - /// Return the current selection (or the position of the cursor with empty-length range). For example when you enter - /// "Cmd-Ctrl-Return" you'll get the Emoji-popup at the rect by firstRectForCharacterRange(actualRange:) where the - /// first range is the result of this method. - public func selectedRange() -> NSRange { - // When the app starts and the Hangul input method is selected, this method gets called very early... - guard self.grid.hasData else { -// NSLog("\(#function): not found") - return NSRange(location: NSNotFound, length: 0) - } - - let result = NSRange(location: self.grid.singleIndexFrom(self.grid.putPosition), length: 0) -// NSLog("\(#function): \(result)") - return result - } - - public func markedRange() -> NSRange { - // FIXME: do we have to handle positions at the column borders? - if let markedText = self.markedText { - let result = NSRange(location: self.grid.singleIndexFrom(self.markedPosition), - length: markedText.characters.count) -// NSLog("\(#function): \(result)") - return result - } - - NSLog("\(#function): returning empty range") - return NSRange(location: NSNotFound, length: 0) - } - - public func hasMarkedText() -> Bool { -// NSLog("\(#function)") - return self.markedText != nil - } - - // FIXME: take into account the "return nil"-case - // FIXME: just fix me, PLEASE... - public func attributedSubstringForProposedRange(aRange: NSRange, actualRange: NSRangePointer) -> NSAttributedString? { -// NSLog("\(#function): \(aRange), \(actualRange[0])") - if aRange.location == NSNotFound { -// NSLog("\(#function): range not found: returning nil") - return nil - } - - guard let lastMarkedText = self.lastMarkedText else { -// NSLog("\(#function): no last marked text: returning nil") - return nil - } - - // we only support last marked text, thus fill dummy characters when Cocoa asks for more characters than marked... - let fillCount = aRange.length - lastMarkedText.characters.count - guard fillCount >= 0 else { - return nil - } - - let fillChars = Array(0.. [String] { - return [] - } - - public func firstRectForCharacterRange(aRange: NSRange, actualRange: NSRangePointer) -> NSRect { - let position = self.grid.positionFromSingleIndex(aRange.location) - -// NSLog("\(#function): \(aRange),\(actualRange[0]) -> \(position.row):\(position.column)") - - let resultInSelf = self.cellRectFor(row: position.row, column: position.column) - let result = self.window?.convertRectToScreen(self.convertRect(resultInSelf, toView: nil)) - - return result! - } - - public func characterIndexForPoint(aPoint: NSPoint) -> Int { -// NSLog("\(#function): \(aPoint)") - return 1 - } - - func vimModifierFlags(modifierFlags: NSEventModifierFlags) -> String? { - var result = "" - - let control = modifierFlags.contains(.ControlKeyMask) - let option = modifierFlags.contains(.AlternateKeyMask) - let command = modifierFlags.contains(.CommandKeyMask) - - if control { - result += "C-" - } - - if option { - result += "M-" - } - - if command { - result += "D-" - } - - if result.characters.count > 0 { - return result - } - - return nil - } -} diff --git a/SwiftNeoVim/NeoVimViewMouseEvents.swift b/SwiftNeoVim/NeoVimViewMouseEvents.swift deleted file mode 100644 index 797a40b5..00000000 --- a/SwiftNeoVim/NeoVimViewMouseEvents.swift +++ /dev/null @@ -1,180 +0,0 @@ -/** - * Tae Won Ha - http://taewon.de - @hataewon - * See LICENSE - */ - -import Cocoa - -extension NeoVimView { - - override public func mouseDown(event: NSEvent) { - self.mouse(event: event, vimName:"LeftMouse") - } - - override public func mouseUp(event: NSEvent) { - self.mouse(event: event, vimName:"LeftRelease") - } - - override public func mouseDragged(event: NSEvent) { - self.mouse(event: event, vimName:"LeftDrag") - } - - override public func scrollWheel(event: NSEvent) { - let (deltaX, deltaY) = (event.scrollingDeltaX, event.scrollingDeltaY) - if deltaX == 0 && deltaY == 0 { - return - } - - let cellPosition = self.cellPositionFor(event: event) - let (vimInputX, vimInputY) = self.vimScrollInputFor(deltaX: deltaX, deltaY: deltaY, - modifierFlags: event.modifierFlags, - cellPosition: cellPosition) - - let (absDeltaX, absDeltaY) = (abs(deltaX), abs(deltaY)) - - // The absolute delta values can get very very big when you use two finger scrolling on the trackpad: - // Cap them using heuristic values... - let numX = deltaX != 0 ? max(1, min(Int(absDeltaX / 20), 25)) : 0 - let numY = deltaY != 0 ? max(1, min(Int(absDeltaY / 20), 25)) : 0 - - for i in 0.. Position { - let location = self.convertPoint(event.locationInWindow, fromView: nil) - let cellPosition = Position( - row: min(Int(floor(location.x / self.cellSize.width)), self.grid.size.width - 1), - column: min(Int(floor((self.bounds.height - location.y) / self.cellSize.height)), self.grid.size.height - 1) - ) - - return cellPosition - } - - private func mouse(event event: NSEvent, vimName: String) { - let cellPosition = self.cellPositionFor(event: event) - guard self.shouldFireVimInputFor(event: event, newCellPosition: cellPosition) else { - return - } - - let vimMouseLocation = self.wrapNamedKeys("\(cellPosition.row),\(cellPosition.column)") - let vimClickCount = self.vimClickCountFrom(event: event) - - let result: String - if let vimModifiers = self.vimModifierFlags(event.modifierFlags) { - result = self.wrapNamedKeys("\(vimModifiers)\(vimClickCount)\(vimName)") + vimMouseLocation - } else { - result = self.wrapNamedKeys("\(vimClickCount)\(vimName)") + vimMouseLocation - } - -// NSLog("\(#function): \(result)") - self.agent.vimInput(result) - } - - private func shouldFireVimInputFor(event event:NSEvent, newCellPosition: Position) -> Bool { - let type = event.type - guard type == .LeftMouseDragged || type == .RightMouseDragged || type == .OtherMouseDragged else { - self.lastClickedCellPosition = newCellPosition - return true - } - - if self.lastClickedCellPosition == newCellPosition { - return false - } - - self.lastClickedCellPosition = newCellPosition - return true - } - - private func vimClickCountFrom(event event: NSEvent) -> String { - let clickCount = event.clickCount - - guard 2 <= clickCount && clickCount <= 4 else { - return "" - } - - switch event.type { - case .LeftMouseDown, .LeftMouseUp, .RightMouseDown, .RightMouseUp: - return "\(clickCount)-" - default: - return "" - } - } - - private func vimScrollEventNamesFor(deltaX deltaX: CGFloat, deltaY: CGFloat) -> (String, String) { - let typeY: String - if deltaY > 0 { - typeY = "ScrollWheelUp" - } else { - typeY = "ScrollWheelDown" - } - - let typeX: String - if deltaX < 0 { - typeX = "ScrollWheelRight" - } else { - typeX = "ScrollWheelLeft" - } - - return (typeX, typeY) - } - - private func vimScrollInputFor(deltaX deltaX: CGFloat, deltaY: CGFloat, - modifierFlags: NSEventModifierFlags, - cellPosition: Position) -> (String, String) - { - let vimMouseLocation = self.wrapNamedKeys("\(cellPosition.row),\(cellPosition.column)") - - let (typeX, typeY) = self.vimScrollEventNamesFor(deltaX: deltaX, deltaY: deltaY) - let resultX: String - let resultY: String - if let vimModifiers = self.vimModifierFlags(modifierFlags) { - resultX = self.wrapNamedKeys("\(vimModifiers)\(typeX)") + vimMouseLocation - resultY = self.wrapNamedKeys("\(vimModifiers)\(typeY)") + vimMouseLocation - } else { - resultX = self.wrapNamedKeys("\(typeX)") + vimMouseLocation - resultY = self.wrapNamedKeys("\(typeY)") + vimMouseLocation - } - - return (resultX, resultY) - } - - private func throttleScrollX(absDelta absDeltaX: CGFloat, vimInput: String) { - if absDeltaX == 0 { - self.scrollGuardCounterX = self.scrollGuardYield - 1 - } else if absDeltaX <= 2 { - // Poor man's throttle for scroll value = 1 or 2 - if self.scrollGuardCounterX % self.scrollGuardYield == 0 { - self.agent.vimInput(vimInput) - self.scrollGuardCounterX = 1 - } else { - self.scrollGuardCounterX += 1 - } - } else { - self.agent.vimInput(vimInput) - } - } - - private func throttleScrollY(absDelta absDeltaY: CGFloat, vimInput: String) { - if absDeltaY == 0 { - self.scrollGuardCounterY = self.scrollGuardYield - 1 - } else if absDeltaY <= 2 { - // Poor man's throttle for scroll value = 1 or 2 - if self.scrollGuardCounterY % self.scrollGuardYield == 0 { - self.agent.vimInput(vimInput) - self.scrollGuardCounterY = 1 - } else { - self.scrollGuardCounterY += 1 - } - } else { - self.agent.vimInput(vimInput) - } - } -} diff --git a/SwiftNeoVim/NeoVimViewUiBridge.swift b/SwiftNeoVim/NeoVimViewUiBridge.swift deleted file mode 100644 index 1f49da98..00000000 --- a/SwiftNeoVim/NeoVimViewUiBridge.swift +++ /dev/null @@ -1,218 +0,0 @@ -/** - * Tae Won Ha - http://taewon.de - @hataewon - * See LICENSE - */ - -import Cocoa - -extension NeoVimView: NeoVimUiBridgeProtocol { - - public func neoVimUiIsReady() { - DispatchUtils.gui { - self.resizeNeoVimUiTo(size: self.frame.size) - } - } - - public func resizeToWidth(width: Int32, height: Int32) { - DispatchUtils.gui { - NSLog("\(#function): \(width):\(height)") - self.grid.resize(Size(width: Int(width), height: Int(height))) - self.needsDisplay = true - } - } - - public func clear() { - DispatchUtils.gui { - self.grid.clear() - self.needsDisplay = true - } - } - - public func eolClear() { - DispatchUtils.gui { - self.grid.eolClear() - - let origin = self.pointInViewFor(position: self.grid.putPosition) - let size = CGSize( - width: CGFloat(self.grid.region.right - self.grid.putPosition.column + 1) * self.cellSize.width, - height: self.cellSize.height - ) - let rect = CGRect(origin: origin, size: size) - self.setNeedsDisplayInRect(rect) - } - } - - public func gotoPosition(position: Position, screenCursor: Position) { - DispatchUtils.gui { -// NSLog("\(#function): \(position), \(screenCursor)") - - // Because neovim fills blank space with "Space" and when we enter "Space" we don't get the puts. - self.setNeedsDisplay(cellPosition: self.grid.putPosition) - self.setNeedsDisplay(cellPosition: self.grid.nextCellPosition(self.grid.putPosition)) - self.setNeedsDisplay(screenCursor: position) - - self.grid.goto(position) - self.grid.moveCursor(screenCursor) - } - } - - public func updateMenu() { - } - - public func busyStart() { - } - - public func busyStop() { - } - - public func mouseOn() { - } - - public func mouseOff() { - } - - public func modeChange(mode: Int32) { - } - - public func setScrollRegionToTop(top: Int32, bottom: Int32, left: Int32, right: Int32) { - DispatchUtils.gui { - let region = Region(top: Int(top), bottom: Int(bottom), left: Int(left), right: Int(right)) - self.grid.setScrollRegion(region) - self.setNeedsDisplay(region: region) - } - } - - public func scroll(count: Int32) { - DispatchUtils.gui { - self.grid.scroll(Int(count)) - self.setNeedsDisplay(region: self.grid.region) - } - } - - public func highlightSet(attrs: CellAttributes) { - DispatchUtils.gui { - self.grid.attrs = attrs - } - } - - public func put(string: String) { - DispatchUtils.gui { - let curPos = self.grid.putPosition -// NSLog("\(#function): \(curPos) -> \(string)") - self.grid.put(string) - self.setNeedsDisplay(cellPosition: curPos) - // When the cursor is in the command line, then we need this... - self.setNeedsDisplay(cellPosition: self.grid.nextCellPosition(curPos)) - - self.setNeedsDisplay(screenCursor: self.grid.screenCursor) - } - } - - public func putMarkedText(markedText: String) { - DispatchUtils.gui { - NSLog("\(#function): '\(markedText)'") - let curPos = self.grid.putPosition - self.grid.putMarkedText(markedText) - - self.setNeedsDisplay(position: curPos) - // When the cursor is in the command line, then we need this... - self.setNeedsDisplay(cellPosition: self.grid.nextCellPosition(curPos)) - if markedText.characters.count == 0 { - self.setNeedsDisplay(position: self.grid.previousCellPosition(curPos)) - } - self.setNeedsDisplay(screenCursor: self.grid.screenCursor) - } - } - - public func unmarkRow(row: Int32, column: Int32) { - DispatchUtils.gui { - let position = Position(row: Int(row), column: Int(column)) - - NSLog("\(#function): \(position)") - - self.grid.unmarkCell(position) - self.setNeedsDisplay(position: position) - - self.setNeedsDisplay(screenCursor: self.grid.screenCursor) - } - } - - public func bell() { - DispatchUtils.gui { - NSBeep() - } - } - - public func visualBell() { - } - - public func flush() { -// NSLog("\(#function)") - } - - public func updateForeground(fg: Int32) { - DispatchUtils.gui { - self.grid.foreground = UInt32(bitPattern: fg) - } - } - - public func updateBackground(bg: Int32) { - DispatchUtils.gui { - self.grid.background = UInt32(bitPattern: bg) - self.layer?.backgroundColor = ColorUtils.colorIgnoringAlpha(self.grid.background).CGColor - } - } - - public func updateSpecial(sp: Int32) { - DispatchUtils.gui { - self.grid.special = UInt32(bitPattern: sp) - } - } - - public func suspend() { - } - - public func setTitle(title: String) { - DispatchUtils.gui { - self.delegate?.setNeoVimTitle(title) - } - } - - public func setIcon(icon: String) { - } - - public func stop() { - } - - private func setNeedsDisplay(region region: Region) { - self.setNeedsDisplayInRect(self.regionRectFor(region: region)) - } - - private func setNeedsDisplay(cellPosition position: Position) { - self.setNeedsDisplay(position: position) - - if self.grid.isCellEmpty(position) { - self.setNeedsDisplay(position: self.grid.previousCellPosition(position)) - } - - if self.grid.isNextCellEmpty(position) { - self.setNeedsDisplay(position: self.grid.nextCellPosition(position)) - } - } - - private func setNeedsDisplay(position position: Position) { - self.setNeedsDisplay(row: position.row, column: position.column) - } - - private func setNeedsDisplay(row row: Int, column: Int) { -// Swift.print("\(#function): \(row):\(column)") - self.setNeedsDisplayInRect(self.cellRectFor(row: row, column: column)) - } - - private func setNeedsDisplay(screenCursor position: Position) { - self.setNeedsDisplay(position: position) - if self.grid.isNextCellEmpty(position) { - self.setNeedsDisplay(position: self.grid.nextCellPosition(position)) - } - } -} diff --git a/VimR.xcodeproj/project.pbxproj b/VimR.xcodeproj/project.pbxproj index 785d8912..1c76e195 100644 --- a/VimR.xcodeproj/project.pbxproj +++ b/VimR.xcodeproj/project.pbxproj @@ -35,7 +35,6 @@ 4B9A15241D2993DA009F9F67 /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B56F29B1D29926600C1F92E /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4B9A15251D2993DA009F9F67 /* Quick.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B56F29C1D29926600C1F92E /* Quick.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 4B9A15261D2993DF009F9F67 /* SwiftNeoVim.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B2A2BF71D0351810074CE9A /* SwiftNeoVim.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 4BC661D41D37F77500EE84F7 /* NeoVimViewMouseEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BC661D31D37F77500EE84F7 /* NeoVimViewMouseEvents.swift */; }; 4BCADE081D11ED12004DAD0F /* CocoaExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BCADE071D11ED12004DAD0F /* CocoaExtensions.swift */; }; 4BD3BF931D32A95800082605 /* MainWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3BF921D32A95800082605 /* MainWindowController.swift */; }; 4BD3BF971D32B0DB00082605 /* MainWindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3BF961D32B0DB00082605 /* MainWindowManager.swift */; }; @@ -59,10 +58,8 @@ 4BEBA50B1CFF374B00673FDF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BEBA50A1CFF374B00673FDF /* Assets.xcassets */; }; 4BEBA50E1CFF374B00673FDF /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4BEBA50C1CFF374B00673FDF /* MainMenu.xib */; }; 4BEBA5191CFF374B00673FDF /* VimRTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEBA5181CFF374B00673FDF /* VimRTests.swift */; }; - 4BEE79121D16D0AC0012EDAA /* NeoVimViewUiBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE79111D16D0AC0012EDAA /* NeoVimViewUiBridge.swift */; }; 4BEE79151D16D2100012EDAA /* DispatchUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE79141D16D2100012EDAA /* DispatchUtils.swift */; }; 4BEE79171D16D3800012EDAA /* CellAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEE79161D16D3800012EDAA /* CellAttributes.swift */; }; - 4BEF363D1D1EC045002A9898 /* NeoVimViewKeyEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BEF363C1D1EC045002A9898 /* NeoVimViewKeyEvents.swift */; }; 4BF6E29C1D34153C0053FA76 /* KeyUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BF6E29B1D34153C0053FA76 /* KeyUtils.swift */; }; /* End PBXBuildFile section */ @@ -173,7 +170,6 @@ 4B854A1A1D31447C00E08DE1 /* NeoVimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NeoVimServer; sourceTree = BUILT_PRODUCTS_DIR; }; 4B854A1C1D31447C00E08DE1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 4B97E2CD1D33F53D00FC0660 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainWindow.xib; sourceTree = ""; }; - 4BC661D31D37F77500EE84F7 /* NeoVimViewMouseEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimViewMouseEvents.swift; sourceTree = ""; }; 4BCADE071D11ED12004DAD0F /* CocoaExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CocoaExtensions.swift; sourceTree = ""; }; 4BCF638F1D323CFD00F15CE4 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = neovim/src/nvim; sourceTree = SOURCE_ROOT; }; 4BD3BF921D32A95800082605 /* MainWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowController.swift; sourceTree = ""; }; @@ -202,10 +198,8 @@ 4BEBA5181CFF374B00673FDF /* VimRTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VimRTests.swift; sourceTree = ""; }; 4BEBA51A1CFF374B00673FDF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4BEBA6621D00157A00673FDF /* runtime */ = {isa = PBXFileReference; lastKnownFileType = folder; name = runtime; path = neovim/runtime; sourceTree = SOURCE_ROOT; }; - 4BEE79111D16D0AC0012EDAA /* NeoVimViewUiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimViewUiBridge.swift; sourceTree = ""; }; 4BEE79141D16D2100012EDAA /* DispatchUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DispatchUtils.swift; sourceTree = ""; }; 4BEE79161D16D3800012EDAA /* CellAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellAttributes.swift; sourceTree = ""; }; - 4BEF363C1D1EC045002A9898 /* NeoVimViewKeyEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimViewKeyEvents.swift; sourceTree = ""; }; 4BF6E29B1D34153C0053FA76 /* KeyUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyUtils.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -409,9 +403,6 @@ isa = PBXGroup; children = ( 1929BF00B466B40629C2AABE /* NeoVimView.swift */, - 4BEF363C1D1EC045002A9898 /* NeoVimViewKeyEvents.swift */, - 4BC661D31D37F77500EE84F7 /* NeoVimViewMouseEvents.swift */, - 4BEE79111D16D0AC0012EDAA /* NeoVimViewUiBridge.swift */, 4B401B191D046E0600D99EDC /* NeoVimViewDelegate.swift */, 4B570DC01D303CAF006EDC21 /* NeoVimAgent.h */, 4B570DC11D303CAF006EDC21 /* NeoVimAgent.m */, @@ -647,13 +638,10 @@ 4B2A2C0F1D0353E30074CE9A /* NeoVim.swift in Sources */, 4B401B1A1D046E0600D99EDC /* NeoVimViewDelegate.swift in Sources */, 1929B728262BAA14FC93F6AC /* NeoVimView.swift in Sources */, - 4BEF363D1D1EC045002A9898 /* NeoVimViewKeyEvents.swift in Sources */, 4B570DC31D303CAF006EDC21 /* NeoVimAgent.m in Sources */, - 4BEE79121D16D0AC0012EDAA /* NeoVimViewUiBridge.swift in Sources */, 4BEE79151D16D2100012EDAA /* DispatchUtils.swift in Sources */, 4BDF641D1D0887C100D47E1D /* TextDrawer.m in Sources */, 4BDF64251D08CAB000D47E1D /* MMCoreTextView.m in Sources */, - 4BC661D41D37F77500EE84F7 /* NeoVimViewMouseEvents.swift in Sources */, 1929BEB90DCDAF7A2B68C886 /* ColorUtils.swift in Sources */, 4B4192181D0C52D700A0BEB2 /* Grid.swift in Sources */, );