mirror of
https://github.com/qvacua/vimr.git
synced 2024-12-26 23:36:08 +03:00
GH-302, GH-421 Add passthrough arguments to vimr script
This commit is contained in:
parent
8241d596fd
commit
3216b08699
@ -10,7 +10,9 @@
|
|||||||
|
|
||||||
@interface NeoVimServer : NSObject
|
@interface NeoVimServer : NSObject
|
||||||
|
|
||||||
- (instancetype)initWithLocalServerName:(NSString *)localServerName remoteServerName:(NSString *)remoteServerName;
|
- (instancetype)initWithLocalServerName:(NSString *)localServerName
|
||||||
|
remoteServerName:(NSString *)remoteServerName
|
||||||
|
nvimArgs:(NSArray<NSString *> *)nvimArgs;
|
||||||
|
|
||||||
- (void)sendMessageWithId:(NeoVimServerMsgId)msgid;
|
- (void)sendMessageWithId:(NeoVimServerMsgId)msgid;
|
||||||
- (void)sendMessageWithId:(NeoVimServerMsgId)msgid data:(NSData *)data;
|
- (void)sendMessageWithId:(NeoVimServerMsgId)msgid data:(NSData *)data;
|
||||||
|
@ -29,6 +29,7 @@ static const double qTimeout = 10;
|
|||||||
|
|
||||||
@interface NeoVimServer ()
|
@interface NeoVimServer ()
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)nvimArgs;
|
||||||
- (NSCondition *)outputCondition;
|
- (NSCondition *)outputCondition;
|
||||||
- (void)handleQuitMsg;
|
- (void)handleQuitMsg;
|
||||||
|
|
||||||
@ -61,7 +62,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
switch (msgid) {
|
switch (msgid) {
|
||||||
|
|
||||||
case NeoVimAgentMsgIdAgentReady:
|
case NeoVimAgentMsgIdAgentReady:
|
||||||
start_neovim();
|
start_neovim(neoVimServer.nvimArgs);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
case NeoVimAgentMsgIdQuit:
|
case NeoVimAgentMsgIdQuit:
|
||||||
@ -110,6 +111,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
@implementation NeoVimServer {
|
@implementation NeoVimServer {
|
||||||
NSString *_localServerName;
|
NSString *_localServerName;
|
||||||
NSString *_remoteServerName;
|
NSString *_remoteServerName;
|
||||||
|
NSArray<NSString *> *_nvimArgs;
|
||||||
|
|
||||||
CFMessagePortRef _remoteServerPort;
|
CFMessagePortRef _remoteServerPort;
|
||||||
|
|
||||||
@ -120,11 +122,18 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
NSCondition *_outputCondition;
|
NSCondition *_outputCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)nvimArgs {
|
||||||
|
return _nvimArgs;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSCondition *)outputCondition {
|
- (NSCondition *)outputCondition {
|
||||||
return _outputCondition;
|
return _outputCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithLocalServerName:(NSString *)localServerName remoteServerName:(NSString *)remoteServerName {
|
- (instancetype)initWithLocalServerName:(NSString *)localServerName
|
||||||
|
remoteServerName:(NSString *)remoteServerName
|
||||||
|
nvimArgs:(NSArray<NSString*> *)nvimArgs {
|
||||||
|
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (self == nil) {
|
if (self == nil) {
|
||||||
return nil;
|
return nil;
|
||||||
@ -134,6 +143,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
|
|
||||||
_localServerName = localServerName;
|
_localServerName = localServerName;
|
||||||
_remoteServerName = remoteServerName;
|
_remoteServerName = remoteServerName;
|
||||||
|
_nvimArgs = nvimArgs;
|
||||||
|
|
||||||
_localServerThread = [[NSThread alloc] initWithTarget:self selector:@selector(runLocalServer) object:nil];
|
_localServerThread = [[NSThread alloc] initWithTarget:self selector:@selector(runLocalServer) object:nil];
|
||||||
_localServerThread.name = localServerName;
|
_localServerThread.name = localServerName;
|
||||||
|
@ -44,10 +44,14 @@ int main(int argc, const char *argv[]) {
|
|||||||
NSArray<NSString *> *arguments = [NSProcessInfo processInfo].arguments;
|
NSArray<NSString *> *arguments = [NSProcessInfo processInfo].arguments;
|
||||||
NSString *remoteServerName = arguments[1];
|
NSString *remoteServerName = arguments[1];
|
||||||
NSString *localServerName = arguments[2];
|
NSString *localServerName = arguments[2];
|
||||||
|
NSArray<NSString *> *nvimArgs = argc > 3 ? [arguments subarrayWithRange:NSMakeRange(3, (NSUInteger) (argc - 3))]
|
||||||
|
: nil;
|
||||||
|
|
||||||
_neovim_server = [[NeoVimServer alloc] initWithLocalServerName:localServerName remoteServerName:remoteServerName];
|
_neovim_server = [[NeoVimServer alloc] initWithLocalServerName:localServerName
|
||||||
DLOG("Started neovim server '%s' and connected it with the remote agent '%s'.",
|
remoteServerName:remoteServerName
|
||||||
localServerName.cstr, remoteServerName.cstr);
|
nvimArgs:nvimArgs];
|
||||||
|
DLOG("Started neovim server '%s' with args '%@' and connected it with the remote agent '%s'.",
|
||||||
|
localServerName.cstr, nvimArgs, remoteServerName.cstr);
|
||||||
|
|
||||||
[_neovim_server notifyReadiness];
|
[_neovim_server notifyReadiness];
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
extern NeoVimServer *_neovim_server;
|
extern NeoVimServer *_neovim_server;
|
||||||
extern CFRunLoopRef _mainRunLoop;
|
extern CFRunLoopRef _mainRunLoop;
|
||||||
|
|
||||||
extern void start_neovim();
|
extern void start_neovim(NSArray<NSString *> *args);
|
||||||
extern void quit_neovim();
|
extern void quit_neovim();
|
||||||
|
|
||||||
extern void neovim_select_window(void **argv);
|
extern void neovim_select_window(void **argv);
|
||||||
|
@ -166,10 +166,27 @@ static void delete_marked_text() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void run_neovim(void *arg __unused) {
|
static void run_neovim(void *arg __unused) {
|
||||||
char *argv[1];
|
int argc = 1;
|
||||||
argv[0] = "nvim";
|
char **argv;
|
||||||
|
|
||||||
nvim_main(1, argv);
|
@autoreleasepool {
|
||||||
|
NSArray<NSString *> *nvimArgs = (NSArray *) arg;
|
||||||
|
NSLog(@"%@", nvimArgs);
|
||||||
|
|
||||||
|
argc = (int) nvimArgs.count + 1;
|
||||||
|
argv = (char **) malloc((argc + 1) * sizeof(char *));
|
||||||
|
|
||||||
|
argv[0] = "nvim";
|
||||||
|
for (int i = 0; i < nvimArgs.count; i++) {
|
||||||
|
argv[i + 1] = (char *) nvimArgs[(NSUInteger) i].cstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[nvimArgs release]; // retained in start_neovim()
|
||||||
|
}
|
||||||
|
|
||||||
|
nvim_main(argc, argv);
|
||||||
|
|
||||||
|
free(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_ui_size(UIBridgeData *bridge, int width, int height) {
|
static void set_ui_size(UIBridgeData *bridge, int width, int height) {
|
||||||
@ -543,7 +560,7 @@ void custom_ui_autocmds_groups(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark Other help functions
|
#pragma mark Other help functions
|
||||||
void start_neovim() {
|
void start_neovim(NSArray<NSString *> *args) {
|
||||||
// set $VIMRUNTIME to ${RESOURCE_PATH_OF_XPC_BUNDLE}/runtime
|
// set $VIMRUNTIME to ${RESOURCE_PATH_OF_XPC_BUNDLE}/runtime
|
||||||
NSString *bundlePath = [NSBundle bundleForClass:[NeoVimServer class]].bundlePath;
|
NSString *bundlePath = [NSBundle bundleForClass:[NeoVimServer class]].bundlePath;
|
||||||
NSString *resourcesPath = [bundlePath.stringByDeletingLastPathComponent
|
NSString *resourcesPath = [bundlePath.stringByDeletingLastPathComponent
|
||||||
@ -557,7 +574,7 @@ void start_neovim() {
|
|||||||
uv_mutex_init(&_mutex);
|
uv_mutex_init(&_mutex);
|
||||||
uv_cond_init(&_condition);
|
uv_cond_init(&_condition);
|
||||||
|
|
||||||
uv_thread_create(&_nvim_thread, run_neovim, NULL);
|
uv_thread_create(&_nvim_thread, run_neovim, [args retain]); // released in run_neovim()
|
||||||
DLOG("NeoVim started");
|
DLOG("NeoVim started");
|
||||||
|
|
||||||
// continue only after our UI main code for neovim has been fully initialized
|
// continue only after our UI main code for neovim has been fully initialized
|
||||||
|
@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@interface NeoVimAgent : NSObject
|
@interface NeoVimAgent : NSObject
|
||||||
|
|
||||||
@property (nonatomic) bool useInteractiveZsh;
|
@property (nonatomic) bool useInteractiveZsh;
|
||||||
|
@property (nonatomic) NSURL *cwd;
|
||||||
|
@property (nonatomic, nullable) NSArray<NSString *> *nvimArgs;
|
||||||
@property (readonly, atomic) bool neoVimIsQuitting;
|
@property (readonly, atomic) bool neoVimIsQuitting;
|
||||||
@property (nonatomic, weak) id <NeoVimUiBridgeProtocol> bridge;
|
@property (nonatomic, weak) id <NeoVimUiBridgeProtocol> bridge;
|
||||||
|
|
||||||
|
@ -23,8 +23,11 @@ static type *data_to_ ## type ## _array(NSData *data, NSUInteger count) { \
|
|||||||
}
|
}
|
||||||
|
|
||||||
data_to_array(NSUInteger)
|
data_to_array(NSUInteger)
|
||||||
|
|
||||||
data_to_array(NSInteger)
|
data_to_array(NSInteger)
|
||||||
|
|
||||||
data_to_array(bool)
|
data_to_array(bool)
|
||||||
|
|
||||||
data_to_array(CellAttributes)
|
data_to_array(CellAttributes)
|
||||||
|
|
||||||
static void log_cfmachport_error(SInt32 err, NeoVimAgentMsgId msgid, NSData *inputData) {
|
static void log_cfmachport_error(SInt32 err, NeoVimAgentMsgId msgid, NSData *inputData) {
|
||||||
@ -168,7 +171,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
_neoVimServerTask.standardInput = inputPipe;
|
_neoVimServerTask.standardInput = inputPipe;
|
||||||
_neoVimServerTask.currentDirectoryPath = NSHomeDirectory();
|
_neoVimServerTask.currentDirectoryPath = self.cwd == nil ? NSHomeDirectory() : self.cwd.path;
|
||||||
_neoVimServerTask.launchPath = shellPath;
|
_neoVimServerTask.launchPath = shellPath;
|
||||||
_neoVimServerTask.arguments = shellArgs;
|
_neoVimServerTask.arguments = shellArgs;
|
||||||
[_neoVimServerTask launch];
|
[_neoVimServerTask launch];
|
||||||
@ -177,6 +180,15 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
[self neoVimServerExecutablePath],
|
[self neoVimServerExecutablePath],
|
||||||
[self localServerName],
|
[self localServerName],
|
||||||
[self remoteServerName]];
|
[self remoteServerName]];
|
||||||
|
if (self.nvimArgs != nil) {
|
||||||
|
NSMutableArray *args = [NSMutableArray new];
|
||||||
|
for (NSString *arg in self.nvimArgs) {
|
||||||
|
[args addObject:[NSString stringWithFormat:@"'%@'", arg]];
|
||||||
|
}
|
||||||
|
NSLog(@"mapped %@", args);
|
||||||
|
cmd = [cmd stringByAppendingFormat:@" %@", [args componentsJoinedByString:@" "]];
|
||||||
|
NSLog(@"%@", cmd);
|
||||||
|
}
|
||||||
|
|
||||||
NSFileHandle *writeHandle = inputPipe.fileHandleForWriting;
|
NSFileHandle *writeHandle = inputPipe.fileHandleForWriting;
|
||||||
[writeHandle writeData:[cmd dataUsingEncoding:NSUTF8StringEncoding]];
|
[writeHandle writeData:[cmd dataUsingEncoding:NSUTF8StringEncoding]];
|
||||||
@ -252,13 +264,13 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)resizeToWidth:(int)width height:(int)height {
|
- (void)resizeToWidth:(int)width height:(int)height {
|
||||||
int values[] = { width, height };
|
int values[] = {width, height};
|
||||||
NSData *data = [[NSData alloc] initWithBytes:values length:(2 * sizeof(int))];
|
NSData *data = [[NSData alloc] initWithBytes:values length:(2 * sizeof(int))];
|
||||||
[self sendMessageWithId:NeoVimAgentMsgIdResize data:data expectsReply:NO];
|
[self sendMessageWithId:NeoVimAgentMsgIdResize data:data expectsReply:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cursorGoToRow:(int)row column:(int)column {
|
- (void)cursorGoToRow:(int)row column:(int)column {
|
||||||
int values[] = { row, column };
|
int values[] = {row, column};
|
||||||
NSData *data = [[NSData alloc] initWithBytes:values length:(2 * sizeof(int))];
|
NSData *data = [[NSData alloc] initWithBytes:values length:(2 * sizeof(int))];
|
||||||
[self sendMessageWithId:NeoVimAgentMsgIdCursorGoto data:data expectsReply:NO];
|
[self sendMessageWithId:NeoVimAgentMsgIdCursorGoto data:data expectsReply:NO];
|
||||||
}
|
}
|
||||||
@ -275,7 +287,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)escapedFileName:(NSString *)fileName {
|
- (NSString *)escapedFileName:(NSString *)fileName {
|
||||||
NSArray<NSString *> *fileNames = [self escapedFileNames:@[ fileName ]];
|
NSArray<NSString *> *fileNames = [self escapedFileNames:@[fileName]];
|
||||||
if (fileNames.count == 0) {
|
if (fileNames.count == 0) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@ -296,7 +308,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
- (void)setBoolOption:(NSString *)option to:(bool)value {
|
- (void)setBoolOption:(NSString *)option to:(bool)value {
|
||||||
NSMutableData *data = [NSMutableData new];
|
NSMutableData *data = [NSMutableData new];
|
||||||
|
|
||||||
bool values[] = { value };
|
bool values[] = {value};
|
||||||
const char *cstr = [option cStringUsingEncoding:NSUTF8StringEncoding];
|
const char *cstr = [option cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
|
||||||
[data appendBytes:values length:sizeof(bool)];
|
[data appendBytes:values length:sizeof(bool)];
|
||||||
@ -306,18 +318,18 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)scrollHorizontal:(NSInteger)horiz vertical:(NSInteger)vert {
|
- (void)scrollHorizontal:(NSInteger)horiz vertical:(NSInteger)vert {
|
||||||
NSInteger values[] = { horiz, vert };
|
NSInteger values[] = {horiz, vert};
|
||||||
NSData *data = [[NSData alloc] initWithBytes:values length:2 * sizeof(NSInteger)];
|
NSData *data = [[NSData alloc] initWithBytes:values length:2 * sizeof(NSInteger)];
|
||||||
[self sendMessageWithId:NeoVimAgentMsgIdScroll data:data expectsReply:NO];
|
[self sendMessageWithId:NeoVimAgentMsgIdScroll data:data expectsReply:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)selectWindow:(NeoVimWindow *)window {
|
- (void)selectWindow:(NeoVimWindow *)window {
|
||||||
int values[] = { (int) window.handle };
|
int values[] = {(int) window.handle};
|
||||||
NSData *data = [[NSData alloc] initWithBytes:values length:sizeof(int)];
|
NSData *data = [[NSData alloc] initWithBytes:values length:sizeof(int)];
|
||||||
[self sendMessageWithId:NeoVimAgentMsgIdSelectWindow data:data expectsReply:NO];
|
[self sendMessageWithId:NeoVimAgentMsgIdSelectWindow data:data expectsReply:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray <NSString *>*)escapedFileNames:(NSArray <NSString *>*)fileNames {
|
- (NSArray <NSString *> *)escapedFileNames:(NSArray <NSString *> *)fileNames {
|
||||||
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:fileNames];
|
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:fileNames];
|
||||||
NSData *response = [self sendMessageWithId:NeoVimAgentMsgIdGetEscapeFileNames data:data expectsReply:YES];
|
NSData *response = [self sendMessageWithId:NeoVimAgentMsgIdGetEscapeFileNames data:data expectsReply:YES];
|
||||||
if (response == nil) {
|
if (response == nil) {
|
||||||
@ -483,8 +495,8 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
|
|
||||||
case NeoVimServerMsgIdSetPosition: {
|
case NeoVimServerMsgIdSetPosition: {
|
||||||
NSInteger *values = data_to_NSInteger_array(data, 4);
|
NSInteger *values = data_to_NSInteger_array(data, 4);
|
||||||
[_bridge gotoPosition:(Position) { .row = values[0], .column = values[1] }
|
[_bridge gotoPosition:(Position) {.row = values[0], .column = values[1]}
|
||||||
textPosition:(Position) { .row = values[2], .column = values[3] }];
|
textPosition:(Position) {.row = values[2], .column = values[3]}];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -617,7 +629,7 @@ static CFDataRef local_server_callback(CFMessagePortRef local, SInt32 msgid, CFD
|
|||||||
if (data.length == sizeof(NSUInteger) + sizeof(NSInteger)) {
|
if (data.length == sizeof(NSUInteger) + sizeof(NSInteger)) {
|
||||||
NSUInteger *values = (NSUInteger *) data.bytes;
|
NSUInteger *values = (NSUInteger *) data.bytes;
|
||||||
NeoVimAutoCommandEvent event = (NeoVimAutoCommandEvent) values[0];
|
NeoVimAutoCommandEvent event = (NeoVimAutoCommandEvent) values[0];
|
||||||
NSInteger bufferHandle = ((NSInteger *)(values + 1))[0];
|
NSInteger bufferHandle = ((NSInteger *) (values + 1))[0];
|
||||||
[_bridge autoCommandEvent:event bufferHandle:bufferHandle];
|
[_bridge autoCommandEvent:event bufferHandle:bufferHandle];
|
||||||
} else {
|
} else {
|
||||||
NSUInteger *values = data_to_NSUInteger_array(data, 1);
|
NSUInteger *values = data_to_NSUInteger_array(data, 1);
|
||||||
|
@ -14,9 +14,16 @@ public class NeoVimView: NSView,
|
|||||||
public struct Config {
|
public struct Config {
|
||||||
|
|
||||||
var useInteractiveZsh: Bool
|
var useInteractiveZsh: Bool
|
||||||
|
var cwd: URL
|
||||||
|
var nvimArgs: [String]?
|
||||||
|
|
||||||
|
public init(useInteractiveZsh: Bool,
|
||||||
|
cwd: URL = URL(fileURLWithPath: NSHomeDirectory()),
|
||||||
|
nvimArgs: [String]? = nil) {
|
||||||
|
|
||||||
public init(useInteractiveZsh: Bool) {
|
|
||||||
self.useInteractiveZsh = useInteractiveZsh
|
self.useInteractiveZsh = useInteractiveZsh
|
||||||
|
self.cwd = cwd
|
||||||
|
self.nvimArgs = nvimArgs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +122,8 @@ public class NeoVimView: NSView,
|
|||||||
// We cannot set bridge in init since self is not available before super.init()...
|
// We cannot set bridge in init since self is not available before super.init()...
|
||||||
self.agent.bridge = self
|
self.agent.bridge = self
|
||||||
self.agent.useInteractiveZsh = config.useInteractiveZsh
|
self.agent.useInteractiveZsh = config.useInteractiveZsh
|
||||||
|
self.agent.cwd = config.cwd
|
||||||
|
self.agent.nvimArgs = config.nvimArgs
|
||||||
|
|
||||||
self.launchNeoVim()
|
self.launchNeoVim()
|
||||||
}
|
}
|
||||||
|
@ -8,23 +8,12 @@ import RxSwift
|
|||||||
import PureLayout
|
import PureLayout
|
||||||
import Sparkle
|
import Sparkle
|
||||||
|
|
||||||
/// Keep the rawValues in sync with Action in the `vimr` Python script.
|
|
||||||
fileprivate enum VimRUrlAction: String {
|
|
||||||
case activate = "activate"
|
|
||||||
case open = "open"
|
|
||||||
case newWindow = "open-in-new-window"
|
|
||||||
case separateWindows = "open-in-separate-windows"
|
|
||||||
}
|
|
||||||
|
|
||||||
fileprivate let filePrefix = "file="
|
|
||||||
fileprivate let cwdPrefix = "cwd="
|
|
||||||
|
|
||||||
@NSApplicationMain
|
@NSApplicationMain
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
enum Action {
|
enum Action {
|
||||||
|
|
||||||
case newMainWindow(urls: [URL], cwd: URL)
|
case newMainWindow(urls: [URL], cwd: URL, nvimArgs: [String]?)
|
||||||
case openInKeyWindow(urls: [URL], cwd: URL)
|
case openInKeyWindow(urls: [URL], cwd: URL)
|
||||||
|
|
||||||
case preferences
|
case preferences
|
||||||
@ -172,7 +161,7 @@ extension AppDelegate {
|
|||||||
// For drag & dropping files on the App icon.
|
// For drag & dropping files on the App icon.
|
||||||
func application(_ sender: NSApplication, openFiles filenames: [String]) {
|
func application(_ sender: NSApplication, openFiles filenames: [String]) {
|
||||||
let urls = filenames.map { URL(fileURLWithPath: $0) }
|
let urls = filenames.map { URL(fileURLWithPath: $0) }
|
||||||
self.emit(.newMainWindow(urls: urls, cwd: FileUtils.userHomeUrl))
|
self.emit(.newMainWindow(urls: urls, cwd: FileUtils.userHomeUrl, nvimArgs: nil))
|
||||||
|
|
||||||
sender.reply(toOpenOrPrint: .success)
|
sender.reply(toOpenOrPrint: .success)
|
||||||
}
|
}
|
||||||
@ -216,13 +205,24 @@ extension AppDelegate {
|
|||||||
switch action {
|
switch action {
|
||||||
|
|
||||||
case .activate, .newWindow:
|
case .activate, .newWindow:
|
||||||
self.emit(.newMainWindow(urls: urls, cwd: cwd))
|
self.emit(.newMainWindow(urls: urls, cwd: cwd, nvimArgs: nil))
|
||||||
|
|
||||||
case .open:
|
case .open:
|
||||||
self.emit(.openInKeyWindow(urls: urls, cwd: cwd))
|
self.emit(.openInKeyWindow(urls: urls, cwd: cwd))
|
||||||
|
|
||||||
case .separateWindows:
|
case .separateWindows:
|
||||||
urls.forEach { self.emit(.newMainWindow(urls: [$0], cwd: cwd)) }
|
urls.forEach { self.emit(.newMainWindow(urls: [$0], cwd: cwd, nvimArgs: nil)) }
|
||||||
|
|
||||||
|
case .nvim:
|
||||||
|
guard let nvimArgs = queryParams?
|
||||||
|
.filter({ $0.hasPrefix(nvimArgsPrefix) })
|
||||||
|
.flatMap({ $0.without(prefix: nvimArgsPrefix).removingPercentEncoding }) else {
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog("app delegate: \(nvimArgs)")
|
||||||
|
self.emit(.newMainWindow(urls: [], cwd: cwd, nvimArgs: nvimArgs))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ extension AppDelegate {
|
|||||||
extension AppDelegate {
|
extension AppDelegate {
|
||||||
|
|
||||||
@IBAction func newDocument(_ sender: Any?) {
|
@IBAction func newDocument(_ sender: Any?) {
|
||||||
self.emit(.newMainWindow(urls: [], cwd: FileUtils.userHomeUrl))
|
self.emit(.newMainWindow(urls: [], cwd: FileUtils.userHomeUrl, nvimArgs: nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func openInNewWindow(_ sender: Any?) {
|
@IBAction func openInNewWindow(_ sender: Any?) {
|
||||||
@ -256,7 +256,21 @@ extension AppDelegate {
|
|||||||
let urls = panel.urls
|
let urls = panel.urls
|
||||||
let commonParentUrl = FileUtils.commonParent(of: urls)
|
let commonParentUrl = FileUtils.commonParent(of: urls)
|
||||||
|
|
||||||
self.emit(.newMainWindow(urls: urls, cwd: commonParentUrl))
|
self.emit(.newMainWindow(urls: urls, cwd: commonParentUrl, nvimArgs: nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Keep the rawValues in sync with Action in the `vimr` Python script.
|
||||||
|
fileprivate enum VimRUrlAction: String {
|
||||||
|
case activate = "activate"
|
||||||
|
case open = "open"
|
||||||
|
case newWindow = "open-in-new-window"
|
||||||
|
case separateWindows = "open-in-separate-windows"
|
||||||
|
case nvim = "nvim"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fileprivate let filePrefix = "file="
|
||||||
|
fileprivate let cwdPrefix = "cwd="
|
||||||
|
fileprivate let nvimArgsPrefix = "nvim-args="
|
||||||
|
@ -18,8 +18,14 @@ class AppDelegateReducer {
|
|||||||
|
|
||||||
switch pair.action {
|
switch pair.action {
|
||||||
|
|
||||||
case let .newMainWindow(urls, cwd):
|
case let .newMainWindow(urls, cwd, nvimArgs):
|
||||||
let mainWindow = self.newMainWindow(with: state, urls: urls, cwd: cwd)
|
let mainWindow: MainWindow.State
|
||||||
|
if let args = nvimArgs {
|
||||||
|
mainWindow = self.newMainWindow(with: state, urls: [], cwd: cwd, nvimArgs: args)
|
||||||
|
} else {
|
||||||
|
mainWindow = self.newMainWindow(with: state, urls: urls, cwd: cwd)
|
||||||
|
}
|
||||||
|
|
||||||
state.mainWindows[mainWindow.uuid] = mainWindow
|
state.mainWindows[mainWindow.uuid] = mainWindow
|
||||||
|
|
||||||
case let .openInKeyWindow(urls, cwd):
|
case let .openInKeyWindow(urls, cwd):
|
||||||
@ -42,7 +48,11 @@ class AppDelegateReducer {
|
|||||||
|
|
||||||
fileprivate let baseServerUrl: URL
|
fileprivate let baseServerUrl: URL
|
||||||
|
|
||||||
fileprivate func newMainWindow(with state: AppState, urls: [URL], cwd: URL) -> MainWindow.State {
|
fileprivate func newMainWindow(with state: AppState,
|
||||||
|
urls: [URL],
|
||||||
|
cwd: URL,
|
||||||
|
nvimArgs: [String]? = nil) -> MainWindow.State {
|
||||||
|
|
||||||
var mainWindow = state.mainWindowTemplate
|
var mainWindow = state.mainWindowTemplate
|
||||||
mainWindow.uuid = UUID().uuidString
|
mainWindow.uuid = UUID().uuidString
|
||||||
mainWindow.isDirty = false
|
mainWindow.isDirty = false
|
||||||
@ -50,6 +60,7 @@ class AppDelegateReducer {
|
|||||||
htmlFile: nil,
|
htmlFile: nil,
|
||||||
server: Marked(self.baseServerUrl.appendingPathComponent(HtmlPreviewToolReducer.selectFirstPath))
|
server: Marked(self.baseServerUrl.appendingPathComponent(HtmlPreviewToolReducer.selectFirstPath))
|
||||||
)
|
)
|
||||||
|
mainWindow.nvimArgs = nvimArgs
|
||||||
|
|
||||||
mainWindow.urlsToOpen = urls.toDict { url in MainWindow.OpenMode.default }
|
mainWindow.urlsToOpen = urls.toDict { url in MainWindow.OpenMode.default }
|
||||||
|
|
||||||
|
@ -79,8 +79,10 @@ class MainWindow: NSObject,
|
|||||||
self.editorPosition = state.preview.editorPosition
|
self.editorPosition = state.preview.editorPosition
|
||||||
self.previewPosition = state.preview.previewPosition
|
self.previewPosition = state.preview.previewPosition
|
||||||
|
|
||||||
self.neoVimView = NeoVimView(frame: CGRect.zero,
|
let neoVimViewConfig = NeoVimView.Config(useInteractiveZsh: state.useInteractiveZsh,
|
||||||
config: NeoVimView.Config(useInteractiveZsh: state.useInteractiveZsh))
|
cwd: state.cwd,
|
||||||
|
nvimArgs: state.nvimArgs)
|
||||||
|
self.neoVimView = NeoVimView(frame: .zero, config: neoVimViewConfig)
|
||||||
self.neoVimView.configureForAutoLayout()
|
self.neoVimView.configureForAutoLayout()
|
||||||
|
|
||||||
let workspace = Workspace(mainView: self.neoVimView)
|
let workspace = Workspace(mainView: self.neoVimView)
|
||||||
|
@ -216,6 +216,7 @@ extension MainWindow {
|
|||||||
|
|
||||||
var appearance = AppearanceState.default
|
var appearance = AppearanceState.default
|
||||||
var useInteractiveZsh = false
|
var useInteractiveZsh = false
|
||||||
|
var nvimArgs: [String]?
|
||||||
|
|
||||||
// to be cleaned
|
// to be cleaned
|
||||||
var urlsToOpen = [URL: OpenMode]()
|
var urlsToOpen = [URL: OpenMode]()
|
||||||
|
45
VimR/vimr
45
VimR/vimr
@ -4,6 +4,7 @@ import urllib
|
|||||||
import subprocess
|
import subprocess
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
|
||||||
def call_open(arg, dry_run=False):
|
def call_open(arg, dry_run=False):
|
||||||
@ -17,9 +18,21 @@ def abspath(path):
|
|||||||
return os.path.abspath(os.path.expanduser(path))
|
return os.path.abspath(os.path.expanduser(path))
|
||||||
|
|
||||||
|
|
||||||
def vimr(action, args=None, dry_run=False):
|
def vimr_nvim(args=None, dry_run=False):
|
||||||
files = args.file
|
cwd = os.getcwd()
|
||||||
|
|
||||||
|
query_params = {
|
||||||
|
"cwd": cwd
|
||||||
|
}
|
||||||
|
|
||||||
|
if args:
|
||||||
|
query_params["nvim-args"] = args
|
||||||
|
|
||||||
|
url = "vimr://{0}?{1}".format(action, urllib.urlencode(query_params, True).replace('+', '%20'))
|
||||||
|
call_open(url, dry_run)
|
||||||
|
|
||||||
|
|
||||||
|
def vimr(action, args=None, dry_run=False):
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
if args.cwd is not None:
|
if args.cwd is not None:
|
||||||
cwd = abspath(args.cwd)
|
cwd = abspath(args.cwd)
|
||||||
@ -28,6 +41,7 @@ def vimr(action, args=None, dry_run=False):
|
|||||||
"cwd": cwd
|
"cwd": cwd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
files = args.file
|
||||||
if files:
|
if files:
|
||||||
query_params["file"] = [abspath(f) for f in files]
|
query_params["file"] = [abspath(f) for f in files]
|
||||||
|
|
||||||
@ -40,6 +54,7 @@ class Action:
|
|||||||
OPEN = "open"
|
OPEN = "open"
|
||||||
NEW_WINDOW = "open-in-new-window"
|
NEW_WINDOW = "open-in-new-window"
|
||||||
SEPARATE_WINDOWS = "open-in-separate-windows"
|
SEPARATE_WINDOWS = "open-in-separate-windows"
|
||||||
|
NVIM = "nvim"
|
||||||
|
|
||||||
description = """
|
description = """
|
||||||
Open files in VimR: By default all files are open in tabs in the front most window or in a new window if there is none.
|
Open files in VimR: By default all files are open in tabs in the front most window or in a new window if there is none.
|
||||||
@ -50,21 +65,31 @@ parser = argparse.ArgumentParser(description=description)
|
|||||||
|
|
||||||
parser.add_argument("--dry-run", action="store_true", dest="dry_run", help="Just print the 'open' command.")
|
parser.add_argument("--dry-run", action="store_true", dest="dry_run", help="Just print the 'open' command.")
|
||||||
parser.add_argument("--cwd", action="store", help="Set the working directory.")
|
parser.add_argument("--cwd", action="store", help="Set the working directory.")
|
||||||
|
parser.add_argument("--nvim", action="store_true", help="All other arguments will be passthrough to nvim.")
|
||||||
group = parser.add_mutually_exclusive_group()
|
group = parser.add_mutually_exclusive_group()
|
||||||
# no option => Open files in tabs in the front most window.
|
# no option => Open files in tabs in the front most window.
|
||||||
group.add_argument("-n", action="store_true", dest="new_window", help="Open files in tabs in a new window.")
|
group.add_argument("-n", action="store_true", dest="new_window", help="Open files in tabs in a new window.")
|
||||||
group.add_argument("-s", action="store_true", dest="separate_windows", help="Open files in separate windows.")
|
group.add_argument("-s", action="store_true", dest="separate_windows", help="Open files in separate windows.")
|
||||||
parser.add_argument("file", nargs="*")
|
parser.add_argument("file", nargs="*")
|
||||||
args = parser.parse_args()
|
args, _ = parser.parse_known_args()
|
||||||
dry_run = args.dry_run
|
dry_run = args.dry_run
|
||||||
|
|
||||||
if not args.file:
|
if args.nvim is not None:
|
||||||
action = Action.ACTIVATE
|
action = Action.NVIM
|
||||||
elif args.new_window:
|
nvim_parser = argparse.ArgumentParser()
|
||||||
action = Action.NEW_WINDOW
|
nvim_parser.add_argument("--nvim", action="store_true")
|
||||||
elif args.separate_windows:
|
nvim_parser.add_argument("--dry-run", action="store_true")
|
||||||
action = Action.SEPARATE_WINDOWS
|
_, nvim_args = nvim_parser.parse_known_args()
|
||||||
|
vimr_nvim(nvim_args, dry_run)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
if not args.file:
|
||||||
|
action = Action.ACTIVATE
|
||||||
|
elif args.new_window:
|
||||||
|
action = Action.NEW_WINDOW
|
||||||
|
elif args.separate_windows:
|
||||||
|
action = Action.SEPARATE_WINDOWS
|
||||||
|
else:
|
||||||
action = Action.OPEN
|
action = Action.OPEN
|
||||||
|
|
||||||
vimr(action, args, dry_run)
|
vimr(action, args, dry_run)
|
||||||
|
Loading…
Reference in New Issue
Block a user