forked from dabeeeenster/terminaltabswitching
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 195d237
Showing
7 changed files
with
512 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,6 @@ | |||
build | |||
*.xcodeproj/*.pbxuser | |||
*.xcodeproj/*.perspectivev3 | |||
*.xcodeproj/*.mode1v3 | |||
*.xcodeproj/*.tm_build_errors | |||
*.tmproj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,37 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |||
<plist version="1.0"> | |||
<dict> | |||
<key>CFBundleDevelopmentRegion</key> | |||
<string>English</string> | |||
<key>CFBundleExecutable</key> | |||
<string>${EXECUTABLE_NAME}</string> | |||
<key>CFBundleName</key> | |||
<string>${PRODUCT_NAME}</string> | |||
<key>CFBundleIconFile</key> | |||
<string></string> | |||
<key>CFBundleIdentifier</key> | |||
<string>sh.ciaranwal.terminaltabswitching</string> | |||
<key>CFBundleInfoDictionaryVersion</key> | |||
<string>6.0</string> | |||
<key>CFBundlePackageType</key> | |||
<string>BNDL</string> | |||
<key>CFBundleSignature</key> | |||
<string>????</string> | |||
<key>CFBundleVersion</key> | |||
<string>1.0</string> | |||
<key>NSPrincipalClass</key> | |||
<string>TerminalTabSwitching</string> | |||
<key>SIMBLTargetApplications</key> | |||
<array> | |||
<dict> | |||
<key>BundleIdentifier</key> | |||
<string>com.apple.Terminal</string> | |||
<key>MaxBundleVersion</key> | |||
<string>240</string> | |||
<key>MinBundleVersion</key> | |||
<string>237</string> | |||
</dict> | |||
</array> | |||
</dict> | |||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,13 @@ | |||
/******************************************************************************* | |||
JRSwizzle.h | |||
Copyright (c) 2007 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com> | |||
Some rights reserved: <http://opensource.org/licenses/mit-license.php> | |||
***************************************************************************/ | |||
|
|||
#import <Foundation/Foundation.h> | |||
|
|||
@interface NSObject (JRSwizzle) | |||
+ (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_; | |||
+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_; | |||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,115 @@ | |||
/******************************************************************************* | |||
JRSwizzle.m | |||
Copyright (c) 2007 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com> | |||
Some rights reserved: <http://opensource.org/licenses/mit-license.php> | |||
***************************************************************************/ | |||
|
|||
#import "JRSwizzle.h" | |||
#import <objc/objc-class.h> | |||
|
|||
#define SetNSError(ERROR_VAR, FORMAT,...) \ | |||
if (ERROR_VAR) { \ | |||
NSString *errStr = [@"+[NSObject(JRSwizzle) jr_swizzleMethod:withMethod:error:]: " stringByAppendingFormat:FORMAT,##__VA_ARGS__]; \ | |||
*ERROR_VAR = [NSError errorWithDomain:@"NSCocoaErrorDomain" \ | |||
code:-1 \ | |||
userInfo:[NSDictionary dictionaryWithObject:errStr forKey:NSLocalizedDescriptionKey]]; \ | |||
} | |||
|
|||
@implementation NSObject (JRSwizzle) | |||
|
|||
+ (BOOL)jr_swizzleMethod:(SEL)origSel_ withMethod:(SEL)altSel_ error:(NSError**)error_ { | |||
#if OBJC_API_VERSION >= 2 | |||
Method origMethod = class_getInstanceMethod(self, origSel_); | |||
if (!origMethod) { | |||
SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]); | |||
return NO; | |||
} | |||
|
|||
Method altMethod = class_getInstanceMethod(self, altSel_); | |||
if (!altMethod) { | |||
SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]); | |||
return NO; | |||
} | |||
|
|||
class_addMethod(self, | |||
origSel_, | |||
class_getMethodImplementation(self, origSel_), | |||
method_getTypeEncoding(origMethod)); | |||
class_addMethod(self, | |||
altSel_, | |||
class_getMethodImplementation(self, altSel_), | |||
method_getTypeEncoding(altMethod)); | |||
|
|||
method_exchangeImplementations(class_getInstanceMethod(self, origSel_), class_getInstanceMethod(self, altSel_)); | |||
return YES; | |||
#else | |||
// Scan for non-inherited methods. | |||
Method directOriginalMethod = NULL, directAlternateMethod = NULL; | |||
|
|||
void *iterator = NULL; | |||
struct objc_method_list *mlist = class_nextMethodList(self, &iterator); | |||
while (mlist) { | |||
int method_index = 0; | |||
for (; method_index < mlist->method_count; method_index++) { | |||
if (mlist->method_list[method_index].method_name == origSel_) { | |||
assert(!directOriginalMethod); | |||
directOriginalMethod = &mlist->method_list[method_index]; | |||
} | |||
if (mlist->method_list[method_index].method_name == altSel_) { | |||
assert(!directAlternateMethod); | |||
directAlternateMethod = &mlist->method_list[method_index]; | |||
} | |||
} | |||
mlist = class_nextMethodList(self, &iterator); | |||
} | |||
|
|||
// If either method is inherited, copy it up to the target class to make it non-inherited. | |||
if (!directOriginalMethod || !directAlternateMethod) { | |||
Method inheritedOriginalMethod = NULL, inheritedAlternateMethod = NULL; | |||
if (!directOriginalMethod) { | |||
inheritedOriginalMethod = class_getInstanceMethod(self, origSel_); | |||
if (!inheritedOriginalMethod) { | |||
SetNSError(error_, @"original method %@ not found for class %@", NSStringFromSelector(origSel_), [self className]); | |||
return NO; | |||
} | |||
} | |||
if (!directAlternateMethod) { | |||
inheritedAlternateMethod = class_getInstanceMethod(self, altSel_); | |||
if (!inheritedAlternateMethod) { | |||
SetNSError(error_, @"alternate method %@ not found for class %@", NSStringFromSelector(altSel_), [self className]); | |||
return NO; | |||
} | |||
} | |||
|
|||
int hoisted_method_count = !directOriginalMethod && !directAlternateMethod ? 2 : 1; | |||
struct objc_method_list *hoisted_method_list = malloc(sizeof(struct objc_method_list) + (sizeof(struct objc_method)*(hoisted_method_count-1))); | |||
hoisted_method_list->method_count = hoisted_method_count; | |||
Method hoisted_method = hoisted_method_list->method_list; | |||
|
|||
if (!directOriginalMethod) { | |||
bcopy(inheritedOriginalMethod, hoisted_method, sizeof(struct objc_method)); | |||
directOriginalMethod = hoisted_method++; | |||
} | |||
if (!directAlternateMethod) { | |||
bcopy(inheritedAlternateMethod, hoisted_method, sizeof(struct objc_method)); | |||
directAlternateMethod = hoisted_method; | |||
} | |||
class_addMethods(self, hoisted_method_list); | |||
} | |||
|
|||
// Swizzle. | |||
IMP temp = directOriginalMethod->method_imp; | |||
directOriginalMethod->method_imp = directAlternateMethod->method_imp; | |||
directAlternateMethod->method_imp = temp; | |||
|
|||
return YES; | |||
#endif | |||
} | |||
|
|||
+ (BOOL)jr_swizzleClassMethod:(SEL)origSel_ withClassMethod:(SEL)altSel_ error:(NSError**)error_ { | |||
assert(0); | |||
return NO; | |||
} | |||
|
|||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,63 @@ | |||
#import "JRSwizzle.h" | |||
|
|||
@implementation NSWindowController (Mine) | |||
- (void)updateTabListMenu | |||
{ | |||
NSMenu* windowsMenu = [[NSApplication sharedApplication] windowsMenu]; | |||
|
|||
for(NSMenuItem* menuItem in [windowsMenu itemArray]) | |||
{ | |||
if([menuItem action] == @selector(selectRepresentedTabViewItem:)) | |||
[windowsMenu removeItem:menuItem]; | |||
} | |||
|
|||
NSArray* tabViewItems = [[self valueForKey:@"tabView"] tabViewItems]; | |||
for(size_t tabIndex = 0; tabIndex < [tabViewItems count]; ++tabIndex) | |||
{ | |||
NSString* keyEquivalent = (tabIndex < 10) ? [NSString stringWithFormat:@"%d", (tabIndex+1)%10] : @""; | |||
NSTabViewItem* tabViewItem = [tabViewItems objectAtIndex:tabIndex]; | |||
NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:[tabViewItem label] | |||
action:@selector(selectRepresentedTabViewItem:) | |||
keyEquivalent:keyEquivalent]; | |||
[menuItem setRepresentedObject:tabViewItem]; | |||
[windowsMenu addItem:menuItem]; | |||
[menuItem release]; | |||
} | |||
} | |||
|
|||
- (void)TerminalTabSwitching_windowDidBecomeMain:(id)fp8; | |||
{ | |||
[self TerminalTabSwitching_windowDidBecomeMain:fp8]; | |||
[self updateTabListMenu]; | |||
} | |||
|
|||
- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView*)aTabView | |||
{ | |||
[self updateTabListMenu]; | |||
} | |||
|
|||
- (void)TerminalTabSwitching_awakeFromNib; | |||
{ | |||
[[NSApplication sharedApplication] removeWindowsItem:[self window]]; | |||
[[self window] setExcludedFromWindowsMenu:YES]; | |||
[self TerminalTabSwitching_awakeFromNib]; | |||
} | |||
|
|||
- (void)selectRepresentedTabViewItem:(NSMenuItem*)item | |||
{ | |||
NSTabViewItem* tabViewItem = [item representedObject]; | |||
[[tabViewItem tabView] selectTabViewItem:tabViewItem]; | |||
} | |||
@end | |||
|
|||
@interface TerminalTabSwitching : NSObject | |||
@end | |||
|
|||
@implementation TerminalTabSwitching | |||
+ (void)load | |||
{ | |||
[[[NSApplication sharedApplication] windowsMenu] addItem:[NSMenuItem separatorItem]]; | |||
[NSClassFromString(@"TTWindowController") jr_swizzleMethod:@selector(windowDidBecomeMain:) withMethod:@selector(TerminalTabSwitching_windowDidBecomeMain:) error:NULL]; | |||
[NSClassFromString(@"TTWindowController") jr_swizzleMethod:@selector(awakeFromNib) withMethod:@selector(TerminalTabSwitching_awakeFromNib) error:NULL]; | |||
} | |||
@end |
Oops, something went wrong.