mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-24 03:25:03 +03:00
Make hanja menu pop up
- Very rudimentary: since we don't use the replacement range when setting marked text, the original hangul character won't be replaced. - We probably should use a different mechanism for returning attributed string: e.g. ask neovim to return the correct string...
This commit is contained in:
parent
5a8fdbe9bc
commit
1d1c46c3fc
@ -48,14 +48,20 @@ static uv_cond_t _condition;
|
||||
|
||||
static id <NeoVimUiBridgeProtocol> _neo_vim_osx_ui;
|
||||
|
||||
static int _row = 0;
|
||||
static int _column = 0;
|
||||
static int _markedRow = 0;
|
||||
static int _markedColumn = 0;
|
||||
static NSString *_markedText = nil;
|
||||
|
||||
static dispatch_queue_t _queue;
|
||||
|
||||
static inline int cursorRow() {
|
||||
return curwin->w_winrow + curwin->w_wrow;
|
||||
}
|
||||
|
||||
static inline int cursorColumn() {
|
||||
return curwin->w_wincol + curwin->w_wcol;
|
||||
}
|
||||
|
||||
static void xpc_async(void (^block)()) {
|
||||
dispatch_async(_queue, block);
|
||||
}
|
||||
@ -145,9 +151,6 @@ static void xpc_ui_eol_clear(UI *ui __unused) {
|
||||
static void xpc_ui_cursor_goto(UI *ui __unused, int row, int col) {
|
||||
xpc_async(^{
|
||||
//printf("cursor goto %d:%d\n", row, col);
|
||||
_row = row;
|
||||
_column = col;
|
||||
|
||||
[_neo_vim_osx_ui cursorGotoRow:row column:col];
|
||||
});
|
||||
}
|
||||
@ -243,15 +246,14 @@ static void xpc_ui_put(UI *ui __unused, uint8_t *str, size_t len) {
|
||||
NSString *string = [[NSString alloc] initWithBytes:str length:len encoding:NSUTF8StringEncoding];
|
||||
// printf("put: %lu:'%s'\n", len, [string cStringUsingEncoding:NSUTF8StringEncoding]);
|
||||
|
||||
if (_markedText != nil && _markedColumn == _column && _markedRow == _row) {
|
||||
if (_markedText != nil && _markedColumn == cursorColumn() && _markedRow == cursorRow()) {
|
||||
[_neo_vim_osx_ui putMarkedText:string];
|
||||
} else if (_markedText != nil && len == 0 && _markedColumn == _column - 1) {
|
||||
} else if (_markedText != nil && len == 0 && _markedColumn == cursorColumn() - 1) {
|
||||
[_neo_vim_osx_ui putMarkedText:string];
|
||||
} else {
|
||||
[_neo_vim_osx_ui put:string];
|
||||
}
|
||||
|
||||
_column += 1;
|
||||
[string release];
|
||||
});
|
||||
}
|
||||
@ -458,6 +460,7 @@ static void neovim_input(void **argv) {
|
||||
}
|
||||
|
||||
- (void)vimInput:(NSString *_Nonnull)input {
|
||||
|
||||
xpc_async(^{
|
||||
if (_markedText == nil) {
|
||||
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [input retain])); // release in neovim_input
|
||||
@ -468,9 +471,9 @@ static void neovim_input(void **argv) {
|
||||
// inserted. Neovim's drawing code is optimized such that it does not call put in this case again, thus, we
|
||||
// have to manually unmark the cells in the main app.
|
||||
if ([_markedText isEqualToString:input]) {
|
||||
[_neo_vim_osx_ui unmarkRow:_row column:MAX(_column - 1, 0)];
|
||||
if (ScreenLines[_row * screen_Columns + MAX(_column - 1, 0)] == 0x00) {
|
||||
[_neo_vim_osx_ui unmarkRow:_row column:MAX(_column - 2, 0)];
|
||||
[_neo_vim_osx_ui unmarkRow:cursorRow() column:MAX(cursorColumn() - 1, 0)];
|
||||
if (ScreenLines[cursorRow() * screen_Columns + MAX(cursorColumn() - 1, 0)] == 0x00) {
|
||||
[_neo_vim_osx_ui unmarkRow:cursorRow() column:MAX(cursorColumn() - 2, 0)];
|
||||
}
|
||||
}
|
||||
|
||||
@ -490,8 +493,8 @@ static void neovim_input(void **argv) {
|
||||
}
|
||||
|
||||
- (void)insertMarkedText:(NSString *_Nonnull)markedText {
|
||||
_markedRow = _row;
|
||||
_markedColumn = _column;
|
||||
_markedRow = cursorRow();
|
||||
_markedColumn = cursorColumn();
|
||||
_markedText = [markedText retain]; // release when the final text is input in -vimInput
|
||||
|
||||
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [_markedText retain])); // release in neovim_input
|
||||
|
@ -29,6 +29,7 @@ struct Cell: CustomStringConvertible {
|
||||
struct Position: CustomStringConvertible {
|
||||
|
||||
static let zero = Position(row: 0, column: 0)
|
||||
static let null = Position(row: -1, column: -1)
|
||||
|
||||
var row: Int
|
||||
var column: Int
|
||||
@ -175,21 +176,45 @@ class Grid: CustomStringConvertible {
|
||||
}
|
||||
|
||||
func unmarkCell(position: Position) {
|
||||
print("!!!!! unmarking: \(position)")
|
||||
// NSLog("\(#function): \(position)")
|
||||
self.cells[position.row][position.column].marked = false
|
||||
}
|
||||
|
||||
func isNextCellEmpty(position: Position) -> Bool {
|
||||
if self.cells[position.row][min(position.column + 1, self.size.width - 1)].string.characters.count == 0 {
|
||||
func singleIndexFrom(position: Position) -> Int {
|
||||
return position.row * self.size.width + position.column
|
||||
}
|
||||
|
||||
func positionFromSingleIndex(idx: Int) -> Position {
|
||||
let row = Int(floor(Double(idx) / Double(self.size.width)))
|
||||
let column = idx - row * self.size.width
|
||||
|
||||
return Position(row: row, column: column)
|
||||
}
|
||||
|
||||
func isCellEmpty(position: Position) -> Bool {
|
||||
if self.cells[position.row][position.column].string.characters.count == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func isPreviousCellEmpty(position: Position) -> Bool {
|
||||
return self.isCellEmpty(Position(row: position.row, column: max(position.column - 1, 0)))
|
||||
}
|
||||
|
||||
func isNextCellEmpty(position: Position) -> Bool {
|
||||
return self.isCellEmpty(Position(row: position.row, column: min(position.column + 1, self.size.width - 1)))
|
||||
}
|
||||
|
||||
func nextCellPosition(position: Position) -> Position {
|
||||
return Position(row: position.row, column: min(position.column + 1, self.size.width - 1))
|
||||
}
|
||||
|
||||
func cellForSingleIndex(idx: Int) -> Cell {
|
||||
let position = self.positionFromSingleIndex(idx)
|
||||
return self.cells[position.row][position.column]
|
||||
}
|
||||
|
||||
private func clearRegion(region: Region) {
|
||||
// FIXME: sometimes clearRegion gets called without first resizing the Grid. Should we handle this?
|
||||
|
@ -16,125 +16,17 @@ public class InputTestView: NSView, NSTextInputClient {
|
||||
*/
|
||||
public func insertText(aString: AnyObject, replacementRange: NSRange) {
|
||||
Swift.print("\(#function): \(aString), \(replacementRange)")
|
||||
|
||||
self.vimInput(String(aString))
|
||||
self.markedText = nil
|
||||
}
|
||||
|
||||
/* The receiver invokes the action specified by aSelector.
|
||||
*/
|
||||
public override func doCommandBySelector(aSelector: Selector) {
|
||||
self.handledBySelector = true
|
||||
Swift.print("\(#function): \(aSelector)")
|
||||
if aSelector == NSSelectorFromString("noop:") {
|
||||
self.handledBySelector = false
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
public func moveForward(sender: AnyObject?)
|
||||
public func moveRight(sender: AnyObject?)
|
||||
public func moveBackward(sender: AnyObject?)
|
||||
public func moveLeft(sender: AnyObject?)
|
||||
public func moveUp(sender: AnyObject?)
|
||||
public func moveDown(sender: AnyObject?)
|
||||
public func moveWordForward(sender: AnyObject?)
|
||||
public func moveWordBackward(sender: AnyObject?)
|
||||
public func moveToBeginningOfLine(sender: AnyObject?)
|
||||
public func moveToEndOfLine(sender: AnyObject?)
|
||||
public func moveToBeginningOfParagraph(sender: AnyObject?)
|
||||
public func moveToEndOfParagraph(sender: AnyObject?)
|
||||
public func moveToEndOfDocument(sender: AnyObject?)
|
||||
public func moveToBeginningOfDocument(sender: AnyObject?)
|
||||
public func pageDown(sender: AnyObject?)
|
||||
public func pageUp(sender: AnyObject?)
|
||||
public func centerSelectionInVisibleArea(sender: AnyObject?)
|
||||
|
||||
public func moveBackwardAndModifySelection(sender: AnyObject?)
|
||||
public func moveForwardAndModifySelection(sender: AnyObject?)
|
||||
public func moveWordForwardAndModifySelection(sender: AnyObject?)
|
||||
public func moveWordBackwardAndModifySelection(sender: AnyObject?)
|
||||
public func moveUpAndModifySelection(sender: AnyObject?)
|
||||
public func moveDownAndModifySelection(sender: AnyObject?)
|
||||
|
||||
public func moveToBeginningOfLineAndModifySelection(sender: AnyObject?)
|
||||
public func moveToEndOfLineAndModifySelection(sender: AnyObject?)
|
||||
public func moveToBeginningOfParagraphAndModifySelection(sender: AnyObject?)
|
||||
public func moveToEndOfParagraphAndModifySelection(sender: AnyObject?)
|
||||
public func moveToEndOfDocumentAndModifySelection(sender: AnyObject?)
|
||||
public func moveToBeginningOfDocumentAndModifySelection(sender: AnyObject?)
|
||||
public func pageDownAndModifySelection(sender: AnyObject?)
|
||||
public func pageUpAndModifySelection(sender: AnyObject?)
|
||||
public func moveParagraphForwardAndModifySelection(sender: AnyObject?)
|
||||
public func moveParagraphBackwardAndModifySelection(sender: AnyObject?)
|
||||
|
||||
public func moveWordRight(sender: AnyObject?)
|
||||
public func moveWordLeft(sender: AnyObject?)
|
||||
public func moveRightAndModifySelection(sender: AnyObject?)
|
||||
public func moveLeftAndModifySelection(sender: AnyObject?)
|
||||
public func moveWordRightAndModifySelection(sender: AnyObject?)
|
||||
public func moveWordLeftAndModifySelection(sender: AnyObject?)
|
||||
|
||||
public func moveToLeftEndOfLine(sender: AnyObject?)
|
||||
public func moveToRightEndOfLine(sender: AnyObject?)
|
||||
public func moveToLeftEndOfLineAndModifySelection(sender: AnyObject?)
|
||||
public func moveToRightEndOfLineAndModifySelection(sender: AnyObject?)
|
||||
|
||||
public func scrollPageUp(sender: AnyObject?)
|
||||
public func scrollPageDown(sender: AnyObject?)
|
||||
public func scrollLineUp(sender: AnyObject?)
|
||||
public func scrollLineDown(sender: AnyObject?)
|
||||
|
||||
public func scrollToBeginningOfDocument(sender: AnyObject?)
|
||||
public func scrollToEndOfDocument(sender: AnyObject?)
|
||||
|
||||
public func transpose(sender: AnyObject?)
|
||||
public func transposeWords(sender: AnyObject?)
|
||||
|
||||
public func selectAll(sender: AnyObject?)
|
||||
public func selectParagraph(sender: AnyObject?)
|
||||
public func selectLine(sender: AnyObject?)
|
||||
public func selectWord(sender: AnyObject?)
|
||||
|
||||
public func indent(sender: AnyObject?)
|
||||
public func insertTab(sender: AnyObject?)
|
||||
public func insertBacktab(sender: AnyObject?)
|
||||
public func insertNewline(sender: AnyObject?)
|
||||
public func insertParagraphSeparator(sender: AnyObject?)
|
||||
public func insertNewlineIgnoringFieldEditor(sender: AnyObject?)
|
||||
public func insertTabIgnoringFieldEditor(sender: AnyObject?)
|
||||
public func insertLineBreak(sender: AnyObject?)
|
||||
public func insertContainerBreak(sender: AnyObject?)
|
||||
public func insertSingleQuoteIgnoringSubstitution(sender: AnyObject?)
|
||||
public func insertDoubleQuoteIgnoringSubstitution(sender: AnyObject?)
|
||||
|
||||
public func changeCaseOfLetter(sender: AnyObject?)
|
||||
public func uppercaseWord(sender: AnyObject?)
|
||||
public func lowercaseWord(sender: AnyObject?)
|
||||
public func capitalizeWord(sender: AnyObject?)
|
||||
|
||||
public func deleteForward(sender: AnyObject?)
|
||||
public func deleteBackward(sender: AnyObject?)
|
||||
public func deleteBackwardByDecomposingPreviousCharacter(sender: AnyObject?)
|
||||
public func deleteWordForward(sender: AnyObject?)
|
||||
public func deleteWordBackward(sender: AnyObject?)
|
||||
public func deleteToBeginningOfLine(sender: AnyObject?)
|
||||
public func deleteToEndOfLine(sender: AnyObject?)
|
||||
public func deleteToBeginningOfParagraph(sender: AnyObject?)
|
||||
public func deleteToEndOfParagraph(sender: AnyObject?)
|
||||
|
||||
public func yank(sender: AnyObject?)
|
||||
|
||||
public func complete(sender: AnyObject?)
|
||||
|
||||
public func setMark(sender: AnyObject?)
|
||||
public func deleteToMark(sender: AnyObject?)
|
||||
public func selectToMark(sender: AnyObject?)
|
||||
public func swapWithMark(sender: AnyObject?)
|
||||
|
||||
public func cancelOperation(sender: AnyObject?)
|
||||
*/
|
||||
}
|
||||
|
||||
/* The receiver inserts aString replacing the content specified by replacementRange. aString can be either an NSString or NSAttributedString instance. selectedRange specifies the selection inside the string being inserted; hence, the location is relative to the beginning of aString. When aString is an NSString, the receiver is expected to render the marked text with distinguishing appearance (i.e. NSTextView renders with -markedTextAttributes).
|
||||
@ -162,13 +54,13 @@ public class InputTestView: NSView, NSTextInputClient {
|
||||
/* Returns the marked range. Returns {NSNotFound, 0} if no marked range.
|
||||
*/
|
||||
public func markedRange() -> NSRange {
|
||||
Swift.print("\(#function): ")
|
||||
|
||||
if let markedText = self.markedText {
|
||||
return NSRange(location: self.text.characters.count, length: markedText.characters.count)
|
||||
Swift.print("\(#function): returning \(NSRange(location: 0, length: 1))")
|
||||
return NSRange(location: 0, length: 1)
|
||||
}
|
||||
|
||||
return NSRange(location: NSNotFound, length: 1)
|
||||
|
||||
Swift.print("\(#function): returning \(NSRange(location: NSNotFound, length: 0))")
|
||||
return NSRange(location: NSNotFound, length: 0)
|
||||
}
|
||||
|
||||
/* Returns whether or not the receiver has marked text.
|
||||
@ -182,7 +74,7 @@ public class InputTestView: NSView, NSTextInputClient {
|
||||
/* Returns attributed string specified by aRange. It may return nil. If non-nil return value and actualRange is non-NULL, it contains the actual range for the return value. The range can be adjusted from various reasons (i.e. adjust to grapheme cluster boundary, performance optimization, etc).
|
||||
*/
|
||||
public func attributedSubstringForProposedRange(aRange: NSRange, actualRange: NSRangePointer) -> NSAttributedString? {
|
||||
Swift.print("\(#function): \(aRange), \(actualRange)")
|
||||
Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||
return NSAttributedString(string: "하")
|
||||
}
|
||||
|
||||
@ -197,11 +89,12 @@ public class InputTestView: NSView, NSTextInputClient {
|
||||
*/
|
||||
public func firstRectForCharacterRange(aRange: NSRange, actualRange: NSRangePointer) -> NSRect {
|
||||
if actualRange != nil {
|
||||
Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||
// Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||
} else {
|
||||
Swift.print("\(#function): \(aRange), nil")
|
||||
// Swift.print("\(#function): \(aRange), nil")
|
||||
}
|
||||
|
||||
Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||
|
||||
let resultInSelf = NSRect(x: 0, y: 0, width: 10, height: 10)
|
||||
let result = self.window?.convertRectToScreen(self.convertRect(resultInSelf, toView: nil))
|
||||
|
||||
@ -243,15 +136,15 @@ public class InputTestView: NSView, NSTextInputClient {
|
||||
let charsIgnoringModifiers = shift || capslock ? theEvent.charactersIgnoringModifiers!.lowercaseString
|
||||
: theEvent.charactersIgnoringModifiers!
|
||||
|
||||
Swift.print("characters: \(chars)")// = " + String(format:"%x", theEvent.characters!.unicodeScalars.first!.value))
|
||||
Swift.print("characters ign: \(charsIgnoringModifiers)")// = " + String(format:"%x", theEvent.charactersIgnoringModifiers!.unicodeScalars.first!.value))
|
||||
// Swift.print("characters: \(chars)")// = " + String(format:"%x", theEvent.characters!.unicodeScalars.first!.value))
|
||||
// Swift.print("characters ign: \(charsIgnoringModifiers)")// = " + String(format:"%x", theEvent.charactersIgnoringModifiers!.unicodeScalars.first!.value))
|
||||
// Swift.print(String(format: "keycode: %x", theEvent.keyCode))
|
||||
Swift.print("shift: \(shift), command: \(command), control: \(control), option: \(option)")
|
||||
// Swift.print("shift: \(shift), command: \(command), control: \(control), option: \(option)")
|
||||
|
||||
let inputContext = NSTextInputContext.currentInputContext()!
|
||||
let handled = inputContext.handleEvent(theEvent)
|
||||
if handled {
|
||||
Swift.print("Cocoa handled it")
|
||||
// Swift.print("Cocoa handled it")
|
||||
}
|
||||
|
||||
// self.text += theEvent.charactersIgnoringModifiers!
|
||||
@ -264,6 +157,6 @@ public class InputTestView: NSView, NSTextInputClient {
|
||||
}
|
||||
|
||||
private func vimInput(string: String) {
|
||||
Swift.print("### vim input: \(string)")
|
||||
// Swift.print("### vim input: \(string)")
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,11 @@ public class NeoVimView: NSView {
|
||||
let xpc: NeoVimXpc
|
||||
|
||||
var markedText: String?
|
||||
var markedPosition = Position.null {
|
||||
didSet {
|
||||
// Swift.print("\(self.markedPosition)")
|
||||
}
|
||||
}
|
||||
var keyDownDone = true
|
||||
|
||||
var cellSize = CGSize.zero
|
||||
|
@ -32,6 +32,181 @@ extension NeoVimView: NSTextInputClient {
|
||||
|
||||
self.keyDownDone = true
|
||||
}
|
||||
|
||||
public func insertText(aString: AnyObject, replacementRange: NSRange) {
|
||||
NSLog("\(#function): \(replacementRange): \(aString)")
|
||||
|
||||
switch aString {
|
||||
case let string as String:
|
||||
self.xpc.vimInput(self.vimPlainString(string))
|
||||
case let attributedString as NSAttributedString:
|
||||
self.xpc.vimInput(self.vimPlainString(attributedString.string))
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// unmarkText()
|
||||
self.markedText = nil
|
||||
self.markedPosition = Position.null
|
||||
// TODO: necessary?
|
||||
self.setNeedsDisplayInRect(self.cellRect(row: self.grid.position.row, column: self.grid.position.column))
|
||||
self.keyDownDone = true
|
||||
}
|
||||
|
||||
public override func doCommandBySelector(aSelector: Selector) {
|
||||
// NSLog("\(#function): "\(aSelector)")
|
||||
|
||||
// TODO: 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.position
|
||||
}
|
||||
|
||||
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.xpc.vimInputMarkedText(self.markedText!)
|
||||
self.keyDownDone = true
|
||||
}
|
||||
|
||||
public func unmarkText() {
|
||||
NSLog("\(#function): ")
|
||||
self.markedText = nil
|
||||
self.markedPosition = Position.null
|
||||
// TODO: necessary?
|
||||
self.setNeedsDisplayInRect(self.cellRect(row: self.grid.position.row, column: self.grid.position.column))
|
||||
self.keyDownDone = true
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
// if self.markedText == nil {
|
||||
// let result = NSRange(location: self.grid.singleIndexFrom(self.grid.position), length: 0)
|
||||
// NSLog("\(#function): \(result)")
|
||||
// return result
|
||||
// }
|
||||
|
||||
// FIXME: do we have to handle positions at the column borders?
|
||||
if self.grid.isPreviousCellEmpty(self.grid.position) {
|
||||
let result = NSRange(
|
||||
location: self.grid.singleIndexFrom(
|
||||
Position(row: self.grid.position.row, column: self.grid.position.column - 1)
|
||||
),
|
||||
length: 0
|
||||
)
|
||||
NSLog("\(#function): \(result)")
|
||||
return result
|
||||
}
|
||||
|
||||
let result = NSRange(location: self.grid.singleIndexFrom(self.grid.position), 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 {
|
||||
let result = self.markedText != nil
|
||||
// NSLog("\(#function): "returning \(result)")
|
||||
return result
|
||||
}
|
||||
|
||||
// FIXME: REFACTOR and take into account the "return nil"-case
|
||||
public func attributedSubstringForProposedRange(aRange: NSRange, actualRange: NSRangePointer) -> NSAttributedString? {
|
||||
// NSLog("\(#function): \(aRange), \(actualRange[0])")
|
||||
|
||||
// first check whether the first cell is empty and if so, jump one character backward
|
||||
var length = aRange.length
|
||||
var location = aRange.location
|
||||
var position = self.grid.positionFromSingleIndex(aRange.location)
|
||||
if self.grid.isCellEmpty(position) {
|
||||
length += 1
|
||||
location -= 1
|
||||
position = self.grid.positionFromSingleIndex(location)
|
||||
}
|
||||
|
||||
// check whether the range extend to multiple lines
|
||||
let multipleLines = position.column + length >= self.grid.size.width
|
||||
|
||||
if !multipleLines {
|
||||
// FIXME: do we have to handle position.column + aRange.length >= self.grid.width?
|
||||
let string = self.grid.cells[position.row][position.column...(position.column + length)].reduce("") {
|
||||
$0 + $1.string
|
||||
}
|
||||
actualRange[0].length = string.characters.count
|
||||
NSLog("\(#function): \(aRange), \(actualRange[0]): \(string)")
|
||||
return NSAttributedString(string: string)
|
||||
}
|
||||
|
||||
// TODO: maybe make Grid a Indexable or similar
|
||||
var string = ""
|
||||
for i in location...(location + length) {
|
||||
string += self.grid.cellForSingleIndex(i).string
|
||||
}
|
||||
NSLog("\(#function): \(aRange), \(actualRange[0]): \(string)")
|
||||
return NSAttributedString(string: string)
|
||||
}
|
||||
|
||||
public func validAttributesForMarkedText() -> [String] {
|
||||
// Swift.print("\(#function): ")
|
||||
return []
|
||||
}
|
||||
|
||||
public func firstRectForCharacterRange(aRange: NSRange, actualRange: NSRangePointer) -> NSRect {
|
||||
NSLog("\(#function): \(aRange), \(actualRange[0])")
|
||||
if actualRange != nil {
|
||||
Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||
} else {
|
||||
Swift.print("\(#function): \(aRange), nil")
|
||||
}
|
||||
|
||||
let row = Int(floor(Double(aRange.location / self.grid.size.width)))
|
||||
let column = aRange.location - row * self.grid.size.width
|
||||
|
||||
let resultInSelf = self.cellRect(row: row, column: 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 = ""
|
||||
@ -55,114 +230,6 @@ extension NeoVimView: NSTextInputClient {
|
||||
return result
|
||||
}
|
||||
|
||||
public func insertText(aString: AnyObject, replacementRange: NSRange) {
|
||||
// Swift.print("\(#function): \(aString), \(replacementRange)")
|
||||
|
||||
switch aString {
|
||||
case let string as String:
|
||||
self.xpc.vimInput(self.vimPlainString(string))
|
||||
case let attributedString as NSAttributedString:
|
||||
self.xpc.vimInput(self.vimPlainString(attributedString.string))
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
self.markedText = nil
|
||||
self.keyDownDone = true
|
||||
}
|
||||
|
||||
public override func doCommandBySelector(aSelector: Selector) {
|
||||
Swift.print("\(#function): \(aSelector)")
|
||||
|
||||
// TODO: handle when ㅎ -> delete
|
||||
|
||||
if self.respondsToSelector(aSelector) {
|
||||
Swift.print("\(#function): calling \(aSelector)")
|
||||
self.performSelector(aSelector, withObject: self)
|
||||
self.keyDownDone = true
|
||||
return
|
||||
}
|
||||
|
||||
Swift.print("\(#function): \(aSelector) not implemented, forwarding input to vim")
|
||||
self.keyDownDone = false
|
||||
}
|
||||
|
||||
public func setMarkedText(aString: AnyObject, selectedRange: NSRange, replacementRange: NSRange) {
|
||||
Swift.print("\(#function): \(aString), \(selectedRange), \(replacementRange)")
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
self.xpc.vimInputMarkedText(self.markedText!)
|
||||
self.keyDownDone = true
|
||||
}
|
||||
|
||||
public func unmarkText() {
|
||||
Swift.print("\(#function): ")
|
||||
self.markedText = nil
|
||||
self.setNeedsDisplayInRect(self.cellRect(row: self.grid.position.row, column: self.grid.position.column))
|
||||
self.keyDownDone = true
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
let result = NSRange(location: 13, length: 0)
|
||||
Swift.print("\(#function): returning \(result)")
|
||||
return result
|
||||
}
|
||||
|
||||
public func markedRange() -> NSRange {
|
||||
Swift.print("\(#function): ")
|
||||
|
||||
if let markedText = self.markedText {
|
||||
// return NSRange(location: self.text.characters.count, length: markedText.characters.count)
|
||||
}
|
||||
|
||||
return NSRange(location: NSNotFound, length: 0)
|
||||
}
|
||||
|
||||
public func hasMarkedText() -> Bool {
|
||||
let result = self.markedText != nil
|
||||
// Swift.print("\(#function): returning \(result)")
|
||||
return result
|
||||
}
|
||||
|
||||
public func attributedSubstringForProposedRange(aRange: NSRange, actualRange: NSRangePointer) -> NSAttributedString? {
|
||||
Swift.print("\(#function): \(aRange), \(actualRange)")
|
||||
return NSAttributedString(string: "t")
|
||||
}
|
||||
|
||||
public func validAttributesForMarkedText() -> [String] {
|
||||
// Swift.print("\(#function): ")
|
||||
return []
|
||||
}
|
||||
|
||||
public func firstRectForCharacterRange(aRange: NSRange, actualRange: NSRangePointer) -> NSRect {
|
||||
if actualRange != nil {
|
||||
Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||
} else {
|
||||
Swift.print("\(#function): \(aRange), nil")
|
||||
}
|
||||
|
||||
let resultInSelf = NSRect(x: 0, y: 0, width: 10, height: 10)
|
||||
let result = self.window?.convertRectToScreen(self.convertRect(resultInSelf, toView: nil))
|
||||
|
||||
return result!
|
||||
}
|
||||
|
||||
public func characterIndexForPoint(aPoint: NSPoint) -> Int {
|
||||
Swift.print("\(#function): \(aPoint)")
|
||||
return 1
|
||||
}
|
||||
|
||||
/*
|
||||
public func moveWordForward(sender: AnyObject?)
|
||||
public func moveWordBackward(sender: AnyObject?)
|
||||
|
@ -14,7 +14,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
height: CGFloat(height) * self.cellSize.height
|
||||
)
|
||||
|
||||
Swift.print("### resize to \(width):\(height)")
|
||||
// Swift.print("### resize to \(width):\(height)")
|
||||
self.grid.resize(Size(width: Int(width), height: Int(height)))
|
||||
self.delegate?.resizeToSize(rectSize)
|
||||
}
|
||||
@ -22,7 +22,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
|
||||
public func clear() {
|
||||
DispatchUtils.gui {
|
||||
Swift.print("### clear")
|
||||
// Swift.print("### clear")
|
||||
self.grid.clear()
|
||||
self.needsDisplay = true
|
||||
}
|
||||
@ -30,7 +30,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
|
||||
public func eolClear() {
|
||||
DispatchUtils.gui {
|
||||
Swift.print("### eol clear")
|
||||
// Swift.print("### eol clear")
|
||||
self.grid.eolClear()
|
||||
|
||||
let origin = self.positionOnView(self.grid.position.row, column: self.grid.position.column)
|
||||
@ -45,10 +45,10 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
|
||||
public func cursorGotoRow(row: Int32, column: Int32) {
|
||||
DispatchUtils.gui {
|
||||
Swift.print("### goto: \(row):\(column)")
|
||||
self.setCursorNeedsDisplay()
|
||||
NSLog("\(#function): \(row):\(column)")
|
||||
self.setCursorNeedsDisplay(self.grid.position)
|
||||
self.grid.goto(Position(row: Int(row), column: Int(column)))
|
||||
self.setCursorNeedsDisplay()
|
||||
self.setCursorNeedsDisplay(self.grid.position)
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,11 +73,11 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
}
|
||||
|
||||
public func modeChange(mode: Int32) {
|
||||
Swift.print("### mode change to: \(String(format: "%04X", mode))")
|
||||
// Swift.print("### mode change to: \(String(format: "%04X", mode))")
|
||||
}
|
||||
|
||||
public func setScrollRegionToTop(top: Int32, bottom: Int32, left: Int32, right: Int32) {
|
||||
Swift.print("### set scroll region: \(top), \(bottom), \(left), \(right)")
|
||||
// Swift.print("### set scroll region: \(top), \(bottom), \(left), \(right)")
|
||||
DispatchUtils.gui {
|
||||
let region = Region(top: Int(top), bottom: Int(bottom), left: Int(left), right: Int(right))
|
||||
self.grid.setScrollRegion(region)
|
||||
@ -86,7 +86,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
}
|
||||
|
||||
public func scroll(count: Int32) {
|
||||
Swift.print("### scroll count: \(count)")
|
||||
// Swift.print("### scroll count: \(count)")
|
||||
|
||||
DispatchUtils.gui {
|
||||
self.grid.scroll(Int(count))
|
||||
@ -112,15 +112,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
if string.characters.count == 0 {
|
||||
self.setNeedsDisplayAt(row: curPos.row, column: max(curPos.column - 1, 0))
|
||||
}
|
||||
self.setCursorNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
private func setCursorNeedsDisplay() {
|
||||
let position = self.grid.position
|
||||
self.setNeedsDisplayAt(position: position)
|
||||
if self.grid.isNextCellEmpty(position) {
|
||||
self.setNeedsDisplayAt(position: self.grid.nextCellPosition(position))
|
||||
self.setCursorNeedsDisplay(self.grid.position)
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,7 +126,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
if markedText.characters.count == 0 {
|
||||
self.setNeedsDisplayAt(row: curPos.row, column: max(curPos.column - 1, 0))
|
||||
}
|
||||
self.setCursorNeedsDisplay()
|
||||
self.setCursorNeedsDisplay(self.grid.position)
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +135,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
// Swift.print("\(#function): \(row):\(column)")
|
||||
self.grid.unmarkCell(Position(row: Int(row), column: Int(column)))
|
||||
self.setNeedsDisplayAt(row: Int(row), column: Int(column))
|
||||
self.setCursorNeedsDisplay()
|
||||
self.setCursorNeedsDisplay(self.grid.position)
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,7 +189,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
Swift.print("### stop")
|
||||
// Swift.print("### stop")
|
||||
}
|
||||
|
||||
private func setNeedsDisplayAt(position position: Position) {
|
||||
@ -208,4 +200,11 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
// Swift.print("\(#function): \(row):\(column)")
|
||||
self.setNeedsDisplayInRect(self.cellRect(row: row, column: column))
|
||||
}
|
||||
|
||||
private func setCursorNeedsDisplay(position: Position) {
|
||||
self.setNeedsDisplayAt(position: position)
|
||||
if self.grid.isNextCellEmpty(position) {
|
||||
self.setNeedsDisplayAt(position: self.grid.nextCellPosition(position))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user