1
1
mirror of https://github.com/qvacua/vimr.git synced 2024-12-25 06:43:24 +03:00

Merge remote-tracking branch 'origin/develop' into update-neovim

This commit is contained in:
Tae Won Ha 2018-05-13 18:24:26 +02:00
commit 52e3401760
21 changed files with 422 additions and 516 deletions

View File

@ -8,7 +8,7 @@ github "qvacua/RxMsgpackRpc" == 0.0.1
github "qvacua/RxMessagePort" == 0.0.1
github "qvacua/RxNeovimApi" "nightly"
github "sindresorhus/github-markdown-css" == 2.10.0
github "qvacua/swifter" "stable"
github "httpswift/swifter" == 1.4.1
github "a2/MessagePack.swift" == 3.0.0
github "Quick/Nimble" == 7.0.3

View File

@ -3,11 +3,11 @@ github "Quick/Nimble" "v7.0.3"
github "ReactiveX/RxSwift" "4.1.2"
github "a2/MessagePack.swift" "3.0.0"
github "eonil/FileSystemEvents" "85a089104af37f04a6bf7f2d07d7a93cac0b4fe1"
github "httpswift/swifter" "1.4.1"
github "qvacua/CocoaFontAwesome" "76cf6c4ef3088d84f78988183c56fc6abdc19f83"
github "qvacua/CocoaMarkdown" "7756ad96d5fb390c66531004868e828bb54d3609"
github "qvacua/RxMessagePort" "v0.0.1"
github "qvacua/RxMsgpackRpc" "v0.0.1"
github "qvacua/RxNeovimApi" "nightly"
github "qvacua/swifter" "6fc24bdb5bbafd01efa8e448070c6e8ba89fcf0f"
github "sindresorhus/github-markdown-css" "v2.10.0"
github "sparkle-project/Sparkle" "1.18.1"

View File

@ -1,14 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import <Foundation/Foundation.h>
@interface DataWrapper : NSObject
@property (strong) NSData *data;
@property (getter=isDataReady) bool dataReady;
@end

View File

@ -1,9 +0,0 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
#import "DataWrapper.h"
@implementation DataWrapper { } @end

View File

@ -15,7 +15,8 @@
nvimArgs:(NSArray<NSString *> *)nvimArgs;
- (void)sendMessageWithId:(NvimServerMsgId)msgid;
- (void)sendMessageWithId:(NvimServerMsgId)msgid data:(NSData *)data;
- (void)sendMessageWithId:(NvimServerMsgId)msgid data:(CFDataRef)data;
- (void)notifyReadiness;
@end

View File

