mirror of
https://github.com/qvacua/vimr.git
synced 2024-11-28 19:47:41 +03:00
Merge branch 'issue/228-open'
This commit is contained in:
commit
054a152939
30
NeoVimServer/NeoVimBuffer.h
Normal file
30
NeoVimServer/NeoVimBuffer.h
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NeoVimBuffer : NSObject <NSCoding>
|
||||
|
||||
@property (nonatomic, readonly) NSUInteger handle;
|
||||
@property (nonatomic, retain, nullable) NSString *fileName;
|
||||
@property (nonatomic, readonly, getter=isDirty) bool dirty;
|
||||
@property (nonatomic, readonly, getter=isCurrent) bool current;
|
||||
@property (nonatomic, readonly, getter=isTransient) bool transient;
|
||||
|
||||
- (instancetype)initWithHandle:(NSUInteger)handle
|
||||
fileName:(NSString * _Nullable)fileName
|
||||
dirty:(bool)dirty
|
||||
current:(bool)current;
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder;
|
||||
- (void)encodeWithCoder:(NSCoder *)coder;
|
||||
|
||||
- (NSString *)description;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
69
NeoVimServer/NeoVimBuffer.m
Normal file
69
NeoVimServer/NeoVimBuffer.m
Normal file
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Tae Won Ha - http://taewon.de - @hataewon
|
||||
* See LICENSE
|
||||
*/
|
||||
|
||||
#import "NeoVimBuffer.h"
|
||||
|
||||
@implementation NeoVimBuffer
|
||||
|
||||
- (instancetype)initWithHandle:(NSUInteger)handle
|
||||
fileName:(NSString *)fileName
|
||||
dirty:(bool)dirty
|
||||
current:(bool)current {
|
||||
self = [super init];
|
||||
if (self == nil) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
_handle = handle;
|
||||
_fileName = fileName;
|
||||
_dirty = dirty;
|
||||
_current = current;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)coder {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
NSNumber *objHandle = [coder decodeObjectForKey:@"handle"];
|
||||
_handle = objHandle.unsignedIntegerValue;
|
||||
_fileName = [coder decodeObjectForKey:@"fileName"];
|
||||
_dirty = [coder decodeBoolForKey:@"dirty"];
|
||||
_current = [coder decodeBoolForKey:@"current"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)coder {
|
||||
[coder encodeObject:@(self.handle) forKey:@"handle"];
|
||||
[coder encodeObject:self.fileName forKey:@"fileName"];
|
||||
[coder encodeBool:self.dirty forKey:@"dirty"];
|
||||
[coder encodeBool:self.current forKey:@"current"];
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
NSMutableString *description = [NSMutableString stringWithFormat:@"<%@: ", NSStringFromClass([self class])];
|
||||
[description appendFormat:@"self.handle=%lu", self.handle];
|
||||
[description appendFormat:@", self.fileName=%@", self.fileName];
|
||||
[description appendFormat:@", self.dirty=%d", self.dirty];
|
||||
[description appendFormat:@", self.current=%d", self.current];
|
||||
[description appendString:@">"];
|
||||
return description;
|
||||
}
|
||||
|
||||
- (bool)isTransient {
|
||||
if (self.dirty) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
if (self.fileName != nil) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
@ -48,8 +48,11 @@ typedef NS_ENUM(NSUInteger, NeoVimAgentMsgId) {
|
||||
NeoVimAgentMsgIdInputMarked,
|
||||
NeoVimAgentMsgIdDelete,
|
||||
NeoVimAgentMsgIdResize,
|
||||
|
||||
NeoVimAgentMsgIdDirtyDocs,
|
||||
|
||||
NeoVimAgentMsgIdEscapeFileNames,
|
||||
NeoVimAgentMsgIdGetBuffers,
|
||||
|
||||
#ifdef DEBUG
|
||||
NeoVimAgentDebug1,
|
||||
#endif
|
||||
|
@ -37,7 +37,6 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log4Debug("server returning data: %@", responseData);
|
||||
return CFDataCreateCopy(kCFAllocatorDefault, (__bridge CFDataRef) responseData);
|
||||
}
|
||||
}
|
||||
@ -185,6 +184,21 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
||||
return [NSData dataWithBytes:&dirty length:sizeof(bool)];
|
||||
}
|
||||
|
||||
case NeoVimAgentMsgIdEscapeFileNames: {
|
||||
NSArray <NSString *> *fileNames = [NSKeyedUnarchiver unarchiveObjectWithData:data];
|
||||
NSMutableArray <NSString *> *result = [NSMutableArray new];
|
||||
|
||||
[fileNames enumerateObjectsUsingBlock:^(NSString* fileName, NSUInteger idx, BOOL *stop) {
|
||||
[result addObject:server_escaped_filename(fileName)];
|
||||
}];
|
||||
|
||||
return [NSKeyedArchiver archivedDataWithRootObject:result];
|
||||
}
|
||||
|
||||
case NeoVimAgentMsgIdGetBuffers: {
|
||||
return [NSKeyedArchiver archivedDataWithRootObject:server_buffers()];
|
||||
}
|
||||
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
|
@ -17,4 +17,6 @@ extern void server_delete(NSInteger count);
|
||||
extern void server_resize(int width, int height);
|
||||
extern void server_vim_input_marked_text(NSString *markedText);
|
||||
extern void server_insert_marked_text(NSString *markedText);
|
||||
extern bool server_has_dirty_docs();
|
||||
extern bool server_has_dirty_docs();
|
||||
extern NSString *server_escaped_filename(NSString *filename);
|
||||
extern NSArray *server_buffers();
|
@ -8,6 +8,7 @@
|
||||
#import "server_globals.h"
|
||||
#import "NeoVimServer.h"
|
||||
#import "NeoVimUiBridgeProtocol.h"
|
||||
#import "NeoVimBuffer.h"
|
||||
|
||||
// FileInfo and Boolean are #defined by Carbon and NeoVim: Since we don't need the Carbon versions of them, we rename
|
||||
// them.
|
||||
@ -20,7 +21,7 @@
|
||||
#import <nvim/ui_bridge.h>
|
||||
#import <nvim/event/signal.h>
|
||||
#import <nvim/main.h>
|
||||
#import <nvim/screen.h>
|
||||
#import <nvim/ex_getln.h>
|
||||
|
||||
|
||||
#define pun_type(t, x) (*((t *)(&x)))
|
||||
@ -426,11 +427,6 @@ static void server_ui_stop(UI *ui __unused) {
|
||||
|
||||
#pragma mark Helper functions
|
||||
|
||||
static void force_redraw(void **argv __unused) {
|
||||
must_redraw = CLEAR;
|
||||
update_screen(0);
|
||||
}
|
||||
|
||||
static void refresh_ui(void **argv __unused) {
|
||||
ui_refresh();
|
||||
}
|
||||
@ -650,3 +646,31 @@ bool server_has_dirty_docs() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NSString *server_escaped_filename(NSString *filename) {
|
||||
const char *file_system_rep = filename.fileSystemRepresentation;
|
||||
|
||||
char_u *escaped_filename = vim_strsave_fnameescape((char_u *) file_system_rep, 0);
|
||||
NSString *result = [NSString stringWithCString:(const char *) escaped_filename encoding:NSUTF8StringEncoding];
|
||||
xfree(escaped_filename);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NSArray *server_buffers() {
|
||||
NSMutableArray <NeoVimBuffer *> *result = [[NSMutableArray new] autorelease];
|
||||
FOR_ALL_BUFFERS(buf) {
|
||||
NSString *fileName = nil;
|
||||
if (buf->b_ffname != NULL) {
|
||||
fileName = [NSString stringWithCString:(const char *) buf->b_ffname encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
bool current = curbuf == buf;
|
||||
NeoVimBuffer *buffer = [[NeoVimBuffer alloc] initWithHandle:buf->handle
|
||||
fileName:fileName
|
||||
dirty:buf->b_changed
|
||||
current:current];
|
||||
[result addObject:buffer];
|
||||
[buffer release];
|
||||
}
|
||||
return result;
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extracted from Snapshot-104 of MacVim
|
||||
* Extracted from snapshot-106 of MacVim
|
||||
* https://github.com/macvim-dev/macvim
|
||||
* See VIM.LICENSE
|
||||
*/
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
@protocol NeoVimUiBridgeProtocol;
|
||||
@class NeoVimBuffer;
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
@ -28,6 +29,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)resizeToWidth:(int)width height:(int)height;
|
||||
|
||||
- (bool)hasDirtyDocs;
|
||||
- (NSArray <NSString *> *)escapedFileNames:(NSArray <NSString *> *)fileNames;
|
||||
- (NSArray <NeoVimBuffer *> *)buffers;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#import "NeoVimMsgIds.h"
|
||||
#import "NeoVimUiBridgeProtocol.h"
|
||||
#import "Logging.h"
|
||||
#import "NeoVimBuffer.h"
|
||||
|
||||
|
||||
static const double qTimeout = 10;
|
||||
@ -96,32 +97,32 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
||||
|
||||
- (void)vimCommand:(NSString *)string {
|
||||
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdCommand data:data];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdCommand data:data expectsReply:false];
|
||||
}
|
||||
|
||||
- (void)vimInput:(NSString *)string {
|
||||
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdInput data:data];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdInput data:data expectsReply:false];
|
||||
}
|
||||
|
||||
- (void)vimInputMarkedText:(NSString *_Nonnull)markedText {
|
||||
NSData *data = [markedText dataUsingEncoding:NSUTF8StringEncoding];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdInputMarked data:data];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdInputMarked data:data expectsReply:false];
|
||||
}
|
||||
|
||||
- (void)deleteCharacters:(NSInteger)count {
|
||||
NSData *data = [[NSData alloc] initWithBytes:&count length:sizeof(NSInteger)];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdDelete data:data];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdDelete data:data expectsReply:false];
|
||||
}
|
||||
|
||||
- (void)resizeToWidth:(int)width height:(int)height {
|
||||
int values[] = { width, height };
|
||||
NSData *data = [[NSData alloc] initWithBytes:values length:(2 * sizeof(int))];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdResize data:data];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdResize data:data expectsReply:false];
|
||||
}
|
||||
|
||||
- (bool)hasDirtyDocs {
|
||||
NSData *responseData = [self sendMessageWithId:NeoVimAgentMsgIdDirtyDocs data:nil];
|
||||
NSData *responseData = [self sendMessageWithId:NeoVimAgentMsgIdDirtyDocs data:nil expectsReply:YES];
|
||||
if (responseData == NULL) {
|
||||
NSLog(@"WARNING: agent got response data null");
|
||||
return false;
|
||||
@ -131,6 +132,20 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
||||
return values[0];
|
||||
}
|
||||
|
||||
- (NSArray <NSString *>*)escapedFileNames:(NSArray <NSString *>*)fileNames {
|
||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:fileNames];
|
||||
NSData *response = [self sendMessageWithId:NeoVimAgentMsgIdEscapeFileNames data:data expectsReply:YES];
|
||||
|
||||
NSArray <NSString *> *escapedFileNames = [NSKeyedUnarchiver unarchiveObjectWithData:response];
|
||||
return escapedFileNames;
|
||||
}
|
||||
|
||||
- (NSArray <NeoVimBuffer *> *)buffers {
|
||||
NSData *response = [self sendMessageWithId:NeoVimAgentMsgIdGetBuffers data:nil expectsReply:YES];
|
||||
NSArray <NeoVimBuffer *> *buffers = [NSKeyedUnarchiver unarchiveObjectWithData:response];
|
||||
return buffers;
|
||||
}
|
||||
|
||||
- (void)runLocalServer {
|
||||
@autoreleasepool {
|
||||
CFMessagePortContext localContext = {
|
||||
@ -166,22 +181,17 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
||||
(__bridge CFStringRef) [self remoteServerName]
|
||||
);
|
||||
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdAgentReady data:nil];
|
||||
[self sendMessageWithId:NeoVimAgentMsgIdAgentReady data:nil expectsReply:false];
|
||||
}
|
||||
|
||||
- (NSData *)sendMessageWithId:(NeoVimAgentMsgId)msgid data:(NSData *)data {
|
||||
- (NSData *)sendMessageWithId:(NeoVimAgentMsgId)msgid data:(NSData *)data expectsReply:(bool)expectsReply {
|
||||
if (_remoteServerPort == NULL) {
|
||||
log4Warn("Remote server is null: The msg (%lu:%@) could not be sent.", (unsigned long) msgid, data);
|
||||
return nil;
|
||||
}
|
||||
|
||||
CFDataRef responseData = NULL;
|
||||
CFStringRef replyMode = NULL;
|
||||
|
||||
// We only expect reply from NeoVimAgentMsgIdDirtyDocs
|
||||
if (msgid == NeoVimAgentMsgIdDirtyDocs) {
|
||||
replyMode = kCFRunLoopDefaultMode;
|
||||
}
|
||||
CFStringRef replyMode = expectsReply ? kCFRunLoopDefaultMode : NULL;
|
||||
|
||||
SInt32 responseCode = CFMessagePortSendRequest(
|
||||
_remoteServerPort, msgid, (__bridge CFDataRef) data, qTimeout, qTimeout, replyMode, &responseData
|
||||
|
@ -114,6 +114,10 @@ public class NeoVimView: NSView, NSUserInterfaceValidations {
|
||||
self.agent.establishLocalServer()
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.agent.cleanUp()
|
||||
}
|
||||
@ -125,6 +129,58 @@ public class NeoVimView: NSView, NSUserInterfaceValidations {
|
||||
public func debugInfo() {
|
||||
Swift.print(self.grid)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - API
|
||||
extension NeoVimView {
|
||||
|
||||
public func hasDirtyDocs() -> Bool {
|
||||
return self.agent.hasDirtyDocs()
|
||||
}
|
||||
|
||||
public func newTab() {
|
||||
switch self.mode {
|
||||
case .Normal:
|
||||
self.agent.vimInput(":tabe<CR>")
|
||||
default:
|
||||
self.agent.vimInput("<Esc>:tabe<CR>")
|
||||
}
|
||||
}
|
||||
|
||||
public func open(urls urls: [NSURL]) {
|
||||
let currentBufferIsTransient = self.agent.buffers().filter { $0.current }.first?.transient ?? false
|
||||
|
||||
urls.enumerate().forEach { (idx, url) in
|
||||
if idx == 0 && currentBufferIsTransient {
|
||||
self.open(url, cmd: ":e")
|
||||
} else {
|
||||
self.open(url, cmd: ":tabe")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func openInNewTab(urls urls: [NSURL]) {
|
||||
urls.forEach { self.open($0, cmd: ":tabe") }
|
||||
}
|
||||
|
||||
private func open(url: NSURL, cmd: String) {
|
||||
guard let path = url.path else {
|
||||
return
|
||||
}
|
||||
|
||||
let escapedFileName = self.agent.escapedFileNames([path])[0]
|
||||
|
||||
switch self.mode {
|
||||
case .Normal:
|
||||
self.agent.vimInput("\(cmd) \(escapedFileName)<CR>")
|
||||
default:
|
||||
self.agent.vimInput("<Esc>\(cmd) \(escapedFileName)<CR>")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Resizing
|
||||
extension NeoVimView {
|
||||
|
||||
override public func setFrameSize(newSize: NSSize) {
|
||||
super.setFrameSize(newSize)
|
||||
@ -160,6 +216,10 @@ public class NeoVimView: NSView, NSUserInterfaceValidations {
|
||||
|
||||
self.agent.resizeToWidth(Int32(discreteSize.width), height: Int32(discreteSize.height))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Drawing
|
||||
extension NeoVimView {
|
||||
|
||||
override public func drawRect(dirtyUnionRect: NSRect) {
|
||||
guard self.grid.hasData else {
|
||||
@ -216,10 +276,6 @@ public class NeoVimView: NSView, NSUserInterfaceValidations {
|
||||
self.drawCursor(self.grid.foreground)
|
||||
}
|
||||
|
||||
public func hasDirtyDocs() -> Bool {
|
||||
return self.agent.hasDirtyDocs()
|
||||
}
|
||||
|
||||
private func drawCursor(foreground: UInt32) {
|
||||
// FIXME: for now do some rudimentary cursor drawing
|
||||
let cursorPosition = self.mode == .Cmdline ? self.grid.putPosition : self.grid.screenCursor
|
||||
@ -344,10 +400,6 @@ public class NeoVimView: NSView, NSUserInterfaceValidations {
|
||||
private func vimPlainString(string: String) -> String {
|
||||
return string.stringByReplacingOccurrencesOfString("<", withString: self.wrapNamedKeys("lt"))
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - NSUserInterfaceValidationsProtocol
|
||||
@ -952,7 +1004,7 @@ extension NeoVimView: NeoVimUiBridgeProtocol {
|
||||
}
|
||||
|
||||
public func modeChange(mode: Mode) {
|
||||
NSLog("mode changed to: %02x", mode.rawValue)
|
||||
// NSLog("mode changed to: %02x", mode.rawValue)
|
||||
self.mode = mode
|
||||
}
|
||||
|
||||
|
@ -16,3 +16,4 @@ FOUNDATION_EXPORT const unsigned char SwiftNeoVimVersionString[];
|
||||
#import <SwiftNeoVim/TextDrawer.h>
|
||||
#import <SwiftNeoVim/NeoVimAgent.h>
|
||||
#import <SwiftNeoVim/NeoVimMsgIds.h>
|
||||
#import <SwiftNeoVim/NeoVimBuffer.h>
|
@ -12,7 +12,9 @@
|
||||
1929BEB90DCDAF7A2B68C886 /* ColorUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1929BA6128BFDD54CA92F46E /* ColorUtils.swift */; };
|
||||
1929BF81A40B4154D3EA33CE /* server_ui.m in Sources */ = {isa = PBXBuildFile; fileRef = 1929B93013228985F509C8F6 /* server_ui.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
|
||||
4B029F1A1D45E349004EE0D3 /* PrefWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B029F1C1D45E349004EE0D3 /* PrefWindow.xib */; };
|
||||
4B1BB3531D16C5E500CA4FEF /* InputTestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1BB3521D16C5E500CA4FEF /* InputTestView.swift */; };
|
||||
4B0C905B1D5DED69007753A3 /* NeoVimBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0C905A1D5DED69007753A3 /* NeoVimBuffer.m */; };
|
||||
4B0E22581D5DEDC700C072E6 /* NeoVimBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0C90591D5DED69007753A3 /* NeoVimBuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
4B0E22591D5DF62E00C072E6 /* NeoVimBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0C905A1D5DED69007753A3 /* NeoVimBuffer.m */; };
|
||||
4B238BE11D3BF24200CBDD98 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B238BE01D3BF24200CBDD98 /* Application.swift */; };
|
||||
4B238BEC1D3ED54D00CBDD98 /* AppearancePrefPane.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B238BEB1D3ED54D00CBDD98 /* AppearancePrefPane.swift */; };
|
||||
4B2A2BEC1D02261F0074CE9A /* RxCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B2A2BE21D0225800074CE9A /* RxCocoa.framework */; };
|
||||
@ -156,6 +158,8 @@
|
||||
1929BA6128BFDD54CA92F46E /* ColorUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorUtils.swift; sourceTree = "<group>"; };
|
||||
1929BF00B466B40629C2AABE /* NeoVimView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NeoVimView.swift; sourceTree = "<group>"; };
|
||||
4B029F1B1D45E349004EE0D3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/PrefWindow.xib; sourceTree = "<group>"; };
|
||||
4B0C90591D5DED69007753A3 /* NeoVimBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NeoVimBuffer.h; sourceTree = "<group>"; };
|
||||
4B0C905A1D5DED69007753A3 /* NeoVimBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NeoVimBuffer.m; sourceTree = "<group>"; };
|
||||
4B1BB3521D16C5E500CA4FEF /* InputTestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTestView.swift; sourceTree = "<group>"; };
|
||||
4B238BE01D3BF24200CBDD98 /* Application.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = "<group>"; };
|
||||
4B238BEB1D3ED54D00CBDD98 /* AppearancePrefPane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppearancePrefPane.swift; sourceTree = "<group>"; };
|
||||
@ -341,6 +345,8 @@
|
||||
4BDCFADC1D3145EA00F62670 /* lib */,
|
||||
4B7BD3321D32530900AAA45E /* Logging.h */,
|
||||
4BDCFAE91D3147A300F62670 /* NeoVimMsgIds.h */,
|
||||
4B0C90591D5DED69007753A3 /* NeoVimBuffer.h */,
|
||||
4B0C905A1D5DED69007753A3 /* NeoVimBuffer.m */,
|
||||
4BDCFAC91D31449700F62670 /* NeoVimServer.h */,
|
||||
4BDCFACA1D31449700F62670 /* NeoVimServer.m */,
|
||||
4B854A1C1D31447C00E08DE1 /* main.m */,
|
||||
@ -449,6 +455,7 @@
|
||||
4B2A2C091D0352CB0074CE9A /* NeoVimUiBridgeProtocol.h in Headers */,
|
||||
4B570DC21D303CAF006EDC21 /* NeoVimAgent.h in Headers */,
|
||||
4BDF641C1D0887C100D47E1D /* TextDrawer.h in Headers */,
|
||||
4B0E22581D5DEDC700C072E6 /* NeoVimBuffer.h in Headers */,
|
||||
4BDCFAEA1D31486E00F62670 /* NeoVimMsgIds.h in Headers */,
|
||||
4B2A2BFA1D0351810074CE9A /* SwiftNeoVim.h in Headers */,
|
||||
4BDF64241D08CAB000D47E1D /* MMCoreTextView.h in Headers */,
|
||||
@ -664,10 +671,10 @@
|
||||
files = (
|
||||
4BEE79171D16D3800012EDAA /* CellAttributes.swift in Sources */,
|
||||
4BF6E29C1D34153C0053FA76 /* KeyUtils.swift in Sources */,
|
||||
4B1BB3531D16C5E500CA4FEF /* InputTestView.swift in Sources */,
|
||||
4BCADE081D11ED12004DAD0F /* CocoaExtensions.swift in Sources */,
|
||||
4B401B1A1D046E0600D99EDC /* NeoVimViewDelegate.swift in Sources */,
|
||||
1929B728262BAA14FC93F6AC /* NeoVimView.swift in Sources */,
|
||||
4B0E22591D5DF62E00C072E6 /* NeoVimBuffer.m in Sources */,
|
||||
4B570DC31D303CAF006EDC21 /* NeoVimAgent.m in Sources */,
|
||||
4BEE79151D16D2100012EDAA /* DispatchUtils.swift in Sources */,
|
||||
4BDF641D1D0887C100D47E1D /* TextDrawer.m in Sources */,
|
||||
@ -692,6 +699,7 @@
|
||||
4BDCFACB1D31449700F62670 /* NeoVimServer.m in Sources */,
|
||||
4B854A1D1D31447C00E08DE1 /* main.m in Sources */,
|
||||
1929BF81A40B4154D3EA33CE /* server_ui.m in Sources */,
|
||||
4B0C905B1D5DED69007753A3 /* NeoVimBuffer.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -947,6 +955,7 @@
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.11;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_SWIFT_FLAGS = "-D DEBUG";
|
||||
SDKROOT = macosx;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
@ -10,6 +10,8 @@ import PureLayout
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
@IBOutlet var debugMenu: NSMenuItem!
|
||||
|
||||
private let disposeBag = DisposeBag()
|
||||
|
||||
private let changeSubject = PublishSubject<Any>()
|
||||
@ -22,7 +24,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
private let mainWindowManager: MainWindowManager
|
||||
private let prefWindowComponent: PrefWindowComponent
|
||||
|
||||
|
||||
override init() {
|
||||
self.actionSink = self.actionSubject.asObservable()
|
||||
self.changeSink = self.changeSubject.asObservable()
|
||||
@ -46,20 +48,20 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
.subscribe(self.actionSubject)
|
||||
.addDisposableTo(self.disposeBag)
|
||||
}
|
||||
|
||||
@IBAction func newDocument(sender: AnyObject!) {
|
||||
self.mainWindowManager.newMainWindow()
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction func showPrefWindow(sender: AnyObject!) {
|
||||
self.prefWindowComponent.show()
|
||||
}
|
||||
// MARK: - NSApplicationDelegate
|
||||
extension AppDelegate {
|
||||
|
||||
func applicationDidFinishLaunching(aNotification: NSNotification) {
|
||||
// let testView = InputTestView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
|
||||
// self.window.contentView?.addSubview(testView)
|
||||
// self.window.makeFirstResponder(testView)
|
||||
|
||||
#if DEBUG
|
||||
self.debugMenu.hidden = false
|
||||
#endif
|
||||
|
||||
self.newDocument(self)
|
||||
}
|
||||
|
||||
@ -80,4 +82,36 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
return .TerminateNow
|
||||
}
|
||||
|
||||
// For drag & dropping files on the App icon.
|
||||
func application(sender: NSApplication, openFiles filenames: [String]) {
|
||||
let urls = filenames.map { NSURL(fileURLWithPath: $0) }
|
||||
self.mainWindowManager.newMainWindow(urls: urls)
|
||||
sender.replyToOpenOrPrint(.Success)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - IBActions
|
||||
extension AppDelegate {
|
||||
|
||||
@IBAction func showPrefWindow(sender: AnyObject!) {
|
||||
self.prefWindowComponent.show()
|
||||
}
|
||||
|
||||
@IBAction func newDocument(sender: AnyObject!) {
|
||||
self.mainWindowManager.newMainWindow()
|
||||
}
|
||||
|
||||
// Invoked when no main window is open.
|
||||
@IBAction func openDocument(sender: AnyObject!) {
|
||||
let panel = NSOpenPanel()
|
||||
panel.canChooseDirectories = true
|
||||
panel.beginWithCompletionHandler { result in
|
||||
guard result == NSFileHandlingPanelOKButton else {
|
||||
return
|
||||
}
|
||||
|
||||
self.mainWindowManager.newMainWindow(urls: panel.URLs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,11 @@
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="VimR" customModuleProvider="target"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="VimR" customModuleProvider="target">
|
||||
<connections>
|
||||
<outlet property="debugMenu" destination="RmS-Zn-Snd" id="anN-h2-97s"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
<menuItem title="VimR" id="1Xt-HY-uBw">
|
||||
@ -72,25 +76,18 @@
|
||||
<action selector="newDocument:" target="-1" id="4Si-XN-c54"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<menuItem title="New Tab" keyEquivalent="t" id="TX9-92-Oe2">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="bVn-NM-KNZ"/>
|
||||
<action selector="newTab:" target="-1" id="RfK-C0-Bu9"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem title="Open Recent" id="tXI-mr-wws">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="oas-Oc-fiZ">
|
||||
<items>
|
||||
<menuItem title="Clear Menu" id="vNY-rz-j42">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="clearRecentDocuments:" target="-1" id="Daa-9d-B3U"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="m54-Is-iLE"/>
|
||||
<menuItem title="Open…" keyEquivalent="o" id="IAo-SY-fd9">
|
||||
<connections>
|
||||
<action selector="openDocument:" target="-1" id="zbe-h0-oBM"/>
|
||||
</connections>
|
||||
</menuItem>
|
||||
<menuItem isSeparatorItem="YES" id="t9v-Ee-SaA"/>
|
||||
<menuItem title="Close" keyEquivalent="w" id="DVo-aG-piG">
|
||||
<connections>
|
||||
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
|
||||
@ -204,11 +201,11 @@
|
||||
</items>
|
||||
</menu>
|
||||
</menuItem>
|
||||
<menuItem title="Debug" id="RmS-Zn-Snd">
|
||||
<menuItem title="Debug" hidden="YES" id="RmS-Zn-Snd">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<menu key="submenu" title="Debug" id="FMz-3N-3Eu">
|
||||
<items>
|
||||
<menuItem title="Debug1" id="IFh-6Q-w93">
|
||||
<menuItem title="Debug 1" id="IFh-6Q-w93">
|
||||
<modifierMask key="keyEquivalentModifierMask"/>
|
||||
<connections>
|
||||
<action selector="debug1:" target="-1" id="OSW-j0-HVo"/>
|
||||
|
@ -4,6 +4,21 @@
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>Document</string>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>public.data</string>
|
||||
</array>
|
||||
<key>LSTypeIsPackage</key>
|
||||
<integer>0</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
|
@ -23,6 +23,8 @@ class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Compo
|
||||
private let windowController = NSWindowController(windowNibName: "MainWindow")
|
||||
private let window: NSWindow
|
||||
|
||||
private let urlsToBeOpenedWhenReady: [NSURL]
|
||||
|
||||
private var defaultEditorFont: NSFont
|
||||
private var usesLigatures: Bool
|
||||
|
||||
@ -31,13 +33,14 @@ class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Compo
|
||||
}
|
||||
|
||||
private let neoVimView = NeoVimView(forAutoLayout: ())
|
||||
|
||||
init(source: Observable<Any>, manager: MainWindowManager, initialData: PrefData) {
|
||||
|
||||
init(source: Observable<Any>, manager: MainWindowManager, urls: [NSURL] = [], initialData: PrefData) {
|
||||
self.source = source
|
||||
self.mainWindowManager = manager
|
||||
self.window = self.windowController.window!
|
||||
self.defaultEditorFont = initialData.appearance.editorFont
|
||||
self.usesLigatures = initialData.appearance.editorUsesLigatures
|
||||
self.urlsToBeOpenedWhenReady = urls
|
||||
|
||||
super.init()
|
||||
|
||||
@ -49,7 +52,6 @@ class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Compo
|
||||
|
||||
self.window.makeFirstResponder(self.neoVimView)
|
||||
self.windowController.showWindow(self)
|
||||
|
||||
}
|
||||
|
||||
deinit {
|
||||
@ -77,6 +79,27 @@ class MainWindowComponent: NSObject, NSWindowDelegate, NeoVimViewDelegate, Compo
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - File Menu Items
|
||||
extension MainWindowComponent {
|
||||
|
||||
@IBAction func newTab(sender: AnyObject!) {
|
||||
self.neoVimView.newTab()
|
||||
}
|
||||
|
||||
@IBAction func openDocument(sender: AnyObject!) {
|
||||
let panel = NSOpenPanel()
|
||||
panel.canChooseDirectories = true
|
||||
panel.beginSheetModalForWindow(self.window) { result in
|
||||
guard result == NSFileHandlingPanelOKButton else {
|
||||
return
|
||||
}
|
||||
|
||||
// The open panel can choose only one file.
|
||||
self.neoVimView.open(urls: panel.URLs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Font Menu Items
|
||||
extension MainWindowComponent {
|
||||
|
||||
@ -109,6 +132,8 @@ extension MainWindowComponent {
|
||||
func neoVimReady() {
|
||||
self.neoVimView.font = self.defaultEditorFont
|
||||
self.neoVimView.usesLigatures = self.usesLigatures
|
||||
|
||||
self.neoVimView.open(urls: self.urlsToBeOpenedWhenReady)
|
||||
}
|
||||
|
||||
func neoVimStopped() {
|
||||
|
@ -22,9 +22,13 @@ class MainWindowManager {
|
||||
self.addReactions()
|
||||
}
|
||||
|
||||
func newMainWindow() {
|
||||
let mainWindowComponent = MainWindowComponent(source: self.source, manager: self, initialData: self.data)
|
||||
func newMainWindow(urls urls: [NSURL] = []) -> MainWindowComponent {
|
||||
let mainWindowComponent = MainWindowComponent(source: self.source,
|
||||
manager: self,
|
||||
urls: urls,
|
||||
initialData: self.data)
|
||||
self.mainWindowComponents[mainWindowComponent.uuid] = mainWindowComponent
|
||||
return mainWindowComponent
|
||||
}
|
||||
|
||||
func closeMainWindow(mainWindowComponent: MainWindowComponent) {
|
||||
|
Loading…
Reference in New Issue
Block a user