diff --git a/NeoVimServer/CocoaCategories.h b/NeoVimServer/CocoaCategories.h index e55226d8..482b1f9a 100644 --- a/NeoVimServer/CocoaCategories.h +++ b/NeoVimServer/CocoaCategories.h @@ -15,5 +15,6 @@ @interface NSString (NeoVimServer) @property (readonly, nonnull) const char *cstr; +@property (readonly) NSUInteger clength; @end diff --git a/NeoVimServer/CocoaCategories.m b/NeoVimServer/CocoaCategories.m index 5ecf4f44..42b45f41 100644 --- a/NeoVimServer/CocoaCategories.m +++ b/NeoVimServer/CocoaCategories.m @@ -19,4 +19,8 @@ return [self cStringUsingEncoding:NSUTF8StringEncoding]; } +- (NSUInteger)clength { + return [self lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; +} + @end diff --git a/NeoVimServer/NeoVimMsgIds.h b/NeoVimServer/NeoVimMsgIds.h index a0215634..8ea74d56 100644 --- a/NeoVimServer/NeoVimMsgIds.h +++ b/NeoVimServer/NeoVimMsgIds.h @@ -59,6 +59,9 @@ typedef NS_ENUM(NSUInteger, NeoVimAgentMsgId) { NeoVimAgentMsgIdGetBuffers, NeoVimAgentMsgIdGetTabs, + NeoVimAgentMsgIdGetBoolOption, + NeoVimAgentMsgIdSetBoolOption, + #ifdef DEBUG NeoVimAgentDebug1, #endif diff --git a/NeoVimServer/NeoVimServer.m b/NeoVimServer/NeoVimServer.m index c63214c4..69e94d32 100644 --- a/NeoVimServer/NeoVimServer.m +++ b/NeoVimServer/NeoVimServer.m @@ -251,6 +251,20 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD return [NSKeyedArchiver archivedDataWithRootObject:server_tabs()]; } + case NeoVimAgentMsgIdGetBoolOption: { + NSString *optionName = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + return [NSKeyedArchiver archivedDataWithRootObject:server_get_bool_option(optionName)]; + } + + case NeoVimAgentMsgIdSetBoolOption: { + bool *values = (bool *) data.bytes; + const char *string = (const char *)(values + 1); + NSString *optionName = [[NSString alloc] initWithCString:string encoding:NSUTF8StringEncoding]; + + server_set_bool_option(optionName, values[0]); + return nil; + } + default: return nil; } diff --git a/NeoVimServer/server_globals.h b/NeoVimServer/server_globals.h index 31eecda5..2f1ed92e 100644 --- a/NeoVimServer/server_globals.h +++ b/NeoVimServer/server_globals.h @@ -21,5 +21,7 @@ extern bool server_has_dirty_docs(); extern NSString *server_escaped_filename(NSString *filename); extern NSArray *server_buffers(); extern NSArray *server_tabs(); +extern id server_get_bool_option(NSString *option); +extern void server_set_bool_option(NSString *option, bool value); extern void server_select_win(int window_handle); extern void server_quit(); diff --git a/NeoVimServer/server_ui.m b/NeoVimServer/server_ui.m index 7be9c3c4..f3dd091b 100644 --- a/NeoVimServer/server_ui.m +++ b/NeoVimServer/server_ui.m @@ -90,6 +90,10 @@ static inline void queue(void (^block)()) { }); } +static inline String vim_string_from(NSString *str) { + return (String) { .data = (char *) str.cstr, .size = str.clength }; +} + static void set_ui_size(UIBridgeData *bridge, int width, int height) { bridge->ui->width = width; bridge->ui->height = height; @@ -411,10 +415,7 @@ static void neovim_command(void **argv) { NSString *input = (NSString *) argv[0]; Error err; - nvim_command((String) { - .data = (char *) input.cstr, - .size = [input lengthOfBytesUsingEncoding:NSUTF8StringEncoding] - }, &err); + nvim_command(vim_string_from(input), &err); // FIXME: handle err.set == true @@ -436,10 +437,7 @@ static void neovim_command_output(void **argv) { // .size = [input lengthOfBytesUsingEncoding:NSUTF8StringEncoding] // }, &err); do_cmdline_cmd("redir => v:command_output"); - nvim_command((String) { - .data = (char *) input.cstr, - .size = [input lengthOfBytesUsingEncoding:NSUTF8StringEncoding] - }, &err); + nvim_command(vim_string_from(input), &err); do_cmdline_cmd("redir END"); char_u *output = get_vim_var_str(VV_COMMAND_OUTPUT); @@ -462,10 +460,7 @@ static void neovim_input(void **argv) { 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((String) { - .data = (char *) input.cstr, - .size = [input lengthOfBytesUsingEncoding:NSUTF8StringEncoding] - }); + nvim_input(vim_string_from(input)); [input release]; // retained in loop_schedule(&main_loop, ...) (in _queue) somewhere } @@ -802,6 +797,38 @@ void server_select_win(int window_handle) { } } +id server_get_bool_option(NSString *option) { + Error err; + Object result = nvim_get_option(vim_string_from(option), &err); + + if (err.set) { + WLOG("Error getting the option '%s': %s", option.cstr, err.msg); + return NSNull.null; + } + + switch (result.type) { + case kObjectTypeBoolean: + return [@(result.data.boolean) autorelease]; + default: + WLOG("The result type was %d, not a boolean value for '%s'", result.type, option.cstr); + return NSNull.null; + } +} + +void server_set_bool_option(NSString *option, bool value) { + Error err; + + Object object = OBJECT_INIT; + object.type = kObjectTypeBoolean; + object.data.boolean = value; + + nvim_set_option(vim_string_from(option), object, &err); + + if (err.set) { + WLOG("Error setting the option '%s' to %d: %s", option.cstr, value, err.msg); + } +} + void server_quit() { DLOG("NeoVimServer exiting..."); exit(0); diff --git a/SwiftNeoVim/NeoVimAgent.h b/SwiftNeoVim/NeoVimAgent.h index a05b15da..9ca4d65b 100644 --- a/SwiftNeoVim/NeoVimAgent.h +++ b/SwiftNeoVim/NeoVimAgent.h @@ -38,6 +38,8 @@ NS_ASSUME_NONNULL_BEGIN - (NSArray *)escapedFileNames:(NSArray *)fileNames; - (NSArray *)buffers; - (NSArray *)tabs; +- (bool)boolOption:(NSString *)option; +- (void)setBoolOption:(NSString *)option to:(bool)value; - (void)selectWindow:(NeoVimWindow *)window; @end diff --git a/SwiftNeoVim/NeoVimAgent.m b/SwiftNeoVim/NeoVimAgent.m index b679eba3..e154c4fe 100644 --- a/SwiftNeoVim/NeoVimAgent.m +++ b/SwiftNeoVim/NeoVimAgent.m @@ -225,6 +225,31 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD return [self escapedFileNames:@[ fileName ]][0]; } +- (bool)boolOption:(NSString *)option { + NSData *data = [option dataUsingEncoding:NSUTF8StringEncoding]; + NSData *response = [self sendMessageWithId:NeoVimAgentMsgIdGetBoolOption data:data expectsReply:YES]; + id object = [NSKeyedUnarchiver unarchiveObjectWithData:response]; + + if ([object isKindOfClass:[NSNumber class]]) { + return ((NSNumber *) object).boolValue; + } + + return NO; +} + +- (void)setBoolOption:(NSString *)option to:(bool)value { + NSMutableData *data = [NSMutableData new]; + + bool values[] = { value }; + const char *cstr = [option cStringUsingEncoding:NSUTF8StringEncoding]; + NSUInteger clength = [option lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; + + [data appendBytes:values length:sizeof(bool)]; + [data appendBytes:cstr length:clength + 1]; + + [self sendMessageWithId:NeoVimAgentMsgIdSetBoolOption data:data expectsReply:YES]; +} + - (void)selectWindow:(NeoVimWindow *)window { int values[] = { (int) window.handle }; NSData *data = [[NSData alloc] initWithBytes:values length:sizeof(int)]; diff --git a/SwiftNeoVim/NeoVimView.swift b/SwiftNeoVim/NeoVimView.swift index f5f416ba..927d0fc6 100644 --- a/SwiftNeoVim/NeoVimView.swift +++ b/SwiftNeoVim/NeoVimView.swift @@ -200,8 +200,7 @@ public class NeoVimView: NSView, NSUserInterfaceValidations { @IBAction public func debug1(_ sender: AnyObject!) { NSLog("DEBUG 1 - Start") - let buffers = self.agent.tabs().map { $0.allBuffers() }.flatMap { $0 } - NSLog("\(Set(buffers))") + self.agent.setBoolOption("paste", to: true) NSLog("DEBUG 1 - End") }