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

GH-339 Restructure slightly

This commit is contained in:
Tae Won Ha 2017-01-06 10:16:55 +01:00
parent cd776791eb
commit fa82e30cc4
No known key found for this signature in database
GPG Key ID: E40743465B5B8B44
3 changed files with 114 additions and 166 deletions

View File

@ -9,13 +9,13 @@
#import "CocoaCategories.h"
#import "Wrapper.h"
// FileInfo and Boolean are #defined by Carbon and NeoVim: Since we don't need the Carbon versions of them, we rename
// them.
#define FileInfo CarbonFileInfo
#define Boolean CarbonBoolean
#import <nvim/vim.h>
#import <nvim/api/vim.h>
#import <nvim/main.h>
#import <nvim/ui.h>
// When #define'd you can execute the NeoVimServer binary and neovim will be started:
@ -40,7 +40,7 @@ data_to_array(NSInteger)
@interface NeoVimServer ()
- (NSCondition *)outputCondition;
- (NSData *)handleMessageWithId:(SInt32)msgid data:(NSData *)data;
- (void)handleQuitMsg;
@end
@ -76,8 +76,10 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
switch (msgid) {
case NeoVimAgentMsgIdAgentReady:
server_start_neovim();
return nil;
start_neovim();
return NULL;
case NeoVimAgentMsgIdQuit: [neoVimServer handleQuitMsg];
case NeoVimAgentMsgIdCommandOutput: return data_sync(data, outputCondition, neovim_vim_command_output);
@ -105,17 +107,9 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
case NeoVimAgentMsgIdDelete: return null_data_async(data, neovim_delete);
default: break;
default: return NULL;
}
NSData *responseData = [neoVimServer handleMessageWithId:msgid data:(__bridge NSData *) data];
if (responseData == nil) {
return NULL;
}
return CFDataCreateCopy(kCFAllocatorDefault, (__bridge CFDataRef) responseData);
}
}
@ -240,20 +234,12 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
}
- (void)quit {
server_quit();
quit_neovim();
}
- (NSData *)handleMessageWithId:(SInt32)msgid data:(NSData *)data {
switch (msgid) {
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];
return nil;
default:
return nil;
}
- (void)handleQuitMsg {
// 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];
}
@end

View File

@ -10,8 +10,8 @@
extern NeoVimServer *_neovim_server;
extern void server_start_neovim();
extern void server_quit();
extern void start_neovim();
extern void quit_neovim();
extern void neovim_select_window(void **argv);
extern void neovim_tabs(void **argv);

View File

