mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-07 15:37:14 +02:00
Rebuild cache when vimrc/gvimrc files have been modified
This commit is contained in:
@@ -107,7 +107,8 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
- (void)preloadVimController:(id)sender;
|
||||
- (int)maxPreloadCacheSize;
|
||||
- (MMVimController *)takeVimControllerFromCache;
|
||||
- (void)clearPreloadCache;
|
||||
- (void)clearPreloadCacheWithCount:(int)count;
|
||||
- (NSDate *)rcFilesModificationDate;
|
||||
- (BOOL)openVimControllerWithArguments:(NSDictionary *)arguments;
|
||||
|
||||
#ifdef MM_ENABLE_PLUGINS
|
||||
@@ -822,8 +823,8 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
// A cached controller requires no loading times and results in the new
|
||||
// window popping up instantaneously. If the cache is empty it may take
|
||||
// 1-2 seconds to start a new Vim process.
|
||||
if ([cachedVimControllers count]) {
|
||||
MMVimController *vc = [self takeVimControllerFromCache];
|
||||
MMVimController *vc = [self takeVimControllerFromCache];
|
||||
if (vc) {
|
||||
[[vc backendProxy] acknowledgeConnection];
|
||||
} else {
|
||||
[self launchVimProcessWithArguments:nil];
|
||||
@@ -835,7 +836,7 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
// Open a new window, but clear the preload cache first so that any
|
||||
// subsequent windows opening will have sourced the current .[g]vimrc
|
||||
// files.
|
||||
[self clearPreloadCache];
|
||||
[self clearPreloadCacheWithCount:-1];
|
||||
[self launchVimProcessWithArguments:nil];
|
||||
[self scheduleVimControllerPreloadAfterDelay:2.0];
|
||||
}
|
||||
@@ -947,6 +948,7 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
[vc setIsPreloading:YES];
|
||||
[cachedVimControllers addObject:vc];
|
||||
[self scheduleVimControllerPreloadAfterDelay:1];
|
||||
|
||||
return vc;
|
||||
}
|
||||
|
||||
@@ -1418,8 +1420,32 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
// NOTE: After calling this message the backend corresponding to the
|
||||
// returned vim controller must be sent an acknowledgeConnection message,
|
||||
// else the vim process will be stuck.
|
||||
//
|
||||
// This method may return nil even though the cache might be non-empty; the
|
||||
// caller should handle this by starting a new Vim process.
|
||||
|
||||
if ([cachedVimControllers count] == 0) return nil;
|
||||
int i, count = [cachedVimControllers count];
|
||||
if (0 == count) return nil;
|
||||
|
||||
// Locate the first Vim controller with up-to-date rc-files sourced.
|
||||
NSDate *rcDate = [self rcFilesModificationDate];
|
||||
for (i = 0; i < count; ++i) {
|
||||
MMVimController *vc = [cachedVimControllers objectAtIndex:i];
|
||||
NSDate *date = [vc creationDate];
|
||||
if ([date compare:rcDate] != NSOrderedAscending)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
// Clear out cache entries whose vimrc/gvimrc files were sourced before
|
||||
// the latest modification date for those files. This ensures that the
|
||||
// latest rc-files are always sourced for new windows.
|
||||
[self clearPreloadCacheWithCount:i];
|
||||
[self scheduleVimControllerPreloadAfterDelay:2.0];
|
||||
}
|
||||
|
||||
if ([cachedVimControllers count] == 0)
|
||||
return nil;
|
||||
|
||||
MMVimController *vc = [cachedVimControllers objectAtIndex:0];
|
||||
[vimControllers addObject:vc];
|
||||
@@ -1438,26 +1464,70 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
return vc;
|
||||
}
|
||||
|
||||
- (void)clearPreloadCache
|
||||
- (void)clearPreloadCacheWithCount:(int)count
|
||||
{
|
||||
if ([cachedVimControllers count] == 0)
|
||||
// Remove the 'count' first entries in the preload cache. It is assumed
|
||||
// that objects are added/removed from the cache in a FIFO manner so that
|
||||
// this effectively clears the 'count' oldest entries.
|
||||
// If 'count' is negative, then the entire cache is cleared.
|
||||
|
||||
if ([cachedVimControllers count] == 0 || count == 0)
|
||||
return;
|
||||
|
||||
if (count < 0)
|
||||
count = [cachedVimControllers count];
|
||||
|
||||
// Make sure the preloaded Vim processes get killed or they'll just hang
|
||||
// around being useless until MacVim is terminated.
|
||||
NSEnumerator *e = [cachedVimControllers objectEnumerator];
|
||||
MMVimController *vc;
|
||||
while ((vc = [e nextObject])) {
|
||||
int n = count;
|
||||
while ((vc = [e nextObject]) && n-- > 0) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:vc];
|
||||
[vc sendMessage:TerminateNowMsgID data:nil];
|
||||
|
||||
// Since the preloaded processes were killed "prematurely" we have to
|
||||
// manually tell them to cleanup (it is not enough to simply release
|
||||
// them since deallocation and cleanup are separated).
|
||||
[vc cleanup];
|
||||
}
|
||||
|
||||
// Since the preloaded processes were killed "prematurely" we have to
|
||||
// manually tell them to cleanup (it is not enough to simply release them
|
||||
// since deallocation and cleanup are separated).
|
||||
[cachedVimControllers makeObjectsPerformSelector:@selector(cleanup)];
|
||||
n = count;
|
||||
while (n-- > 0 && [cachedVimControllers count] > 0)
|
||||
[cachedVimControllers removeObjectAtIndex:0];
|
||||
}
|
||||
|
||||
[cachedVimControllers removeAllObjects];
|
||||
- (NSDate *)rcFilesModificationDate
|
||||
{
|
||||
// Check modification dates for ~/.vimrc and ~/.gvimrc and return the
|
||||
// latest modification date. If ~/.vimrc does not exist, check ~/_vimrc
|
||||
// and similarly for gvimrc.
|
||||
// Returns distantPath if no rc files were found.
|
||||
|
||||
NSDate *date = [NSDate distantPast];
|
||||
NSFileManager *fm = [NSFileManager defaultManager];
|
||||
|
||||
NSString *path = [@"~/.vimrc" stringByExpandingTildeInPath];
|
||||
NSDictionary *attr = [fm fileAttributesAtPath:path traverseLink:YES];
|
||||
if (!attr) {
|
||||
path = [@"~/_vimrc" stringByExpandingTildeInPath];
|
||||
attr = [fm fileAttributesAtPath:path traverseLink:YES];
|
||||
}
|
||||
NSDate *modDate = [attr objectForKey:NSFileModificationDate];
|
||||
if (modDate)
|
||||
date = modDate;
|
||||
|
||||
path = [@"~/.gvimrc" stringByExpandingTildeInPath];
|
||||
attr = [fm fileAttributesAtPath:path traverseLink:YES];
|
||||
if (!attr) {
|
||||
path = [@"~/_gvimrc" stringByExpandingTildeInPath];
|
||||
attr = [fm fileAttributesAtPath:path traverseLink:YES];
|
||||
}
|
||||
modDate = [attr objectForKey:NSFileModificationDate];
|
||||
if (modDate)
|
||||
date = [date laterDate:modDate];
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
- (BOOL)openVimControllerWithArguments:(NSDictionary *)arguments
|
||||
@@ -1476,11 +1546,10 @@ static int executeInLoginShell(NSString *path, NSArray *args);
|
||||
// TODO: When the findUntitledWindow heuristic changes, this has to be
|
||||
// fixed for real.
|
||||
[[vc windowController] setTitle:@""];
|
||||
} else if ([cachedVimControllers count] > 0) {
|
||||
} else if ((vc = [self takeVimControllerFromCache])) {
|
||||
// Open files in a new window using a cached vim controller. This
|
||||
// requires virtually no loading time so the new window will pop up
|
||||
// instantaneously.
|
||||
vc = [self takeVimControllerFromCache];
|
||||
[vc passArguments:arguments];
|
||||
[[vc backendProxy] acknowledgeConnection];
|
||||
} else {
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
MMPlugInInstanceMediator *instanceMediator;
|
||||
#endif
|
||||
BOOL isPreloading;
|
||||
NSDate *creationDate;
|
||||
}
|
||||
|
||||
- (id)initWithBackend:(id)backend pid:(int)processIdentifier;
|
||||
@@ -51,6 +52,7 @@
|
||||
- (NSMenu *)mainMenu;
|
||||
- (BOOL)isPreloading;
|
||||
- (void)setIsPreloading:(BOOL)yn;
|
||||
- (NSDate *)creationDate;
|
||||
- (void)cleanup;
|
||||
- (void)dropFiles:(NSArray *)filenames forceOpen:(BOOL)force;
|
||||
- (void)dropString:(NSString *)string;
|
||||
|
||||
@@ -103,51 +103,54 @@ static BOOL isUnsafeMessage(int msgid);
|
||||
|
||||
- (id)initWithBackend:(id)backend pid:(int)processIdentifier
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
windowController =
|
||||
[[MMWindowController alloc] initWithVimController:self];
|
||||
backendProxy = [backend retain];
|
||||
sendQueue = [NSMutableArray new];
|
||||
receiveQueue = [NSMutableArray new];
|
||||
popupMenuItems = [[NSMutableArray alloc] init];
|
||||
toolbarItemDict = [[NSMutableDictionary alloc] init];
|
||||
pid = processIdentifier;
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
NSConnection *connection = [backendProxy connectionForProxy];
|
||||
windowController =
|
||||
[[MMWindowController alloc] initWithVimController:self];
|
||||
backendProxy = [backend retain];
|
||||
sendQueue = [NSMutableArray new];
|
||||
receiveQueue = [NSMutableArray new];
|
||||
popupMenuItems = [[NSMutableArray alloc] init];
|
||||
toolbarItemDict = [[NSMutableDictionary alloc] init];
|
||||
pid = processIdentifier;
|
||||
creationDate = [[NSDate alloc] init];
|
||||
|
||||
// TODO: Check that this will not set the timeout for the root proxy
|
||||
// (in MMAppController).
|
||||
[connection setRequestTimeout:MMBackendProxyRequestTimeout];
|
||||
NSConnection *connection = [backendProxy connectionForProxy];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(connectionDidDie:)
|
||||
name:NSConnectionDidDieNotification object:connection];
|
||||
// TODO: Check that this will not set the timeout for the root proxy
|
||||
// (in MMAppController).
|
||||
[connection setRequestTimeout:MMBackendProxyRequestTimeout];
|
||||
|
||||
// Set up a main menu with only a "MacVim" menu (copied from a template
|
||||
// which itself is set up in MainMenu.nib). The main menu is populated
|
||||
// by Vim later on.
|
||||
mainMenu = [[NSMenu alloc] initWithTitle:@"MainMenu"];
|
||||
NSMenuItem *appMenuItem = [[MMAppController sharedInstance]
|
||||
appMenuItemTemplate];
|
||||
appMenuItem = [[appMenuItem copy] autorelease];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(connectionDidDie:)
|
||||
name:NSConnectionDidDieNotification object:connection];
|
||||
|
||||
// Note: If the title of the application menu is anything but what
|
||||
// CFBundleName says then the application menu will not be typeset in
|
||||
// boldface for some reason. (It should already be set when we copy
|
||||
// from the default main menu, but this is not the case for some
|
||||
// reason.)
|
||||
NSString *appName = [[NSBundle mainBundle]
|
||||
objectForInfoDictionaryKey:@"CFBundleName"];
|
||||
[appMenuItem setTitle:appName];
|
||||
// Set up a main menu with only a "MacVim" menu (copied from a template
|
||||
// which itself is set up in MainMenu.nib). The main menu is populated
|
||||
// by Vim later on.
|
||||
mainMenu = [[NSMenu alloc] initWithTitle:@"MainMenu"];
|
||||
NSMenuItem *appMenuItem = [[MMAppController sharedInstance]
|
||||
appMenuItemTemplate];
|
||||
appMenuItem = [[appMenuItem copy] autorelease];
|
||||
|
||||
[mainMenu addItem:appMenuItem];
|
||||
// Note: If the title of the application menu is anything but what
|
||||
// CFBundleName says then the application menu will not be typeset in
|
||||
// boldface for some reason. (It should already be set when we copy
|
||||
// from the default main menu, but this is not the case for some
|
||||
// reason.)
|
||||
NSString *appName = [[NSBundle mainBundle]
|
||||
objectForInfoDictionaryKey:@"CFBundleName"];
|
||||
[appMenuItem setTitle:appName];
|
||||
|
||||
[mainMenu addItem:appMenuItem];
|
||||
|
||||
#ifdef MM_ENABLE_PLUGINS
|
||||
instanceMediator = [[MMPlugInInstanceMediator alloc] initWithVimController:self];
|
||||
instanceMediator = [[MMPlugInInstanceMediator alloc]
|
||||
initWithVimController:self];
|
||||
#endif
|
||||
|
||||
isInitialized = YES;
|
||||
}
|
||||
isInitialized = YES;
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -174,6 +177,7 @@ static BOOL isUnsafeMessage(int msgid);
|
||||
|
||||
[vimState release]; vimState = nil;
|
||||
[mainMenu release]; mainMenu = nil;
|
||||
[creationDate release]; creationDate = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
@@ -210,6 +214,11 @@ static BOOL isUnsafeMessage(int msgid);
|
||||
isPreloading = yn;
|
||||
}
|
||||
|
||||
- (NSDate *)creationDate
|
||||
{
|
||||
return creationDate;
|
||||
}
|
||||
|
||||
- (void)setServerName:(NSString *)name
|
||||
{
|
||||
if (name != serverName) {
|
||||
|
||||
Reference in New Issue
Block a user