1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-25 23:02:35 +03:00

GH-339 Migrate input methods

This commit is contained in:
Tae Won Ha 2017-01-06 10:06:47 +01:00
parent 2b91b32e9b
commit cd776791eb
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
3 changed files with 99 additions and 108 deletions

View File

@ -99,6 +99,12 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
case NeoVimAgentMsgIdCommand: return null_data_async(data, neovim_vim_command);
case NeoVimAgentMsgIdInput: return null_data_async(data, neovim_vim_input);
case NeoVimAgentMsgIdInputMarked: return null_data_async(data, neovim_vim_input_marked_text);
case NeoVimAgentMsgIdDelete: return null_data_async(data, neovim_delete);
default: break;
}
@ -240,26 +246,6 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
- (NSData *)handleMessageWithId:(SInt32)msgid data:(NSData *)data {
switch (msgid) {
case NeoVimAgentMsgIdInput: {
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
server_vim_input(string);
return nil;
}
case NeoVimAgentMsgIdInputMarked: {
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
server_vim_input_marked_text(string);
return nil;
}
case NeoVimAgentMsgIdDelete: {
NSInteger *values = data_to_NSInteger_array(data, 1);
server_delete(values[0]);
return nil;
}
case NeoVimAgentMsgIdQuit:
// exit() after returning the response such that the agent can get the response and so does not log a warning.
[self performSelector:@selector(quit) onThread:_localServerThread withObject:nil waitUntilDone:NO];

View File

@ -11,9 +11,6 @@
extern NeoVimServer *_neovim_server;
extern void server_start_neovim();
extern void server_vim_input(NSString *input);
extern void server_delete(NSInteger count);
extern void server_vim_input_marked_text(NSString *markedText);
extern void server_quit();
extern void neovim_select_window(void **argv);
@ -26,3 +23,7 @@ extern void neovim_escaped_filenames(void **argv);
extern void neovim_has_dirty_docs(void **argv);
extern void neovim_resize(void **argv);
extern void neovim_vim_command(void **argv);
extern void neovim_vim_input(void **argv);
extern void neovim_vim_input_marked_text(void **argv);
extern void neovim_delete(void **argv);

View File

@ -406,17 +406,6 @@ static void server_ui_stop(UI *ui __unused) {
}
#pragma mark Helper functions
static void neovim_input(void **argv) {
@autoreleasepool {
NSString *input = (NSString *) argv[0];
// FIXME: check the length of the consumed bytes by neovim and if not fully consumed, call vim_input again.
nvim_input(vim_string_from(input));
[input release]; // retained in loop_schedule(&main_loop, ...) (in _queue) somewhere
}
}
static bool has_dirty_docs() {
FOR_ALL_BUFFERS(buffer) {
if (buffer->b_p_bl == 0) {
@ -448,7 +437,7 @@ static void send_dirty_status() {
static void insert_marked_text(NSString *markedText) {
_marked_text = [markedText retain]; // release when the final text is input in -vimInput
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [_marked_text retain])); // release in neovim_input
nvim_input(vim_string_from(markedText));
}
static void delete_marked_text() {
@ -458,7 +447,7 @@ static void delete_marked_text() {
_marked_text = nil;
for (int i = 0; i < length; i++) {
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [_backspace retain])); // release in neovim_input
nvim_input(vim_string_from(_backspace));
}
}
@ -572,78 +561,6 @@ void server_start_neovim() {
[data release];
}
void server_delete(NSInteger count) {
queue(^{
_marked_delta = 0;
// Very ugly: When we want to have the Hanja for , Cocoa first finalizes , then sets the Hanja as marked text.
// The main app will call this method when this happens, thus compute how many cell we have to go backward to
// correctly mark the will-be-soon-inserted Hanja... See also docs/notes-on-cocoa-text-input.md
int emptyCounter = 0;
for (int i = 0; i < count; i++) {
_marked_delta -= 1;
// TODO: -1 because we assume that the cursor is one cell ahead, probably not always correct...
schar_T character = ScreenLines[_put_row * screen_Rows + _put_column - i - emptyCounter - 1];
if (character == 0x00 || character == ' ') {
// FIXME: dunno yet, why we have to also match ' '...
_marked_delta -= 1;
emptyCounter += 1;
}
}
DLOG("put cursor: %d:%d, count: %li, delta: %d", _put_row, _put_column, count, _marked_delta);
for (int i = 0; i < count; i++) {
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [_backspace retain])); // release in neovim_input
}
});
}
void server_vim_input(NSString *input) {
queue(^{
if (_marked_text == nil) {
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [input retain])); // release in neovim_input
return;
}
// Handle cases like -> arrow key: The previously marked text is the same as the finalized text which should
// 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 ([_marked_text isEqualToString:input]) {
DLOG("unmarking text: '%s'\t now at %d:%d", input.cstr, _put_row, _put_column);
const char *str = _marked_text.cstr;
size_t cellCount = mb_string2cells((const char_u *) str);
for (int i = 1; i <= cellCount; i++) {
DLOG("unmarking at %d:%d", _put_row, _put_column - i);
int values[] = { _put_row, MAX(_put_column - i, 0) };
NSData *data = [[NSData alloc] initWithBytes:values length:(2 * sizeof(int))];
[_neovim_server sendMessageWithId:NeoVimServerMsgIdUnmark data:data];
[data release];
}
}
delete_marked_text();
loop_schedule(&main_loop, event_create(1, neovim_input, 1, [input retain])); // release in neovim_input
});
}
void server_vim_input_marked_text(NSString *markedText) {
queue(^{
if (_marked_text == nil) {
_marked_row = _put_row;
_marked_column = _put_column + _marked_delta;
DLOG("marking position: %d:%d(%d + %d)", _put_row, _marked_column, _put_column, _marked_delta);
_marked_delta = 0;
} else {
delete_marked_text();
}
DLOG("inserting marked text '%s' at %d:%d", markedText.cstr, _put_row, _put_column);
insert_marked_text(markedText);
});
}
static NeoVimBuffer *buffer_for(buf_T *buf) {
// To be sure...
if (buf == NULL) {
@ -958,3 +875,90 @@ void neovim_vim_command(void **argv) {
return nil;
});
}
void neovim_vim_input(void **argv) {
work_async(argv, ^NSData *(NSData *data) {
NSString *input = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
if (_marked_text == nil) {
nvim_input(vim_string_from(input));
return nil;
}
// Handle cases like -> arrow key: The previously marked text is the same as the finalized text which should
// 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 ([_marked_text isEqualToString:input]) {
DLOG("unmarking text: '%s'\t now at %d:%d", input.cstr, _put_row, _put_column);
const char *str = _marked_text.cstr;
size_t cellCount = mb_string2cells((const char_u *) str);
for (int i = 1; i <= cellCount; i++) {
DLOG("unmarking at %d:%d", _put_row, _put_column - i);
int values[] = {_put_row, MAX(_put_column - i, 0)};
NSData *unmarkData = [[NSData alloc] initWithBytes:values length:(2 * sizeof(int))];
[_neovim_server sendMessageWithId:NeoVimServerMsgIdUnmark data:unmarkData];
[unmarkData release];
}
}
delete_marked_text();
nvim_input(vim_string_from(input));
return nil;
});
}
void neovim_vim_input_marked_text(void **argv) {
work_async(argv, ^NSData *(NSData *data) {
NSString *markedText = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
if (_marked_text == nil) {
_marked_row = _put_row;
_marked_column = _put_column + _marked_delta;
DLOG("marking position: %d:%d(%d + %d)", _put_row, _marked_column, _put_column, _marked_delta);
_marked_delta = 0;
} else {
delete_marked_text();
}
DLOG("inserting marked text '%s' at %d:%d", markedText.cstr, _put_row, _put_column);
insert_marked_text(markedText);
return nil;
});
}
void neovim_delete(void **argv) {
work_async(argv, ^NSData *(NSData *data) {
NSInteger *values = data.bytes;
NSInteger count = values[0];
_marked_delta = 0;
// Very ugly: When we want to have the Hanja for , Cocoa first finalizes , then sets the Hanja as marked text.
// The main app will call this method when this happens, thus compute how many cell we have to go backward to
// correctly mark the will-be-soon-inserted Hanja... See also docs/notes-on-cocoa-text-input.md
int emptyCounter = 0;
for (int i = 0; i < count; i++) {
_marked_delta -= 1;
// TODO: -1 because we assume that the cursor is one cell ahead, probably not always correct...
schar_T character = ScreenLines[_put_row * screen_Rows + _put_column - i - emptyCounter - 1];
if (character == 0x00 || character == ' ') {
// FIXME: dunno yet, why we have to also match ' '...
_marked_delta -= 1;
emptyCounter += 1;
}
}
DLOG("put cursor: %d:%d, count: %li, delta: %d", _put_row, _put_column, count, _marked_delta);
for (int i = 0; i < count; i++) {
nvim_input(vim_string_from(_backspace));
}
return nil;
});
}