@ -7,7 +7,6 @@
#import "server_ui.h"
#import "Logging.h"
#import "CocoaCategories.h"
#import "DataWrapper.h"
// FileInfo and Boolean are #defined by Carbon and NeoVim: Since we don't need the Carbon versions of them, we rename
// them.
@ -23,63 +22,59 @@
//#define DEBUG_NEOVIM_SERVER_STANDALONE
static const double qTimeout = 10;
static const double qTimeout = 5;
@interface NvimServer ()
- (NSArray<NSString *> *)nvimArgs;
- (NSCondition *)outputCondition;
@end
static CFDataRef data_sync(CFDataRef data, NSCondition *condition, argv_callback cb) {
DataWrapper *wrapper = [[DataWrapper alloc] init];
NSDate *deadline = [[NSDate date] dateByAddingTimeInterval:qTimeout];
[condition lock];
loop_schedule(&main_loop, event_create(cb, 3, data, condition, wrapper));
while (wrapper.isDataReady == false && [condition waitUntilDate:deadline]);
[condition unlock];
if (wrapper.data == nil) {
return NULL;
}
return CFDataCreateCopy(kCFAllocatorDefault, (__bridge CFDataRef) wrapper.data);
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) {
@autoreleasepool {
NvimServer *neoVimServer = (__bridge NvimServer *) info;
NSCondition *outputCondition = neoVimServer.outputCondition;
CFRetain(data); // release in the loop callbacks!
CFRetain(data); // release in the loop callbacks! (or in the case clause when not passed to the callback)
switch (msgid) {
switch (msgid) {
case NvimBridgeMsgIdAgentReady: {
case NvimBridgeMsgIdAgentReady: {
@autoreleasepool {
NSInteger *values = (NSInteger *) CFDataGetBytePtr(data);
start_neovim(values[0], values[1], neoVimServer.nvimArgs);
return NULL;
NvimServer *nvimServer = (__bridge NvimServer *) info;
start_neovim(values[0], values[1], nvimServer.nvimArgs);
CFRelease(data);
}
case NvimBridgeMsgIdScroll: return data_sync(data, outputCondition, neovim_scroll);
case NvimBridgeMsgIdResize: return data_sync(data, outputCondition, neovim_resize);
case NvimBridgeMsgIdInput: return data_sync(data, outputCondition, neovim_vim_input);
case NvimBridgeMsgIdInputMarked: return data_sync(data, outputCondition, neovim_vim_input_marked_text);
case NvimBridgeMsgIdDelete: return data_sync(data, outputCondition, neovim_delete);
case NvimBridgeMsgIdFocusGained: return data_sync(data, outputCondition, neovim_focus_gained);
default: return NULL;
return NULL;
}
case NvimBridgeMsgIdScroll:
return data_async(data, neovim_scroll);
case NvimBridgeMsgIdResize:
return data_async(data, neovim_resize);
case NvimBridgeMsgIdInput:
return data_async(data, neovim_vim_input);
case NvimBridgeMsgIdInputMarked:
return data_async(data, neovim_vim_input_marked_text);
case NvimBridgeMsgIdDelete:
return data_async(data, neovim_delete);
case NvimBridgeMsgIdFocusGained:
return data_async(data, neovim_focus_gained);
default:
CFRelease(data);
return NULL;
}
}
@ -108,7 +103,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
- (instancetype)initWithLocalServerName:(NSString *)localServerName
remoteServerName:(NSString *)remoteServerName
nvimArgs:(NSArray<NSString*> *)nvimArgs {
nvimArgs:(NSArray<NSString *> *)nvimArgs {
self = [super init];
if (self == nil) {
@ -182,33 +177,31 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
}
- (void)sendMessageWithId:(NvimServerMsgId)msgid {
[self sendMessageWithId:msgid data:nil];
[self sendMessageWithId:msgid data:NULL];
}
- (void)sendMessageWithId:(NvimServerMsgId)msgid data:(NSData *)data {
- (void)sendMessageWithId:(NvimServerMsgId)msgid data:(CFDataRef)data {
#ifdef DEBUG_NEOVIM_SERVER_STANDALONE
return;
#endif
if (_remoteServerPort == NULL) {
WLOG("Remote server is null: The msg (%lu:%s) could not be sent.", (unsigned long) msgid, data.cdesc);
WLOG("Remote server is null: The msg (%lu) could not be sent.", (unsigned long) msgid);
return;
}
SInt32 responseCode = CFMessagePortSendRequest(
_remoteServerPort, msgid, (__bridge CFDataRef) data, qTimeout, qTimeout, NULL, NULL
);
SInt32 responseCode = CFMessagePortSendRequest(_remoteServerPort, msgid, data, qTimeout, qTimeout, NULL, NULL);
if (responseCode == kCFMessagePortSuccess) {
return;
}
WLOG("The msg (%lu:%s) could not be sent: %d", (unsigned long) msgid, data.cdesc, responseCode);
WLOG("The msg (%lu) could not be sent: %d", (unsigned long) msgid, responseCode);
}
- (void)notifyReadiness {
#ifndef DEBUG_NEOVIM_SERVER_STANDALONE
[self sendMessageWithId:NvimServerMsgIdServerReady data:nil];
[self sendMessageWithId:NvimServerMsgIdServerReady data:NULL];
#endif
}

View File

@ -48,8 +48,8 @@ int main(int argc, const char *argv[]) {
: nil;
_neovim_server = [[NvimServer alloc] initWithLocalServerName:localServerName
remoteServerName:remoteServerName
nvimArgs:nvimArgs];
remoteServerName:remoteServerName
nvimArgs:nvimArgs];
DLOG("Started neovim server '%s' with args '%@' and connected it with the remote agent '%s'.",
localServerName.cstr, nvimArgs, remoteServerName.cstr);

View File

@ -9,8 +9,6 @@
#import "server_ui.h"
#import "NvimServer.h"
#import "CocoaCategories.h"
#import "DataWrapper.h"
#import "SharedTypes.h"
// FileInfo and Boolean are #defined by Carbon and NeoVim:
// Since we don't need the Carbon versions of them, we rename
@ -22,7 +20,6 @@
#import <nvim/api/vim.h>
#import <nvim/ui.h>
#import <nvim/ui_bridge.h>
#import <nvim/ex_getln.h>
#import <nvim/fileio.h>
#import <nvim/undo.h>
#import <nvim/mouse.h>
@ -32,8 +29,11 @@
#import <nvim/aucmd.h>
#import <nvim/msgpack_rpc/helpers.h>
#import <msgpack.h>
#import <nvim/api/private/helpers.h>
#define let __auto_type const
#define var __auto_type
#define pun_type(t, x) (*((t *) (&(x))))
@ -42,10 +42,10 @@ static NSInteger _default_background = 0xFFFFFFFF;
static NSInteger _default_special = 0xFFFF0000;
typedef struct {
UIBridgeData *bridge;
Loop *loop;
UIBridgeData *bridge;
Loop *loop;
bool stop;
bool stop;
} ServerUiData;
// We declare nvim_main because it's not declared in any header files of neovim
@ -82,11 +82,14 @@ static bool _dirty = false;
static NSInteger _initialWidth = 30;
static NSInteger _initialHeight = 15;
static NSMutableArray <NSData *> *_render_data;
static msgpack_sbuffer msg_sbuffer;
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 };
return (String) {.data = (char *) str.cstr, .size = str.clength};
}
static void refresh_ui_screen(int type) {
@ -105,8 +108,39 @@ static bool has_dirty_docs() {
return false;
}
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) {
msgpack_packer packer;
msgpack_packer_init(&packer, &msg_sbuffer, msgpack_sbuffer_write);
body(&packer);
let data = CFDataCreateWithBytesNoCopy(
kCFAllocatorDefault, (const UInt8 *) msg_sbuffer.data, msg_sbuffer.size, kCFAllocatorNull
);
[_neovim_server sendMessageWithId:msgid data:data];
CFRelease(data);
msgpack_sbuffer_clear(&msg_sbuffer);
}
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() {
bool new_dirty_status = has_dirty_docs();
var new_dirty_status = has_dirty_docs();
DLOG("dirty status: %d vs. %d", _dirty, new_dirty_status);
if (_dirty == new_dirty_status) {
return;
@ -114,23 +148,25 @@ static void send_dirty_status() {
_dirty = new_dirty_status;
DLOG("sending dirty status: %d", _dirty);
NSData *data = [[NSData alloc] initWithBytes:&_dirty length:sizeof(bool)];
[_neovim_server sendMessageWithId:NvimServerMsgIdDirtyStatusChanged data:data];
[data release];
send_msg_packing(NvimServerMsgIdDirtyStatusChanged, ^(msgpack_packer *packer) {
msgpack_pack_bool(packer, _dirty);
});
}
static void send_cwd() {
char_u *temp = xmalloc(MAXPATHL);
var temp = xmalloc(MAXPATHL);
if (os_dirname(temp, MAXPATHL) == FAIL) {
xfree(temp);
[_neovim_server sendMessageWithId:NvimServerMsgIdCwdChanged];
}
NSString *pwd = [NSString stringWithCString:(const char *) temp encoding:NSUTF8StringEncoding];
xfree(temp);
NSData *resultData = [pwd dataUsingEncoding:NSUTF8StringEncoding];
[_neovim_server sendMessageWithId:NvimServerMsgIdCwdChanged data:resultData];
send_msg_packing(NvimServerMsgIdCwdChanged, ^(msgpack_packer *packer) {
let value = cstr_to_string((const char *) temp);
msgpack_rpc_from_string(value, packer);
api_free_string(value);
xfree(temp);
});
}
static HlAttrs HlAttrsFromAttrCode(int attr_code) {
@ -139,18 +175,6 @@ static HlAttrs HlAttrsFromAttrCode(int attr_code) {
return rgb_attrs;
}
static void add_to_render_data(RenderDataType type, NSData *data) {
NSMutableData *rData = [NSMutableData new];
[rData appendBytes:&type length:sizeof(RenderDataType)];
if (data != nil) {
[rData appendData:data];
}
[_render_data addObject:rData];
[rData release];
}
static int foreground_for(HlAttrs attrs) {
int mask = attrs.rgb_ae_attr;
return mask & HL_INVERSE ? attrs.rgb_bg_color: attrs.rgb_fg_color;
@ -171,14 +195,14 @@ static void send_colorscheme() {
HlAttrs visualAttrs = HlAttrsFromAttrCode(highlight_attr[HLF_V]);
HlAttrs dirAttrs = HlAttrsFromAttrCode(highlight_attr[HLF_D]);
NSInteger values[] = {
normal_fg, normal_bg,
foreground_for(visualAttrs), background_for(visualAttrs),
foreground_for(dirAttrs),
};
NSData *resultData = [NSData dataWithBytes:values length:5 * sizeof(NSInteger)];
[_neovim_server sendMessageWithId:NvimServerMsgIdColorSchemeChanged data:resultData];
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 insert_marked_text(NSString *markedText) {
@ -188,7 +212,7 @@ static void insert_marked_text(NSString *markedText) {
}
static void delete_marked_text() {
NSUInteger length = [_marked_text lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4;
let length = [_marked_text lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4;
[_marked_text release];
_marked_text = nil;
@ -203,13 +227,13 @@ static void run_neovim(void *arg) {
char **argv;
@autoreleasepool {
NSArray<NSString *> *nvimArgs = (NSArray *) arg;
let nvimArgs = (NSArray<NSString *> *) arg;
argc = (int) nvimArgs.count + 1;
argv = (char **) malloc((argc + 1) * sizeof(char *));
argv[0] = "nvim";
for (int i = 0; i < nvimArgs.count; i++) {
for (var i = 0; i < nvimArgs.count; i++) {
argv[i + 1] = (char *) nvimArgs[(NSUInteger) i].cstr;
}
@ -235,7 +259,9 @@ static void server_ui_scheduler(Event event, void *d) {
}
static void server_ui_main(UIBridgeData *bridge, UI *ui) {
_render_data = [NSMutableArray new];
msgpack_sbuffer_init(&msg_sbuffer);
msgpack_sbuffer_init(&flush_sbuffer);
flush_packer = msgpack_packer_new(&flush_sbuffer, msgpack_sbuffer_write);
Loop loop;
loop_init(&loop, NULL);
@ -265,64 +291,63 @@ static void server_ui_main(UIBridgeData *bridge, UI *ui) {
xfree(_server_ui_data);
xfree(ui);
[_render_data release];
msgpack_sbuffer_clear(&flush_sbuffer);
msgpack_packer_free(flush_packer);
}
#pragma mark NeoVim's UI callbacks
static void server_ui_flush(UI *ui __unused) {
@autoreleasepool {
if (_render_data.count == 0) {
return;
}
[_neovim_server sendMessageWithId:NvimServerMsgIdFlush
data:[NSKeyedArchiver archivedDataWithRootObject:_render_data]];
[_render_data removeAllObjects];
if (flush_sbuffer.size == 0) {
return;
}
let data = CFDataCreateWithBytesNoCopy(
kCFAllocatorDefault, (const UInt8 *) flush_sbuffer.data, flush_sbuffer.size, kCFAllocatorNull
);
[_neovim_server sendMessageWithId:NvimServerMsgIdFlush data:data];
CFRelease(data);
msgpack_sbuffer_clear(&flush_sbuffer);
msgpack_packer_free(flush_packer);
flush_packer = msgpack_packer_new(&flush_sbuffer, msgpack_sbuffer_write);
}
static void server_ui_resize(UI *ui __unused, Integer width, Integer height) {
@autoreleasepool {
server_ui_flush(NULL);
server_ui_flush(NULL);
NSInteger values[] = {width, height};
NSData *data = [[NSData alloc] initWithBytes:values length:(2 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdResize data:data];
[data release];
}
send_msg_packing(NvimServerMsgIdResize, ^(msgpack_packer *packer) {
msgpack_pack_array(packer, 2);
msgpack_pack_int64(packer, width);
msgpack_pack_int64(packer, height);
});
}
static void server_ui_clear(UI *ui __unused) {
@autoreleasepool {
server_ui_flush(NULL);
}
server_ui_flush(NULL);
[_neovim_server sendMessageWithId:NvimServerMsgIdClear];
}
static void server_ui_eol_clear(UI *ui __unused) {
@autoreleasepool {
add_to_render_data(RenderDataTypeEolClear, nil);
}
pack_flush_data(RenderDataTypeEolClear, ^(msgpack_packer *packer) {
msgpack_pack_nil(packer);
});
}
static void server_ui_cursor_goto(UI *ui __unused, Integer row, Integer col) {
@autoreleasepool {
_put_row = row;
_put_column = col;
_put_row = row;
_put_column = col;
NSInteger values[] = {
row, col,
(NSInteger) curwin->w_cursor.lnum, curwin->w_cursor.col + 1
};
DLOG("%d:%d - %d:%d - %d:%d", row, col, curwin->w_cursor.lnum, curwin->w_cursor.col + 1);
DLOG("%d:%d - %d:%d - %d:%d", values[0], values[1], values[2], values[3]);
NSData *data = [[NSData alloc] initWithBytes:values length:(4 * sizeof(NSInteger))];
add_to_render_data(RenderDataTypeGoto, data);
[data release];
}
pack_flush_data(RenderDataTypeGoto, ^(msgpack_packer *packer) {
msgpack_pack_array(packer, 4);
msgpack_pack_int64(packer, row);
msgpack_pack_int64(packer, col);
msgpack_pack_int64(packer, curwin->w_cursor.lnum);
msgpack_pack_int64(packer, curwin->w_cursor.col + 1);
});
}
static void server_ui_update_menu(UI *ui __unused) {
@ -345,46 +370,40 @@ static void server_ui_mouse_off(UI *ui __unused) {
[_neovim_server sendMessageWithId:NvimServerMsgIdMouseOff];
}
static void server_ui_mode_info_set(UI *ui __unused, Boolean enabled __unused,
Array cursor_styles __unused) {
static void server_ui_mode_info_set(UI *ui __unused, Boolean enabled __unused, Array cursor_styles __unused) {
// yet noop
}
static void server_ui_mode_change(UI *ui __unused, String mode_str __unused, Integer mode) {
@autoreleasepool {
NSInteger value = mode;
NSData *data = [[NSData alloc] initWithBytes:&value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdModeChange data:data];
[data release];
send_msg_packing(NvimServerMsgIdModeChange, ^(msgpack_packer *packer) {
msgpack_pack_int64(packer, mode);
});
}
}
static void server_ui_set_scroll_region(UI *ui __unused, Integer top, Integer bot,
Integer left, Integer right) {
static void server_ui_set_scroll_region(UI *ui __unused, Integer top, Integer bot, Integer left, Integer right) {
server_ui_flush(NULL);
@autoreleasepool {
server_ui_flush(NULL);
NSInteger values[] = {top, bot, left, right};
NSData *data = [[NSData alloc] initWithBytes:values length:(4 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetScrollRegion data:data];
[data release];
}
send_msg_packing(NvimServerMsgIdSetScrollRegion, ^(msgpack_packer *packer) {
msgpack_pack_array(packer, 4);
msgpack_pack_int64(packer, top);
msgpack_pack_int64(packer, bot);
msgpack_pack_int64(packer, left);
msgpack_pack_int64(packer, right);
});
}
static void server_ui_scroll(UI *ui __unused, Integer count) {
@autoreleasepool {
server_ui_flush(NULL);
server_ui_flush(NULL);
NSInteger value = count;
NSData *data = [[NSData alloc] initWithBytes:&value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdScroll data:data];
[data release];
}
send_msg_packing(NvimServerMsgIdScroll, ^(msgpack_packer *packer) {
msgpack_pack_int64(packer, count);
});
}
static void server_ui_highlight_set(UI *ui __unused, HlAttrs attrs) {
FontTrait trait = FontTraitNone;
var trait = FontTraitNone;
if (attrs.rgb_ae_attr & HL_ITALIC) {
trait |= FontTraitItalic;
}
@ -400,52 +419,49 @@ static void server_ui_highlight_set(UI *ui __unused, HlAttrs attrs) {
CellAttributes cellAttrs;
cellAttrs.fontTrait = trait;
NSInteger fg = attrs.rgb_fg_color == -1 ? _default_foreground : attrs.rgb_fg_color;
NSInteger bg = attrs.rgb_bg_color == -1 ? _default_background : attrs.rgb_bg_color;
let fg = attrs.rgb_fg_color == -1 ? _default_foreground : attrs.rgb_fg_color;
let bg = attrs.rgb_bg_color == -1 ? _default_background : attrs.rgb_bg_color;
cellAttrs.foreground = attrs.rgb_ae_attr & HL_INVERSE ? bg : fg;
cellAttrs.background = attrs.rgb_ae_attr & HL_INVERSE ? fg : bg;
cellAttrs.special = attrs.rgb_sp_color == -1 ? _default_special : pun_type(unsigned int, attrs.rgb_sp_color);
@autoreleasepool {
NSData *data = [[NSData alloc] initWithBytes:&cellAttrs length:sizeof(CellAttributes)];
add_to_render_data(RenderDataTypeHighlight, data);
[data release];
}
pack_flush_data(RenderDataTypeHighlight, ^(msgpack_packer *packer) {
msgpack_pack_bin(packer, sizeof(cellAttrs));
msgpack_pack_bin_body(packer, &cellAttrs, sizeof(cellAttrs));
});
}
static void server_ui_put(UI *ui __unused, String str) {
NSString *string = [[NSString alloc] initWithBytes:str.data
length:str.size
encoding:NSUTF8StringEncoding];
if (_marked_text != nil
&& _marked_row == _put_row
&& _marked_column == _put_column) {
@autoreleasepool {
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
DLOG("putting marked text: '%s'", str.data);
pack_flush_data(RenderDataTypePutMarked, ^(msgpack_packer *packer) {
msgpack_rpc_from_string(str, packer);
});
if (_marked_text != nil && _marked_row == _put_row && _marked_column == _put_column) {
} else if (_marked_text != nil
&& str.size == 0
&& _marked_row == _put_row
&& _marked_column == _put_column - 1) {
DLOG("putting marked text: '%s'", string.cstr);
add_to_render_data(RenderDataTypePutMarked, data);
DLOG("putting marked text cuz zero");
pack_flush_data(RenderDataTypePutMarked, ^(msgpack_packer *packer) {
msgpack_rpc_from_string(str, packer);
});
} else if (_marked_text != nil
&& str.size == 0
&& _marked_row == _put_row
&& _marked_column == _put_column - 1) {
} else {
DLOG("putting marked text cuz zero");
add_to_render_data(RenderDataTypePutMarked, data);
DLOG("putting non-marked text: '%s'", str.data);
pack_flush_data(RenderDataTypePut, ^(msgpack_packer *packer) {
msgpack_rpc_from_string(str, packer);
});
} else {
DLOG("putting non-marked text: '%s'", string.cstr);
add_to_render_data(RenderDataTypePut, data);
}
_put_column += 1;
[string release];
}
_put_column += 1;
}
static void server_ui_bell(UI *ui __unused) {
@ -458,65 +474,38 @@ static void server_ui_visual_bell(UI *ui __unused) {
static void server_ui_update_fg(UI *ui __unused, Integer fg) {
@autoreleasepool {
NSInteger value[1];
if (fg == -1) {
value[0] = _default_foreground;
NSData *data = [[NSData alloc] initWithBytes:value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetForeground data:data];
[data release];
return;
if (fg != -1) {
_default_foreground = fg;
}
_default_foreground = fg;
value[0] = fg;
NSData *data = [[NSData alloc] initWithBytes:value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetForeground data:data];
[data release];
send_msg_packing(NvimServerMsgIdSetForeground, ^(msgpack_packer *packer) {
msgpack_pack_int64(packer, _default_foreground);
});
}
}
static void server_ui_update_bg(UI *ui __unused, Integer bg) {
@autoreleasepool {
NSInteger value[1];
if (bg == -1) {
value[0] = _default_background;
NSData *data = [[NSData alloc] initWithBytes:value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetBackground data:data];
[data release];
return;
if (bg != -1) {
_default_background = bg;
}
_default_background = bg;
value[0] = bg;
NSData *data = [[NSData alloc] initWithBytes:value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetBackground data:data];
[data release];
send_msg_packing(NvimServerMsgIdSetBackground, ^(msgpack_packer *packer) {
msgpack_pack_int64(packer, _default_background);
});
}
}
static void server_ui_update_sp(UI *ui __unused, Integer sp) {
@autoreleasepool {
NSInteger value[2];
if (sp == -1) {
value[0] = _default_special;
NSData *data = [[NSData alloc] initWithBytes:&value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetSpecial data:data];
[data release];
return;
if (sp != -1) {
_default_special = sp;
}
_default_special = sp;
value[0] = sp;
NSData *data = [[NSData alloc] initWithBytes:&value length:(1 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetSpecial data:data];
[data release];
send_msg_packing(NvimServerMsgIdSetSpecial, ^(msgpack_packer *packer) {
msgpack_pack_int64(packer, _default_special);
});
}
}
@ -536,10 +525,11 @@ static void server_ui_default_colors_set(
_default_special = rgb_sp;
}
NSInteger values[] = { rgb_fg, rgb_bg, rgb_sp };
NSData *resultData = [NSData dataWithBytes:values length:3 * sizeof(NSInteger)];
[_neovim_server sendMessageWithId:NvimServerMsgIdDefaultColorsChanged data:resultData];
send_msg_packing(NvimServerMsgIdDefaultColorsChanged, ^(msgpack_packer *packer) {
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) {
@ -548,10 +538,9 @@ static void server_ui_set_title(UI *ui __unused, String title) {
return;
}
NSString *string = [[NSString alloc] initWithCString:title.data encoding:NSUTF8StringEncoding];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetTitle
data:[string dataUsingEncoding:NSUTF8StringEncoding]];
[string release];
send_msg_packing(NvimServerMsgIdSetTitle, ^(msgpack_packer *packer) {
msgpack_rpc_from_string(title, packer);
});
}
}
@ -561,10 +550,9 @@ static void server_ui_set_icon(UI *ui __unused, String icon) {
return;
}
NSString *string = [[NSString alloc] initWithCString:icon.data encoding:NSUTF8StringEncoding];
[_neovim_server sendMessageWithId:NvimServerMsgIdSetIcon
data:[string dataUsingEncoding:NSUTF8StringEncoding]];
[string release];
send_msg_packing(NvimServerMsgIdSetTitle, ^(msgpack_packer *packer) {
msgpack_rpc_from_string(icon, packer);
});
}
}
@ -592,7 +580,7 @@ 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];
ServerUiData *data = (ServerUiData *) ui->data;
let data = (ServerUiData *) ui->data;
data->stop = true;
}
@ -663,42 +651,35 @@ void custom_ui_autocmds_groups(
}
if (event == EVENT_TEXTCHANGED
|| event == EVENT_TEXTCHANGEDI
|| event == EVENT_BUFWRITEPOST
|| event == EVENT_BUFLEAVE)
{
|| event == EVENT_TEXTCHANGEDI
|| event == EVENT_BUFWRITEPOST
|| event == EVENT_BUFLEAVE) {
send_dirty_status();
}
NSInteger eventCode = (NSInteger) event;
NSMutableData *data;
if (buf == NULL) {
data = [[NSMutableData alloc] initWithBytes:&eventCode length:sizeof(NSInteger)];
} else {
NSInteger bufHandle = buf->handle;
data = [[NSMutableData alloc] initWithCapacity:(sizeof(NSInteger) + sizeof(NSInteger))];
[data appendBytes:&eventCode length:sizeof(NSInteger)];
[data appendBytes:&bufHandle length:sizeof(NSInteger)];
}
[_neovim_server sendMessageWithId:NvimServerMsgIdAutoCommandEvent data:data];
[data release];
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);
}
});
}
}
#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 *bundlePath = [NSBundle bundleForClass:[NvimServer class]].bundlePath;
NSString *resourcesPath = [bundlePath.stringByDeletingLastPathComponent
stringByAppendingPathComponent:@"Resources"];
NSString *runtimePath = [resourcesPath stringByAppendingPathComponent:@"runtime"];
let bundlePath = [NSBundle bundleForClass:[NvimServer class]].bundlePath;
let resourcesPath = [bundlePath.stringByDeletingLastPathComponent stringByAppendingPathComponent:@"Resources"];
let 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.
@ -722,10 +703,9 @@ void start_neovim(NSInteger width, NSInteger height, NSArray<NSString *> *args)
_backspace = [[NSString alloc] initWithString:@"<BS>"];
bool value = msg_didany > 0;
NSData *data = [[NSData alloc] initWithBytes:&value length:sizeof(bool)];
[_neovim_server sendMessageWithId:NvimServerMsgIdNvimReady data:data];
[data release];
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();
@ -733,42 +713,26 @@ void start_neovim(NSInteger width, NSInteger height, NSArray<NSString *> *args)
#pragma mark Functions for neovim's main loop
typedef NSData *(^work_block)(NSData *);
typedef void (^async_work_block)(NSData *);
static void work_and_write_data_sync(void **argv, work_block block) {
static void work_async(void **argv, async_work_block block) {
@autoreleasepool {
NSCondition *outputCondition = argv[1];
[outputCondition lock];
NSData *data = argv[0];
DataWrapper *wrapper = argv[2];
wrapper.data = block(data);
wrapper.dataReady = YES;
block(data);
[data release]; // retained in local_server_callback
[outputCondition signal];
[outputCondition unlock];
}
}
//static void work_async(void **argv, work_block block) {
// @autoreleasepool {
// NSData *data = argv[0];
// block(data);
// [data release]; // retained in local_server_callback
// }
//}
void neovim_scroll(void **argv) {
work_and_write_data_sync(argv, ^NSData *(NSData *data) {
NSInteger *values = (NSInteger *) data.bytes;
work_async(argv, ^(NSData *data) {
let values = (NSInteger *) data.bytes;
int horiz = (int) values[0];
int vert = (int) values[1];
int row = (int) values[2];
int column = (int) values[3];
if (horiz == 0 && vert == 0) {
return nil;
return;
}
if (row < 0 || column < 0) {
@ -780,41 +744,37 @@ void neovim_scroll(void **argv) {
int horizDir;
int vertDir;
if (horiz != 0) {
horizDir = horiz > 0 ? MSCR_RIGHT: MSCR_LEFT;
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;
vertDir = vert > 0 ? MSCR_DOWN : MSCR_UP;
custom_ui_scroll(vertDir, ABS(vert), row, column);
}
refresh_ui_screen(VALID);
return nil;
});
}
void neovim_resize(void **argv) {
work_and_write_data_sync(argv, ^NSData *(NSData *data) {
work_async(argv, ^(NSData *data) {
const NSInteger *values = data.bytes;
NSInteger width = values[0];
NSInteger height = values[1];
let width = values[0];
let height = values[1];
set_ui_size(_server_ui_data->bridge, (int) width, (int) height);
ui_refresh();
return nil;
});
}
void neovim_vim_input(void **argv) {
work_and_write_data_sync(argv, ^NSData *(NSData *data) {
NSString *input = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
work_async(argv, ^(NSData *data) {
let input = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
if (_marked_text == nil) {
nvim_input(vim_string_from(input));
return nil;
return;
}
// Handle cases like -> arrow key: The previously marked text is the same as the finalized
@ -827,31 +787,29 @@ void neovim_vim_input(void **argv) {
for (int i = 1; i <= cellCount; i++) {
DLOG("unmarking at %d:%d", _put_row, _put_column - i);
NSInteger values[] = {_put_row, MAX(_put_column - i, 0)};
NSData *unmarkData = [[NSData alloc] initWithBytes:values length:(2 * sizeof(NSInteger))];
[_neovim_server sendMessageWithId:NvimServerMsgIdUnmark data:unmarkData];
[unmarkData release];
send_msg_packing(NvimServerMsgIdUnmark, ^(msgpack_packer *packer) {
msgpack_pack_array(packer, 2);
msgpack_pack_int64(packer, _put_row);
msgpack_pack_int64(packer, MAX(_put_column - i, 0));
});
}
}
delete_marked_text();
nvim_input(vim_string_from(input));
return nil;
});
}
void neovim_vim_input_marked_text(void **argv) {
work_and_write_data_sync(argv, ^NSData *(NSData *data) {
NSString *markedText = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
work_async(argv, ^(NSData *data) {
let markedText = [[[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding] autorelease];
if (_marked_text == nil) {
_marked_row = _put_row;
_marked_column = _put_column + _marked_delta;
DLOG(
"marking position: %d:%d(%d + %d)", _put_row, _marked_column, _put_column, _marked_delta
"marking position: %d:%d(%d + %d)", _put_row, _marked_column, _put_column, _marked_delta
);
_marked_delta = 0;
} else {
@ -860,13 +818,11 @@ void neovim_vim_input_marked_text(void **argv) {
DLOG("inserting marked text '%s' at %d:%d", markedText.cstr, _put_row, _put_column);
insert_marked_text(markedText);
return nil;
});
}
void neovim_delete(void **argv) {
work_and_write_data_sync(argv, ^NSData *(NSData *data) {
work_async(argv, ^(NSData *data) {
const NSInteger *values = data.bytes;
NSInteger count = values[0];
@ -895,23 +851,19 @@ void neovim_delete(void **argv) {
for (int i = 0; i < count; i++) {
nvim_input(vim_string_from(_backspace));
}
return nil;
});
}
void neovim_focus_gained(void **argv) {
work_and_write_data_sync(argv, ^NSData *(NSData *data) {
work_async(argv, ^(NSData *data) {
const bool *values = data.bytes;
aucmd_schedule_focusgained(values[0]);
return nil;
});
}
void neovim_debug1(void **argv) {
work_and_write_data_sync(argv, ^NSData *(NSData *data) {
work_async(argv, ^(NSData *data) {
NSLog(@"normal fg: %#08X", normal_fg);
NSLog(@"normal bg: %#08X", normal_bg);
NSLog(@"normal sp: %#08X", normal_sp);
@ -919,7 +871,5 @@ void neovim_debug1(void **argv) {
for (int i = 0; i < HLF_COUNT; i++) {
NSLog(@"%s: %#08X", hlf_names[i], HlAttrsFromAttrCode(highlight_attr[i]).rgb_fg_color);
}
return nil;
});
}

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
1929B30D6C4175835D1F5B21 /* MessagePackCommons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B44323D6611E2927EC3B /* MessagePackCommons.swift */; };
1929B40A751BDA2882D4FC94 /* NvimViewObjects.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B22A0CAD417EC3790F02 /* NvimViewObjects.swift */; };
1929B86897DAEFDBABAB1C14 /* NvimApiExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BBD7F88AE4F01E626691 /* NvimApiExtension.swift */; };
1929BA70C221E3C199833B8C /* UiBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929B52174EC68D2974B5BAE /* UiBridge.swift */; };
@ -38,7 +39,6 @@
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 */; };
4B90F06A1FD2AFF7008A39E0 /* DataWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0611FD2AFF7008A39E0 /* DataWrapper.m */; };
4B90F06B1FD2AFF7008A39E0 /* NvimServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90F0641FD2AFF7008A39E0 /* NvimServer.m */; };
4B9E5E1C20990DF2006455C3 /* RxMessagePort.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B9E5E1B20990DF1006455C3 /* RxMessagePort.framework */; };
4BB1F5C9209740E400EC394A /* RxMsgpackRpc.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB1F5C8209740E400EC394A /* RxMsgpackRpc.framework */; };
@ -94,6 +94,7 @@
/* Begin PBXFileReference section */
1929B22A0CAD417EC3790F02 /* NvimViewObjects.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NvimViewObjects.swift; sourceTree = "<group>"; };
1929B44323D6611E2927EC3B /* MessagePackCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackCommons.swift; sourceTree = "<group>"; };
1929B4F32708E99C40A57020 /* SharedTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SharedTypes.h; sourceTree = "<group>"; };
1929B52174EC68D2974B5BAE /* UiBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UiBridge.swift; sourceTree = "<group>"; };
1929B6F4B70B90F7CFB7B523 /* RxSwiftCommons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxSwiftCommons.swift; sourceTree = "<group>"; };
@ -130,8 +131,6 @@
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>"; };
4B90F05C1FD2AFF7008A39E0 /* DataWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataWrapper.h; sourceTree = "<group>"; };
4B90F0611FD2AFF7008A39E0 /* DataWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DataWrapper.m; 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>"; };
@ -225,6 +224,7 @@
1929BBD7F88AE4F01E626691 /* NvimApiExtension.swift */,
1929B52174EC68D2974B5BAE /* UiBridge.swift */,
1929B6F4B70B90F7CFB7B523 /* RxSwiftCommons.swift */,
1929B44323D6611E2927EC3B /* MessagePackCommons.swift */,
);
path = NvimView;
sourceTree = "<group>";
@ -235,8 +235,6 @@
4B90F0511FD2AFD3008A39E0 /* main.m */,
4B90F0571FD2AFF7008A39E0 /* CocoaCategories.h */,
4B90F05A1FD2AFF7008A39E0 /* CocoaCategories.m */,
4B90F05C1FD2AFF7008A39E0 /* DataWrapper.h */,
4B90F0611FD2AFF7008A39E0 /* DataWrapper.m */,
4B90F05B1FD2AFF7008A39E0 /* Logging.h */,
4B90F0621FD2AFF7008A39E0 /* NvimServer.h */,
4B90F0641FD2AFF7008A39E0 /* NvimServer.m */,
@ -406,6 +404,7 @@
1929B86897DAEFDBABAB1C14 /* NvimApiExtension.swift in Sources */,
1929BA70C221E3C199833B8C /* UiBridge.swift in Sources */,
1929BA93BDEA029011F034FF /* RxSwiftCommons.swift in Sources */,
1929B30D6C4175835D1F5B21 /* MessagePackCommons.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -417,7 +416,6 @@
4B90F0661FD2AFF7008A39E0 /* server_ui.m in Sources */,
4B90F0521FD2AFD3008A39E0 /* main.m in Sources */,
4B90F0681FD2AFF7008A39E0 /* CocoaCategories.m in Sources */,
4B90F06A1FD2AFF7008A39E0 /* DataWrapper.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -464,7 +462,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 275;
CURRENT_PROJECT_VERSION = 277;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -524,7 +522,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 275;
CURRENT_PROJECT_VERSION = 277;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -551,7 +549,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 275;
DYLIB_CURRENT_VERSION = 277;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
FRAMEWORK_VERSION = A;
@ -573,7 +571,7 @@
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 275;
DYLIB_CURRENT_VERSION = 277;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/../Carthage/Build/Mac";
FRAMEWORK_VERSION = A;

View File

@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.23.0</string>
<string>SNAPSHOT-277</string>
<key>CFBundleVersion</key>
<string>275</string>
<string>277</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Tae Won Ha. All rights reserved.</string>
<key>NSPrincipalClass</key>

View File

@ -0,0 +1,18 @@
/**
* Tae Won Ha - http://taewon.de - @hataewon
* See LICENSE
*/
import Foundation
import MessagePack
extension MessagePackValue {
var intValue: Int? {
guard let i64 = self.integerValue else {
return nil
}
return Int(i64)
}
}

View File

@ -6,6 +6,7 @@
import Cocoa
import RxNeovimApi
import RxSwift
import MessagePack
extension NvimView {
@ -67,59 +68,51 @@ extension NvimView {
}
}
func flush(_ renderData: [Data]) {
func flush(_ renderData: [MessagePackValue]) {
self.bridgeLogger.hr()
gui.async {
var goto: Position? = nil
renderData.forEach { data in
data.withUnsafeBytes { (pointer: UnsafePointer<RenderDataType>) in
let sizeOfType = MemoryLayout<RenderDataType>.size
let rawPointer = UnsafeRawPointer(pointer).advanced(by: sizeOfType);
let renderType = pointer[0]
switch renderType {
case .put:
guard let str = String(data: Data(bytes: rawPointer, count: data.count - sizeOfType),
encoding: .utf8)
else {
break
}
self.doPut(string: str)
case .putMarked:
guard let str = String(data: Data(bytes: rawPointer, count: data.count - sizeOfType),
encoding: .utf8)
else {
break
}
self.doPut(markedText: str)
case .highlight:
let attr = rawPointer.load(as: CellAttributes.self)
self.doHighlightSet(attr)
case .goto:
let values = rawPointer.bindMemory(to: Int.self, capacity: 4)
goto = Position(row: values[2], column: values[3])
self.doGoto(position: Position(row: values[0], column: values[1]), textPosition: goto!)
case .eolClear:
self.doEolClear()
}
renderData.forEach { value in
guard let renderEntry = value.arrayValue,
renderEntry.count == 2,
let rawType = renderEntry[0].intValue,
let type = RenderDataType(rawValue: rawType) else { return }
switch type {
case .put:
guard let str = renderEntry[1].stringValue else { return }
self.doPut(string: str)
case .putMarked:
guard let str = renderEntry[1].stringValue else { return }
self.doPut(markedText: str)
case .highlight:
guard let data = renderEntry[1].dataValue else { return }
let attr = data.withUnsafeBytes { (pointer: UnsafePointer<CellAttributes>) in pointer.pointee }
self.doHighlightSet(attr)
case .goto:
guard let rawValues = renderEntry[1].arrayValue else { return }
let values = rawValues.compactMap { $0.intValue }
guard values.count == 4 else { return }
goto = Position(row: values[2], column: values[3])
self.doGoto(position: Position(row: values[0], column: values[1]), textPosition: goto!)
case .eolClear:
self.doEolClear()
}
}
if let pos = goto {
self.eventsSubject.onNext(.cursor(pos))
}
self.shouldDrawCursor = true
if self.usesLigatures {
self.markForRender(region: self.grid.regionOfWord(at: self.grid.position))
} else {
@ -250,8 +243,6 @@ extension NvimView {
self.markForRender(cellPosition: self.grid.position)
self.grid.goto(position)
self.eventsSubject.onNext(.cursor(textPosition))
}
func doEolClear() {

View File

@ -28,7 +28,7 @@ class UiBridge {
case unmark(row: Int, column: Int)
case bell
case visualBell
case flush([Data])
case flush([MessagePackValue])
case setForeground(Int)
case setBackground(Int)
case setSpecial(Int)
@ -162,16 +162,18 @@ class UiBridge {
self.streamSubject.onNext(.ready)
let isInitErrorPresent = data?.asArray(ofType: Bool.self, count: 1)?[0] ?? false
let isInitErrorPresent = value(from: data, conversion: { $0.boolValue }) ?? false
if isInitErrorPresent {
self.streamSubject.onNext(.initVimError)
}
case .resize:
guard let values = data?.asArray(ofType: Int.self, count: 2) else {
guard let values = array(from: data, ofSize: 2, conversion: { v -> Int? in
guard let i64 = v.integerValue else { return nil }
return Int(i64)
}) else {
return
}
self.streamSubject.onNext(.resize(width: values[0], height: values[1]))
case .clear:
@ -193,28 +195,31 @@ class UiBridge {
self.streamSubject.onNext(.mouseOff)
case .modeChange:
guard let values = data?.asArray(ofType: CursorModeShape.self, count: 1) else {
guard let value = value(from: data, conversion: { v -> CursorModeShape? in
guard let i64 = v.integerValue else { return nil }
return CursorModeShape(rawValue: UInt(i64))
}) else {
return
}
self.streamSubject.onNext(.modeChange(values[0]))
self.streamSubject.onNext(.modeChange(value))
case .setScrollRegion:
guard let values = data?.asArray(ofType: Int.self, count: 4) else {
guard let values = array(from: data, ofSize: 4, conversion: { $0.intValue }) else {
return
}
self.streamSubject.onNext(.setScrollRegion(top: values[0], bottom: values[1], left: values[2], right: values[3]))
case .scroll:
guard let values = data?.asArray(ofType: Int.self, count: 1) else {
guard let value = value(from: data, conversion: { $0.intValue }) else {
return
}
self.streamSubject.onNext(.scroll(values[0]))
self.streamSubject.onNext(.scroll(value))
case .unmark:
guard let values = data?.asArray(ofType: Int.self, count: 2) else {
guard let values = array(from: data, ofSize: 2, conversion: { $0.intValue }) else {
return
}
@ -227,42 +232,42 @@ class UiBridge {
self.streamSubject.onNext(.visualBell)
case .flush:
guard let d = data, let renderData = NSKeyedUnarchiver.unarchiveObject(with: d) as? [Data] else {
guard let d = data, let renderData = try? unpackAll(d) else {
return
}
self.streamSubject.onNext(.flush(renderData))
case .setForeground:
guard let values = data?.asArray(ofType: Int.self, count: 1) else {
guard let value = value(from: data, conversion: { $0.intValue }) else {
return
}
self.streamSubject.onNext(.setForeground(values[0]))
self.streamSubject.onNext(.setForeground(value))
case .setBackground:
guard let values = data?.asArray(ofType: Int.self, count: 1) else {
guard let value = value(from: data, conversion: { $0.intValue }) else {
return
}
self.streamSubject.onNext(.setBackground(values[0]))
self.streamSubject.onNext(.setBackground(value))
case .setSpecial:
guard let values = data?.asArray(ofType: Int.self, count: 1) else {
guard let value = value(from: data, conversion: { $0.intValue }) else {
return
}
self.streamSubject.onNext(.setSpecial(values[0]))
self.streamSubject.onNext(.setSpecial(value))
case .setTitle:
guard let d = data, let title = String(data: d, encoding: .utf8) else {
guard let title = value(from: data, conversion: { $0.stringValue }) else {
return
}
self.streamSubject.onNext(.setTitle(title))
case .setIcon:
guard let d = data, let icon = String(data: d, encoding: .utf8) else {
guard let icon = value(from: data, conversion: { $0.stringValue }) else {
return
}
@ -272,31 +277,32 @@ class UiBridge {
self.streamSubject.onNext(.stop)
case .dirtyStatusChanged:
guard let values = data?.asArray(ofType: Bool.self, count: 1) else {
guard let value = value(from: data, conversion: { $0.boolValue }) else {
return
}
self.streamSubject.onNext(.dirtyStatusChanged(values[0]))
self.streamSubject.onNext(.dirtyStatusChanged(value))
case .cwdChanged:
guard let d = data, let cwd = String(data: d, encoding: .utf8) else {
guard let cwd = value(from: data, conversion: { $0.stringValue }) else {
return
}
self.streamSubject.onNext(.cwdChanged(cwd))
case .defaultColorsChanged:
guard let values = data?.asArray(ofType: Int.self, count: 3) else {
guard let values = array(from: data, ofSize: 3, conversion: { $0.intValue }) else {
return
}
self.streamSubject.onNext(.defaultColorsChanged(values))
case .colorSchemeChanged:
guard let values = data?.asArray(ofType: Int.self, count: 5) else {
guard let d = data, let rawValues = (try? unpack(d))?.value.arrayValue else {
return
}
let values = rawValues.compactMap { $0.integerValue }.map { Int($0) }
self.streamSubject.onNext(.colorSchemeChanged(values))
case .optionSet:
@ -314,22 +320,10 @@ class UiBridge {
self.streamSubject.onNext(.optionSet(key: key, value: value))
case .autoCommandEvent:
if data?.count == 2 * MemoryLayout<Int>.stride {
guard let values = data?.asArray(ofType: Int.self, count: 2),
let cmd = NvimAutoCommandEvent(rawValue: values[0])
else {
return
}
guard let values = array(from: data, ofSize: 2, conversion: { $0.intValue }),
let cmd = NvimAutoCommandEvent(rawValue: values[0]) else { return }
self.streamSubject.onNext(.autoCommandEvent(autocmd: cmd, bufferHandle: values[1]))
} else {
guard let values = data?.asArray(ofType: NvimAutoCommandEvent.self, count: 1) else {
return
}
self.streamSubject.onNext(.autoCommandEvent(autocmd: values[0], bufferHandle: -1))
}
self.streamSubject.onNext(.autoCommandEvent(autocmd: cmd, bufferHandle: values[1]))
case .debug1:
self.streamSubject.onNext(.debug1)
@ -457,17 +451,6 @@ class UiBridge {
private let timeout = CFTimeInterval(5)
private extension Data {
func asArray<T>(ofType: T.Type, count: Int) -> [T]? {
guard (self.count / MemoryLayout<T>.stride) <= count else {
return nil
}
return self.withUnsafeBytes { (p: UnsafePointer<T>) in Array(UnsafeBufferPointer(start: p, count: count)) }
}
}
private extension Array {
func data() -> Data {
@ -484,3 +467,23 @@ private extension Array {
}
}
}
private func value<T>(from data: Data?, conversion: (MessagePackValue) -> T?) -> T? {
guard let d = data, let value = (try? unpack(d))?.value else {
return nil
}
return conversion(value)
}
private func array<T>(from data: Data?, ofSize size: Int, conversion: (MessagePackValue) -> T?) -> [T]? {
guard let d = data, let array = (try? unpack(d))?.value.arrayValue else {
return nil
}
guard array.count == size else {
return nil
}
return array.compactMap(conversion)
}

View File

@ -980,7 +980,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 275;
CURRENT_PROJECT_VERSION = 277;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -1037,7 +1037,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 275;
CURRENT_PROJECT_VERSION = 277;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;

View File

@ -75,30 +75,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele
return
}
let alert = NSAlert()
alert.alertStyle = .warning
alert.messageText = "FontAwesome could not be loaded."
let accessoryView = NSTextField(frame: CGRect(x: 0, y: 0, width: 300, height: 40))
accessoryView.isEditable = false
accessoryView.drawsBackground = false
accessoryView.isBordered = false
accessoryView.usesSingleLineMode = false
// both are needed, otherwise hyperlink won't accept mousedown
accessoryView.isSelectable = true
accessoryView.allowsEditingTextAttributes = true
accessoryView.attributedStringValue = NSAttributedString.infoLabel(markdown: """
Unfortunately we don't know yet what is causing this. This seems to happen only to some users.
We use the FontAwesome font for icons in the tools, e.g. the file browser. Those icons are now
shown as `?`.
You can track the progress on this issue at [GitHub](https://github.com/qvacua/vimr/issues/611).
""")
alert.accessoryView = accessoryView
// alert.runModal()
let notification = NSUserNotification()
notification.title = "FontAwesome could not be loaded."
notification.subtitle = "Unfortunately we don't know yet what is causing this."

View File

@ -1,4 +1,4 @@
{\rtf1\ansi\ansicpg1252\cocoartf1504\cocoasubrtf830
{\rtf1\ansi\ansicpg1252\cocoartf1561\cocoasubrtf400
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
@ -38,7 +38,7 @@ By:
\
\b Using stuff from:\
NeoVim\
Neovim\
{\field{\*\fldinst{HYPERLINK "https://github.com/neovim/neovim"}}{\fldrslt
\b0 https://github.com/neovim/neovim}}
\b0 \
@ -93,12 +93,6 @@ By:
\b0 {\field{\*\fldinst{HYPERLINK "https://github.com/sindresorhus/github-markdown-css"}}{\fldrslt https://github.com/sindresorhus/github-markdown-css}}\
\
\b Result\
{\field{\*\fldinst{HYPERLINK "https://github.com/antitypical/Result"}}{\fldrslt
\b0 https://github.com/antitypical/Result}}
\b0 \
\
\b MessagePack.swift\
{\field{\*\fldinst{HYPERLINK "https://github.com/a2/MessagePack.swift"}}{\fldrslt
\b0 https://github.com/a2/MessagePack.swift}}

View File

@ -32,7 +32,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.23.0</string>
<string>SNAPSHOT-277</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
@ -49,7 +49,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>275</string>
<string>277</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.productivity</string>
<key>LSMinimumSystemVersion</key>

View File

@ -206,11 +206,6 @@ class MainWindow: NSObject,
self.neoVimView.usesLiveResize = state.useLiveResize
self.updateNeoVimAppearance()
self.window.setFrame(state.frame, display: true)
self.window.makeFirstResponder(self.neoVimView)
self.open(urls: state.urlsToOpen)
Observable
.of(self.scrollDebouncer.observable, self.cursorDebouncer.observable)
.merge()
@ -221,7 +216,7 @@ class MainWindow: NSObject,
self.neoVimView.events
.observeOn(MainScheduler.instance)
.subscribe(onNext: { event in
.subscribe(onNext: { [unowned self] event in
switch event {
case .neoVimStopped: self.neoVimStopped()
@ -336,6 +331,11 @@ class MainWindow: NSObject,
}
})
.disposed(by: self.disposeBag)
self.window.setFrame(state.frame, display: true)
self.window.makeFirstResponder(self.neoVimView)
self.open(urls: state.urlsToOpen)
}
func uuidAction(for action: Action) -> UuidAction<Action> {
@ -432,8 +432,10 @@ class MainWindow: NSObject,
private func showInitError() {
let notification = NSUserNotification()
notification.title = "Error during initialization"
notification.informativeText = "There was an error during the initialization of NeoVim. " +
"Use :messages to view the error messages."
notification.informativeText = """
There was an error during the initialization of NeoVim.
Use :messages to view the error messages.
"""
NSUserNotificationCenter.default.deliver(notification)
}

View File

@ -15,10 +15,10 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>0.23.0</string>
<string>SNAPSHOT-277</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>275</string>
<string>277</string>
</dict>
</plist>

View File

@ -7,20 +7,23 @@
<description>Most recent changes with links to updates for VimR.</description>
<language>en</language>
<item>
<title>v0.23.0-275</title>
<title>SNAPSHOT-277</title>
<description><![CDATA[
<p>GH-419: File browser sorts folders on the top. (Thanks @laibulle for the PR)</p>
<p><em>WARNING</em>: This snapshot may very well be instable!</p>
<ul>
<li>Some <em>more</em> refactorings in the communication layer between the UI and the backend Neovim process. (Scrolling got a bit faster, I think 🙂)</li>
</ul>
]]></description>
<releaseNotesLink>
https://github.com/qvacua/vimr/releases/tag/v0.23.0-275
https://github.com/qvacua/vimr/releases/tag/snapshot/277
</releaseNotesLink>
<pubDate>2018-05-05T10:32:16.520757</pubDate>
<pubDate>2018-05-13T17:19:23.286126</pubDate>
<minimumSystemVersion>10.10.0</minimumSystemVersion>
<enclosure url="https://github.com/qvacua/vimr/releases/download/v0.23.0-275/VimR-v0.23.0-275.tar.bz2"
sparkle:version="275"
sparkle:shortVersionString="0.23.0"
sparkle:dsaSignature="MC0CFQCi65UeKDlPEFa1PBiBAFae2TssJAIUaM4zcNPIxFzlE2cCQPCNwUQX3PM="
length="12162223"
<enclosure url="https://github.com/qvacua/vimr/releases/download/snapshot/277/VimR-SNAPSHOT-277.tar.bz2"
sparkle:version="277"
sparkle:shortVersionString="SNAPSHOT-277"
sparkle:dsaSignature="MC0CFGdf4V1p+6xmrgx9QcRF9zeppeF0AhUAw+Uh6O+1/jyMin2h/ytnfWDFqm4="
length="12541702"
type="application/octet-stream"/>
</item>
</channel>

View File

@ -22,7 +22,7 @@ agvtool new-marketing-version ${MARKETING_VERSION}
popd
for proj in 'MsgPackRpc' 'NvimMsgPack' 'NvimView'; do
for proj in 'NvimView'; do
pushd ${proj}
agvtool new-version -all ${BUNDLE_VERSION}
agvtool new-marketing-version ${MARKETING_VERSION}