Added partial client/server support (scripting not yet supported)

git-svn-id: http://macvim.googlecode.com/svn/trunk@225 96c4425d-ca35-0410-94e5-3396d5c13a8f
This commit is contained in:
Bjorn Winckler
2007-09-01 19:35:31 +00:00
parent 5db52978b5
commit ffa192240a
7 changed files with 296 additions and 4 deletions
+37
View File
@@ -433,6 +433,43 @@ static NSTimeInterval MMTerminateTimeout = 3;
return vc;
}
- (NSArray *)serverList
{
NSMutableArray *array = [NSMutableArray array];
unsigned i, count = [vimControllers count];
for (i = 0; i < count; ++i) {
MMVimController *controller = [vimControllers objectAtIndex:i];
id proxy = [controller backendProxy];
NSConnection *connection = [proxy connectionForProxy];
if (!connection)
continue;
// Set low timeouts since we don't want this call to potentially lock
// up MacVim for a while.
NSTimeInterval req = [connection requestTimeout];
NSTimeInterval rep = [connection replyTimeout];
[connection setRequestTimeout:0];
[connection setReplyTimeout:.1];
@try {
NSString *eval = [proxy evaluateExpression:@"v:servername"];
if (eval) {
[array addObject:eval];
}
}
@catch (NSException *e) {
NSLog(@"WARNING: Got exception while listing servers: \"%@\"", e);
}
@finally {
[connection setRequestTimeout:req];
[connection setReplyTimeout:rep];
}
}
return array;
}
@end // MMAppController
+2
View File
@@ -54,6 +54,7 @@
- (void)setSpecialColor:(int)color;
- (void)setDefaultColorsBackground:(int)bg foreground:(int)fg;
- (NSString *)macVimConnectionName;
- (BOOL)checkin;
- (BOOL)openVimWindow;
- (void)clearAll;
@@ -103,6 +104,7 @@
- (void)startBlink;
- (void)stopBlink;
- (void)adjustLinespace:(int)linespace;
- (void)activate;
- (int)lookupColorWithKey:(NSString *)key;
- (BOOL)hasSpecialKeyWithValue:(NSString *)value;
+39 -4
View File
@@ -135,14 +135,19 @@ enum {
[self queueMessage:SetDefaultColorsMsgID data:data];
}
- (NSString *)macVimConnectionName
{
// NOTE! If the name of the connection changes here it must also be
// updated in MMAppController.m.
return [NSString stringWithFormat:@"%@-connection",
[[NSBundle mainBundle] bundleIdentifier]];
}
- (BOOL)checkin
{
NSBundle *mainBundle = [NSBundle mainBundle];
// NOTE! If the name of the connection changes here it must also be
// updated in MMAppController.m.
NSString *name = [NSString stringWithFormat:@"%@-connection",
[mainBundle bundleIdentifier]];
NSString *name = [self macVimConnectionName];
connection = [NSConnection connectionWithRegisteredName:name host:nil];
if (!connection) {
#if 0
@@ -365,6 +370,12 @@ enum {
- (void)exit
{
#ifdef MAC_CLIENTSERVER
// The default connection is used for the client/server code.
[[NSConnection defaultConnection] setRootObject:nil];
[[NSConnection defaultConnection] invalidate];
#endif
// By invalidating the NSConnection the MMWindowController immediately
// finds out that the connection is down and as a result
// [MMWindowController connectionDidDie:] is invoked.
@@ -843,6 +854,11 @@ enum {
[self queueMessage:AdjustLinespaceMsgID data:data];
}
- (void)activate
{
[self queueMessage:ActivateMsgID data:nil];
}
- (int)lookupColorWithKey:(NSString *)key
{
if (!(key && [key length] > 0))
@@ -1003,6 +1019,19 @@ enum {
return NO;
}
- (NSString *)evaluateExpression:(in bycopy NSString *)expr
{
NSString *eval = nil;
char_u *res = eval_client_expr_to_string((char_u*)[expr UTF8String]);
if (res != NULL) {
eval = [NSString stringWithUTF8String:(char*)res];
vim_free(res);
}
return eval;
}
@end // MMBackend
@@ -1363,6 +1392,12 @@ enum {
const void *bytes = [data bytes];
int shape = *((int*)bytes); bytes += sizeof(int);
update_mouseshape(shape);
} else if (ServerAddInputMsgID == msgid) {
const void *bytes = [data bytes];
/*int len = *((int*)bytes);*/ bytes += sizeof(int);
char_u *cmd = (char_u*)bytes;
server_to_input_buf(cmd);
} else {
NSLog(@"WARNING: Unknown message received (msgid=%d)", msgid);
}
+3
View File
@@ -749,6 +749,9 @@ static NSMenuItem *findMenuItemWithTagInMenu(NSMenu *root, int tag)
int linespace = *((int*)bytes); bytes += sizeof(int);
[windowController adjustLinespace:linespace];
} else if (ActivateMsgID == msgid) {
[NSApp activateIgnoringOtherApps:YES];
[[windowController window] makeKeyAndOrderFront:self];
} else {
NSLog(@"WARNING: Unknown message received (msgid=%d)", msgid);
}
+4
View File
@@ -35,6 +35,7 @@
- (BOOL)checkForModifiedBuffers;
- (oneway void)setDialogReturn:(in bycopy id)obj;
- (BOOL)starRegisterToPasteboard:(byref NSPasteboard *)pboard;
- (NSString *)evaluateExpression:(in bycopy NSString *)expr;
@end
@@ -62,6 +63,7 @@
@protocol MMAppProtocol
- (byref id <MMFrontendProtocol>)connectBackend:
(byref in id <MMBackendProtocol>)backend pid:(int)pid;
- (NSArray *)serverList;
@end
@@ -119,6 +121,8 @@ enum {
MouseMovedMsgID,
SetMouseShapeMsgID,
AdjustLinespaceMsgID,
ActivateMsgID,
ServerAddInputMsgID,
};
+2
View File
@@ -57,6 +57,8 @@ char *MessageStrings[] =
"MouseMovedMsgID",
"SetMouseShapeMsgID",
"AdjustLinespaceMsgID",
"ActivateMsgID",
"ServerAddInputMsgID",
};
+209
View File
@@ -1247,6 +1247,7 @@ gui_mch_invert_rectangle(int r, int c, int nr, int nc)
void
gui_mch_set_foreground(void)
{
[[MMBackend sharedInstance] activate];
}
#endif
@@ -1326,3 +1327,211 @@ gui_macvim_is_valid_action(NSString *action)
return [actionDict objectForKey:action] != nil;
}
// -- Client/Server ---------------------------------------------------------
#ifdef MAC_CLIENTSERVER
//
// NOTE: Client/Server stuff only works with the GUI. Theoretically it would
// be possible to make this code work with terminal Vim, but it would require
// that a run-loop is set up and checked, etc.
//
static unsigned MMServerMax = 1000;
static NSTimeInterval MMEvaluateExpressionTimeout = 3;
static NSTimeInterval MMServerListTimeout = 3;
static NSString *
shortToLongName(NSString *shortName)
{
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
return [NSString stringWithFormat:@"%@.%@", bundleIdentifier, shortName];
}
static NSString *
longToShortName(NSString *longName)
{
NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
NSRange range = [longName rangeOfString:bundleIdentifier];
return NSNotFound != range.location
? [longName substringFromIndex:1+NSMaxRange(range)]
: longName;
}
/*
* Register connection with 'name'. The actual connection is named something
* like 'org.vim.MacVim.VIM3', whereas the server is called 'VIM3'.
*/
void
serverSetName(char_u *name)
{
NSString *baseName =
shortToLongName([NSString stringWithUTF8String:(char*)name]);
NSString *longName = baseName;
NSConnection *connection = [NSConnection defaultConnection];
unsigned i;
for (i = 1; i < MMServerMax; ++i) {
//NSLog(@"Client-Server: Try to register connection '%@'", longName);
if ([connection registerName:longName]) {
NSString *shortName = longToShortName(longName);
//NSLog(@"Client-Server: Did register server '%@'", shortName);
serverName = vim_strsave((char_u*)[shortName UTF8String]);
#ifdef FEAT_EVAL
set_vim_var_string(VV_SEND_SERVER, serverName, -1);
#endif
#ifdef FEAT_TITLE
need_maketitle = TRUE;
#endif
// Don't wait for requests (time-out means that the message is
// dropped).
[connection setRequestTimeout:0];
//[connection setReplyTimeout:MMReplyTimeout];
[connection setRootObject:[MMBackend sharedInstance]];
break;
}
longName = [NSString stringWithFormat:@"%@%d", baseName, i];
}
}
/*
* Send to an instance of Vim.
* Returns 0 for OK, negative for an error.
*/
int
serverSendToVim(char_u *name, char_u *cmd, char_u **result,
int *server, int asExpr, int silent)
{
//NSLog(@"serverSendToVim(name=%s, cmd=%s, asExpr=%d, silent=%d)",
// name, cmd, asExpr, silent);
NSString *longName =
shortToLongName([NSString stringWithUTF8String:(char*)name]);
NSConnection *connection = [NSConnection
connectionWithRegisteredName:longName host:nil];
if (!connection) {
if (!silent)
EMSG2(_(e_noserver), name);
return -1;
}
[connection setRequestTimeout:0];
id proxy = [connection rootProxy];
[proxy setProtocolForProxy:@protocol(MMBackendProtocol)];
// Expressions need to wait for a reply; otherwise just send off the input
// asynchronously.
if (asExpr) {
[connection setReplyTimeout:MMEvaluateExpressionTimeout];
@try {
NSString *expr = [NSString stringWithUTF8String:(char*)cmd];
NSString *eval = [proxy evaluateExpression:expr];
if (result) {
*result = (eval ? vim_strsave((char_u*)[eval UTF8String])
: vim_strsave((char_u*)_(e_invexprmsg)));
}
}
@catch (NSException *e) {
NSLog(@"WARNING: Caught exception during expression evaluation "
"\"%@\"", e);
return -1;
}
} else {
int len = 1 + STRLEN(cmd);
NSMutableData *data = [NSMutableData data];
[data appendBytes:&len length:sizeof(int)];
[data appendBytes:cmd length:len];
[proxy processInput:ServerAddInputMsgID data:data];
}
return 0;
}
/*
* Ask MacVim for the names of all Vim servers.
*/
char_u *
serverGetVimNames(void)
{
char_u *names = NULL;
NSString *name = [[MMBackend sharedInstance] macVimConnectionName];
NSConnection *connection = [NSConnection connectionWithRegisteredName:name
host:nil];
if (connection) {
NSArray *serverNames = nil;
id proxy = [connection rootProxy];
[proxy setProtocolForProxy:@protocol(MMAppProtocol)];
[connection setRequestTimeout:0];
[connection setReplyTimeout:MMServerListTimeout];
@try {
serverNames = [proxy serverList];
}
@catch (NSException *e) {
NSLog(@"Exception caught when listing servers: \"%@\"", e);
}
if (serverNames) {
NSString *string = [serverNames componentsJoinedByString:@"\n"];
names = vim_strsave((char_u*)[string UTF8String]);
}
}
return names;
}
/*
* Check for replies from 'serverid'.
* Return TRUE and a non-malloc'ed string if there is. Else return FALSE.
*/
int
serverPeekReply(char_u *serverid, char_u **str)
{
return FALSE;
}
/*
* Wait for replies from server 'name'.
* Return 0 and the malloc'ed string when a reply is available.
* Return -1 on error.
*/
int
serverReadReply(char_u *name, char_u **str)
{
//NSLog(@"serverReadReply(name=%s)", name);
return -1;
}
/*
* Send a reply string (notification) to client with id "name".
* Return -1 if the window is invalid.
*/
int
serverSendReply(char_u *name, char_u *reply)
{
//NSLog(@"serverSendReply(name=%s, reply=%s)", name, reply);
return -1;
}
#endif // MAC_CLIENTSERVER