Skip to content

Commit

Permalink
Merge pull request #178 from tiennou/feature/iterm2-support
Browse files Browse the repository at this point in the history
iTerm2 support
  • Loading branch information
tiennou committed Jan 29, 2019
2 parents 6f5d027 + 953cf33 commit 63c307c
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 8 deletions.
78 changes: 70 additions & 8 deletions Classes/Util/PBTerminalUtil.m
Expand Up @@ -7,23 +7,85 @@

#import "PBTerminalUtil.h"
#import "Terminal.h"
#import "iTerm2GeneratedScriptingBridge.h"
#import "PBGitDefaults.h"

@interface PBTerminalUtil () <SBApplicationDelegate>
@end

@implementation PBTerminalUtil

+ (NSString *) initialCommand:(NSURL *)workingDirectory {
return [NSString stringWithFormat:@"cd \"%@\"; clear; echo '# Opened by GitX'; ",
workingDirectory.path];
+ (void)runCommand:(NSString *)command inDirectory:(NSURL *)directory {
[[self terminalHandler] runCommand:command inDirectory:directory];
}

+ (instancetype)terminalHandler {
static dispatch_once_t onceToken;
static PBTerminalUtil *term = nil;
dispatch_once(&onceToken, ^{
term = [[self alloc] init];
});
return term;
}

- (void)runCommand:(NSString *)command inDirectory:(NSURL *)directory {
NSString *terminalHandler = [PBGitDefaults terminalHandler];
BOOL ran = NO;

if ([terminalHandler isEqualToString:@"com.googlecode.iterm2"]) {
ran = [self runiTerm2Command:command inDirectory:directory];
}

// Fall back to Apple Terminal.
if (!ran) {
if (![terminalHandler isEqualToString:@"com.apple.Terminal"])
NSLog(@"Unexpected terminal handler %@, using Terminal.app", terminalHandler);
ran = [self runTerminalCommand:command inDirectory:directory];
}

if (!ran) {
NSLog(@"No usable terminal handler found");
}
}

+ (void) runCommand:(NSString *)command inDirectory:(NSURL *)directory {
NSString * initialCommand = [self initialCommand:directory];
NSString * fullCommand = [initialCommand stringByAppendingString:command];

- (nullable id)eventDidFail:(const AppleEvent *)event withError:(NSError *)error {
NSLog(@"terminal handler error: %@", error);
return nil;
}

- (BOOL)runTerminalCommand:(NSString *)command inDirectory:(NSURL *)directory {
NSString *fullCommand = [NSString stringWithFormat:@"cd \"%@\"; clear; echo '# Opened by GitX'; %@", directory.path, command];

TerminalApplication *term = [SBApplication applicationWithBundleIdentifier: @"com.apple.Terminal"];
if (!term)
return NO;
term.delegate = self;

[term doScript:fullCommand in: nil];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[term activate];
});

return YES;
}

- (BOOL)runiTerm2Command:(NSString *)command inDirectory:(NSURL *)directory {
NSString *fullCommand = [NSString stringWithFormat:@"cd \"%@\"; clear; echo '# Opened by GitX'; %@", directory.path, command];

iTerm2Application *term = [SBApplication applicationWithBundleIdentifier: @"com.googlecode.iterm2"];
if (!term)
return NO;
term.delegate = self;

iTerm2Window *win = [term createWindowWithDefaultProfileCommand:nil];
[win.currentSession writeContentsOfFile:nil text:fullCommand newline:YES];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[term activate];
});

return YES;
}

@end
@end
1 change: 1 addition & 0 deletions Classes/git/PBGitDefaults.h
Expand Up @@ -31,6 +31,7 @@
+ (NSInteger)historySearchMode;
+ (void)setHistorySearchMode:(NSInteger)mode;
+ (BOOL)useRepositoryWatcher;
+ (NSString *)terminalHandler;


// Suppressed Dialog Warnings
Expand Down
8 changes: 8 additions & 0 deletions Classes/git/PBGitDefaults.m
Expand Up @@ -30,6 +30,7 @@
#define kHistorySearchMode @"PBHistorySearchMode"
#define kSuppressedDialogWarnings @"Suppressed Dialog Warnings"
#define kUseRepositoryWatcher @"PBUseRepositoryWatcher"
#define kTerminalHandler @"PBTerminalHandler"

@implementation PBGitDefaults

Expand Down Expand Up @@ -64,6 +65,8 @@ + (void)initialize
forKey:kHistorySearchMode];
[defaultValues setObject:[NSNumber numberWithBool:YES]
forKey:kUseRepositoryWatcher];
[defaultValues setObject:@"com.apple.Terminal"
forKey:kTerminalHandler];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues];
}

Expand Down Expand Up @@ -226,4 +229,9 @@ + (BOOL) useRepositoryWatcher
return [[NSUserDefaults standardUserDefaults] boolForKey:kUseRepositoryWatcher];
}

+ (NSString *)terminalHandler
{
return [[NSUserDefaults standardUserDefaults] stringForKey:kTerminalHandler];
}

