Skip to content

Commit

Permalink
[python] Expose theme through variable. Add python binding for it.
Browse files Browse the repository at this point in the history
  • Loading branch information
gnachman committed Sep 19, 2018
1 parent 8cc06f7 commit eb45138
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 0 deletions.
13 changes: 13 additions & 0 deletions api/library/python/iterm2/iterm2/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,19 @@ async def async_set_variable(self, name, value):
if status != iterm2.api_pb2.VariableResponse.Status.Value("OK"):
raise iterm2.rpc.RPCException(iterm2.api_pb2.VariableResponse.Status.Name(status))

async def async_get_theme(self):
"""
Gets attributes the current theme.
The automatic and minimal themes will always include "dark" or "light".
On macOS 10.14, the light or dark attribute may be inferred from the system setting.
:returns: An array of one or more strings from the set: light, dark, automatic, minimal, highContrast.
"""
s = await self.async_get_variable("effectiveTheme")
return s.split(" ")

async def async_get_variable(self, name):
"""
Fetches an application variable.
Expand Down
8 changes: 8 additions & 0 deletions iTerm2.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,8 @@
53BBA0FA214236AC0074D061 /* iterm2_git_poll.sh in Resources */ = {isa = PBXBuildFile; fileRef = 53BBA0F7214236AC0074D061 /* iterm2_git_poll.sh */; };
53C166AA20C21FBB003B03AF /* iTermMigrationHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 53C166A820C21FBB003B03AF /* iTermMigrationHelper.h */; };
53C166AB20C21FBB003B03AF /* iTermMigrationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 53C166A920C21FBB003B03AF /* iTermMigrationHelper.m */; };
53C2D3A52152CA3900FF6471 /* NSUserDefaults+iTerm.h in Headers */ = {isa = PBXBuildFile; fileRef = 53C2D3A32152CA3900FF6471 /* NSUserDefaults+iTerm.h */; };
53C2D3A62152CA3900FF6471 /* NSUserDefaults+iTerm.m in Sources */ = {isa = PBXBuildFile; fileRef = 53C2D3A42152CA3900FF6471 /* NSUserDefaults+iTerm.m */; };
53E184F11FE32F2800DB78F3 /* iTermMetalBufferPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 53E184EF1FE32F2800DB78F3 /* iTermMetalBufferPool.h */; };
53E184F21FE32F2800DB78F3 /* iTermMetalBufferPool.m in Sources */ = {isa = PBXBuildFile; fileRef = 53E184F01FE32F2800DB78F3 /* iTermMetalBufferPool.m */; };
53FF980B20918D23008688D7 /* template_basic_simple.py in Resources */ = {isa = PBXBuildFile; fileRef = 53FF980A20918D23008688D7 /* template_basic_simple.py */; };
Expand Down Expand Up @@ -3971,6 +3973,8 @@
53BBA0F7214236AC0074D061 /* iterm2_git_poll.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; name = iterm2_git_poll.sh; path = sources/iterm2_git_poll.sh; sourceTree = "<group>"; };
53C166A820C21FBB003B03AF /* iTermMigrationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iTermMigrationHelper.h; sourceTree = "<group>"; };
53C166A920C21FBB003B03AF /* iTermMigrationHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iTermMigrationHelper.m; sourceTree = "<group>"; };
53C2D3A32152CA3900FF6471 /* NSUserDefaults+iTerm.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSUserDefaults+iTerm.h"; sourceTree = "<group>"; };
53C2D3A42152CA3900FF6471 /* NSUserDefaults+iTerm.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSUserDefaults+iTerm.m"; sourceTree = "<group>"; };
53E184EF1FE32F2800DB78F3 /* iTermMetalBufferPool.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iTermMetalBufferPool.h; sourceTree = "<group>"; };
53E184F01FE32F2800DB78F3 /* iTermMetalBufferPool.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iTermMetalBufferPool.m; sourceTree = "<group>"; };
53EBF29B1DCBFF7C00766613 /* iTermAPIServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iTermAPIServer.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -6477,6 +6481,8 @@
A675271C213DB6E800035F2B /* NSImageView+iTerm.m */,
53BBA0F3214205200074D061 /* NSAlert+iTerm.h */,
53BBA0F4214205200074D061 /* NSAlert+iTerm.m */,
53C2D3A32152CA3900FF6471 /* NSUserDefaults+iTerm.h */,
53C2D3A42152CA3900FF6471 /* NSUserDefaults+iTerm.m */,
);
name = Categories;
sourceTree = "<group>";
Expand Down Expand Up @@ -9042,6 +9048,7 @@
A68AC8F31F05C0860023A216 /* NSBundle+iTerm.h in Headers */,
A630118D20E6B71A008114B7 /* iTermStatusBarSetupCollectionViewItem.h in Headers */,
A69C9332212108BC00531438 /* iTermStatusBarComposerComponent.h in Headers */,
53C2D3A52152CA3900FF6471 /* NSUserDefaults+iTerm.h in Headers */,
A6047134213D9E7B009C6C6D /* iTermWorkingDirectoryPoller.h in Headers */,
A66719331DCE36C3000CE608 /* iTermWebSocketFrame.h in Headers */,
A66719341DCE36C3000CE608 /* iTermQuickLookController.h in Headers */,
Expand Down Expand Up @@ -11290,6 +11297,7 @@
A6BC9B1F214A2AE900F50C09 /* iTermVariableReference.m in Sources */,
A6A4868020B6817900493302 /* WindowArrangements.m in Sources */,
A6A4867D20B67F7E00493302 /* ProfilesWindowPreferencesViewController.m in Sources */,
53C2D3A62152CA3900FF6471 /* NSUserDefaults+iTerm.m in Sources */,
A60C0373208A56AB00FE2F1F /* iTermAPIConnectionIdentifierController.m in Sources */,
A6556EAE1FD37ED6000CC89C /* iTermASCIITexture.m in Sources */,
A6971F3420D8D3C30075CFD4 /* iTermAdvancedGPUSettingsViewController.m in Sources */,
Expand Down
18 changes: 18 additions & 0 deletions sources/NSUserDefaults+iTerm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// NSUserDefaults+iTerm.h
// iTerm2SharedARC
//
// Created by George Nachman on 9/19/18.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSUserDefaults (iTerm)

- (void)it_addObserverForKey:(NSString *)key
block:(void (^)(id newValue))block;
@end

NS_ASSUME_NONNULL_END
55 changes: 55 additions & 0 deletions sources/NSUserDefaults+iTerm.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// NSUserDefaults+iTerm.m
// iTerm2SharedARC
//
// Created by George Nachman on 9/19/18.
//

#import "NSUserDefaults+iTerm.h"
#import "NSDictionary+iTerm.h"

static char iTermUserDefaultsKVOKey;
typedef void (^iTermUserDefaultsBlock)(id);

@implementation NSUserDefaults (iTerm)

static NSMutableDictionary<NSString *, NSMutableArray<iTermUserDefaultsBlock> *> *iTermUserDefaultsObserverBlocks(void) {
static NSMutableDictionary<NSString *, NSMutableArray<iTermUserDefaultsBlock> *> *blocks;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
blocks = [NSMutableDictionary dictionary];
});
return blocks;
}

- (void)it_addObserverForKey:(NSString *)key
block:(void (^)(id newValue))block {
[iTermUserDefaultsObserverBlocks() it_addObject:block toMutableArrayForKey:key];
[[NSUserDefaults standardUserDefaults] addObserver:self
forKeyPath:key
options:NSKeyValueObservingOptionNew
context:(void *)&iTermUserDefaultsKVOKey];
}

// This is called when user defaults are changed anywhere.
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if (context == &iTermUserDefaultsKVOKey) {
NSMutableDictionary<NSString *, NSMutableArray<iTermUserDefaultsBlock> *> *blocks =
iTermUserDefaultsObserverBlocks();
NSMutableArray<iTermUserDefaultsBlock> *array = blocks[keyPath];
id newValue = change[NSKeyValueChangeNewKey];
for (iTermUserDefaultsBlock block in array) {
block(newValue);
}
} else {
[super observeValueForKeyPath:keyPath
ofObject:object
change:change
context:context];
}
}

@end
68 changes: 68 additions & 0 deletions sources/iTermApplicationDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
#import "NSFileManager+iTerm.h"
#import "NSObject+iTerm.h"
#import "NSStringITerm.h"
#import "NSUserDefaults+iTerm.h"
#import "NSWindow+iTerm.h"
#import "NSView+RecursiveDescription.h"
#import "PFMoveApplication.h"
Expand Down Expand Up @@ -1005,6 +1006,60 @@ - (void)selectWindowAtMouseRect:(NSRect)mouseRect {
}
}

- (NSString *)effectiveTheme {
BOOL dark = NO;
BOOL light = NO;
BOOL highContrast = NO;
BOOL minimal = NO;

switch ([iTermPreferences intForKey:kPreferenceKeyTabStyle]) {
case TAB_STYLE_DARK:
dark = YES;
break;

case TAB_STYLE_LIGHT:
light = YES;
break;

case TAB_STYLE_DARK_HIGH_CONTRAST:
dark = YES;
highContrast = YES;
break;

case TAB_STYLE_LIGHT_HIGH_CONTRAST:
light = YES;
highContrast = YES;
break;

case TAB_STYLE_MINIMAL:
minimal = YES;
// fall through

case TAB_STYLE_AUTOMATIC: {
NSString *systemMode = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
if ([systemMode isEqual:@"Dark"]) {
dark = YES;
} else {
light = YES;
}
break;
}
}
NSMutableArray *array = [NSMutableArray array];
if (dark) {
[array addObject:@"dark"];
} else if (light) {
[array addObject:@"light"];
}
if (highContrast) {
[array addObject:@"highContrast"];
}
if (minimal) {
[array addObject:@"minimal"];
}
return [array componentsJoinedByString:@" "];
}

- (void)applicationWillFinishLaunching:(NSNotification *)aNotification {
[iTermMenuBarObserver sharedInstance];
// Cleanly crash on uncaught exceptions, such as during actions.
Expand All @@ -1020,6 +1075,19 @@ - (void)applicationWillFinishLaunching:(NSNotification *)aNotification {
}

[[iTermVariableScope globalsScope] setValue:@(getpid()) forVariableNamed:iTermVariableKeyApplicationPID];
[[iTermVariableScope globalsScope] setValue:[self effectiveTheme]
forVariableNamed:iTermVariableKeyApplicationEffectiveTheme];
void (^themeDidChange)(id _Nonnull) = ^(id _Nonnull newValue) {
dispatch_async(dispatch_get_main_queue(), ^{
[[iTermVariableScope globalsScope] setValue:[self effectiveTheme]
forVariableNamed:iTermVariableKeyApplicationEffectiveTheme];
});
};
[[NSUserDefaults standardUserDefaults] it_addObserverForKey:@"AppleInterfaceStyle"
block:themeDidChange];
[[NSUserDefaults standardUserDefaults] it_addObserverForKey:kPreferenceKeyTabStyle
block:themeDidChange];

[[iTermLocalHostNameGuesser sharedInstance] callBlockWhenReady:^(NSString *name) {
[[iTermVariableScope globalsScope] setValue:name forVariableNamed:iTermVariableKeyApplicationLocalhostName];
}];
Expand Down
1 change: 1 addition & 0 deletions sources/iTermVariables.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extern NSString *const iTermVariableKeyGlobalScopeName;

extern NSString *const iTermVariableKeyApplicationPID;
extern NSString *const iTermVariableKeyApplicationLocalhostName;
extern NSString *const iTermVariableKeyApplicationEffectiveTheme;

extern NSString *const iTermVariableKeyTabTitleOverride;
extern NSString *const iTermVariableKeyTabCurrentSession;
Expand Down
2 changes: 2 additions & 0 deletions sources/iTermVariables.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

NSString *const iTermVariableKeyApplicationPID = @"pid";
NSString *const iTermVariableKeyApplicationLocalhostName = @"localhostName";
NSString *const iTermVariableKeyApplicationEffectiveTheme = @"effectiveTheme";

NSString *const iTermVariableKeyTabTitleOverride = @"titleOverride";
NSString *const iTermVariableKeyTabCurrentSession = @"currentSession";
Expand Down Expand Up @@ -131,6 +132,7 @@ + (void)recordBuiltInVariables {
// App context
[self recordUseOfVariableNamed:iTermVariableKeyApplicationPID inContext:iTermVariablesSuggestionContextApp];
[self recordUseOfVariableNamed:iTermVariableKeyApplicationLocalhostName inContext:iTermVariablesSuggestionContextApp];
[self recordUseOfVariableNamed:iTermVariableKeyApplicationEffectiveTheme inContext:iTermVariablesSuggestionContextApp];
}

+ (NSMutableDictionary<NSNumber *, NSMutableSet<NSString *> *> *)mutableRecordedNames {
Expand Down

0 comments on commit eb45138

Please sign in to comment.