mirror of
https://github.com/qvacua/vimr.git
synced 2024-12-25 06:43:24 +03:00
Make NvimServer (only) a CoreFoundation exe
This commit is contained in:
parent
b5282a89a8
commit
9912e538ac
@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface NSObject (NeoVimServer)
|
||||
|
||||
@property (readonly, nonnull) const char *cdesc;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSString (NeoVimServer)
|
||||
|
||||
@property (readonly, nonnull) const char *cstr;
|
||||
@property (readonly) NSUInteger clength;
|
||||
|
||||
@end
|
@ -1,18 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import "CocoaCategories.h"
|
||||
|
||||
@implementation NSString (NeoVimServer)
|
||||
|
||||
- (const char *)cstr {
|
||||
return [self cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
- (NSUInteger)clength {
|
||||
return [self lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
@end
|
@ -1,9 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <os/log.h>
|
||||
|
||||
extern os_log_t logger;
|
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "SharedTypes.h"
|
||||
|
||||
|
||||
@interface NvimServer : NSObject
|
||||
|
||||
- (instancetype)initWithLocalServerName:(NSString *)localServerName
|
||||
remoteServerName:(NSString *)remoteServerName
|
||||
nvimArgs:(NSArray<NSString *> *)nvimArgs;
|
||||
|
||||
- (void)sendMessageWithId:(NvimServerMsgId)msgid;
|
||||
|
||||
- (void)sendMessageWithId:(NvimServerMsgId)msgid data:(CFDataRef)data;
|
||||
- (void)notifyReadiness;
|
||||
|
||||
@end
|
@ -1,222 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import "NvimServer.h"
|
||||
#import "server_ui.h"
|
||||
#import "Logging.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/main.h>
|
||||
|
||||
|
||||
// When #define'd you can execute the NvimServer binary
|
||||
// and neovim will be started:
|
||||
// $ ./NvimServer local remote
|
||||
#undef DEBUG_NEOVIM_SERVER_STANDALONE
|
||||
//#define DEBUG_NEOVIM_SERVER_STANDALONE
|
||||
|
||||
|
||||
static const double qTimeout = 5;
|
||||
|
||||
|
||||
@interface NvimServer ()
|
||||
|
||||
- (NSArray<NSString *> *)nvimArgs;
|
||||
|
||||
@end
|
||||
|
||||
static CFDataRef data_async(CFDataRef data, argv_callback cb) {
|
||||
loop_schedule(&main_loop, event_create(cb, 3, data));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static CFDataRef local_server_callback(
|
||||
CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info
|
||||
) {
|
||||
// release in the loop callbacks!
|
||||
// (or in the case clause when not passed to the callback)
|
||||
CFRetain(data);
|
||||
|
||||
switch (msgid) {
|
||||
|
||||
case NvimBridgeMsgIdAgentReady: {
|
||||
@autoreleasepool {
|
||||
const NSInteger *const values = (NSInteger *) CFDataGetBytePtr(data);
|
||||
NvimServer *const nvimServer = (__bridge NvimServer *) info;
|
||||
|
||||
start_neovim(values[0], values[1], nvimServer.nvimArgs);
|
||||
|
||||
CFRelease(data);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
case NvimBridgeMsgIdScroll:
|
||||
return data_async(data, neovim_scroll);
|
||||
|
||||
case NvimBridgeMsgIdResize:
|
||||
return data_async(data, neovim_resize);
|
||||
|
||||
case NvimBridgeMsgIdDeleteInput:
|
||||
return data_async(data, neovim_delete_and_input);
|
||||
|
||||
case NvimBridgeMsgIdFocusGained:
|
||||
return data_async(data, neovim_focus_gained);
|
||||
|
||||
case NvimBridgeMsgIdReadyForRpcEvents:
|
||||
return data_async(data, neovim_ready_for_rpcevents);
|
||||
|
||||
default:
|
||||
CFRelease(data);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@implementation NvimServer {
|
||||
NSString *_localServerName;
|
||||
NSString *_remoteServerName;
|
||||
NSArray<NSString *> *_nvimArgs;
|
||||
|
||||
CFMessagePortRef _remoteServerPort;
|
||||
|
||||
NSThread *_localServerThread;
|
||||
CFMessagePortRef _localServerPort;
|
||||
CFRunLoopRef _localServerRunLoop;
|
||||
}
|
||||
|
||||
- (NSArray<NSString *> *)nvimArgs {
|
||||
return _nvimArgs;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLocalServerName:(NSString *)localServerName
|
||||
remoteServerName:(NSString *)remoteServerName
|
||||
nvimArgs:(NSArray<NSString *> *)nvimArgs {
|
||||
|
||||
self = [super init];
|
||||
if (self == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_localServerName = localServerName;
|
||||
_remoteServerName = remoteServerName;
|
||||
_nvimArgs = nvimArgs;
|
||||
|
||||
_localServerThread = [
|
||||
[NSThread alloc] initWithTarget:self
|
||||
selector:@selector(runLocalServer)
|
||||
object:nil
|
||||
];
|
||||
_localServerThread.name = localServerName;
|
||||
[_localServerThread start];
|
||||
|
||||
#ifndef DEBUG_NEOVIM_SERVER_STANDALONE
|
||||
_remoteServerPort = CFMessagePortCreateRemote(
|
||||
kCFAllocatorDefault,
|
||||
(__bridge CFStringRef) _remoteServerName
|
||||
);
|
||||
#endif
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (CFMessagePortIsValid(_remoteServerPort)) {
|
||||
CFMessagePortInvalidate(_remoteServerPort);
|
||||
}
|
||||
CFRelease(_remoteServerPort);
|
||||
|
||||
if (CFMessagePortIsValid(_localServerPort)) {
|
||||
CFMessagePortInvalidate(_localServerPort);
|
||||
}
|
||||
CFRelease(_localServerPort);
|
||||
|
||||
CFRunLoopStop(_localServerRunLoop);
|
||||
[_localServerThread cancel];
|
||||
}
|
||||
|
||||
- (void)runLocalServer {
|
||||
@autoreleasepool {
|
||||
unsigned char shouldFree = false; // Carbon Boolean = unsigned char
|
||||
CFMessagePortContext localContext = {
|
||||
.version = 0,
|
||||
.info = (__bridge void *) self,
|
||||
.retain = NULL,
|
||||
.release = NULL,
|
||||
.copyDescription = NULL
|
||||
};
|
||||
|
||||
_localServerPort = CFMessagePortCreateLocal(
|
||||
kCFAllocatorDefault,
|
||||
(__bridge CFStringRef) _localServerName,
|
||||
local_server_callback,
|
||||
&localContext,
|
||||
&shouldFree
|
||||
);
|
||||
|
||||
// FIXME: handle shouldFree == true
|
||||
}
|
||||
|
||||
_localServerRunLoop = CFRunLoopGetCurrent();
|
||||
CFRunLoopSourceRef const runLoopSrc = CFMessagePortCreateRunLoopSource(
|
||||
kCFAllocatorDefault,
|
||||
_localServerPort,
|
||||
0
|
||||
);
|
||||
CFRunLoopAddSource(_localServerRunLoop, runLoopSrc, kCFRunLoopCommonModes);
|
||||
CFRelease(runLoopSrc);
|
||||
|
||||
#ifdef DEBUG_NEOVIM_SERVER_STANDALONE
|
||||
server_start_neovim();
|
||||
#endif
|
||||
|
||||
CFRunLoopRun();
|
||||
}
|
||||
|
||||
- (void)sendMessageWithId:(NvimServerMsgId)msgid {
|
||||
[self sendMessageWithId:msgid data:NULL];
|
||||
}
|
||||
|
||||
- (void)sendMessageWithId:(NvimServerMsgId)msgid data:(CFDataRef)data {
|
||||
#ifdef DEBUG_NEOVIM_SERVER_STANDALONE
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (_remoteServerPort == NULL) {
|
||||
os_log_error(
|
||||
logger,
|
||||
"Remote server is null: The msg (%lu) could not be sent.",
|
||||
(unsigned long) msgid
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
SInt32 responseCode = CFMessagePortSendRequest(
|
||||
_remoteServerPort, msgid, data, qTimeout, qTimeout, NULL, NULL
|
||||
);
|
||||
|
||||
if (responseCode == kCFMessagePortSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
os_log_error(
|
||||
logger,
|
||||
"The msg (%lu) could not be sent: %d",
|
||||
(unsigned long) msgid, responseCode
|
||||
);
|
||||
}
|
||||
|
||||
- (void)notifyReadiness {
|
||||
#ifndef DEBUG_NEOVIM_SERVER_STANDALONE
|
||||
[self sendMessageWithId:NvimServerMsgIdServerReady data:NULL];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
14
NvimView/NvimServer/foundation_shim.h
Normal file
14
NvimView/NvimServer/foundation_shim.h
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#ifndef NVIMSERVER_FOUNDATION_SHIM_H
|
||||
#define NVIMSERVER_FOUNDATION_SHIM_H
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#define NSInteger long
|
||||
#define NSUInteger unsigned long
|
||||
|
||||
#endif // NVIMSERVER_FOUNDATION_SHIM_H
|
64
NvimView/NvimServer/main.c
Normal file
64
NvimView/NvimServer/main.c
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#include "server_log.h"
|
||||
#include "server.h"
|
||||
|
||||
os_log_t logger;
|
||||
|
||||
static void observe_parent_termination(void);
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
logger = os_log_create("com.qvacua.NvimServer", "server");
|
||||
observe_parent_termination();
|
||||
|
||||
const int nvim_argc = argc - 3;
|
||||
const char **nvim_args = &argv[3];
|
||||
const char *remote_port_name = argv[1];
|
||||
const char *local_port_name = argv[2];
|
||||
|
||||
server_set_nvim_args(nvim_argc, nvim_argc == 0 ? NULL : nvim_args);
|
||||
server_init_local_port(local_port_name);
|
||||
server_init_remote_port(remote_port_name);
|
||||
|
||||
server_send_msg(NvimServerMsgIdServerReady, NULL);
|
||||
|
||||
os_log_debug(
|
||||
logger,
|
||||
"Started NvimServer '%s' and connected it with GUI '%s'.",
|
||||
local_port_name, remote_port_name
|
||||
);
|
||||
CFRunLoopRun();
|
||||
os_log_debug(logger, "NvimServer exiting.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void observe_parent_termination() {
|
||||
const pid_t parent_pid = getppid();
|
||||
|
||||
const dispatch_queue_t queue = dispatch_get_global_queue(
|
||||
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0
|
||||
);
|
||||
dispatch_source_t source = dispatch_source_create(
|
||||
DISPATCH_SOURCE_TYPE_PROC,
|
||||
(uintptr_t) parent_pid,
|
||||
DISPATCH_PROC_EXIT,
|
||||
queue
|
||||
);
|
||||
|
||||
if (source == NULL) {
|
||||
os_log_error(logger, "No parent process monitoring...");
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_source_set_event_handler(source, ^{
|
||||
os_log_fault(logger, "Exiting neovim server due to parent termination.");
|
||||
CFRunLoopStop(CFRunLoopGetMain());
|
||||
dispatch_source_cancel(source);
|
||||
});
|
||||
|
||||
dispatch_resume(source);
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "NvimServer.h"
|
||||
#import "Logging.h"
|
||||
|
||||
|
||||
NvimServer *_neovim_server;
|
||||
os_log_t logger;
|
||||
|
||||
static void observe_parent_termination(CFRunLoopRef mainRunLoop) {
|
||||
const pid_t parent_pid = getppid();
|
||||
|
||||
const dispatch_queue_t queue = dispatch_get_global_queue(
|
||||
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0
|
||||
);
|
||||
dispatch_source_t source = dispatch_source_create(
|
||||
DISPATCH_SOURCE_TYPE_PROC,
|
||||
(uintptr_t) parent_pid,
|
||||
DISPATCH_PROC_EXIT,
|
||||
queue
|
||||
);
|
||||
|
||||
if (source == NULL) {
|
||||
os_log_error(logger, "No parent process monitoring...");
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch_source_set_event_handler(source, ^{
|
||||
os_log_fault(logger, "Exiting neovim server due to parent termination.");
|
||||
CFRunLoopStop(mainRunLoop);
|
||||
dispatch_source_cancel(source);
|
||||
});
|
||||
|
||||
dispatch_resume(source);
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
logger = os_log_create("com.qvacua.NvimServer", "server");
|
||||
|
||||
CFRunLoopRef const mainRunLoop = CFRunLoopGetCurrent();
|
||||
observe_parent_termination(mainRunLoop);
|
||||
|
||||
@autoreleasepool {
|
||||
NSArray<NSString *> *const arguments
|
||||
= [NSProcessInfo processInfo].arguments;
|
||||
NSString *const remoteServerName = arguments[1];
|
||||
NSString *const localServerName = arguments[2];
|
||||
NSArray<NSString *> *const nvimArgs = argc > 3
|
||||
? [arguments subarrayWithRange:NSMakeRange(3, (NSUInteger) (argc - 3))]
|
||||
: nil;
|
||||
|
||||
_neovim_server = [
|
||||
[NvimServer alloc] initWithLocalServerName:localServerName
|
||||
remoteServerName:remoteServerName
|
||||
nvimArgs:nvimArgs
|
||||
];
|
||||
os_log_debug(
|
||||
logger,
|
||||
"Started neovim server '%@' with args '%@'"
|
||||
" and connected it with the remote agent '%@'.",
|
||||
localServerName, nvimArgs, remoteServerName
|
||||
);
|
||||
|
||||
[_neovim_server notifyReadiness];
|
||||
}
|
||||
|
||||
CFRunLoopRun();
|
||||
|
||||
os_log_debug(logger, "NvimServer returning.");
|
||||
return 0;
|
||||
}
|
438
NvimView/NvimServer/server.c
Normal file
438
NvimView/NvimServer/server.c
Normal file
@ -0,0 +1,438 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#include <uv.h>
|
||||
#include "server.h"
|
||||
#include "server_log.h"
|
||||
#include "server_ui_bridge.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
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <nvim/main.h>
|
||||
#include <nvim/edit.h>
|
||||
#include <nvim/mouse.h>
|
||||
#include <nvim/screen.h>
|
||||
#include <nvim/fileio.h>
|
||||
#include <nvim/api/private/helpers.h>
|
||||
#include <api/vim.h.generated.h>
|
||||
#include <nvim/aucmd.h>
|
||||
|
||||
#pragma mark cond_var_t
|
||||
typedef struct {
|
||||
uv_mutex_t mutex;
|
||||
uv_cond_t condition;
|
||||
uint64_t timeout;
|
||||
bool posted;
|
||||
} cond_var_t;
|
||||
|
||||
static void cond_var_init(cond_var_t *cond_var, uint64_t timeout, bool posted) {
|
||||
memset(cond_var, 0, sizeof((*cond_var)));
|
||||
(*cond_var).timeout = timeout;
|
||||
(*cond_var).posted = posted;
|
||||
uv_cond_init(&(*cond_var).condition);
|
||||
uv_mutex_init(&(*cond_var).mutex);
|
||||
}
|
||||
|
||||
static void cond_var_destroy(cond_var_t *cond_var) {
|
||||
uv_mutex_destroy(&(*cond_var).mutex);
|
||||
uv_cond_destroy(&(*cond_var).condition);
|
||||
}
|
||||
|
||||
#pragma mark server
|
||||
static CFMessagePortRef local_port;
|
||||
static CFRunLoopRef local_port_run_loop;
|
||||
static uv_thread_t local_port_thread;
|
||||
|
||||
static CFMessagePortRef remote_port;
|
||||
|
||||
static uv_thread_t nvim_thread;
|
||||
|
||||
static const char *cfstr2cstr(CFStringRef cfstr, bool *free_bytes);
|
||||
|
||||
static void setenv_vimruntime(void);
|
||||
static void start_nvim(void *_);
|
||||
static int nvim_argc = 0;
|
||||
static const char **nvim_argv;
|
||||
static CFDataRef data_async(CFDataRef data, argv_callback cb);
|
||||
typedef void (^async_work_block)(CFDataRef);
|
||||
|
||||
static void run_local_port(void *cond_var);
|
||||
static CFDataRef local_port_callback(
|
||||
CFMessagePortRef local,
|
||||
SInt32 msgid,
|
||||
CFDataRef data,
|
||||
void *info
|
||||
);
|
||||
|
||||
static String backspace;
|
||||
static void scroll(void **argv);
|
||||
static void resize(void **argv);
|
||||
static void delete_and_input(void **argv);
|
||||
static void focus_gained(void **argv);
|
||||
static void ready_for_rpcevents(void **argv);
|
||||
static void debug1(void **argv);
|
||||
static void do_autocmd_guienter(void **argv);
|
||||
|
||||
// We declare nvim_main because it's not declared in any header files of neovim
|
||||
extern int nvim_main(int argc, const char **argv);
|
||||
|
||||
|
||||
void server_set_nvim_args(int argc, const char **const argv) {
|
||||
nvim_argc = argc + 1;
|
||||
nvim_argv = malloc(nvim_argc * sizeof(char *));
|
||||
|
||||
nvim_argv[0] = "nvim";
|
||||
for (int i = 0; i < argc; i++) { nvim_argv[i + 1] = argv[i]; }
|
||||
}
|
||||
|
||||
void server_init_local_port(const char *name) {
|
||||
CFStringRef name_cf = CFStringCreateWithCString(
|
||||
kCFAllocatorDefault,
|
||||
name,
|
||||
kCFStringEncodingUTF8
|
||||
);
|
||||
local_port = CFMessagePortCreateLocal(
|
||||
kCFAllocatorDefault,
|
||||
name_cf,
|
||||
local_port_callback,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
CFRelease(name_cf);
|
||||
|
||||
cond_var_t cond_var;
|
||||
cond_var_init(&cond_var, 5, false);
|
||||
|
||||
uv_thread_create(&local_port_thread, run_local_port, &cond_var);
|
||||
|
||||
uv_mutex_lock(&cond_var.mutex);
|
||||
while (!cond_var.posted) {
|
||||
uv_cond_timedwait(&cond_var.condition, &cond_var.mutex, cond_var.timeout);
|
||||
}
|
||||
uv_mutex_unlock(&cond_var.mutex);
|
||||
|
||||
cond_var_destroy(&cond_var);
|
||||
}
|
||||
|
||||
void server_destroy_local_port() {
|
||||
CFRunLoopStop(local_port_run_loop);
|
||||
if (CFMessagePortIsValid(local_port)) { CFMessagePortInvalidate(local_port); }
|
||||
CFRelease(local_port);
|
||||
}
|
||||
|
||||
void server_init_remote_port(const char *name) {
|
||||
CFStringRef name_cf = CFStringCreateWithCString(
|
||||
kCFAllocatorDefault,
|
||||
name,
|
||||
kCFStringEncodingUTF8
|
||||
);
|
||||
remote_port = CFMessagePortCreateRemote(kCFAllocatorDefault, name_cf);
|
||||
CFRelease(name_cf);
|
||||
}
|
||||
|
||||
void server_destroy_remote_port() {
|
||||
if (CFMessagePortIsValid(remote_port)) {
|
||||
CFMessagePortInvalidate(remote_port);
|
||||
}
|
||||
CFRelease(remote_port);
|
||||
}
|
||||
|
||||
void server_send_msg(NvimServerMsgId msgid, CFDataRef data) {
|
||||
SInt32 response_code = CFMessagePortSendRequest(
|
||||
remote_port,
|
||||
(SInt32) msgid,
|
||||
data,
|
||||
5.0,
|
||||
5.0,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (response_code == kCFMessagePortSuccess) { return; }
|
||||
|
||||
os_log_error(
|
||||
logger,
|
||||
"The msg (%lu) could not be sent: %d",
|
||||
(long) msgid, response_code
|
||||
);
|
||||
}
|
||||
|
||||
static void start_nvim(void *_) {
|
||||
backspace = cstr_as_string("<BS>");
|
||||
|
||||
setenv_vimruntime();
|
||||
|
||||
// Set $LANG to en_US.UTF-8 such that the copied text to the system clipboard
|
||||
// is not garbled.
|
||||
setenv("LANG", "en_US.UTF-8", true);
|
||||
|
||||
nvim_main(nvim_argc, nvim_argv);
|
||||
}
|
||||
|
||||
static void setenv_vimruntime() {
|
||||
CFBundleRef main_bundle = CFBundleGetMainBundle();
|
||||
CFURLRef exe_url = CFBundleCopyBundleURL(main_bundle);
|
||||
|
||||
CFURLRef bundle_url = CFURLCreateCopyDeletingLastPathComponent(
|
||||
kCFAllocatorDefault,
|
||||
exe_url
|
||||
);
|
||||
CFRelease(exe_url);
|
||||
|
||||
CFURLRef rsrc_url = CFURLCreateCopyAppendingPathComponent(
|
||||
kCFAllocatorDefault,
|
||||
bundle_url,
|
||||
CFSTR("Resources"),
|
||||
true
|
||||
);
|
||||
CFRelease(bundle_url);
|
||||
|
||||
CFURLRef runtime_url = CFURLCreateCopyAppendingPathComponent(
|
||||
kCFAllocatorDefault,
|
||||
rsrc_url,
|
||||
CFSTR("runtime"),
|
||||
true
|
||||
);
|
||||
CFRelease(rsrc_url);
|
||||
|
||||
CFStringRef runtime_path = CFURLCopyPath(runtime_url);
|
||||
CFRelease(runtime_url);
|
||||
|
||||
bool free_runtime_cstr;
|
||||
const char *runtime_cstr = cfstr2cstr(runtime_path, &free_runtime_cstr);
|
||||
|
||||
setenv("VIMRUNTIME", runtime_cstr, true);
|
||||
|
||||
if (free_runtime_cstr) { free((void *) runtime_cstr); }
|
||||
|
||||
CFRelease(runtime_path);
|
||||
}
|
||||
|
||||
static CFDataRef data_async(CFDataRef data, argv_callback cb) {
|
||||
loop_schedule(&main_loop, event_create(cb, 3, data));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void work_async(void **argv, async_work_block body) {
|
||||
CFDataRef data = argv[0];
|
||||
body(data);
|
||||
CFRelease(data); // retained in local_port_callback
|
||||
}
|
||||
|
||||
static CFDataRef local_port_callback(
|
||||
CFMessagePortRef local __unused,
|
||||
SInt32 msgid,
|
||||
CFDataRef data,
|
||||
void *info __unused
|
||||
) {
|
||||
if (data != NULL) {
|
||||
CFRetain(data); // released in work_async (or in the case block below)
|
||||
}
|
||||
|
||||
switch (msgid) {
|
||||
|
||||
case NvimBridgeMsgIdAgentReady: {
|
||||
const NSInteger *const values = (NSInteger *) CFDataGetBytePtr(data);
|
||||
bridge_data.init_width = (int) values[0];
|
||||
bridge_data.init_height = (int) values[1];
|
||||
CFRelease(data);
|
||||
|
||||
uv_thread_create(&nvim_thread, start_nvim, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
case NvimBridgeMsgIdScroll:
|
||||
return data_async(data, scroll);
|
||||
|
||||
case NvimBridgeMsgIdResize:
|
||||
return data_async(data, resize);
|
||||
|
||||
case NvimBridgeMsgIdDeleteInput:
|
||||
return data_async(data, delete_and_input);
|
||||
|
||||
case NvimBridgeMsgIdFocusGained:
|
||||
return data_async(data, focus_gained);
|
||||
|
||||
case NvimBridgeMsgIdReadyForRpcEvents:
|
||||
return data_async(data, ready_for_rpcevents);
|
||||
|
||||
case NvimBridgeMsgIdDebug1:
|
||||
return data_async(data, debug1);
|
||||
|
||||
default:
|
||||
os_log(logger, "msgid received: %{public}ld", (long) msgid);
|
||||
if (data != NULL) { CFRelease(data); }
|
||||
return NULL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void run_local_port(void *arg) {
|
||||
local_port_run_loop = CFRunLoopGetCurrent();
|
||||
CFRunLoopSourceRef const run_loop_src = CFMessagePortCreateRunLoopSource(
|
||||
kCFAllocatorDefault,
|
||||
local_port,
|
||||
0
|
||||
);
|
||||
CFRunLoopAddSource(local_port_run_loop, run_loop_src, kCFRunLoopCommonModes);
|
||||
CFRelease(run_loop_src);
|
||||
|
||||
cond_var_t *cond_var = (cond_var_t *) arg;
|
||||
|
||||
uv_mutex_lock(&cond_var->mutex);
|
||||
cond_var->posted = true;
|
||||
uv_cond_signal(&cond_var->condition);
|
||||
uv_mutex_unlock(&cond_var->mutex);
|
||||
|
||||
CFRunLoopRun();
|
||||
}
|
||||
|
||||
static const char *cfstr2cstr(CFStringRef cfstr, bool *free_bytes) {
|
||||
*free_bytes = false;
|
||||
|
||||
const char *cptr = CFStringGetCStringPtr(cfstr, kCFStringEncodingUTF8);
|
||||
if (cptr != NULL) { return cptr; }
|
||||
|
||||
CFIndex out_len = 0;
|
||||
CFRange whole_range = CFRangeMake(0, CFStringGetLength(cfstr));
|
||||
CFIndex converted = CFStringGetBytes(
|
||||
cfstr,
|
||||
whole_range,
|
||||
kCFStringEncodingUTF8,
|
||||
0,
|
||||
false,
|
||||
NULL,
|
||||
0,
|
||||
&out_len
|
||||
);
|
||||
|
||||
if (converted == 0 || out_len == 0) { return NULL; }
|
||||
|
||||
const char *result = malloc((size_t) (out_len + 1));
|
||||
converted = CFStringGetBytes(
|
||||
cfstr,
|
||||
whole_range,
|
||||
kCFStringEncodingUTF8,
|
||||
0,
|
||||
false,
|
||||
(UInt8 *) result,
|
||||
out_len,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (converted == 0) {
|
||||
free((void *) result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*free_bytes = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark local message port callbacks
|
||||
|
||||
static void scroll(void **argv) {
|
||||
work_async(argv, ^(CFDataRef data) {
|
||||
const NSInteger *const values
|
||||
= (const NSInteger *const) CFDataGetBytePtr(data);
|
||||
const int horiz = (int) values[0];
|
||||
const int vert = (int) values[1];
|
||||
int row = (int) values[2];
|
||||
int column = (int) values[3];
|
||||
|
||||
if (horiz == 0 && vert == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (row < 0 || column < 0) {
|
||||
row = 0;
|
||||
column = 0;
|
||||
}
|
||||
|
||||
// value > 0 => down or right
|
||||
int horizDir;
|
||||
int vertDir;
|
||||
if (horiz != 0) {
|
||||
horizDir = horiz > 0 ? MSCR_RIGHT : MSCR_LEFT;
|
||||
custom_ui_scroll(horizDir, abs(horiz), row, column);
|
||||
}
|
||||
if (vert != 0) {
|
||||
vertDir = vert > 0 ? MSCR_DOWN : MSCR_UP;
|
||||
custom_ui_scroll(vertDir, abs(vert), row, column);
|
||||
}
|
||||
|
||||
update_screen(VALID);
|
||||
setcursor();
|
||||
ui_flush();
|
||||
});
|
||||
}
|
||||
|
||||
static void resize(void **argv) {
|
||||
work_async(argv, ^(CFDataRef data) {
|
||||
const NSInteger *const values
|
||||
= (const NSInteger *const) CFDataGetBytePtr(data);
|
||||
const NSInteger width = values[0];
|
||||
const NSInteger height = values[1];
|
||||
|
||||
server_set_ui_size(bridge_data.bridge, (int) width, (int) height);
|
||||
ui_refresh();
|
||||
});
|
||||
}
|
||||
|
||||
static void delete_and_input(void **argv) {
|
||||
work_async(argv, ^(CFDataRef data) {
|
||||
const NSInteger *const values
|
||||
= (const NSInteger *const) CFDataGetBytePtr(data);
|
||||
const NSInteger count = values[0];
|
||||
for (int i = 0; i < count; i++) {
|
||||
nvim_input(backspace);
|
||||
}
|
||||
|
||||
const char *stringPtr = (const char *) (values + 1);
|
||||
String string = cbuf_to_string(
|
||||
stringPtr,
|
||||
CFDataGetLength(data) - sizeof(NSInteger)
|
||||
);
|
||||
nvim_input(string);
|
||||
api_free_string(string);
|
||||
});
|
||||
}
|
||||
|
||||
static void focus_gained(void **argv) {
|
||||
work_async(argv, ^(CFDataRef data) {
|
||||
const bool *values = (const bool *) CFDataGetBytePtr(data);
|
||||
|
||||
aucmd_schedule_focusgained(values[0]);
|
||||
});
|
||||
}
|
||||
|
||||
static void ready_for_rpcevents(void **argv) {
|
||||
work_async(argv, ^(CFDataRef data) {
|
||||
loop_schedule_deferred(&main_loop, event_create(do_autocmd_guienter, 0));
|
||||
});
|
||||
}
|
||||
|
||||
static void debug1(void **argv) {
|
||||
work_async(argv, ^(CFDataRef data) {
|
||||
// yet noop
|
||||
os_log(logger, "debug1");
|
||||
});
|
||||
}
|
||||
|
||||
static void do_autocmd_guienter(void **argv) {
|
||||
static bool recursive = false;
|
||||
|
||||
if (recursive) {
|
||||
return; // disallow recursion
|
||||
}
|
||||
recursive = true;
|
||||
apply_autocmds(EVENT_GUIENTER, NULL, NULL, false, curbuf);
|
||||
recursive = false;
|
||||
}
|
22
NvimView/NvimServer/server.h
Normal file
22
NvimView/NvimServer/server.h
Normal file
@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#ifndef NVIMSERVER_SERVER_H
|
||||
#define NVIMSERVER_SERVER_H
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include "server_shared_types.h"
|
||||
|
||||
void server_set_nvim_args(int argc, const char **const args);
|
||||
|
||||
void server_init_local_port(const char *name);
|
||||
void server_destroy_local_port(void);
|
||||
|
||||
void server_init_remote_port(const char *name);
|
||||
void server_destroy_remote_port(void);
|
||||
|
||||
void server_send_msg(NvimServerMsgId msgId, CFDataRef data);
|
||||
|
||||
#endif // NVIMSERVER_SERVER_H
|
13
NvimView/NvimServer/server_log.h
Normal file
13
NvimView/NvimServer/server_log.h
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#ifndef NVIMSERVER_LOG_H
|
||||
#define NVIMSERVER_LOG_H
|
||||
|
||||
#include <os/log.h>
|
||||
|
||||
extern os_log_t logger;
|
||||
|
||||
#endif // NVIMSERVER_LOG_H
|
@ -3,9 +3,12 @@
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#ifndef NVIMSERVER_SHARED_TYPES_H
|
||||
#define NVIMSERVER_SHARED_TYPES_H
|
||||
|
||||
typedef NS_OPTIONS(NSUInteger, FontTrait) {
|
||||
#include "foundation_shim.h"
|
||||
|
||||
typedef CF_OPTIONS(NSUInteger, FontTrait) {
|
||||
FontTraitNone = 0,
|
||||
FontTraitItalic = (1 << 0),
|
||||
FontTraitBold = (1 << 1),
|
||||
@ -13,13 +16,13 @@ typedef NS_OPTIONS(NSUInteger, FontTrait) {
|
||||
FontTraitUndercurl = (1 << 3)
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, RenderDataType) {
|
||||
typedef CF_ENUM(NSInteger, RenderDataType) {
|
||||
RenderDataTypeRawLine,
|
||||
RenderDataTypeGoto,
|
||||
RenderDataTypeScroll,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, NvimServerMsgId) {
|
||||
typedef CF_ENUM(NSInteger, NvimServerMsgId) {
|
||||
NvimServerMsgIdServerReady = 0,
|
||||
NvimServerMsgIdNvimReady,
|
||||
NvimServerMsgIdResize,
|
||||
@ -35,7 +38,7 @@ typedef NS_ENUM(NSInteger, NvimServerMsgId) {
|
||||
NvimServerMsgIdSetTitle,
|
||||
NvimServerMsgIdStop,
|
||||
NvimServerMsgIdOptionSet,
|
||||
|
||||
|
||||
NvimServerMsgIdDirtyStatusChanged,
|
||||
NvimServerMsgIdCwdChanged,
|
||||
NvimServerMsgIdColorSchemeChanged,
|
||||
@ -46,14 +49,16 @@ typedef NS_ENUM(NSInteger, NvimServerMsgId) {
|
||||
NvimServerMsgIdDebug1,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, NvimBridgeMsgId) {
|
||||
typedef CF_ENUM(NSInteger, NvimBridgeMsgId) {
|
||||
NvimBridgeMsgIdAgentReady = 0,
|
||||
NvimBridgeMsgIdReadyForRpcEvents,
|
||||
NvimBridgeMsgIdDeleteInput,
|
||||
NvimBridgeMsgIdResize,
|
||||
NvimBridgeMsgIdScroll,
|
||||
|
||||
|
||||
NvimBridgeMsgIdFocusGained,
|
||||
|
||||
|
||||
NvimBridgeMsgIdDebug1,
|
||||
};
|
||||
|
||||
#endif // NVIMSERVER_SHARED_TYPES_H
|
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@class NvimServer;
|
||||
|
||||
extern NvimServer *_neovim_server;
|
||||
|
||||
extern void start_neovim(NSInteger width, NSInteger height, NSArray<NSString *> *args);
|
||||
|
||||
extern void neovim_scroll(void **argv);
|
||||
extern void neovim_resize(void **argv);
|
||||
|
||||
extern void neovim_delete_and_input(void **argv);
|
||||
|
||||
extern void neovim_focus_gained(void **argv);
|
||||
extern void neovim_ready_for_rpcevents(void **argv);
|
||||
|
||||
extern void neovim_debug1(void **argv);
|
@ -3,277 +3,47 @@
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#include "server_log.h"
|
||||
#include "server_shared_types.h"
|
||||
#include "server.h"
|
||||
#include "server_ui_bridge.h"
|
||||
|
||||
#import "Logging.h"
|
||||
#import "server_ui.h"
|
||||
#import "NvimServer.h"
|
||||
#import "CocoaCategories.h"
|
||||
#include <nvim/vim.h>
|
||||
#include <nvim/fileio.h>
|
||||
#include <nvim/undo.h>
|
||||
#include <nvim/syntax.h>
|
||||
#include <nvim/highlight.h>
|
||||
#include <nvim/msgpack_rpc/helpers.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
|
||||
server_ui_bridge_data_t bridge_data;
|
||||
|
||||
#import <nvim/main.h>
|
||||
#import <nvim/vim.h>
|
||||
#import <nvim/api/vim.h>
|
||||
#import <nvim/ui.h>
|
||||
#import <nvim/ui_bridge.h>
|
||||
#import <nvim/fileio.h>
|
||||
#import <nvim/undo.h>
|
||||
#import <nvim/mouse.h>
|
||||
#import <nvim/screen.h>
|
||||
#import <nvim/edit.h>
|
||||
#import <nvim/syntax.h>
|
||||
#import <nvim/aucmd.h>
|
||||
#import <nvim/highlight.h>
|
||||
#import <nvim/msgpack_rpc/helpers.h>
|
||||
#pragma mark server_ui_bridge
|
||||
|
||||
static NSInteger default_foreground = 0xFF000000;
|
||||
static NSInteger default_background = 0xFFFFFFFF;
|
||||
static NSInteger default_special = 0xFFFF0000;
|
||||
|
||||
static NSInteger _default_foreground = 0xFF000000;
|
||||
static NSInteger _default_background = 0xFFFFFFFF;
|
||||
static NSInteger _default_special = 0xFFFF0000;
|
||||
|
||||
typedef struct {
|
||||
UIBridgeData *bridge;
|
||||
Loop *loop;
|
||||
|
||||
bool stop;
|
||||
} ServerUiData;
|
||||
|
||||
// We declare nvim_main because it's not declared in any header files of neovim
|
||||
extern int nvim_main(int argc, char **argv);
|
||||
|
||||
|
||||
// The thread in which neovim's main runs
|
||||
static uv_thread_t _nvim_thread;
|
||||
|
||||
static ServerUiData *_server_ui_data;
|
||||
|
||||
static NSString *_backspace = @"<BS>";
|
||||
|
||||
static bool _dirty = false;
|
||||
|
||||
static NSInteger _initialWidth = 30;
|
||||
static NSInteger _initialHeight = 15;
|
||||
static bool are_buffers_dirty = false;
|
||||
|
||||
static msgpack_sbuffer flush_sbuffer;
|
||||
static msgpack_packer flush_packer;
|
||||
|
||||
|
||||
#pragma mark Helper functions
|
||||
|
||||
static inline String vim_string_from(NSString *str) {
|
||||
return (String) {.data = (char *) str.cstr, .size = str.clength};
|
||||
}
|
||||
|
||||
static void refresh_ui_screen(int type) {
|
||||
update_screen(type);
|
||||
setcursor();
|
||||
ui_flush();
|
||||
}
|
||||
|
||||
static bool has_dirty_docs() {
|
||||
FOR_ALL_BUFFERS(buffer) {
|
||||
if (bufIsChanged(buffer)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void msgpack_pack_cstr(msgpack_packer *packer, const char *cstr) {
|
||||
const size_t len = strlen(cstr);
|
||||
msgpack_pack_str(packer, len);
|
||||
msgpack_pack_str_body(packer, cstr, len);
|
||||
}
|
||||
|
||||
static void msgpack_pack_bool(msgpack_packer *packer, bool value) {
|
||||
if (value) {
|
||||
msgpack_pack_true(packer);
|
||||
} else {
|
||||
msgpack_pack_false(packer);
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (^pack_block)(msgpack_packer *packer);
|
||||
static void send_msg_packing(NvimServerMsgId msgid, pack_block body);
|
||||
static void msgpack_pack_bool(msgpack_packer *packer, bool value);
|
||||
static void pack_flush_data(RenderDataType type, pack_block body);
|
||||
static void msgpack_pack_cstr(msgpack_packer *packer, const char *cstr);
|
||||
static void send_cwd(void);
|
||||
static void send_dirty_status(void);
|
||||
static void send_colorscheme(void);
|
||||
|
||||
static void send_msg_packing(NvimServerMsgId msgid, pack_block body) {
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
static void server_ui_scheduler(Event event, void *d);
|
||||
static void server_ui_main(UIBridgeData *bridge, UI *ui);
|
||||
|
||||
msgpack_packer packer;
|
||||
msgpack_packer_init(&packer, &sbuf, msgpack_sbuffer_write);
|
||||
|
||||
body(&packer);
|
||||
|
||||
CFDataRef const data = CFDataCreateWithBytesNoCopy(
|
||||
kCFAllocatorDefault,
|
||||
(const UInt8 *) sbuf.data,
|
||||
sbuf.size,
|
||||
kCFAllocatorNull
|
||||
);
|
||||
[_neovim_server sendMessageWithId:msgid data:data];
|
||||
CFRelease(data);
|
||||
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
|
||||
static void pack_flush_data(RenderDataType type, pack_block body) {
|
||||
msgpack_pack_array(&flush_packer, 2);
|
||||
msgpack_pack_int64(&flush_packer, type);
|
||||
body(&flush_packer);
|
||||
}
|
||||
|
||||
static void send_dirty_status() {
|
||||
const bool new_dirty_status = has_dirty_docs();
|
||||
if (_dirty == new_dirty_status) {
|
||||
return;
|
||||
}
|
||||
|
||||
_dirty = new_dirty_status;
|
||||
|
||||
send_msg_packing(
|
||||
NvimServerMsgIdDirtyStatusChanged,
|
||||
^(msgpack_packer *packer) {
|
||||
msgpack_pack_bool(packer, _dirty);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static void send_cwd() {
|
||||
char_u *const temp = xmalloc(MAXPATHL);
|
||||
if (os_dirname(temp, MAXPATHL) == FAIL) {
|
||||
xfree(temp);
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdCwdChanged];
|
||||
}
|
||||
|
||||
send_msg_packing(NvimServerMsgIdCwdChanged, ^(msgpack_packer *packer) {
|
||||
msgpack_pack_cstr(packer, (const char *) temp);
|
||||
xfree(temp);
|
||||
});
|
||||
}
|
||||
|
||||
static int foreground_for(HlAttrs attrs) {
|
||||
const int mask = attrs.rgb_ae_attr;
|
||||
return mask & HL_INVERSE ? attrs.rgb_bg_color : attrs.rgb_fg_color;
|
||||
}
|
||||
|
||||
static int background_for(HlAttrs attrs) {
|
||||
const int mask = attrs.rgb_ae_attr;
|
||||
return mask & HL_INVERSE ? attrs.rgb_fg_color : attrs.rgb_bg_color;
|
||||
}
|
||||
|
||||
static void send_colorscheme() {
|
||||
// It seems that the highlight groupt only gets updated when the screen is
|
||||
// redrawn. Since there's a guard var, probably it's safe to call it here...
|
||||
if (need_highlight_changed) {
|
||||
highlight_changed();
|
||||
}
|
||||
|
||||
const HlAttrs visualAttrs = syn_attr2entry(highlight_attr[HLF_V]);
|
||||
const HlAttrs dirAttrs = syn_attr2entry(highlight_attr[HLF_D]);
|
||||
|
||||
send_msg_packing(
|
||||
NvimServerMsgIdColorSchemeChanged,
|
||||
^(msgpack_packer *packer) {
|
||||
msgpack_pack_array(packer, 5);
|
||||
msgpack_pack_int64(packer, normal_fg);
|
||||
msgpack_pack_int64(packer, normal_bg);
|
||||
msgpack_pack_int64(packer, foreground_for(visualAttrs));
|
||||
msgpack_pack_int64(packer, background_for(visualAttrs));
|
||||
msgpack_pack_int64(packer, foreground_for(dirAttrs));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static void run_neovim(void *arg) {
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
@autoreleasepool {
|
||||
NSArray<NSString *> *nvimArgs = arg;
|
||||
|
||||
argc = (int) nvimArgs.count + 1;
|
||||
argv = (char **) malloc((argc + 1) * sizeof(char *));
|
||||
|
||||
argv[0] = "nvim";
|
||||
for (NSUInteger i = 0; i < nvimArgs.count; i++) {
|
||||
char *str = (char *) nvimArgs[i].cstr;
|
||||
argv[i + 1] = malloc(strlen(str) + 1);
|
||||
strcpy(argv[i + 1], str);
|
||||
}
|
||||
|
||||
[nvimArgs release]; // retained in start_neovim()
|
||||
}
|
||||
|
||||
nvim_main(argc, argv);
|
||||
|
||||
for (int i = 0; i < argc - 1; i++) {
|
||||
free(argv[i + 1]);
|
||||
}
|
||||
free(argv);
|
||||
}
|
||||
|
||||
static void set_ui_size(UIBridgeData *bridge, int width, int height) {
|
||||
bridge->ui->width = width;
|
||||
bridge->ui->height = height;
|
||||
bridge->bridge.width = width;
|
||||
bridge->bridge.height = height;
|
||||
}
|
||||
|
||||
static void server_ui_scheduler(Event event, void *d) {
|
||||
UI *const ui = d;
|
||||
ServerUiData *data = ui->data;
|
||||
loop_schedule(data->loop, event);
|
||||
}
|
||||
|
||||
static void server_ui_main(UIBridgeData *bridge, UI *ui) {
|
||||
msgpack_sbuffer_init(&flush_sbuffer);
|
||||
msgpack_packer_init(&flush_packer, &flush_sbuffer, msgpack_sbuffer_write);
|
||||
|
||||
Loop loop;
|
||||
loop_init(&loop, NULL);
|
||||
|
||||
_server_ui_data = xcalloc(1, sizeof(ServerUiData));
|
||||
ui->data = _server_ui_data;
|
||||
_server_ui_data->bridge = bridge;
|
||||
_server_ui_data->loop = &loop;
|
||||
|
||||
set_ui_size(bridge, (int) _initialWidth, (int) _initialHeight);
|
||||
|
||||
_server_ui_data->stop = false;
|
||||
CONTINUE(bridge);
|
||||
|
||||
send_msg_packing(NvimServerMsgIdNvimReady, ^(msgpack_packer *packer) {
|
||||
msgpack_pack_bool(packer, msg_didany > 0);
|
||||
});
|
||||
|
||||
// We have to manually trigger this to initially get the colorscheme.
|
||||
send_colorscheme();
|
||||
|
||||
while (!_server_ui_data->stop) {
|
||||
loop_poll_events(&loop, -1);
|
||||
}
|
||||
|
||||
ui_bridge_stopped(bridge);
|
||||
loop_close(&loop, false);
|
||||
|
||||
xfree(_server_ui_data);
|
||||
xfree(ui);
|
||||
|
||||
free(msgpack_sbuffer_release(&flush_sbuffer));
|
||||
}
|
||||
|
||||
#pragma mark NeoVim's UI callbacks
|
||||
#pragma mark ui_bridge callbacks
|
||||
|
||||
static void server_ui_flush(UI *ui __unused) {
|
||||
if (flush_sbuffer.size == 0) {
|
||||
return;
|
||||
}
|
||||
if (flush_sbuffer.size == 0) { return; }
|
||||
|
||||
CFDataRef const data = CFDataCreateWithBytesNoCopy(
|
||||
kCFAllocatorDefault,
|
||||
@ -281,7 +51,7 @@ static void server_ui_flush(UI *ui __unused) {
|
||||
flush_sbuffer.size,
|
||||
kCFAllocatorNull
|
||||
);
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdFlush data:data];
|
||||
server_send_msg(NvimServerMsgIdFlush, data);
|
||||
CFRelease(data);
|
||||
|
||||
free(msgpack_sbuffer_release(&flush_sbuffer));
|
||||
@ -301,11 +71,14 @@ static void server_ui_grid_resize(
|
||||
}
|
||||
|
||||
static void server_ui_grid_clear(UI *ui __unused, Integer grid __unused) {
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdClear];
|
||||
server_send_msg(NvimServerMsgIdClear, NULL);
|
||||
}
|
||||
|
||||
static void server_ui_cursor_goto(
|
||||
UI *ui __unused, Integer grid __unused, Integer row, Integer col
|
||||
UI *ui __unused,
|
||||
Integer grid __unused,
|
||||
Integer row,
|
||||
Integer col
|
||||
) {
|
||||
pack_flush_data(RenderDataTypeGoto, ^(msgpack_packer *packer) {
|
||||
msgpack_pack_array(packer, 2);
|
||||
@ -315,25 +88,27 @@ static void server_ui_cursor_goto(
|
||||
}
|
||||
|
||||
static void server_ui_update_menu(UI *ui __unused) {
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdSetMenu];
|
||||
server_send_msg(NvimServerMsgIdSetMenu, NULL);
|
||||
}
|
||||
|
||||
static void server_ui_busy_start(UI *ui __unused) {
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdBusyStart];
|
||||
server_send_msg(NvimServerMsgIdBusyStart, NULL);
|
||||
}
|
||||
|
||||
static void server_ui_busy_stop(UI *ui __unused) {
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdBusyStop];
|
||||
server_send_msg(NvimServerMsgIdBusyStop, NULL);
|
||||
}
|
||||
|
||||
static void server_ui_mode_info_set(
|
||||
UI *ui __unused, Boolean enabled __unused, Array cursor_styles __unused
|
||||
) {
|
||||
// yet noop
|
||||
}
|
||||
UI *ui __unused,
|
||||
Boolean enabled __unused,
|
||||
Array cursor_styles __unused
|
||||
) {}
|
||||
|
||||
static void server_ui_mode_change(
|
||||
UI *ui __unused, String mode_str __unused, Integer mode
|
||||
UI *ui __unused,
|
||||
String mode_str __unused,
|
||||
Integer mode
|
||||
) {
|
||||
send_msg_packing(NvimServerMsgIdModeChange, ^(msgpack_packer *packer) {
|
||||
msgpack_pack_int64(packer, mode);
|
||||
@ -368,18 +143,10 @@ static void server_ui_hl_attr_define(
|
||||
Array info __unused
|
||||
) {
|
||||
FontTrait trait = FontTraitNone;
|
||||
if (attrs.rgb_ae_attr & HL_ITALIC) {
|
||||
trait |= FontTraitItalic;
|
||||
}
|
||||
if (attrs.rgb_ae_attr & HL_BOLD) {
|
||||
trait |= FontTraitBold;
|
||||
}
|
||||
if (attrs.rgb_ae_attr & HL_UNDERLINE) {
|
||||
trait |= FontTraitUnderline;
|
||||
}
|
||||
if (attrs.rgb_ae_attr & HL_UNDERCURL) {
|
||||
trait |= FontTraitUndercurl;
|
||||
}
|
||||
if (attrs.rgb_ae_attr & HL_ITALIC) { trait |= FontTraitItalic; }
|
||||
if (attrs.rgb_ae_attr & HL_BOLD) { trait |= FontTraitBold; }
|
||||
if (attrs.rgb_ae_attr & HL_UNDERLINE) { trait |= FontTraitUnderline; }
|
||||
if (attrs.rgb_ae_attr & HL_UNDERCURL) { trait |= FontTraitUndercurl; }
|
||||
|
||||
send_msg_packing(NvimServerMsgIdHighlightAttrs, ^(msgpack_packer *packer) {
|
||||
msgpack_pack_array(packer, 6);
|
||||
@ -400,7 +167,7 @@ static void server_ui_raw_line(
|
||||
Integer endcol,
|
||||
Integer clearcol,
|
||||
Integer clearattr,
|
||||
Boolean wrap,
|
||||
Boolean wrap __unused,
|
||||
const schar_T *chunk,
|
||||
const sattr_T *attrs
|
||||
) {
|
||||
@ -427,11 +194,11 @@ static void server_ui_raw_line(
|
||||
}
|
||||
|
||||
static void server_ui_bell(UI *ui __unused) {
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdBell];
|
||||
server_send_msg(NvimServerMsgIdBell, NULL);
|
||||
}
|
||||
|
||||
static void server_ui_visual_bell(UI *ui __unused) {
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdVisualBell];
|
||||
server_send_msg(NvimServerMsgIdVisualBell, NULL);
|
||||
}
|
||||
|
||||
static void server_ui_default_colors_set(
|
||||
@ -442,39 +209,27 @@ static void server_ui_default_colors_set(
|
||||
Integer cterm_fg __unused,
|
||||
Integer cterm_bg __unused
|
||||
) {
|
||||
if (rgb_fg != -1) {
|
||||
_default_foreground = rgb_fg;
|
||||
}
|
||||
|
||||
if (rgb_bg != -1) {
|
||||
_default_background = rgb_bg;
|
||||
}
|
||||
|
||||
if (rgb_sp != -1) {
|
||||
_default_special = rgb_sp;
|
||||
}
|
||||
if (rgb_fg != -1) { default_foreground = rgb_fg; }
|
||||
if (rgb_bg != -1) { default_background = rgb_bg; }
|
||||
if (rgb_sp != -1) { default_special = rgb_sp; }
|
||||
|
||||
send_msg_packing(
|
||||
NvimServerMsgIdDefaultColorsChanged,
|
||||
^(msgpack_packer *packer) {
|
||||
msgpack_pack_array(packer, 3);
|
||||
msgpack_pack_int64(packer, _default_foreground);
|
||||
msgpack_pack_int64(packer, _default_background);
|
||||
msgpack_pack_int64(packer, _default_special);
|
||||
msgpack_pack_int64(packer, default_foreground);
|
||||
msgpack_pack_int64(packer, default_background);
|
||||
msgpack_pack_int64(packer, default_special);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static void server_ui_set_title(UI *ui __unused, String title) {
|
||||
@autoreleasepool {
|
||||
if (title.size == 0) {
|
||||
return;
|
||||
}
|
||||
if (title.size == 0) { return; }
|
||||
|
||||
send_msg_packing(NvimServerMsgIdSetTitle, ^(msgpack_packer *packer) {
|
||||
msgpack_rpc_from_string(title, packer);
|
||||
});
|
||||
}
|
||||
send_msg_packing(NvimServerMsgIdSetTitle, ^(msgpack_packer *packer) {
|
||||
msgpack_rpc_from_string(title, packer);
|
||||
});
|
||||
}
|
||||
|
||||
static void server_ui_option_set(UI *ui __unused, String name, Object value) {
|
||||
@ -486,22 +241,17 @@ static void server_ui_option_set(UI *ui __unused, String name, Object value) {
|
||||
}
|
||||
|
||||
static void server_ui_stop(UI *ui __unused) {
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdStop];
|
||||
server_send_msg(NvimServerMsgIdStop, NULL);
|
||||
|
||||
ServerUiData *const data = ui->data;
|
||||
server_ui_bridge_data_t *const data = ui->data;
|
||||
data->stop = true;
|
||||
}
|
||||
|
||||
static void dummy(UI *ui __unused) {
|
||||
static void dummy(UI *ui __unused) {}
|
||||
|
||||
}
|
||||
static void dummy2(UI *ui __unused, String icon __unused) {}
|
||||
|
||||
static void dummy2(UI *ui __unused, String icon) {
|
||||
|
||||
}
|
||||
|
||||
#pragma mark Public
|
||||
// called by neovim
|
||||
#pragma mark called by nvim
|
||||
|
||||
void custom_ui_start(void) {
|
||||
UI *const ui = xcalloc(1, sizeof(UI));
|
||||
@ -538,8 +288,7 @@ void custom_ui_start(void) {
|
||||
|
||||
void custom_ui_rpcevent_subscribed() {
|
||||
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
|
||||
[_neovim_server sendMessageWithId:NvimServerMsgIdRpcEventSubscribed
|
||||
data:NULL];
|
||||
server_send_msg(NvimServerMsgIdRpcEventSubscribed, NULL);
|
||||
});
|
||||
}
|
||||
|
||||
@ -571,176 +320,189 @@ void custom_ui_autocmds_groups(
|
||||
return;
|
||||
}
|
||||
|
||||
@autoreleasepool {
|
||||
if (event == EVENT_DIRCHANGED) {
|
||||
send_cwd();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event == EVENT_COLORSCHEME) {
|
||||
send_colorscheme();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event == EVENT_TEXTCHANGED
|
||||
|| event == EVENT_TEXTCHANGEDI
|
||||
|| event == EVENT_BUFWRITEPOST
|
||||
|| event == EVENT_BUFLEAVE) {
|
||||
send_dirty_status();
|
||||
}
|
||||
|
||||
send_msg_packing(
|
||||
NvimServerMsgIdAutoCommandEvent,
|
||||
^(msgpack_packer *packer) {
|
||||
msgpack_pack_array(packer, 2);
|
||||
msgpack_pack_int64(packer, (NSInteger) event);
|
||||
if (buf == NULL) {
|
||||
msgpack_pack_int64(packer, -1);
|
||||
} else {
|
||||
msgpack_pack_int64(packer, (NSInteger) buf->handle);
|
||||
}
|
||||
});
|
||||
if (event == EVENT_DIRCHANGED) {
|
||||
send_cwd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Other help functions
|
||||
|
||||
void start_neovim(
|
||||
NSInteger width, NSInteger height, NSArray<NSString *> *args
|
||||
) {
|
||||
// The caller has an @autoreleasepool.
|
||||
_initialWidth = width;
|
||||
_initialHeight = height;
|
||||
|
||||
// set $VIMRUNTIME to ${RESOURCE_PATH_OF_XPC_BUNDLE}/runtime
|
||||
NSString *const bundlePath = [
|
||||
NSBundle bundleForClass:[NvimServer class]
|
||||
].bundlePath;
|
||||
NSString *const resourcesPath = [bundlePath.stringByDeletingLastPathComponent
|
||||
stringByAppendingPathComponent:@"Resources"];
|
||||
NSString *const runtimePath
|
||||
= [resourcesPath stringByAppendingPathComponent:@"runtime"];
|
||||
setenv("VIMRUNTIME", runtimePath.fileSystemRepresentation, true);
|
||||
|
||||
// Set $LANG to en_US.UTF-8 such that the copied text to the system clipboard
|
||||
// is not garbled.
|
||||
setenv("LANG", "en_US.UTF-8", true);
|
||||
|
||||
// released in run_neovim()
|
||||
uv_thread_create(&_nvim_thread, run_neovim, [args retain]);
|
||||
}
|
||||
|
||||
#pragma mark Functions for neovim's main loop
|
||||
|
||||
typedef void (^async_work_block)(NSData *);
|
||||
|
||||
static void work_async(void **argv, async_work_block block) {
|
||||
@autoreleasepool {
|
||||
NSData *const data = argv[0];
|
||||
block(data);
|
||||
[data release]; // retained in local_server_callback
|
||||
if (event == EVENT_COLORSCHEME) {
|
||||
send_colorscheme();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void neovim_scroll(void **argv) {
|
||||
work_async(argv, ^(NSData *data) {
|
||||
const NSInteger *const values = data.bytes;
|
||||
const int horiz = (int) values[0];
|
||||
const int vert = (int) values[1];
|
||||
int row = (int) values[2];
|
||||
int column = (int) values[3];
|
||||
|
||||
if (horiz == 0 && vert == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (row < 0 || column < 0) {
|
||||
row = 0;
|
||||
column = 0;
|
||||
}
|
||||
|
||||
// value > 0 => down or right
|
||||
int horizDir;
|
||||
int vertDir;
|
||||
if (horiz != 0) {
|
||||
horizDir = horiz > 0 ? MSCR_RIGHT : MSCR_LEFT;
|
||||
custom_ui_scroll(horizDir, ABS(horiz), row, column);
|
||||
}
|
||||
if (vert != 0) {
|
||||
vertDir = vert > 0 ? MSCR_DOWN : MSCR_UP;
|
||||
custom_ui_scroll(vertDir, ABS(vert), row, column);
|
||||
}
|
||||
|
||||
refresh_ui_screen(VALID);
|
||||
});
|
||||
}
|
||||
|
||||
void neovim_resize(void **argv) {
|
||||
work_async(argv, ^(NSData *data) {
|
||||
const NSInteger *const values = data.bytes;
|
||||
const NSInteger width = values[0];
|
||||
const NSInteger height = values[1];
|
||||
|
||||
set_ui_size(_server_ui_data->bridge, (int) width, (int) height);
|
||||
ui_refresh();
|
||||
});
|
||||
}
|
||||
|
||||
void neovim_delete_and_input(void **argv) {
|
||||
work_async(argv, ^(NSData *data) {
|
||||
const NSInteger *const values = data.bytes;
|
||||
const NSInteger count = values[0];
|
||||
for (int i = 0; i < count; i++) {
|
||||
nvim_input(vim_string_from(_backspace));
|
||||
}
|
||||
|
||||
const void *const stringPtr = (void *) (values + 1);
|
||||
NSString *string = [[NSString alloc]
|
||||
initWithBytes:stringPtr
|
||||
length:data.length - sizeof(NSInteger)
|
||||
encoding:NSUTF8StringEncoding
|
||||
];
|
||||
nvim_input(vim_string_from(string));
|
||||
[string release];
|
||||
});
|
||||
}
|
||||
|
||||
static void do_autocmd_guienter() {
|
||||
static bool recursive = false;
|
||||
|
||||
if (recursive) {
|
||||
return; // disallow recursion
|
||||
if (event == EVENT_TEXTCHANGED
|
||||
|| event == EVENT_TEXTCHANGEDI
|
||||
|| event == EVENT_BUFWRITEPOST
|
||||
|| event == EVENT_BUFLEAVE) {
|
||||
send_dirty_status();
|
||||
}
|
||||
recursive = true;
|
||||
apply_autocmds(EVENT_GUIENTER, NULL, NULL, false, curbuf);
|
||||
recursive = false;
|
||||
|
||||
send_msg_packing(
|
||||
NvimServerMsgIdAutoCommandEvent,
|
||||
^(msgpack_packer *packer) {
|
||||
msgpack_pack_array(packer, 2);
|
||||
msgpack_pack_int64(packer, (NSInteger) event);
|
||||
if (buf == NULL) {
|
||||
msgpack_pack_int64(packer, -1);
|
||||
} else {
|
||||
msgpack_pack_int64(packer, (NSInteger) buf->handle);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void guienter_event(void **argv __unused) {
|
||||
do_autocmd_guienter();
|
||||
#pragma mark helpers
|
||||
|
||||
static bool has_dirty_docs() {
|
||||
FOR_ALL_BUFFERS(buffer) {
|
||||
if (bufIsChanged(buffer)) { return true; }
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void aucmd_schedule_guienter() {
|
||||
loop_schedule_deferred(&main_loop, event_create(guienter_event, 0));
|
||||
static void msgpack_pack_cstr(msgpack_packer *packer, const char *cstr) {
|
||||
const size_t len = strlen(cstr);
|
||||
msgpack_pack_str(packer, len);
|
||||
msgpack_pack_str_body(packer, cstr, len);
|
||||
}
|
||||
|
||||
void neovim_focus_gained(void **argv) {
|
||||
work_async(argv, ^(NSData *data) {
|
||||
const bool *values = data.bytes;
|
||||
static void msgpack_pack_bool(msgpack_packer *packer, bool value) {
|
||||
if (value) { msgpack_pack_true(packer); }
|
||||
else { msgpack_pack_false(packer); }
|
||||
}
|
||||
|
||||
aucmd_schedule_focusgained(values[0]);
|
||||
static void send_msg_packing(NvimServerMsgId msgid, pack_block body) {
|
||||
msgpack_sbuffer sbuf;
|
||||
msgpack_sbuffer_init(&sbuf);
|
||||
|
||||
msgpack_packer packer;
|
||||
msgpack_packer_init(&packer, &sbuf, msgpack_sbuffer_write);
|
||||
|
||||
body(&packer);
|
||||
|
||||
CFDataRef const data = CFDataCreateWithBytesNoCopy(
|
||||
kCFAllocatorDefault,
|
||||
(const UInt8 *) sbuf.data,
|
||||
sbuf.size,
|
||||
kCFAllocatorNull
|
||||
);
|
||||
server_send_msg(msgid, data);
|
||||
CFRelease(data);
|
||||
|
||||
msgpack_sbuffer_destroy(&sbuf);
|
||||
}
|
||||
|
||||
static void pack_flush_data(RenderDataType type, pack_block body) {
|
||||
msgpack_pack_array(&flush_packer, 2);
|
||||
msgpack_pack_int64(&flush_packer, type);
|
||||
body(&flush_packer);
|
||||
}
|
||||
|
||||
static void send_dirty_status() {
|
||||
const bool new_dirty_status = has_dirty_docs();
|
||||
if (are_buffers_dirty == new_dirty_status) { return; }
|
||||
|
||||
are_buffers_dirty = new_dirty_status;
|
||||
|
||||
send_msg_packing(
|
||||
NvimServerMsgIdDirtyStatusChanged,
|
||||
^(msgpack_packer *packer) {
|
||||
msgpack_pack_bool(packer, are_buffers_dirty);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static void send_cwd() {
|
||||
char_u *const temp = xmalloc(MAXPATHL);
|
||||
if (os_dirname(temp, MAXPATHL) == FAIL) {
|
||||
xfree(temp);
|
||||
server_send_msg(NvimServerMsgIdCwdChanged, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
send_msg_packing(NvimServerMsgIdCwdChanged, ^(msgpack_packer *packer) {
|
||||
msgpack_pack_cstr(packer, (const char *) temp);
|
||||
xfree(temp);
|
||||
});
|
||||
}
|
||||
|
||||
void neovim_ready_for_rpcevents(void **argv) {
|
||||
work_async(argv, ^(NSData *data) {
|
||||
aucmd_schedule_guienter();
|
||||
});
|
||||
static int foreground_for(HlAttrs attrs) {
|
||||
const int mask = attrs.rgb_ae_attr;
|
||||
return mask & HL_INVERSE ? attrs.rgb_bg_color : attrs.rgb_fg_color;
|
||||
}
|
||||
|
||||
void neovim_debug1(void **argv) {
|
||||
work_async(argv, ^(NSData *data) {
|
||||
// yet noop
|
||||
os_log(logger, "debug1");
|
||||
});
|
||||
static int background_for(HlAttrs attrs) {
|
||||
const int mask = attrs.rgb_ae_attr;
|
||||
return mask & HL_INVERSE ? attrs.rgb_fg_color : attrs.rgb_bg_color;
|
||||
}
|
||||
|
||||
static void send_colorscheme() {
|
||||
// It seems that the highlight groupt only gets updated when the screen is
|
||||
// redrawn. Since there's a guard var, probably it's safe to call it here...
|
||||
if (need_highlight_changed) { highlight_changed(); }
|
||||
|
||||
const HlAttrs visualAttrs = syn_attr2entry(highlight_attr[HLF_V]);
|
||||
const HlAttrs dirAttrs = syn_attr2entry(highlight_attr[HLF_D]);
|
||||
|
||||
send_msg_packing(
|
||||
NvimServerMsgIdColorSchemeChanged,
|
||||
^(msgpack_packer *packer) {
|
||||
msgpack_pack_array(packer, 5);
|
||||
msgpack_pack_int64(packer, normal_fg);
|
||||
msgpack_pack_int64(packer, normal_bg);
|
||||
msgpack_pack_int64(packer, foreground_for(visualAttrs));
|
||||
msgpack_pack_int64(packer, background_for(visualAttrs));
|
||||
msgpack_pack_int64(packer, foreground_for(dirAttrs));
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void server_set_ui_size(UIBridgeData *bridge, int width, int height) {
|
||||
bridge->ui->width = width;
|
||||
bridge->ui->height = height;
|
||||
bridge->bridge.width = width;
|
||||
bridge->bridge.height = height;
|
||||
}
|
||||
|
||||
static void server_ui_scheduler(Event event, void *d) {
|
||||
UI *const ui = d;
|
||||
server_ui_bridge_data_t *data = ui->data;
|
||||
loop_schedule(data->loop, event);
|
||||
}
|
||||
|
||||
static void server_ui_main(UIBridgeData *bridge, UI *ui) {
|
||||
msgpack_sbuffer_init(&flush_sbuffer);
|
||||
msgpack_packer_init(&flush_packer, &flush_sbuffer, msgpack_sbuffer_write);
|
||||
|
||||
Loop loop;
|
||||
loop_init(&loop, NULL);
|
||||
|
||||
ui->data = &bridge_data;
|
||||
bridge_data.bridge = bridge;
|
||||
bridge_data.loop = &loop;
|
||||
|
||||
server_set_ui_size(bridge, bridge_data.init_width, bridge_data.init_height);
|
||||
|
||||
bridge_data.stop = false;
|
||||
CONTINUE(bridge);
|
||||
|
||||
send_msg_packing(NvimServerMsgIdNvimReady, ^(msgpack_packer *packer) {
|
||||
msgpack_pack_bool(packer, msg_didany > 0);
|
||||
});
|
||||
|
||||
// We have to manually trigger this to initially get the colorscheme.
|
||||
send_colorscheme();
|
||||
|
||||
while (!bridge_data.stop) { loop_poll_events(&loop, -1); }
|
||||
|
||||
ui_bridge_stopped(bridge);
|
||||
loop_close(&loop, false);
|
||||
|
||||
server_destroy_local_port();
|
||||
server_destroy_remote_port();
|
||||
xfree(ui);
|
||||
|
||||
free(msgpack_sbuffer_release(&flush_sbuffer));
|
||||
|
||||
// mch_exit() of neovim will call exit(...)
|
||||
}
|
32
NvimView/NvimServer/server_ui_bridge.h
Normal file
32
NvimView/NvimServer/server_ui_bridge.h
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#ifndef NVIMSERVER_SERVER_UI_BRIDGE_H
|
||||
#define NVIMSERVER_SERVER_UI_BRIDGE_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
|
||||
|
||||
#include <nvim/api/private/defs.h>
|
||||
#include <nvim/ui_bridge.h>
|
||||
|
||||
typedef struct {
|
||||
UIBridgeData *bridge;
|
||||
Loop *loop;
|
||||
|
||||
bool stop;
|
||||
|
||||
int init_width;
|
||||
int init_height;
|
||||
} server_ui_bridge_data_t;
|
||||
|
||||
extern server_ui_bridge_data_t bridge_data;
|
||||
|
||||
void server_set_ui_size(UIBridgeData *bridge, int width, int height);
|
||||
|
||||
#endif // NVIMSERVER_SERVER_UI_BRIDGE_H
|
@ -8,6 +8,7 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1929B00C084F8EA5EF0BE6E2 /* NvimView+Geometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BD896D408673954F4AA2 /* NvimView+Geometry.swift */; };
|
||||
1929B0533B55B2349DE2EFE2 /* foundation_shim.h in Headers */ = {isa = PBXBuildFile; fileRef = 1929B27A8FF9A75A09969777 /* foundation_shim.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
1929B06F50B2585777FFBE48 /* NvimApiCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B002A03693B14B14BE34 /* NvimApiCommons.swift */; };
|
||||
1929B0B1A64AA449F666FCC9 /* 1.json in Resources */ = {isa = PBXBuildFile; fileRef = 1929B8619FD13BC2570CBFB2 /* 1.json */; };
|
||||
1929B14D2EBC34BCFEC78ACB /* CellAttributesCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BB19DD03ECD6ECC35F94 /* CellAttributesCollection.swift */; };
|
||||
@ -49,11 +50,14 @@
|
||||
1929BEA71F454E92A0CE5AB6 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9C55A79D97272894F5D /* SwiftCommons.swift */; };
|
||||
1929BF6E40C70A4157A5C755 /* UGridTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBA08E4195666290EC6A /* UGridTest.swift */; };
|
||||
1929BF95400085EE3F0FFAD5 /* FontTrait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9D7F040B8B9E2F038DF /* FontTrait.swift */; };
|
||||
1929BFEAF40AE8349E800CE4 /* server.c in Sources */ = {isa = PBXBuildFile; fileRef = 1929B7398AD1DE525FA53E38 /* server.c */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
4B06F70A2247FBEE0069C9F2 /* server_ui_bridge.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B06F7092247FBEE0069C9F2 /* server_ui_bridge.c */; };
|
||||
4B0A1B142129F49500F1E02F /* SwiftCommonsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0A1B132129F49500F1E02F /* SwiftCommonsTest.swift */; };
|
||||
4B0A1B39212B332800F1E02F /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B0A1B38212B332800F1E02F /* Nimble.framework */; };
|
||||
4B0A1B3B212B333700F1E02F /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B0A1B38212B332800F1E02F /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4B17E549209E3E4100265C1D /* RxNeovimApi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B17E548209E3E4100265C1D /* RxNeovimApi.framework */; };
|
||||
4B21ED53213D4AEC009FD017 /* CocoaCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B0C89838D8402BB80BFC /* CocoaCommons.swift */; };
|
||||
4B379CCD2248CFB7004B89B4 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B379CCC2248CFB6004B89B4 /* CoreFoundation.framework */; };
|
||||
4B4A48DC222C7C6A00C8E3A1 /* SharedTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B4A48DB222C7C6A00C8E3A1 /* SharedTypes.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4B6DFB39223592B90066BB43 /* OSLogCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B39C7DCDA4E9D5220CD8 /* OSLogCommons.swift */; };
|
||||
4B8662E81FDC3F9F007F490D /* com.qvacua.NvimView.vim in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B8662E41FDC3D4F007F490D /* com.qvacua.NvimView.vim */; };
|
||||
@ -68,10 +72,7 @@
|
||||
4B90F03F1FD2AFAE008A39E0 /* NvimView+Draw.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0211FD2AFAD008A39E0 /* NvimView+Draw.swift */; };
|
||||
4B90F0421FD2AFAE008A39E0 /* NvimView+UiBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */; };
|
||||
4B90F0431FD2AFAE008A39E0 /* NvimView+MenuItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0251FD2AFAD008A39E0 /* NvimView+MenuItems.swift */; };
|
||||
4B90F0521FD2AFD3008A39E0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0511FD2AFD3008A39E0 /* main.m */; };
|
||||
4B90F0661FD2AFF7008A39E0 /* server_ui.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0561FD2AFF7008A39E0 /* server_ui.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
4B90F0681FD2AFF7008A39E0 /* CocoaCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F05A1FD2AFF7008A39E0 /* CocoaCategories.m */; };
|
||||
4B90F06B1FD2AFF7008A39E0 /* NvimServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0641FD2AFF7008A39E0 /* NvimServer.m */; };
|
||||
4B90F0521FD2AFD3008A39E0 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0511FD2AFD3008A39E0 /* main.c */; };
|
||||
4B9E5E1C20990DF2006455C3 /* RxMessagePort.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9E5E1B20990DF1006455C3 /* RxMessagePort.framework */; };
|
||||
4BB1F5C9209740E400EC394A /* RxMsgpackRpc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB1F5C8209740E400EC394A /* RxMsgpackRpc.framework */; };
|
||||
4BB1F5CB209740E900EC394A /* MessagePack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB1F5CA209740E900EC394A /* MessagePack.framework */; };
|
||||
@ -100,7 +101,6 @@
|
||||
4BF01CF0223502CC00411218 /* SwiftCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B9C55A79D97272894F5D /* SwiftCommons.swift */; };
|
||||
4BF01CF1223502D400411218 /* Defs.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BF14AE831C6832659B66 /* Defs.swift */; };
|
||||
4BF01CF2223502DB00411218 /* CoreCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BAB9FFE8345228B559EC /* CoreCommons.swift */; };
|
||||
4BF01CF32235030E00411218 /* OSLogCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B39C7DCDA4E9D5220CD8 /* OSLogCommons.swift */; };
|
||||
4BF18510212DCCEA00954FE7 /* NvimView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B90F0041FD2AF59008A39E0 /* NvimView.framework */; };
|
||||
4BF18511212DCCF600954FE7 /* NvimView.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B90F0041FD2AF59008A39E0 /* NvimView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4BF18512212DCD6E00954FE7 /* RxNeovimApi.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B17E548209E3E4100265C1D /* RxNeovimApi.framework */; };
|
||||
@ -202,12 +202,15 @@
|
||||
1929B0C89838D8402BB80BFC /* CocoaCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CocoaCommons.swift; sourceTree = "<group>"; };
|
||||
1929B114CC85D012D7477D58 /* PerfTester.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerfTester.swift; sourceTree = "<group>"; };
|
||||
1929B22A0CAD417EC3790F02 /* NvimView+Objects.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+Objects.swift"; sourceTree = "<group>"; };
|
||||
1929B27A8FF9A75A09969777 /* foundation_shim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = foundation_shim.h; sourceTree = "<group>"; };
|
||||
1929B2CE622DF2B4D21D0C0E /* FontTrait.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FontTrait.swift; sourceTree = "<group>"; };
|
||||
1929B39C7DCDA4E9D5220CD8 /* OSLogCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OSLogCommons.swift; sourceTree = "<group>"; };
|
||||
1929B3EAE37505620F8AECD5 /* server.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server.h; sourceTree = "<group>"; };
|
||||
1929B47330DAD129520A2273 /* Typesetter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Typesetter.swift; sourceTree = "<group>"; };
|
||||
1929B52174EC68D2974B5BAE /* UiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiBridge.swift; sourceTree = "<group>"; };
|
||||
1929B60D1775A75D7C0F6721 /* SimpleCache.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleCache.swift; sourceTree = "<group>"; };
|
||||
1929B73455764E42DACF6BB8 /* Geometry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Geometry.swift; sourceTree = "<group>"; };
|
||||
1929B7398AD1DE525FA53E38 /* server.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server.c; sourceTree = "<group>"; };
|
||||
1929B8619FD13BC2570CBFB2 /* 1.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = 1.json; sourceTree = "<group>"; };
|
||||
1929B8E176C11DD61A8DCE95 /* RxSwiftCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxSwiftCommons.swift; sourceTree = "<group>"; };
|
||||
1929B9290D503536FFDA9C49 /* MessagePackCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackCommons.swift; sourceTree = "<group>"; };
|
||||
@ -229,12 +232,18 @@
|
||||
1929BF14AE831C6832659B66 /* Defs.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Defs.swift; sourceTree = "<group>"; };
|
||||
1929BF88DE64FC62AFFCBC84 /* NimbleCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NimbleCommons.swift; sourceTree = "<group>"; };
|
||||
1929BFCCDE5C7145BE5A7387 /* TypesetterTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypesetterTest.swift; sourceTree = "<group>"; };
|
||||
1929BFDA282A4CA4838385E9 /* foundation_shim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = foundation_shim.h; sourceTree = "<group>"; };
|
||||
4B06F7082247FBEE0069C9F2 /* server_ui_bridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server_ui_bridge.h; sourceTree = "<group>"; };
|
||||
4B06F7092247FBEE0069C9F2 /* server_ui_bridge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server_ui_bridge.c; sourceTree = "<group>"; };
|
||||
4B06F70B22481D3A0069C9F2 /* include */ = {isa = PBXFileReference; lastKnownFileType = folder; name = include; path = neovim/build/include; sourceTree = "<group>"; };
|
||||
4B06F70C22481D980069C9F2 /* ui_events.generated.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ui_events.generated.h; path = neovim/build/src/nvim/auto/ui_events.generated.h; sourceTree = "<group>"; };
|
||||
4B0A1B112129F49500F1E02F /* NvimViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NvimViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4B0A1B132129F49500F1E02F /* SwiftCommonsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftCommonsTest.swift; sourceTree = "<group>"; };
|
||||
4B0A1B152129F49500F1E02F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
4B0A1B38212B332800F1E02F /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = ../Carthage/Build/Mac/Nimble.framework; sourceTree = "<group>"; };
|
||||
4B17E548209E3E4100265C1D /* RxNeovimApi.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxNeovimApi.framework; path = ../Carthage/Build/Mac/RxNeovimApi.framework; sourceTree = "<group>"; };
|
||||
4B4A48DA222C7C5600C8E3A1 /* SharedTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTypes.h; sourceTree = "<group>"; };
|
||||
4B379CCC2248CFB6004B89B4 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
4B4A48DA222C7C5600C8E3A1 /* server_shared_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server_shared_types.h; sourceTree = "<group>"; };
|
||||
4B4A48DB222C7C6A00C8E3A1 /* SharedTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTypes.h; sourceTree = "<group>"; };
|
||||
4B8662E41FDC3D4F007F490D /* com.qvacua.NvimView.vim */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.vim; path = com.qvacua.NvimView.vim; sourceTree = "<group>"; };
|
||||
4B90F0041FD2AF59008A39E0 /* NvimView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NvimView.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@ -251,14 +260,8 @@
|
||||
4B90F0241FD2AFAD008A39E0 /* NvimView+UiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+UiBridge.swift"; sourceTree = "<group>"; };
|
||||
4B90F0251FD2AFAD008A39E0 /* NvimView+MenuItems.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NvimView+MenuItems.swift"; sourceTree = "<group>"; };
|
||||
4B90F04F1FD2AFD3008A39E0 /* NvimServer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = NvimServer; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4B90F0511FD2AFD3008A39E0 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
4B90F0561FD2AFF7008A39E0 /* server_ui.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = server_ui.m; sourceTree = "<group>"; };
|
||||
4B90F0571FD2AFF7008A39E0 /* CocoaCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CocoaCategories.h; sourceTree = "<group>"; };
|
||||
4B90F05A1FD2AFF7008A39E0 /* CocoaCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CocoaCategories.m; sourceTree = "<group>"; };
|
||||
4B90F05B1FD2AFF7008A39E0 /* Logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logging.h; sourceTree = "<group>"; };
|
||||
4B90F0621FD2AFF7008A39E0 /* NvimServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NvimServer.h; sourceTree = "<group>"; };
|
||||
4B90F0631FD2AFF7008A39E0 /* server_ui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server_ui.h; sourceTree = "<group>"; };
|
||||
4B90F0641FD2AFF7008A39E0 /* NvimServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NvimServer.m; sourceTree = "<group>"; };
|
||||
4B90F0511FD2AFD3008A39E0 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
|
||||
4B90F05B1FD2AFF7008A39E0 /* server_log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = server_log.h; sourceTree = "<group>"; };
|
||||
4B9E5E1B20990DF1006455C3 /* RxMessagePort.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxMessagePort.framework; path = ../Carthage/Build/Mac/RxMessagePort.framework; sourceTree = "<group>"; };
|
||||
4BB1F5C8209740E400EC394A /* RxMsgpackRpc.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RxMsgpackRpc.framework; path = ../Carthage/Build/Mac/RxMsgpackRpc.framework; sourceTree = "<group>"; };
|
||||
4BB1F5CA209740E900EC394A /* MessagePack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessagePack.framework; path = ../Carthage/Build/Mac/MessagePack.framework; sourceTree = "<group>"; };
|
||||
@ -277,7 +280,6 @@
|
||||
4BF1852721313EE500954FE7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||
4BF1852921313EE500954FE7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
4BF18C5A1FD2E72D00DF95D1 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = neovim/src/nvim; sourceTree = "<group>"; };
|
||||
4BF18C5B1FD2E74800DF95D1 /* auto */ = {isa = PBXFileReference; lastKnownFileType = folder; name = auto; path = neovim/build/src/nvim/auto; sourceTree = "<group>"; };
|
||||
4BF18C5C1FD2EEE400DF95D1 /* NvimView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NvimView.h; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
@ -314,6 +316,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4B379CCD2248CFB7004B89B4 /* CoreFoundation.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -381,8 +384,9 @@
|
||||
4B90EFFA1FD2AF59008A39E0 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4BF18C5B1FD2E74800DF95D1 /* auto */,
|
||||
4B06F70C22481D980069C9F2 /* ui_events.generated.h */,
|
||||
4BF18C5A1FD2E72D00DF95D1 /* nvim */,
|
||||
4B06F70B22481D3A0069C9F2 /* include */,
|
||||
4BE45C0B1FD2DA49005C0A95 /* runtime */,
|
||||
4B90F0061FD2AF59008A39E0 /* NvimView */,
|
||||
4B90F0501FD2AFD3008A39E0 /* NvimServer */,
|
||||
@ -434,6 +438,7 @@
|
||||
1929BD896D408673954F4AA2 /* NvimView+Geometry.swift */,
|
||||
1929BA4C89E9FE90065C32F6 /* CursorModeShape.swift */,
|
||||
1929BF14AE831C6832659B66 /* Defs.swift */,
|
||||
1929B27A8FF9A75A09969777 /* foundation_shim.h */,
|
||||
);
|
||||
path = NvimView;
|
||||
sourceTree = "<group>";
|
||||
@ -441,15 +446,14 @@
|
||||
4B90F0501FD2AFD3008A39E0 /* NvimServer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B4A48DA222C7C5600C8E3A1 /* SharedTypes.h */,
|
||||
4B90F0511FD2AFD3008A39E0 /* main.m */,
|
||||
4B90F0571FD2AFF7008A39E0 /* CocoaCategories.h */,
|
||||
4B90F05A1FD2AFF7008A39E0 /* CocoaCategories.m */,
|
||||
4B90F05B1FD2AFF7008A39E0 /* Logging.h */,
|
||||
4B90F0621FD2AFF7008A39E0 /* NvimServer.h */,
|
||||
4B90F0641FD2AFF7008A39E0 /* NvimServer.m */,
|
||||
4B90F0631FD2AFF7008A39E0 /* server_ui.h */,
|
||||
4B90F0561FD2AFF7008A39E0 /* server_ui.m */,
|
||||
4B4A48DA222C7C5600C8E3A1 /* server_shared_types.h */,
|
||||
4B90F0511FD2AFD3008A39E0 /* main.c */,
|
||||
4B90F05B1FD2AFF7008A39E0 /* server_log.h */,
|
||||
1929B3EAE37505620F8AECD5 /* server.h */,
|
||||
1929B7398AD1DE525FA53E38 /* server.c */,
|
||||
4B06F7082247FBEE0069C9F2 /* server_ui_bridge.h */,
|
||||
4B06F7092247FBEE0069C9F2 /* server_ui_bridge.c */,
|
||||
1929BFDA282A4CA4838385E9 /* foundation_shim.h */,
|
||||
);
|
||||
path = NvimServer;
|
||||
sourceTree = "<group>";
|
||||
@ -457,6 +461,7 @@
|
||||
4B90F06F1FD2B9F1008A39E0 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4B379CCC2248CFB6004B89B4 /* CoreFoundation.framework */,
|
||||
4BEBC239215FD19C007113C4 /* Socket.framework */,
|
||||
4B0A1B38212B332800F1E02F /* Nimble.framework */,
|
||||
4B17E548209E3E4100265C1D /* RxNeovimApi.framework */,
|
||||
@ -506,6 +511,7 @@
|
||||
files = (
|
||||
4BF18C5D1FD2EEE400DF95D1 /* NvimView.h in Headers */,
|
||||
4B4A48DC222C7C6A00C8E3A1 /* SharedTypes.h in Headers */,
|
||||
1929B0533B55B2349DE2EFE2 /* foundation_shim.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -711,7 +717,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/bash;
|
||||
shellScript = "if [[ $(md5 -q NvimView/SharedTypes.h) != $(md5 -q NvimServer/SharedTypes.h) ]]; then\n echo \"SharedTypes.h not equal!\"\n exit 1\nfi\n";
|
||||
shellScript = "if [[ $(md5 -q NvimView/SharedTypes.h) != $(md5 -q NvimServer/server_shared_types.h) ]]; then\n echo \"SharedTypes.h not equal!\"\n exit 1\nfi\n";
|
||||
};
|
||||
4BE45C091FD2D92D005C0A95 /* ShellScript */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@ -790,10 +796,9 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
4B90F06B1FD2AFF7008A39E0 /* NvimServer.m in Sources */,
|
||||
4B90F0661FD2AFF7008A39E0 /* server_ui.m in Sources */,
|
||||
4B90F0521FD2AFD3008A39E0 /* main.m in Sources */,
|
||||
4B90F0681FD2AFF7008A39E0 /* CocoaCategories.m in Sources */,
|
||||
4B90F0521FD2AFD3008A39E0 /* main.c in Sources */,
|
||||
1929BFEAF40AE8349E800CE4 /* server.c in Sources */,
|
||||
4B06F70A2247FBEE0069C9F2 /* server_ui_bridge.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1070,17 +1075,19 @@
|
||||
4B90F0541FD2AFD3008A39E0 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = NO;
|
||||
CLANG_LINK_OBJC_RUNTIME = NO;
|
||||
CLANG_MODULES_AUTOLINK = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"$(inherited)",
|
||||
"INCLUDE_GENERATED_DECLARATIONS=1",
|
||||
);
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(PROJECT_DIR)/neovim/build/include",
|
||||
"$(PROJECT_DIR)/neovim/src",
|
||||
"$(PROJECT_DIR)/neovim/build/include",
|
||||
"$(PROJECT_DIR)/neovim/.deps/usr/include",
|
||||
"$(PROJECT_DIR)/neovim/build/config",
|
||||
"$(PROJECT_DIR)/third-party/libintl/include",
|
||||
"$(PROJECT_DIR)/neovim/build/src/nvim/auto",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(PROJECT_DIR)/neovim/build/lib",
|
||||
@ -1111,14 +1118,16 @@
|
||||
4B90F0551FD2AFD3008A39E0 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CLANG_ENABLE_MODULES = NO;
|
||||
CLANG_LINK_OBJC_RUNTIME = NO;
|
||||
CLANG_MODULES_AUTOLINK = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "INCLUDE_GENERATED_DECLARATIONS=1";
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(PROJECT_DIR)/neovim/build/include",
|
||||
"$(PROJECT_DIR)/neovim/src",
|
||||
"$(PROJECT_DIR)/neovim/build/include",
|
||||
"$(PROJECT_DIR)/neovim/.deps/usr/include",
|
||||
"$(PROJECT_DIR)/neovim/build/config",
|
||||
"$(PROJECT_DIR)/third-party/libintl/include",
|
||||
"$(PROJECT_DIR)/neovim/build/src/nvim/auto",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(PROJECT_DIR)/neovim/build/lib",
|
||||
|
@ -63,6 +63,24 @@
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "nvim-local"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "nvim-remote"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
<CommandLineArgument
|
||||
argument = "third"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
<LocationScenarioReference
|
||||
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||
referenceType = "1">
|
||||
</LocationScenarioReference>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
@ -15,3 +15,4 @@ FOUNDATION_EXPORT const unsigned char NvimViewVersionString[];
|
||||
|
||||
// TODO: this header should not be public, but we cannot use a bridging header in a framework.
|
||||
#import <NvimView/SharedTypes.h>
|
||||
#import <NvimView/foundation_shim.h>
|
||||
|
@ -3,9 +3,12 @@
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#ifndef NVIMSERVER_SHARED_TYPES_H
|
||||
#define NVIMSERVER_SHARED_TYPES_H
|
||||
|
||||
typedef NS_OPTIONS(NSUInteger, FontTrait) {
|
||||
#include "foundation_shim.h"
|
||||
|
||||
typedef CF_OPTIONS(NSUInteger, FontTrait) {
|
||||
FontTraitNone = 0,
|
||||
FontTraitItalic = (1 << 0),
|
||||
FontTraitBold = (1 << 1),
|
||||
@ -13,13 +16,13 @@ typedef NS_OPTIONS(NSUInteger, FontTrait) {
|
||||
FontTraitUndercurl = (1 << 3)
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, RenderDataType) {
|
||||
typedef CF_ENUM(NSInteger, RenderDataType) {
|
||||
RenderDataTypeRawLine,
|
||||
RenderDataTypeGoto,
|
||||
RenderDataTypeScroll,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, NvimServerMsgId) {
|
||||
typedef CF_ENUM(NSInteger, NvimServerMsgId) {
|
||||
NvimServerMsgIdServerReady = 0,
|
||||
NvimServerMsgIdNvimReady,
|
||||
NvimServerMsgIdResize,
|
||||
@ -35,7 +38,7 @@ typedef NS_ENUM(NSInteger, NvimServerMsgId) {
|
||||
NvimServerMsgIdSetTitle,
|
||||
NvimServerMsgIdStop,
|
||||
NvimServerMsgIdOptionSet,
|
||||
|
||||
|
||||
NvimServerMsgIdDirtyStatusChanged,
|
||||
NvimServerMsgIdCwdChanged,
|
||||
NvimServerMsgIdColorSchemeChanged,
|
||||
@ -46,14 +49,16 @@ typedef NS_ENUM(NSInteger, NvimServerMsgId) {
|
||||
NvimServerMsgIdDebug1,
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSInteger, NvimBridgeMsgId) {
|
||||
typedef CF_ENUM(NSInteger, NvimBridgeMsgId) {
|
||||
NvimBridgeMsgIdAgentReady = 0,
|
||||
NvimBridgeMsgIdReadyForRpcEvents,
|
||||
NvimBridgeMsgIdDeleteInput,
|
||||
NvimBridgeMsgIdResize,
|
||||
NvimBridgeMsgIdScroll,
|
||||
|
||||
|
||||
NvimBridgeMsgIdFocusGained,
|
||||
|
||||
|
||||
NvimBridgeMsgIdDebug1,
|
||||
};
|
||||
|
||||
#endif // NVIMSERVER_SHARED_TYPES_H
|
||||
|
11
NvimView/NvimView/foundation_shim.h
Normal file
11
NvimView/NvimView/foundation_shim.h
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#ifndef NVIMSERVER_FOUNDATION_SHIM_H
|
||||
#define NVIMSERVER_FOUNDATION_SHIM_H
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
|
||||
#endif // NVIMSERVER_FOUNDATION_SHIM_H
|
@ -1 +1 @@
|
||||
Subproject commit 54c9468a7424d5b4ad754ce22a65910102808a72
|
||||
Subproject commit dcb37af2a59d4e456a2389755afe4e4313d21ca3
|
Loading…
Reference in New Issue
Block a user