@end
158 changes: 158 additions & 0 deletions Classes/iTerm2GeneratedScriptingBridge.h
@@ -0,0 +1,158 @@
/*
* iTerm2.h
*/

#import <AppKit/AppKit.h>
#import <ScriptingBridge/ScriptingBridge.h>


@class iTerm2Application, iTerm2Window, iTerm2Tab, iTerm2Session;

enum iTerm2SaveOptions {
iTerm2SaveOptionsYes = 'yes ' /* Save the file. */,
iTerm2SaveOptionsNo = 'no ' /* Do not save the file. */,
iTerm2SaveOptionsAsk = 'ask ' /* Ask the user whether or not to save the file. */
};
typedef enum iTerm2SaveOptions iTerm2SaveOptions;

@protocol iTerm2GenericMethods

- (void) delete; // Delete an object.
- (void) duplicateTo:(SBObject *)to withProperties:(NSDictionary *)withProperties; // Copy object(s) and put the copies at a new location.
- (BOOL) exists; // Verify if an object exists.
- (void) moveTo:(SBObject *)to; // Move object(s) to a new location.
- (void) close; // Close a document.
- (iTerm2Tab *) createTabWithProfile:(NSString *)withProfile command:(NSString *)command; // Create a new tab
- (iTerm2Tab *) createTabWithDefaultProfileCommand:(NSString *)command; // Create a new tab with the default profile
- (void) writeContentsOfFile:(NSURL *)contentsOfFile text:(NSString *)text newline:(BOOL)newline; // Send text as though it was typed.
- (void) select; // Make receiver visible and selected.
- (iTerm2Session *) splitVerticallyWithProfile:(NSString *)withProfile command:(NSString *)command; // Split a session vertically.
- (iTerm2Session *) splitVerticallyWithDefaultProfileCommand:(NSString *)command; // Split a session vertically, using the default profile for the new session
- (iTerm2Session *) splitVerticallyWithSameProfileCommand:(NSString *)command; // Split a session vertically, using the original session's profile for the new session
- (iTerm2Session *) splitHorizontallyWithProfile:(NSString *)withProfile command:(NSString *)command; // Split a session horizontally.
- (iTerm2Session *) splitHorizontallyWithDefaultProfileCommand:(NSString *)command; // Split a session horizontally, using the default profile for the new session
- (iTerm2Session *) splitHorizontallyWithSameProfileCommand:(NSString *)command; // Split a session horizontally, using the original session's profile for the new session
- (NSString *) variableNamed:(NSString *)named; // Returns the value of a session variable with the given name
- (NSString *) setVariableNamed:(NSString *)named to:(NSString *)to; // Sets the value of a session variable
- (void) revealHotkeyWindow; // Reveals a hotkey window. Only to be called on windows that are hotkey windows.
- (void) hideHotkeyWindow; // Hides a hotkey window. Only to be called on windows that are hotkey windows.
- (void) toggleHotkeyWindow; // Toggles the visibility of a hotkey window. Only to be called on windows that are hotkey windows.

@end



/*
* Standard Suite
*/

// The application's top-level scripting object.
@interface iTerm2Application : SBApplication

- (SBElementArray<iTerm2Window *> *) windows;

@property (copy) iTerm2Window *currentWindow; // The frontmost window
@property (copy, readonly) NSString *name; // The name of the application.
@property (readonly) BOOL frontmost; // Is this the frontmost (active) application?
@property (copy, readonly) NSString *version; // The version of the application.

- (iTerm2Window *) createWindowWithProfile:(NSString *)x command:(NSString *)command; // Create a new window
- (iTerm2Window *) createHotkeyWindowWithProfile:(NSString *)x; // Create a hotkey window
- (iTerm2Window *) createWindowWithDefaultProfileCommand:(NSString *)command; // Create a new window with the default profile

@end

// A window.
@interface iTerm2Window : SBObject <iTerm2GenericMethods>

- (SBElementArray<iTerm2Tab *> *) tabs;

- (NSInteger) id; // The unique identifier of the session.
@property (copy, readonly) NSString *alternateIdentifier; // The alternate unique identifier of the session.
@property (copy, readonly) NSString *name; // The full title of the window.
@property NSInteger index; // The index of the window, ordered front to back.
@property NSRect bounds; // The bounding rectangle of the window.
@property (readonly) BOOL closeable; // Whether the window has a close box.
@property (readonly) BOOL miniaturizable; // Whether the window can be minimized.
@property BOOL miniaturized; // Whether the window is currently minimized.
@property (readonly) BOOL resizable; // Whether the window can be resized.
@property BOOL visible; // Whether the window is currently visible.
@property (readonly) BOOL zoomable; // Whether the window can be zoomed.
@property BOOL zoomed; // Whether the window is currently zoomed.
@property BOOL frontmost; // Whether the window is currently the frontmost window.
@property (copy) iTerm2Tab *currentTab; // The currently selected tab
@property (copy) iTerm2Session *currentSession; // The current session in a window
@property BOOL isHotkeyWindow; // Whether the window is a hotkey window.
@property (copy) NSString *hotkeyWindowProfile; // If the window is a hotkey window, this gives the name of the profile that created the window.
@property NSPoint position; // The position of the window, relative to the upper left corner of the screen.
@property NSPoint origin; // The position of the window, relative to the lower left corner of the screen.
@property NSPoint size; // The width and height of the window
@property NSRect frame; // The bounding rectangle, relative to the lower left corner of the screen.