@ -75,6 +75,7 @@ static NSString *_backspace = nil;
static dispatch_queue_t _queue;
#pragma mark Helper functions
static inline int screen_cursor_row() {
return curwin->w_winrow + curwin->w_wrow;
}
@ -95,6 +96,60 @@ static inline String vim_string_from(NSString *str) {
return (String) { .data = (char *) str.cstr, .size = str.clength };
}
static bool has_dirty_docs() {
FOR_ALL_BUFFERS(buffer) {
if (buffer->b_p_bl == 0) {
continue;
}
if (bufIsChanged(buffer)) {
return true;
}
}
return false;
}
static void send_dirty_status() {
bool new_dirty_status = has_dirty_docs();
DLOG("dirty status: %d vs. %d", _dirty, new_dirty_status);
if (_dirty == new_dirty_status) {
return;
}
_dirty = new_dirty_status;
DLOG("sending dirty status: %d", _dirty);
NSData *data = [[NSData alloc] initWithBytes:&_dirty length:sizeof(bool)];
[_neovim_server sendMessageWithId:NeoVimServerMsgIdDirtyStatusChanged data:data];
[data release];
}
static void insert_marked_text(NSString *markedText) {
_marked_text = [markedText retain]; // release when the final text is input in -vimInput
nvim_input(vim_string_from(markedText));
}
static void delete_marked_text() {
NSUInteger length = [_marked_text lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4;
[_marked_text release];
_marked_text = nil;
for (int i = 0; i < length; i++) {
nvim_input(vim_string_from(_backspace));
}
}
static void run_neovim(void *arg __unused) {
char *argv[1];
argv[0] = "nvim";
int returnCode = nvim_main(1, argv);
NSLog(@"neovim's main returned with code: %d\n", returnCode);
}
static void set_ui_size(UIBridgeData *bridge, int width, int height) {
bridge->ui->width = width;
bridge->ui->height = height;
@ -139,7 +194,6 @@ static void server_ui_main(UIBridgeData *bridge, UI *ui) {
}
#pragma mark NeoVim's UI callbacks
static void server_ui_resize(UI *ui __unused, int width, int height) {
queue(^{
int values[] = { width, height };
@ -405,62 +459,8 @@ static void server_ui_stop(UI *ui __unused) {
});
}
#pragma mark Helper functions
static bool has_dirty_docs() {
FOR_ALL_BUFFERS(buffer) {
if (buffer->b_p_bl == 0) {
continue;
}
if (bufIsChanged(buffer)) {
return true;
}
}
return false;
}
static void send_dirty_status() {
bool new_dirty_status = has_dirty_docs();
DLOG("dirty status: %d vs. %d", _dirty, new_dirty_status);
if (_dirty == new_dirty_status) {
return;
}
_dirty = new_dirty_status;
DLOG("sending dirty status: %d", _dirty);
NSData *data = [[NSData alloc] initWithBytes:&_dirty length:sizeof(bool)];
[_neovim_server sendMessageWithId:NeoVimServerMsgIdDirtyStatusChanged data:data];
[data release];
}
static void insert_marked_text(NSString *markedText) {
_marked_text = [markedText retain]; // release when the final text is input in -vimInput
nvim_input(vim_string_from(markedText));
}
static void delete_marked_text() {
NSUInteger length = [_marked_text lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4;
[_marked_text release];
_marked_text = nil;
for (int i = 0; i < length; i++) {
nvim_input(vim_string_from(_backspace));
}
}
static void run_neovim(void *arg __unused) {
char *argv[1];
argv[0] = "nvim";
int returnCode = nvim_main(1, argv);
NSLog(@"neovim's main returned with code: %d\n", returnCode);
}
#pragma mark Public
// called by neovim
void custom_ui_start(void) {
UI *ui = xcalloc(1, sizeof(UI));
@ -525,7 +525,8 @@ void custom_ui_autocmds_groups(
}
}
void server_start_neovim() {
#pragma mark Other help functions
void start_neovim() {
_queue = dispatch_queue_create("com.qvacua.vimr.neovim-server.queue", DISPATCH_QUEUE_SERIAL);
// set $VIMRUNTIME to ${RESOURCE_PATH_OF_XPC_BUNDLE}/runtime
@ -561,6 +562,46 @@ void server_start_neovim() {
[data release];
}
void quit_neovim() {
DLOG("NeoVimServer exiting...");
exit(0);
}
#pragma mark Functions for neovim's main loop
// already in an autorelease pool and in neovim's main loop
typedef NSData *(^work_block)(NSData *);
static void work_and_write_data_sync(void **argv, work_block block) {
NSCondition *outputCondition = argv[1];
[outputCondition lock];
NSData *data = argv[0];
Wrapper *wrapper = argv[2];
wrapper.data = block(data);
wrapper.dataReady = YES;
[data release]; // retained in local_server_callback
[outputCondition signal];
[outputCondition unlock];
}
static NSString *escaped_filename(NSString *filename) {
const char *file_system_rep = filename.fileSystemRepresentation;
char_u *escaped_filename = vim_strsave_fnameescape((char_u *) file_system_rep, 0);
NSString *result = [NSString stringWithCString:(const char *) escaped_filename encoding:NSUTF8StringEncoding];
xfree(escaped_filename);
return result;
}
static void work_async(void **argv, work_block block) {
NSData *data = argv[0];
block(data);
[data release]; // retained in local_server_callback
}
static NeoVimBuffer *buffer_for(buf_T *buf) {
// To be sure...
if (buf == NULL) {
@ -587,85 +628,6 @@ static NeoVimBuffer *buffer_for(buf_T *buf) {
return [buffer autorelease];
}
NSArray *server_buffers() {
NSMutableArray <NeoVimBuffer *> *result = [[NSMutableArray new] autorelease];
FOR_ALL_BUFFERS(buf) {
NeoVimBuffer *buffer = buffer_for(buf);
if (buffer == nil) {
continue;
}
[result addObject:buffer];
}
return result;
}
NSArray *server_tabs() {
NSMutableArray *tabs = [[NSMutableArray new] autorelease];
FOR_ALL_TABS(t) {
NSMutableArray *windows = [NSMutableArray new];
FOR_ALL_WINDOWS_IN_TAB(win, t) {
NeoVimBuffer *buffer = buffer_for(win->w_buffer);
if (buffer == nil) {
continue;
}
NeoVimWindow *window = [[NeoVimWindow alloc] initWithHandle:win->handle buffer:buffer];
[windows addObject:window];
[window release];
}
NeoVimTab *tab = [[NeoVimTab alloc] initWithHandle:t->handle windows:windows];
[windows release];
[tabs addObject:tab];
[tab release];
}
return tabs;
}
void server_quit() {
DLOG("NeoVimServer exiting...");
exit(0);
}
typedef NSData *(^work_block)(NSData *);
static void work_and_write_data_sync(void **argv, work_block block) {
NSCondition *outputCondition = argv[1];
[outputCondition lock];
NSData *data = argv[0];
Wrapper *wrapper = argv[2];
wrapper.data = block(data);
wrapper.dataReady = YES;
[data release]; // retained in local_server_callback
[outputCondition signal];
[outputCondition unlock];
}
#pragma mark Functions for neovim's main loop
// already in an autorelease pool and in neovim's main loop
static NSString *escaped_filename(NSString *filename) {
const char *file_system_rep = filename.fileSystemRepresentation;
char_u *escaped_filename = vim_strsave_fnameescape((char_u *) file_system_rep, 0);
NSString *result = [NSString stringWithCString:(const char *) escaped_filename encoding:NSUTF8StringEncoding];
xfree(escaped_filename);
return result;
}
static void work_async(void **argv, work_block block) {
NSData *data = argv[0];
block(data);
[data release]; // retained in local_server_callback
}
void neovim_select_window(void **argv) {
work_async(argv, ^NSData *(NSData *data) {
int handle = ((int *) data.bytes)[0];
@ -715,7 +677,7 @@ void neovim_tabs(void **argv) {
[tab release];
}
WLOG("tabs: %s", tabs.description.cstr);
DLOG("tabs: %s", tabs.description.cstr);
return [NSKeyedArchiver archivedDataWithRootObject:tabs];
});
}
@ -732,7 +694,7 @@ void neovim_buffers(void **argv) {
[buffers addObject:buffer];
}
WLOG("buffers: %s", buffers.description.cstr);
DLOG("buffers: %s", buffers.description.cstr);
return [NSKeyedArchiver archivedDataWithRootObject:buffers];
});
}