mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-24 11:37:32 +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 id <NeoVimUiBridgeProtocol> _neo_vim_osx_ui;
|
||||||
|
|
||||||
static int _row = 0;
|
|
||||||
static int _column = 0;
|
|
||||||
static int _markedRow = 0;
|
static int _markedRow = 0;
|
||||||
static int _markedColumn = 0;
|
static int _markedColumn = 0;
|
||||||
static NSString *_markedText = nil;
|
static NSString *_markedText = nil;
|
||||||
|
|
||||||
static dispatch_queue_t _queue;
|
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)()) {
|
static void xpc_async(void (^block)()) {
|
||||||
dispatch_async(_queue, 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) {
|
static void xpc_ui_cursor_goto(UI *ui __unused, int row, int col) {
|
||||||
xpc_async(^{
|
xpc_async(^{
|
||||||
//printf("cursor goto %d:%d\n", row, col);
|
//printf("cursor goto %d:%d\n", row, col);
|
||||||
_row = row;
|
|
||||||
_column = col;
|
|
||||||
|
|
||||||
[_neo_vim_osx_ui cursorGotoRow: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];
|
NSString *string = [[NSString alloc] initWithBytes:str length:len encoding:NSUTF8StringEncoding];
|
||||||
// printf("put: %lu:'%s'\n", len, [string cStringUsingEncoding: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];
|
[_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];
|
[_neo_vim_osx_ui putMarkedText:string];
|
||||||
} else {
|
} else {
|
||||||
[_neo_vim_osx_ui put:string];
|
[_neo_vim_osx_ui put:string];
|
||||||
}
|
}
|
||||||
|
|
||||||
_column += 1;
|
|
||||||
[string release];
|
[string release];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -458,6 +460,7 @@ static void neovim_input(void **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)vimInput:(NSString *_Nonnull)input {
|
- (void)vimInput:(NSString *_Nonnull)input {
|
||||||
|
|
||||||
xpc_async(^{
|
xpc_async(^{
|
||||||
if (_markedText == nil) {
|
if (_markedText == nil) {
|
||||||
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [input retain])); // release in neovim_input
|
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
|
// 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.
|
// have to manually unmark the cells in the main app.
|
||||||
if ([_markedText isEqualToString:input]) {
|
if ([_markedText isEqualToString:input]) {
|
||||||
[_neo_vim_osx_ui unmarkRow:_row column:MAX(_column - 1, 0)];
|
[_neo_vim_osx_ui unmarkRow:cursorRow() column:MAX(cursorColumn() - 1, 0)];
|
||||||
if (ScreenLines[_row * screen_Columns + MAX(_column - 1, 0)] == 0x00) {
|
if (ScreenLines[cursorRow() * screen_Columns + MAX(cursorColumn() - 1, 0)] == 0x00) {
|
||||||
[_neo_vim_osx_ui unmarkRow:_row column:MAX(_column - 2, 0)];
|
[_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 {
|
- (void)insertMarkedText:(NSString *_Nonnull)markedText {
|
||||||
_markedRow = _row;
|
_markedRow = cursorRow();
|
||||||
_markedColumn = _column;
|
_markedColumn = cursorColumn();
|
||||||
_markedText = [markedText retain]; // release when the final text is input in -vimInput
|
_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
|
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 {
|
struct Position: CustomStringConvertible {
|
||||||
|
|
||||||
static let zero = Position(row: 0, column: 0)
|
static let zero = Position(row: 0, column: 0)
|
||||||
|
static let null = Position(row: -1, column: -1)
|
||||||
|
|
||||||
var row: Int
|
var row: Int
|
||||||
var column: Int
|
var column: Int
|
||||||
@ -175,22 +176,46 @@ class Grid: CustomStringConvertible {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func unmarkCell(position: Position) {
|
func unmarkCell(position: Position) {
|
||||||
print("!!!!! unmarking: \(position)")
|
// NSLog("\(#function): \(position)")
|
||||||
self.cells[position.row][position.column].marked = false
|
self.cells[position.row][position.column].marked = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func isNextCellEmpty(position: Position) -> Bool {
|
func singleIndexFrom(position: Position) -> Int {
|
||||||
if self.cells[position.row][min(position.column + 1, self.size.width - 1)].string.characters.count == 0 {
|
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 true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
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 {
|
func nextCellPosition(position: Position) -> Position {
|
||||||
return Position(row: position.row, column: min(position.column + 1, self.size.width - 1))
|
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) {
|
private func clearRegion(region: Region) {
|
||||||
// FIXME: sometimes clearRegion gets called without first resizing the Grid. Should we handle this?
|
// FIXME: sometimes clearRegion gets called without first resizing the Grid. Should we handle this?
|
||||||
guard self.hasData else {
|
guard self.hasData else {
|
||||||
|
@ -16,125 +16,17 @@ public class InputTestView: NSView, NSTextInputClient {
|
|||||||
*/
|
*/
|
||||||
public func insertText(aString: AnyObject, replacementRange: NSRange) {
|
public func insertText(aString: AnyObject, replacementRange: NSRange) {
|
||||||
Swift.print("\(#function): \(aString), \(replacementRange)")
|
Swift.print("\(#function): \(aString), \(replacementRange)")
|
||||||
|
|
||||||
self.vimInput(String(aString))
|
|
||||||
self.markedText = nil
|
self.markedText = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The receiver invokes the action specified by aSelector.
|
/* The receiver invokes the action specified by aSelector.
|
||||||
*/
|
*/
|
||||||
public override func doCommandBySelector(aSelector: Selector) {
|
public override func doCommandBySelector(aSelector: Selector) {
|
||||||
self.handledBySelector = true
|
|
||||||
Swift.print("\(#function): \(aSelector)")
|
Swift.print("\(#function): \(aSelector)")
|
||||||
if aSelector == NSSelectorFromString("noop:") {
|
if aSelector == NSSelectorFromString("noop:") {
|
||||||
self.handledBySelector = false
|
self.handledBySelector = false
|
||||||
return
|
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).
|
/* 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.
|
/* Returns the marked range. Returns {NSNotFound, 0} if no marked range.
|
||||||
*/
|
*/
|
||||||
public func markedRange() -> NSRange {
|
public func markedRange() -> NSRange {
|
||||||
Swift.print("\(#function): ")
|
|
||||||
|
|
||||||
if let markedText = self.markedText {
|
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.
|
/* 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).
|
/* 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? {
|
public func attributedSubstringForProposedRange(aRange: NSRange, actualRange: NSRangePointer) -> NSAttributedString? {
|
||||||
Swift.print("\(#function): \(aRange), \(actualRange)")
|
Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||||
return NSAttributedString(string: "하")
|
return NSAttributedString(string: "하")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,10 +89,11 @@ public class InputTestView: NSView, NSTextInputClient {
|
|||||||
*/
|
*/
|
||||||
public func firstRectForCharacterRange(aRange: NSRange, actualRange: NSRangePointer) -> NSRect {
|
public func firstRectForCharacterRange(aRange: NSRange, actualRange: NSRangePointer) -> NSRect {
|
||||||
if actualRange != nil {
|
if actualRange != nil {
|
||||||
Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
// Swift.print("\(#function): \(aRange), \(actualRange[0])")
|
||||||
} else {
|
} 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 resultInSelf = NSRect(x: 0, y: 0, width: 10, height: 10)
|
||||||
let result = self.window?.convertRectToScreen(self.convertRect(resultInSelf, toView: nil))
|
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
|
let charsIgnoringModifiers = shift || capslock ? theEvent.charactersIgnoringModifiers!.lowercaseString
|
||||||
: theEvent.charactersIgnoringModifiers!
|
: theEvent.charactersIgnoringModifiers!
|
||||||
|
|
||||||
Swift.print("characters: \(chars)")// = " + String(format:"%x", theEvent.characters!.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("characters ign: \(charsIgnoringModifiers)")// = " + String(format:"%x", theEvent.charactersIgnoringModifiers!.unicodeScalars.first!.value))
|
||||||
// Swift.print(String(format: "keycode: %x", theEvent.keyCode))
|
// 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 inputContext = NSTextInputContext.currentInputContext()!
|
||||||
let handled = inputContext.handleEvent(theEvent)
|
let handled = inputContext.handleEvent(theEvent)
|
||||||
if handled {
|
if handled {
|
||||||
Swift.print("Cocoa handled it")
|
// Swift.print("Cocoa handled it")
|
||||||
}
|
}
|
||||||
|
|
||||||
// self.text += theEvent.charactersIgnoringModifiers!
|
// self.text += theEvent.charactersIgnoringModifiers!
|
||||||
@ -264,6 +157,6 @@ public class InputTestView: NSView, NSTextInputClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func vimInput(string: String) {
|
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
|
let xpc: NeoVimXpc
|
||||||
|
|
||||||
var markedText: String?
|
var markedText: String?
|
||||||
|
var markedPosition = Position.null {
|
||||||
|
didSet {
|
||||||
|
// Swift.print("\(self.markedPosition)")
|
||||||
|
}
|
||||||
|
}
|
||||||
var keyDownDone = true
|
var keyDownDone = true
|
||||||
|
|
||||||
var cellSize = CGSize.zero
|
var cellSize = CGSize.zero
|
||||||
|
@ -33,6 +33,181 @@ extension NeoVimView: NSTextInputClient {
|
|||||||
self.keyDownDone = true
|
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 {
|
private func vimModifierFlags(modifierFlags: NSEventModifierFlags) -> String {
|
||||||
var result = ""
|
var result = ""
|
||||||
|
|
||||||
@ -55,114 +230,6 @@ extension NeoVimView: NSTextInputClient {
|
|||||||
return result
|
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 moveWordForward(sender: AnyObject?)
|
||||||
public func moveWordBackward(sender: AnyObject?)
|
public func moveWordBackward(sender: AnyObject?)
|
||||||
|
@ -14,7 +14,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
|||||||
height: CGFloat(height) * self.cellSize.height
|
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.grid.resize(Size(width: Int(width), height: Int(height)))
|
||||||
self.delegate?.resizeToSize(rectSize)
|
self.delegate?.resizeToSize(rectSize)
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
|||||||
|
|
||||||
public func clear() {
|
public func clear() {
|
||||||
DispatchUtils.gui {
|
DispatchUtils.gui {
|
||||||
Swift.print("### clear")
|
// Swift.print("### clear")
|
||||||
self.grid.clear()
|
self.grid.clear()
|
||||||
self.needsDisplay = true
|
self.needsDisplay = true
|
||||||
}
|
}
|
||||||
@ -30,7 +30,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
|||||||
|
|
||||||
public func eolClear() {
|
public func eolClear() {
|
||||||
DispatchUtils.gui {
|
DispatchUtils.gui {
|
||||||
Swift.print("### eol clear")
|
// Swift.print("### eol clear")
|
||||||
self.grid.eolClear()
|
self.grid.eolClear()
|
||||||
|
|
||||||
let origin = self.positionOnView(self.grid.position.row, column: self.grid.position.column)
|
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) {
|
public func cursorGotoRow(row: Int32, column: Int32) {
|
||||||
DispatchUtils.gui {
|
DispatchUtils.gui {
|
||||||
Swift.print("### goto: \(row):\(column)")
|
NSLog("\(#function): \(row):\(column)")
|
||||||
self.setCursorNeedsDisplay()
|
self.setCursorNeedsDisplay(self.grid.position)
|
||||||
self.grid.goto(Position(row: Int(row), column: Int(column)))
|
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) {
|
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) {
|
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 {
|
DispatchUtils.gui {
|
||||||
let region = Region(top: Int(top), bottom: Int(bottom), left: Int(left), right: Int(right))
|
let region = Region(top: Int(top), bottom: Int(bottom), left: Int(left), right: Int(right))
|
||||||
self.grid.setScrollRegion(region)
|
self.grid.setScrollRegion(region)
|
||||||
@ -86,7 +86,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func scroll(count: Int32) {
|
public func scroll(count: Int32) {
|
||||||
Swift.print("### scroll count: \(count)")
|
// Swift.print("### scroll count: \(count)")
|
||||||
|
|
||||||
DispatchUtils.gui {
|
DispatchUtils.gui {
|
||||||
self.grid.scroll(Int(count))
|
self.grid.scroll(Int(count))
|
||||||
@ -112,15 +112,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
|||||||
if string.characters.count == 0 {
|
if string.characters.count == 0 {
|
||||||
self.setNeedsDisplayAt(row: curPos.row, column: max(curPos.column - 1, 0))
|
self.setNeedsDisplayAt(row: curPos.row, column: max(curPos.column - 1, 0))
|
||||||
}
|
}
|
||||||
self.setCursorNeedsDisplay()
|
self.setCursorNeedsDisplay(self.grid.position)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func setCursorNeedsDisplay() {
|
|
||||||
let position = self.grid.position
|
|
||||||
self.setNeedsDisplayAt(position: position)
|
|
||||||
if self.grid.isNextCellEmpty(position) {
|
|
||||||
self.setNeedsDisplayAt(position: self.grid.nextCellPosition(position))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +126,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
|||||||
if markedText.characters.count == 0 {
|
if markedText.characters.count == 0 {
|
||||||
self.setNeedsDisplayAt(row: curPos.row, column: max(curPos.column - 1, 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)")
|
// Swift.print("\(#function): \(row):\(column)")
|
||||||
self.grid.unmarkCell(Position(row: Int(row), column: Int(column)))
|
self.grid.unmarkCell(Position(row: Int(row), column: Int(column)))
|
||||||
self.setNeedsDisplayAt(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() {
|
public func stop() {
|
||||||
Swift.print("### stop")
|
// Swift.print("### stop")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setNeedsDisplayAt(position position: Position) {
|
private func setNeedsDisplayAt(position position: Position) {
|
||||||
@ -208,4 +200,11 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
|||||||
// Swift.print("\(#function): \(row):\(column)")
|
// Swift.print("\(#function): \(row):\(column)")
|
||||||
self.setNeedsDisplayInRect(self.cellRect(row: row, column: 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