@end



/*
* iTerm2 Suite
*/

// A terminal tab
@interface iTerm2Tab : SBObject <iTerm2GenericMethods>

- (SBElementArray<iTerm2Session *> *) sessions;

@property (copy) iTerm2Session *currentSession; // The current session in a tab
@property NSInteger index; // Index of tab in parent tab view control


@end

// A terminal session
@interface iTerm2Session : SBObject <iTerm2GenericMethods>

- (NSString *) id; // The unique identifier of the session.
@property BOOL isProcessing; // The session has received output recently.
@property BOOL isAtShellPrompt; // The terminal is at the shell prompt. Requires shell integration.
@property NSInteger columns;
@property NSInteger rows;
@property (copy, readonly) NSString *tty;
@property (copy) NSString *contents; // The currently visible contents of the session.
@property (copy, readonly) NSString *text; // The currently visible contents of the session.
@property (copy) NSString *colorPreset;
@property (copy) NSColor *backgroundColor;
@property (copy) NSColor *boldColor;
@property (copy) NSColor *cursorColor;
@property (copy) NSColor *cursorTextColor;
@property (copy) NSColor *foregroundColor;
@property (copy) NSColor *selectedTextColor;
@property (copy) NSColor *selectionColor;
@property (copy) NSColor *ANSIBlackColor;
@property (copy) NSColor *ANSIRedColor;
@property (copy) NSColor *ANSIGreenColor;
@property (copy) NSColor *ANSIYellowColor;
@property (copy) NSColor *ANSIBlueColor;
@property (copy) NSColor *ANSIMagentaColor;
@property (copy) NSColor *ANSICyanColor;
@property (copy) NSColor *ANSIWhiteColor;
@property (copy) NSColor *ANSIBrightBlackColor;
@property (copy) NSColor *ANSIBrightRedColor;
@property (copy) NSColor *ANSIBrightGreenColor;
@property (copy) NSColor *ANSIBrightYellowColor;
@property (copy) NSColor *ANSIBrightBlueColor;
@property (copy) NSColor *ANSIBrightMagentaColor;
@property (copy) NSColor *ANSIBrightCyanColor;
@property (copy) NSColor *ANSIBrightWhiteColor;
@property (copy) NSColor *underlineColor;
@property BOOL useUnderlineColor; // Whether the use a dedicated color for underlining.
@property (copy) NSString *backgroundImage;
@property (copy) NSString *name;
@property double transparency;
@property (copy, readonly) NSString *uniqueID;
@property (copy, readonly) NSString *profileName; // The session's profile name
@property (copy) NSString *answerbackString; // ENQ Answerback string


@end

2 changes: 2 additions & 0 deletions GitX.xcodeproj/project.pbxproj
Expand Up @@ -615,6 +615,7 @@
97CF01F618A6C5BB00E30F2B /* deleted_file.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = deleted_file.pdf; sourceTree = "<group>"; };
97CF01F718A6C5BB00E30F2B /* empty_file.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = empty_file.pdf; sourceTree = "<group>"; };
97CF01F818A6C5BB00E30F2B /* new_file.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = new_file.pdf; sourceTree = "<group>"; };
A1021294218C5A2000D97D11 /* iTerm2GeneratedScriptingBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iTerm2GeneratedScriptingBridge.h; sourceTree = "<group>"; };
A2F8D0DD17AAB32500580B84 /* PBGitStash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitStash.h; sourceTree = "<group>"; };
A2F8D0DE17AAB32500580B84 /* PBGitStash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitStash.m; sourceTree = "<group>"; };
A2F8D0E917AAB95E00580B84 /* PBSourceViewGitStashItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBSourceViewGitStashItem.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -872,6 +873,7 @@
4D6E4F791E56851A004C3A6F /* PBMacros.h */,
4DF173E721A1D60A003CD3CE /* NSAppearance+PBDarkMode.h */,
4DF173E821A1D60A003CD3CE /* NSAppearance+PBDarkMode.m */,
A1021294218C5A2000D97D11 /* iTerm2GeneratedScriptingBridge.h */,
);
path = Classes;
sourceTree = "<group>";
Expand Down
2 changes: 2 additions & 0 deletions Resources/Info.plist
Expand Up @@ -52,6 +52,8 @@
<string>0.12</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>NSAppleEventsUsageDescription</key>
<string>GitX needs authorization in order to open your Terminal application.</string>
<key>NSAppleScriptEnabled</key>
<true/>
<key>NSMainNibFile</key>
Expand Down

0 comments on commit 63c307c

Please sign in to comment.