Add `.setShortcut()`, `.getShortcut()`, and `.reset()` methods (#24)
This commit is contained in:
parent
729002c51a
commit
43d7fe58b3
|
@ -7,6 +7,9 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
E3500C3624DEDCEF00F4B055 /* KeyboardShortcutsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3500C3524DEDCEF00F4B055 /* KeyboardShortcutsTests.swift */; };
|
||||||
|
E3500C3824DEDCEF00F4B055 /* KeyboardShortcuts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "KeyboardShortcuts::KeyboardShortcuts::Product" /* KeyboardShortcuts.framework */; };
|
||||||
|
E3500C3F24DEDDEC00F4B055 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3500C3E24DEDDEC00F4B055 /* Utilities.swift */; };
|
||||||
E38103FE246449180023E9A8 /* Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = E38103FD246449180023E9A8 /* Name.swift */; };
|
E38103FE246449180023E9A8 /* Name.swift in Sources */ = {isa = PBXBuildFile; fileRef = E38103FD246449180023E9A8 /* Name.swift */; };
|
||||||
E3AD497024705C7600F51C0D /* NSMenuItem++.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD496F24705C7600F51C0D /* NSMenuItem++.swift */; };
|
E3AD497024705C7600F51C0D /* NSMenuItem++.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3AD496F24705C7600F51C0D /* NSMenuItem++.swift */; };
|
||||||
E3BF5627245C23840024D9BF /* Recorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3BF5626245C23840024D9BF /* Recorder.swift */; };
|
E3BF5627245C23840024D9BF /* Recorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E3BF5626245C23840024D9BF /* Recorder.swift */; };
|
||||||
|
@ -26,6 +29,13 @@
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
E3500C3924DEDCEF00F4B055 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = OBJ_1 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = "KeyboardShortcuts::KeyboardShortcuts";
|
||||||
|
remoteInfo = KeyboardShortcuts;
|
||||||
|
};
|
||||||
E3BF5648245C2D550024D9BF /* PBXContainerItemProxy */ = {
|
E3BF5648245C2D550024D9BF /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = OBJ_1 /* Project object */;
|
containerPortal = OBJ_1 /* Project object */;
|
||||||
|
@ -50,6 +60,10 @@
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
E3500C3324DEDCEF00F4B055 /* KeyboardShortcutsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeyboardShortcutsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
E3500C3524DEDCEF00F4B055 /* KeyboardShortcutsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = KeyboardShortcutsTests.swift; sourceTree = "<group>"; usesTabs = 1; };
|
||||||
|
E3500C3724DEDCEF00F4B055 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
E3500C3E24DEDDEC00F4B055 /* Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Utilities.swift; sourceTree = "<group>"; usesTabs = 1; };
|
||||||
E38103FD246449180023E9A8 /* Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Name.swift; sourceTree = "<group>"; usesTabs = 1; };
|
E38103FD246449180023E9A8 /* Name.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Name.swift; sourceTree = "<group>"; usesTabs = 1; };
|
||||||
E3AD496F24705C7600F51C0D /* NSMenuItem++.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "NSMenuItem++.swift"; sourceTree = "<group>"; usesTabs = 1; };
|
E3AD496F24705C7600F51C0D /* NSMenuItem++.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = "NSMenuItem++.swift"; sourceTree = "<group>"; usesTabs = 1; };
|
||||||
E3BF5626245C23840024D9BF /* Recorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Recorder.swift; sourceTree = "<group>"; usesTabs = 1; };
|
E3BF5626245C23840024D9BF /* Recorder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Recorder.swift; sourceTree = "<group>"; usesTabs = 1; };
|
||||||
|
@ -72,6 +86,14 @@
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
E3500C3024DEDCEF00F4B055 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
E3500C3824DEDCEF00F4B055 /* KeyboardShortcuts.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
E3BF562F245C2BB30024D9BF /* Frameworks */ = {
|
E3BF562F245C2BB30024D9BF /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -90,6 +112,16 @@
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
E3500C3424DEDCEF00F4B055 /* KeyboardShortcutsTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
E3500C3524DEDCEF00F4B055 /* KeyboardShortcutsTests.swift */,
|
||||||
|
E3500C3E24DEDDEC00F4B055 /* Utilities.swift */,
|
||||||
|
E3500C3724DEDCEF00F4B055 /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = KeyboardShortcutsTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
E3BF5633245C2BB30024D9BF /* KeyboardShortcutsExample */ = {
|
E3BF5633245C2BB30024D9BF /* KeyboardShortcutsExample */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -110,18 +142,12 @@
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
OBJ_11 /* Tests */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
);
|
|
||||||
name = Tests;
|
|
||||||
sourceTree = SOURCE_ROOT;
|
|
||||||
};
|
|
||||||
OBJ_12 /* Products */ = {
|
OBJ_12 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
"KeyboardShortcuts::KeyboardShortcuts::Product" /* KeyboardShortcuts.framework */,
|
"KeyboardShortcuts::KeyboardShortcuts::Product" /* KeyboardShortcuts.framework */,
|
||||||
E3BF5632245C2BB30024D9BF /* KeyboardShortcutsExample.app */,
|
E3BF5632245C2BB30024D9BF /* KeyboardShortcutsExample.app */,
|
||||||
|
E3500C3324DEDCEF00F4B055 /* KeyboardShortcutsTests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
|
@ -132,8 +158,8 @@
|
||||||
OBJ_16 /* readme.md */,
|
OBJ_16 /* readme.md */,
|
||||||
OBJ_6 /* Package.swift */,
|
OBJ_6 /* Package.swift */,
|
||||||
OBJ_7 /* Sources */,
|
OBJ_7 /* Sources */,
|
||||||
OBJ_11 /* Tests */,
|
|
||||||
E3BF5633245C2BB30024D9BF /* KeyboardShortcutsExample */,
|
E3BF5633245C2BB30024D9BF /* KeyboardShortcutsExample */,
|
||||||
|
E3500C3424DEDCEF00F4B055 /* KeyboardShortcutsTests */,
|
||||||
OBJ_12 /* Products */,
|
OBJ_12 /* Products */,
|
||||||
E3BF5645245C2D550024D9BF /* Frameworks */,
|
E3BF5645245C2D550024D9BF /* Frameworks */,
|
||||||
);
|
);
|
||||||
|
@ -167,6 +193,24 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
|
E3500C3224DEDCEF00F4B055 /* KeyboardShortcutsTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = E3500C3D24DEDCEF00F4B055 /* Build configuration list for PBXNativeTarget "KeyboardShortcutsTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
E3500C2F24DEDCEF00F4B055 /* Sources */,
|
||||||
|
E3500C3024DEDCEF00F4B055 /* Frameworks */,
|
||||||
|
E3500C3124DEDCEF00F4B055 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
E3500C3A24DEDCEF00F4B055 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
name = KeyboardShortcutsTests;
|
||||||
|
productName = KeyboardShortcutsTests;
|
||||||
|
productReference = E3500C3324DEDCEF00F4B055 /* KeyboardShortcutsTests.xctest */;
|
||||||
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
|
};
|
||||||
E3BF5631245C2BB30024D9BF /* KeyboardShortcutsExample */ = {
|
E3BF5631245C2BB30024D9BF /* KeyboardShortcutsExample */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = E3BF5642245C2BB50024D9BF /* Build configuration list for PBXNativeTarget "KeyboardShortcutsExample" */;
|
buildConfigurationList = E3BF5642245C2BB50024D9BF /* Build configuration list for PBXNativeTarget "KeyboardShortcutsExample" */;
|
||||||
|
@ -225,9 +269,12 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftMigration = 9999;
|
LastSwiftMigration = 9999;
|
||||||
LastSwiftUpdateCheck = 1140;
|
LastSwiftUpdateCheck = 1160;
|
||||||
LastUpgradeCheck = 1150;
|
LastUpgradeCheck = 1150;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
E3500C3224DEDCEF00F4B055 = {
|
||||||
|
CreatedOnToolsVersion = 11.6;
|
||||||
|
};
|
||||||
E3BF5631245C2BB30024D9BF = {
|
E3BF5631245C2BB30024D9BF = {
|
||||||
CreatedOnToolsVersion = 11.4.1;
|
CreatedOnToolsVersion = 11.4.1;
|
||||||
};
|
};
|
||||||
|
@ -249,11 +296,19 @@
|
||||||
"KeyboardShortcuts::KeyboardShortcuts" /* KeyboardShortcuts */,
|
"KeyboardShortcuts::KeyboardShortcuts" /* KeyboardShortcuts */,
|
||||||
"KeyboardShortcuts::SwiftPMPackageDescription" /* KeyboardShortcutsPackageDescription */,
|
"KeyboardShortcuts::SwiftPMPackageDescription" /* KeyboardShortcutsPackageDescription */,
|
||||||
E3BF5631245C2BB30024D9BF /* KeyboardShortcutsExample */,
|
E3BF5631245C2BB30024D9BF /* KeyboardShortcutsExample */,
|
||||||
|
E3500C3224DEDCEF00F4B055 /* KeyboardShortcutsTests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
E3500C3124DEDCEF00F4B055 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
E3BF5630245C2BB30024D9BF /* Resources */ = {
|
E3BF5630245C2BB30024D9BF /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -305,6 +360,15 @@
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
E3500C2F24DEDCEF00F4B055 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
E3500C3F24DEDDEC00F4B055 /* Utilities.swift in Sources */,
|
||||||
|
E3500C3624DEDCEF00F4B055 /* KeyboardShortcutsTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
E3BF562E245C2BB30024D9BF /* Sources */ = {
|
E3BF562E245C2BB30024D9BF /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
@ -341,6 +405,11 @@
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
|
E3500C3A24DEDCEF00F4B055 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = "KeyboardShortcuts::KeyboardShortcuts" /* KeyboardShortcuts */;
|
||||||
|
targetProxy = E3500C3924DEDCEF00F4B055 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
E3BF5649245C2D550024D9BF /* PBXTargetDependency */ = {
|
E3BF5649245C2D550024D9BF /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
target = "KeyboardShortcuts::KeyboardShortcuts" /* KeyboardShortcuts */;
|
target = "KeyboardShortcuts::KeyboardShortcuts" /* KeyboardShortcuts */;
|
||||||
|
@ -360,6 +429,84 @@
|
||||||
/* End PBXVariantGroup section */
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
|
E3500C3B24DEDCEF00F4B055 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
DEVELOPMENT_TEAM = YG56YK5RN5;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
INFOPLIST_FILE = KeyboardShortcutsTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@loader_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.KeyboardShortcutsTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
E3500C3C24DEDCEF00F4B055 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEVELOPMENT_TEAM = YG56YK5RN5;
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
INFOPLIST_FILE = KeyboardShortcutsTests/Info.plist;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@loader_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = com.sindresorhus.KeyboardShortcutsTests;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
E3BF5643245C2BB50024D9BF /* Debug */ = {
|
E3BF5643245C2BB50024D9BF /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
@ -703,6 +850,15 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
|
E3500C3D24DEDCEF00F4B055 /* Build configuration list for PBXNativeTarget "KeyboardShortcutsTests" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
E3500C3B24DEDCEF00F4B055 /* Debug */,
|
||||||
|
E3500C3C24DEDCEF00F4B055 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
E3BF5642245C2BB50024D9BF /* Build configuration list for PBXNativeTarget "KeyboardShortcutsExample" */ = {
|
E3BF5642245C2BB50024D9BF /* Build configuration list for PBXNativeTarget "KeyboardShortcutsExample" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1160"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "E3500C3224DEDCEF00F4B055"
|
||||||
|
BuildableName = "KeyboardShortcutsTests.xctest"
|
||||||
|
BlueprintName = "KeyboardShortcutsTests"
|
||||||
|
ReferencedContainer = "container:KeyboardShortcuts.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -24,6 +24,11 @@ struct ContentView: View {
|
||||||
Text("Pressed? \(isPressed2 ? "👍" : "👎")")
|
Text("Pressed? \(isPressed2 ? "👍" : "👎")")
|
||||||
.frame(width: 100, alignment: .leading)
|
.frame(width: 100, alignment: .leading)
|
||||||
}
|
}
|
||||||
|
Spacer()
|
||||||
|
Divider()
|
||||||
|
Button("Reset All") {
|
||||||
|
KeyboardShortcuts.reset(.testShortcut1, .testShortcut2)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.frame(maxWidth: 300)
|
.frame(maxWidth: 300)
|
||||||
.padding(60)
|
.padding(60)
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?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>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
|
@ -0,0 +1,30 @@
|
||||||
|
import XCTest
|
||||||
|
import KeyboardShortcuts
|
||||||
|
|
||||||
|
final class KeyboardShortcutsTests: XCTestCase {
|
||||||
|
// TODO: Add more tests.
|
||||||
|
|
||||||
|
override func setUpWithError() throws {
|
||||||
|
UserDefaults.standard.removeAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testSetShortcutAndReset() throws {
|
||||||
|
let defaultShortcut = KeyboardShortcuts.Shortcut(.c)
|
||||||
|
let shortcut1 = KeyboardShortcuts.Shortcut(.a)
|
||||||
|
let shortcut2 = KeyboardShortcuts.Shortcut(.b)
|
||||||
|
|
||||||
|
let shortcutName1 = KeyboardShortcuts.Name("testSetShortcutAndReset1")
|
||||||
|
let shortcutName2 = KeyboardShortcuts.Name("testSetShortcutAndReset2", default: defaultShortcut)
|
||||||
|
|
||||||
|
KeyboardShortcuts.setShortcut(shortcut1, for: shortcutName1)
|
||||||
|
KeyboardShortcuts.setShortcut(shortcut2, for: shortcutName2)
|
||||||
|
|
||||||
|
XCTAssertEqual(KeyboardShortcuts.getShortcut(for: shortcutName1), shortcut1)
|
||||||
|
XCTAssertEqual(KeyboardShortcuts.getShortcut(for: shortcutName2), shortcut2)
|
||||||
|
|
||||||
|
KeyboardShortcuts.reset(shortcutName1, shortcutName2)
|
||||||
|
|
||||||
|
XCTAssertNil(KeyboardShortcuts.getShortcut(for: shortcutName1))
|
||||||
|
XCTAssertEqual(KeyboardShortcuts.getShortcut(for: shortcutName2), defaultShortcut)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension UserDefaults {
|
||||||
|
/**
|
||||||
|
Remove all entries.
|
||||||
|
|
||||||
|
- Note: This only removes user-defined entries. System-defined entries will remain.
|
||||||
|
*/
|
||||||
|
public func removeAll() {
|
||||||
|
for key in dictionaryRepresentation().keys {
|
||||||
|
removeObject(forKey: key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,135 +5,135 @@ extension KeyboardShortcuts {
|
||||||
// swiftlint:disable identifier_name
|
// swiftlint:disable identifier_name
|
||||||
/// Represents a key on the keyboard.
|
/// Represents a key on the keyboard.
|
||||||
public struct Key: Hashable, RawRepresentable {
|
public struct Key: Hashable, RawRepresentable {
|
||||||
static let a = Self(kVK_ANSI_A)
|
public static let a = Self(kVK_ANSI_A)
|
||||||
static let b = Self(kVK_ANSI_B)
|
public static let b = Self(kVK_ANSI_B)
|
||||||
static let c = Self(kVK_ANSI_C)
|
public static let c = Self(kVK_ANSI_C)
|
||||||
static let d = Self(kVK_ANSI_D)
|
public static let d = Self(kVK_ANSI_D)
|
||||||
static let e = Self(kVK_ANSI_E)
|
public static let e = Self(kVK_ANSI_E)
|
||||||
static let f = Self(kVK_ANSI_F)
|
public static let f = Self(kVK_ANSI_F)
|
||||||
static let g = Self(kVK_ANSI_G)
|
public static let g = Self(kVK_ANSI_G)
|
||||||
static let h = Self(kVK_ANSI_H)
|
public static let h = Self(kVK_ANSI_H)
|
||||||
static let i = Self(kVK_ANSI_I)
|
public static let i = Self(kVK_ANSI_I)
|
||||||
static let j = Self(kVK_ANSI_J)
|
public static let j = Self(kVK_ANSI_J)
|
||||||
static let k = Self(kVK_ANSI_K)
|
public static let k = Self(kVK_ANSI_K)
|
||||||
static let l = Self(kVK_ANSI_L)
|
public static let l = Self(kVK_ANSI_L)
|
||||||
static let m = Self(kVK_ANSI_M)
|
public static let m = Self(kVK_ANSI_M)
|
||||||
static let n = Self(kVK_ANSI_N)
|
public static let n = Self(kVK_ANSI_N)
|
||||||
static let o = Self(kVK_ANSI_O)
|
public static let o = Self(kVK_ANSI_O)
|
||||||
static let p = Self(kVK_ANSI_P)
|
public static let p = Self(kVK_ANSI_P)
|
||||||
static let q = Self(kVK_ANSI_Q)
|
public static let q = Self(kVK_ANSI_Q)
|
||||||
static let r = Self(kVK_ANSI_R)
|
public static let r = Self(kVK_ANSI_R)
|
||||||
static let s = Self(kVK_ANSI_S)
|
public static let s = Self(kVK_ANSI_S)
|
||||||
static let t = Self(kVK_ANSI_T)
|
public static let t = Self(kVK_ANSI_T)
|
||||||
static let u = Self(kVK_ANSI_U)
|
public static let u = Self(kVK_ANSI_U)
|
||||||
static let v = Self(kVK_ANSI_V)
|
public static let v = Self(kVK_ANSI_V)
|
||||||
static let w = Self(kVK_ANSI_W)
|
public static let w = Self(kVK_ANSI_W)
|
||||||
static let x = Self(kVK_ANSI_X)
|
public static let x = Self(kVK_ANSI_X)
|
||||||
static let y = Self(kVK_ANSI_Y)
|
public static let y = Self(kVK_ANSI_Y)
|
||||||
static let z = Self(kVK_ANSI_Z)
|
public static let z = Self(kVK_ANSI_Z)
|
||||||
// swiftlint:enable identifier_name
|
// swiftlint:enable identifier_name
|
||||||
|
|
||||||
// MARK: Numbers
|
// MARK: Numbers
|
||||||
|
|
||||||
static let zero = Self(kVK_ANSI_0)
|
public static let zero = Self(kVK_ANSI_0)
|
||||||
static let one = Self(kVK_ANSI_1)
|
public static let one = Self(kVK_ANSI_1)
|
||||||
static let two = Self(kVK_ANSI_2)
|
public static let two = Self(kVK_ANSI_2)
|
||||||
static let three = Self(kVK_ANSI_3)
|
public static let three = Self(kVK_ANSI_3)
|
||||||
static let four = Self(kVK_ANSI_4)
|
public static let four = Self(kVK_ANSI_4)
|
||||||
static let five = Self(kVK_ANSI_5)
|
public static let five = Self(kVK_ANSI_5)
|
||||||
static let six = Self(kVK_ANSI_6)
|
public static let six = Self(kVK_ANSI_6)
|
||||||
static let seven = Self(kVK_ANSI_7)
|
public static let seven = Self(kVK_ANSI_7)
|
||||||
static let eight = Self(kVK_ANSI_8)
|
public static let eight = Self(kVK_ANSI_8)
|
||||||
static let nine = Self(kVK_ANSI_9)
|
public static let nine = Self(kVK_ANSI_9)
|
||||||
|
|
||||||
// MARK: Modifiers
|
// MARK: Modifiers
|
||||||
|
|
||||||
static let capsLock = Self(kVK_CapsLock)
|
public static let capsLock = Self(kVK_CapsLock)
|
||||||
static let shift = Self(kVK_Shift)
|
public static let shift = Self(kVK_Shift)
|
||||||
static let function = Self(kVK_Function)
|
public static let function = Self(kVK_Function)
|
||||||
static let control = Self(kVK_Control)
|
public static let control = Self(kVK_Control)
|
||||||
static let option = Self(kVK_Option)
|
public static let option = Self(kVK_Option)
|
||||||
static let command = Self(kVK_Command)
|
public static let command = Self(kVK_Command)
|
||||||
static let rightCommand = Self(kVK_RightCommand)
|
public static let rightCommand = Self(kVK_RightCommand)
|
||||||
static let rightOption = Self(kVK_RightOption)
|
public static let rightOption = Self(kVK_RightOption)
|
||||||
static let rightControl = Self(kVK_RightControl)
|
public static let rightControl = Self(kVK_RightControl)
|
||||||
static let rightShift = Self(kVK_RightShift)
|
public static let rightShift = Self(kVK_RightShift)
|
||||||
|
|
||||||
// MARK: Miscellaneous
|
// MARK: Miscellaneous
|
||||||
|
|
||||||
static let `return` = Self(kVK_Return)
|
public static let `return` = Self(kVK_Return)
|
||||||
static let backslash = Self(kVK_ANSI_Backslash)
|
public static let backslash = Self(kVK_ANSI_Backslash)
|
||||||
static let backtick = Self(kVK_ANSI_Grave)
|
public static let backtick = Self(kVK_ANSI_Grave)
|
||||||
static let comma = Self(kVK_ANSI_Comma)
|
public static let comma = Self(kVK_ANSI_Comma)
|
||||||
static let equal = Self(kVK_ANSI_Equal)
|
public static let equal = Self(kVK_ANSI_Equal)
|
||||||
static let minus = Self(kVK_ANSI_Minus)
|
public static let minus = Self(kVK_ANSI_Minus)
|
||||||
static let period = Self(kVK_ANSI_Period)
|
public static let period = Self(kVK_ANSI_Period)
|
||||||
static let quote = Self(kVK_ANSI_Quote)
|
public static let quote = Self(kVK_ANSI_Quote)
|
||||||
static let semicolon = Self(kVK_ANSI_Semicolon)
|
public static let semicolon = Self(kVK_ANSI_Semicolon)
|
||||||
static let slash = Self(kVK_ANSI_Slash)
|
public static let slash = Self(kVK_ANSI_Slash)
|
||||||
static let space = Self(kVK_Space)
|
public static let space = Self(kVK_Space)
|
||||||
static let tab = Self(kVK_Tab)
|
public static let tab = Self(kVK_Tab)
|
||||||
static let leftBracket = Self(kVK_ANSI_LeftBracket)
|
public static let leftBracket = Self(kVK_ANSI_LeftBracket)
|
||||||
static let rightBracket = Self(kVK_ANSI_RightBracket)
|
public static let rightBracket = Self(kVK_ANSI_RightBracket)
|
||||||
static let pageUp = Self(kVK_PageUp)
|
public static let pageUp = Self(kVK_PageUp)
|
||||||
static let pageDown = Self(kVK_PageDown)
|
public static let pageDown = Self(kVK_PageDown)
|
||||||
static let home = Self(kVK_Home)
|
public static let home = Self(kVK_Home)
|
||||||
static let end = Self(kVK_End)
|
public static let end = Self(kVK_End)
|
||||||
static let upArrow = Self(kVK_UpArrow)
|
public static let upArrow = Self(kVK_UpArrow)
|
||||||
static let rightArrow = Self(kVK_RightArrow)
|
public static let rightArrow = Self(kVK_RightArrow)
|
||||||
static let downArrow = Self(kVK_DownArrow)
|
public static let downArrow = Self(kVK_DownArrow)
|
||||||
static let leftArrow = Self(kVK_LeftArrow)
|
public static let leftArrow = Self(kVK_LeftArrow)
|
||||||
static let escape = Self(kVK_Escape)
|
public static let escape = Self(kVK_Escape)
|
||||||
static let delete = Self(kVK_Delete)
|
public static let delete = Self(kVK_Delete)
|
||||||
static let deleteForward = Self(kVK_ForwardDelete)
|
public static let deleteForward = Self(kVK_ForwardDelete)
|
||||||
static let help = Self(kVK_Help)
|
public static let help = Self(kVK_Help)
|
||||||
static let mute = Self(kVK_Mute)
|
public static let mute = Self(kVK_Mute)
|
||||||
static let volumeUp = Self(kVK_VolumeUp)
|
public static let volumeUp = Self(kVK_VolumeUp)
|
||||||
static let volumeDown = Self(kVK_VolumeDown)
|
public static let volumeDown = Self(kVK_VolumeDown)
|
||||||
|
|
||||||
// MARK: Function
|
// MARK: Function
|
||||||
|
|
||||||
static let f1 = Self(kVK_F1)
|
public static let f1 = Self(kVK_F1)
|
||||||
static let f2 = Self(kVK_F2)
|
public static let f2 = Self(kVK_F2)
|
||||||
static let f3 = Self(kVK_F3)
|
public static let f3 = Self(kVK_F3)
|
||||||
static let f4 = Self(kVK_F4)
|
public static let f4 = Self(kVK_F4)
|
||||||
static let f5 = Self(kVK_F5)
|
public static let f5 = Self(kVK_F5)
|
||||||
static let f6 = Self(kVK_F6)
|
public static let f6 = Self(kVK_F6)
|
||||||
static let f7 = Self(kVK_F7)
|
public static let f7 = Self(kVK_F7)
|
||||||
static let f8 = Self(kVK_F8)
|
public static let f8 = Self(kVK_F8)
|
||||||
static let f9 = Self(kVK_F9)
|
public static let f9 = Self(kVK_F9)
|
||||||
static let f10 = Self(kVK_F10)
|
public static let f10 = Self(kVK_F10)
|
||||||
static let f11 = Self(kVK_F11)
|
public static let f11 = Self(kVK_F11)
|
||||||
static let f12 = Self(kVK_F12)
|
public static let f12 = Self(kVK_F12)
|
||||||
static let f13 = Self(kVK_F13)
|
public static let f13 = Self(kVK_F13)
|
||||||
static let f14 = Self(kVK_F14)
|
public static let f14 = Self(kVK_F14)
|
||||||
static let f15 = Self(kVK_F15)
|
public static let f15 = Self(kVK_F15)
|
||||||
static let f16 = Self(kVK_F16)
|
public static let f16 = Self(kVK_F16)
|
||||||
static let f17 = Self(kVK_F17)
|
public static let f17 = Self(kVK_F17)
|
||||||
static let f18 = Self(kVK_F18)
|
public static let f18 = Self(kVK_F18)
|
||||||
static let f19 = Self(kVK_F19)
|
public static let f19 = Self(kVK_F19)
|
||||||
static let f20 = Self(kVK_F20)
|
public static let f20 = Self(kVK_F20)
|
||||||
|
|
||||||
// MARK: Keypad
|
// MARK: Keypad
|
||||||
|
|
||||||
static let keypad0 = Self(kVK_ANSI_Keypad0)
|
public static let keypad0 = Self(kVK_ANSI_Keypad0)
|
||||||
static let keypad1 = Self(kVK_ANSI_Keypad1)
|
public static let keypad1 = Self(kVK_ANSI_Keypad1)
|
||||||
static let keypad2 = Self(kVK_ANSI_Keypad2)
|
public static let keypad2 = Self(kVK_ANSI_Keypad2)
|
||||||
static let keypad3 = Self(kVK_ANSI_Keypad3)
|
public static let keypad3 = Self(kVK_ANSI_Keypad3)
|
||||||
static let keypad4 = Self(kVK_ANSI_Keypad4)
|
public static let keypad4 = Self(kVK_ANSI_Keypad4)
|
||||||
static let keypad5 = Self(kVK_ANSI_Keypad5)
|
public static let keypad5 = Self(kVK_ANSI_Keypad5)
|
||||||
static let keypad6 = Self(kVK_ANSI_Keypad6)
|
public static let keypad6 = Self(kVK_ANSI_Keypad6)
|
||||||
static let keypad7 = Self(kVK_ANSI_Keypad7)
|
public static let keypad7 = Self(kVK_ANSI_Keypad7)
|
||||||
static let keypad8 = Self(kVK_ANSI_Keypad8)
|
public static let keypad8 = Self(kVK_ANSI_Keypad8)
|
||||||
static let keypad9 = Self(kVK_ANSI_Keypad9)
|
public static let keypad9 = Self(kVK_ANSI_Keypad9)
|
||||||
static let keypadClear = Self(kVK_ANSI_KeypadClear)
|
public static let keypadClear = Self(kVK_ANSI_KeypadClear)
|
||||||
static let keypadDecimal = Self(kVK_ANSI_KeypadDecimal)
|
public static let keypadDecimal = Self(kVK_ANSI_KeypadDecimal)
|
||||||
static let keypadDivide = Self(kVK_ANSI_KeypadDivide)
|
public static let keypadDivide = Self(kVK_ANSI_KeypadDivide)
|
||||||
static let keypadEnter = Self(kVK_ANSI_KeypadEnter)
|
public static let keypadEnter = Self(kVK_ANSI_KeypadEnter)
|
||||||
static let keypadEquals = Self(kVK_ANSI_KeypadEquals)
|
public static let keypadEquals = Self(kVK_ANSI_KeypadEquals)
|
||||||
static let keypadMinus = Self(kVK_ANSI_KeypadMinus)
|
public static let keypadMinus = Self(kVK_ANSI_KeypadMinus)
|
||||||
static let keypadMultiply = Self(kVK_ANSI_KeypadMultiply)
|
public static let keypadMultiply = Self(kVK_ANSI_KeypadMultiply)
|
||||||
static let keypadPlus = Self(kVK_ANSI_KeypadPlus)
|
public static let keypadPlus = Self(kVK_ANSI_KeypadPlus)
|
||||||
|
|
||||||
// MARK: Properties
|
// MARK: Properties
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ public enum KeyboardShortcuts {
|
||||||
Disable a keyboard shortcut.
|
Disable a keyboard shortcut.
|
||||||
*/
|
*/
|
||||||
public static func disable(_ name: Name) {
|
public static func disable(_ name: Name) {
|
||||||
guard let shortcut = userDefaultsGet(name: name) else {
|
guard let shortcut = getShortcut(for: name) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,13 +62,103 @@ public enum KeyboardShortcuts {
|
||||||
Enable a disabled keyboard shortcut.
|
Enable a disabled keyboard shortcut.
|
||||||
*/
|
*/
|
||||||
public static func enable(_ name: Name) {
|
public static func enable(_ name: Name) {
|
||||||
guard let shortcut = userDefaultsGet(name: name) else {
|
guard let shortcut = getShortcut(for: name) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
register(shortcut)
|
register(shortcut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the keyboard shortcut for one or more names.
|
||||||
|
|
||||||
|
If the `Name` has a default shortcut, it will reset to that.
|
||||||
|
|
||||||
|
```
|
||||||
|
import SwiftUI
|
||||||
|
import KeyboardShortcuts
|
||||||
|
|
||||||
|
struct PreferencesView: View {
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
// …
|
||||||
|
Button("Reset All") {
|
||||||
|
KeyboardShortcuts.reset(
|
||||||
|
.toggleUnicornMode,
|
||||||
|
.showRainbow
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
public static func reset(_ names: Name...) {
|
||||||
|
reset(names)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reset the keyboard shortcut for one or more names.
|
||||||
|
|
||||||
|
If the `Name` has a default shortcut, it will reset to that.
|
||||||
|
|
||||||
|
- Note: This overload exists as Swift doesn't support splatting.
|
||||||
|
|
||||||
|
```
|
||||||
|
import SwiftUI
|
||||||
|
import KeyboardShortcuts
|
||||||
|
|
||||||
|
struct PreferencesView: View {
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
// …
|
||||||
|
Button("Reset All") {
|
||||||
|
KeyboardShortcuts.reset(
|
||||||
|
.toggleUnicornMode,
|
||||||
|
.showRainbow
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
public static func reset(_ names: [Name]) {
|
||||||
|
for name in names {
|
||||||
|
setShortcut(name.defaultShortcut, for: name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the keyboard shortcut for a name.
|
||||||
|
|
||||||
|
Setting it to `nil` removes the shortcut, even if the `Name` has a default shortcut defined. Use `.reset()` if you want it to respect the default shortcut.
|
||||||
|
|
||||||
|
You would usually not need this as the user would be the one setting the shortcut in a preferences user-interface, but it can be useful when, for example, migrating from a different keyboard shortcuts package.
|
||||||
|
*/
|
||||||
|
public static func setShortcut(_ shortcut: Shortcut?, for name: Name) {
|
||||||
|
guard let shortcut = shortcut else {
|
||||||
|
userDefaultsRemove(name: name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userDefaultsSet(name: name, shortcut: shortcut)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the keyboard shortcut for a name.
|
||||||
|
*/
|
||||||
|
public static func getShortcut(for name: Name) -> Shortcut? {
|
||||||
|
guard
|
||||||
|
let data = UserDefaults.standard.string(forKey: userDefaultsKey(for: name))?.data(using: .utf8),
|
||||||
|
let decoded = try? JSONDecoder().decode(Shortcut.self, from: data)
|
||||||
|
else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return decoded
|
||||||
|
}
|
||||||
|
|
||||||
private static func handleOnKeyDown(_ shortcut: Shortcut) {
|
private static func handleOnKeyDown(_ shortcut: Shortcut) {
|
||||||
guard !isPaused else {
|
guard !isPaused else {
|
||||||
return
|
return
|
||||||
|
@ -81,7 +171,7 @@ public enum KeyboardShortcuts {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, handlers) in userDefaultsKeyDownHandlers {
|
for (name, handlers) in userDefaultsKeyDownHandlers {
|
||||||
guard userDefaultsGet(name: name) == shortcut else {
|
guard getShortcut(for: name) == shortcut else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +193,7 @@ public enum KeyboardShortcuts {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (name, handlers) in userDefaultsKeyUpHandlers {
|
for (name, handlers) in userDefaultsKeyUpHandlers {
|
||||||
guard userDefaultsGet(name: name) == shortcut else {
|
guard getShortcut(for: name) == shortcut else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +232,7 @@ public enum KeyboardShortcuts {
|
||||||
userDefaultsKeyDownHandlers[name]?.append(action)
|
userDefaultsKeyDownHandlers[name]?.append(action)
|
||||||
|
|
||||||
// If the keyboard shortcut already exist, we register it.
|
// If the keyboard shortcut already exist, we register it.
|
||||||
if let shortcut = userDefaultsGet(name: name) {
|
if let shortcut = getShortcut(for: name) {
|
||||||
register(shortcut)
|
register(shortcut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,7 +266,7 @@ public enum KeyboardShortcuts {
|
||||||
userDefaultsKeyUpHandlers[name]?.append(action)
|
userDefaultsKeyUpHandlers[name]?.append(action)
|
||||||
|
|
||||||
// If the keyboard shortcut already exist, we register it.
|
// If the keyboard shortcut already exist, we register it.
|
||||||
if let shortcut = userDefaultsGet(name: name) {
|
if let shortcut = getShortcut(for: name) {
|
||||||
register(shortcut)
|
register(shortcut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,24 +281,12 @@ public enum KeyboardShortcuts {
|
||||||
NotificationCenter.default.post(name: .shortcutByNameDidChange, object: nil, userInfo: ["name": name])
|
NotificationCenter.default.post(name: .shortcutByNameDidChange, object: nil, userInfo: ["name": name])
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Should these be on `Shortcut` instead?
|
|
||||||
static func userDefaultsGet(name: Name) -> Shortcut? {
|
|
||||||
guard
|
|
||||||
let data = UserDefaults.standard.string(forKey: userDefaultsKey(for: name))?.data(using: .utf8),
|
|
||||||
let decoded = try? JSONDecoder().decode(Shortcut.self, from: data)
|
|
||||||
else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return decoded
|
|
||||||
}
|
|
||||||
|
|
||||||
static func userDefaultsSet(name: Name, shortcut: Shortcut) {
|
static func userDefaultsSet(name: Name, shortcut: Shortcut) {
|
||||||
guard let encoded = try? JSONEncoder().encode(shortcut).string else {
|
guard let encoded = try? JSONEncoder().encode(shortcut).string else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if let oldShortcut = userDefaultsGet(name: name) {
|
if let oldShortcut = getShortcut(for: name) {
|
||||||
unregister(oldShortcut)
|
unregister(oldShortcut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +296,7 @@ public enum KeyboardShortcuts {
|
||||||
}
|
}
|
||||||
|
|
||||||
static func userDefaultsRemove(name: Name) {
|
static func userDefaultsRemove(name: Name) {
|
||||||
guard let shortcut = userDefaultsGet(name: name) else {
|
guard let shortcut = getShortcut(for: name) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,19 +18,21 @@ extension KeyboardShortcuts {
|
||||||
public typealias Shortcut = KeyboardShortcuts.Shortcut
|
public typealias Shortcut = KeyboardShortcuts.Shortcut
|
||||||
|
|
||||||
public let rawValue: String
|
public let rawValue: String
|
||||||
|
public let defaultShortcut: Shortcut?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
- Parameter name: Name of the shortcut.
|
- Parameter name: Name of the shortcut.
|
||||||
- Parameter default: Optional default key combination for the shortcut. Do not set this unless it's essential. Users find it annoying when random apps steal their existing keyboard shortcuts. It's generally better to show a welcome screen on the first app launch that lets the user set the shortcut.
|
- Parameter default: Optional default key combination. Do not set this unless it's essential. Users find it annoying when random apps steal their existing keyboard shortcuts. It's generally better to show a welcome screen on the first app launch that lets the user set the shortcut.
|
||||||
*/
|
*/
|
||||||
public init(_ name: String, default defaultShortcut: Shortcut? = nil) {
|
public init(_ name: String, default defaultShortcut: Shortcut? = nil) {
|
||||||
self.rawValue = name
|
self.rawValue = name
|
||||||
|
self.defaultShortcut = defaultShortcut
|
||||||
|
|
||||||
if
|
if
|
||||||
let defaultShortcut = defaultShortcut,
|
let defaultShortcut = defaultShortcut,
|
||||||
!userDefaultsContains(name: self)
|
!userDefaultsContains(name: self)
|
||||||
{
|
{
|
||||||
userDefaultsSet(name: self, shortcut: defaultShortcut)
|
setShortcut(defaultShortcut, for: self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ extension KeyboardShortcuts {
|
||||||
private var eventMonitor: LocalEventMonitor?
|
private var eventMonitor: LocalEventMonitor?
|
||||||
private let shortcutName: Name
|
private let shortcutName: Name
|
||||||
private let onChange: ((_ shortcut: Shortcut?) -> Void)?
|
private let onChange: ((_ shortcut: Shortcut?) -> Void)?
|
||||||
|
private var observer: NSObjectProtocol?
|
||||||
|
|
||||||
/// :nodoc:
|
/// :nodoc:
|
||||||
override public var canBecomeKeyView: Bool { false }
|
override public var canBecomeKeyView: Bool { false }
|
||||||
|
@ -68,7 +69,7 @@ extension KeyboardShortcuts {
|
||||||
self.alignment = .center
|
self.alignment = .center
|
||||||
(self.cell as? NSSearchFieldCell)?.searchButtonCell = nil
|
(self.cell as? NSSearchFieldCell)?.searchButtonCell = nil
|
||||||
|
|
||||||
if let shortcut = userDefaultsGet(name: shortcutName) {
|
if let shortcut = getShortcut(for: shortcutName) {
|
||||||
self.stringValue = "\(shortcut)"
|
self.stringValue = "\(shortcut)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +82,8 @@ extension KeyboardShortcuts {
|
||||||
// Hide the cancel button when not showing the shortcut so the placeholder text is properly centered. Must be last.
|
// Hide the cancel button when not showing the shortcut so the placeholder text is properly centered. Must be last.
|
||||||
self.cancelButton = (self.cell as? NSSearchFieldCell)?.cancelButtonCell
|
self.cancelButton = (self.cell as? NSSearchFieldCell)?.cancelButtonCell
|
||||||
self.showsCancelButton = !stringValue.isEmpty
|
self.showsCancelButton = !stringValue.isEmpty
|
||||||
|
|
||||||
|
setUpEvents()
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(*, unavailable)
|
@available(*, unavailable)
|
||||||
|
@ -88,6 +91,21 @@ extension KeyboardShortcuts {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func setUpEvents() {
|
||||||
|
observer = NotificationCenter.default.addObserver(forName: .shortcutByNameDidChange, object: nil, queue: nil) { [weak self] notification in
|
||||||
|
guard
|
||||||
|
let self = self,
|
||||||
|
let nameInNotification = notification.userInfo?["name"] as? KeyboardShortcuts.Name,
|
||||||
|
nameInNotification == self.shortcutName
|
||||||
|
else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.stringValue = getShortcut(for: nameInNotification).map { "\($0)" } ?? ""
|
||||||
|
self.showsCancelButton = !self.stringValue.isEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// :nodoc:
|
/// :nodoc:
|
||||||
public func controlTextDidChange(_ object: Notification) {
|
public func controlTextDidChange(_ object: Notification) {
|
||||||
if stringValue.isEmpty {
|
if stringValue.isEmpty {
|
||||||
|
@ -222,12 +240,7 @@ extension KeyboardShortcuts {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func saveShortcut(_ shortcut: Shortcut?) {
|
private func saveShortcut(_ shortcut: Shortcut?) {
|
||||||
if let shortcut = shortcut {
|
setShortcut(shortcut, for: shortcutName)
|
||||||
userDefaultsSet(name: shortcutName, shortcut: shortcut)
|
|
||||||
} else {
|
|
||||||
userDefaultsRemove(name: shortcutName)
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange?(shortcut)
|
onChange?(shortcut)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ extension KeyboardShortcuts {
|
||||||
|
|
||||||
/// Initialize from a keyboard shortcut stored by `Recorder` or `RecorderCocoa`.
|
/// Initialize from a keyboard shortcut stored by `Recorder` or `RecorderCocoa`.
|
||||||
public init?(name: Name) {
|
public init?(name: Name) {
|
||||||
guard let shortcut = userDefaultsGet(name: name) else {
|
guard let shortcut = getShortcut(for: name) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue