Open Soromeister opened 2 years ago
+1
Hi, I don't know if you are still looking for this feature. I just finished making something similar and wanted to share my steps to hopefully help someone else.
My code functions to do the following:
My sample profile framework is: Generic - "Default" "Test" "Test 2" ThinkorSwim - "ToS - Default" "ToS - Technical Analysis" "ToS - Fundamental Analysis" Microsoft One Note - "MON - Default" "MON - 2" Apple Notes - "Notes - Default"
Once in the a "primary" app you are able to use 1 key (that will be the same across all apps) to be able to click/cycle through the profiles designated for each app (in my case I am using the 1 key on my mouse that I done a simple modification to assign the value of f19 to)
As you change the profile and as it is changed based on apps you will receive a brief notification in the upper right hand corner.
When the app is first launched for the day/computer session it automatically change the profile to the default profile for that app profile group, but if you leave the app up and access a different app and return it will automatically switch to the last used profile from that app group.
Step 1: Install and Configure Hammerspoon
Download Hammerspoon
Install Hammerspoon:
Configure Hammerspoon
mkdir -p ~/.hammerspoon
- Create the configuration file:
touch ~/.hammerspoon/init.lua
open -e ~/.hammerspoon/init.lua
- Write a sample script for Hammerspoon
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "W", function()
hs.alert.show("Hello World!")
end)
- Save the file (cmd + s)
- Reload the configuration by clicking on hammerspoon in the upper right menu bar on your screen and select "reload config"
- Test Hotkey (cmd+alt+ctrl+W) (should now see "Hello World!" on your screen)
Step 2: Add the Actual Hammerspoon Script Code
open -e ~/.hammerspoon/init.lua
NOTE: You may need to change this line of code: (my karabiner_cli location may be different from your) local command = string.format('/Library/Application\ Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli --select-profile "%s"', profile)
[local appProfiles = {
["com.azul.zulu.java"] = { "ToS - Default", "ToS - Technical Analysis", "ToS - Fundamental Analysis" }, -- ThinkorSwim
["com.microsoft.onenote.mac"] = { "MON - Default", "MON - 2" }, -- Microsoft OneNote
["com.apple.Notes"] = { "Notes - Default" }, -- Apple Notes
}
local generalProfiles = { "Default", "Test", "Test 2" }
-- Track the last used profile for each app
local lastUsedProfile = {}
-- Track the last used generic profile
local lastUsedGenericProfile = "Default"
-- Track the current profile to avoid redundant notifications
local currentProfile = ""
-- Function to switch profiles using Karabiner CLI
function switchProfile(profile)
if profile ~= currentProfile then
local command = string.format('/Library/Application\\ Support/org.pqrs/Karabiner-Elements/bin/karabiner_cli --select-profile "%s"', profile)
hs.execute(command)
-- Add a delay to ensure the profile switch has time to execute before sending the notification
hs.timer.doAfter(0.1, function()
hs.notify.new({
title = "Karabiner Elements",
informativeText = string.format('"%s" Profile Activated', profile)
}):send()
end)
print("Switched to profile: " .. profile) -- Debug print statement
currentProfile = profile
end
end
-- Switch profiles based on the current application
function switchProfileForApp(bundleID)
local profiles = appProfiles[bundleID] or generalProfiles
local profile
if profiles == generalProfiles then
profile = lastUsedGenericProfile
else
profile = lastUsedProfile[bundleID] or profiles[1]
end
if profile then
switchProfile(profile)
if profiles == generalProfiles then
lastUsedGenericProfile = profile
else
lastUsedProfile[bundleID] = profile
end
end
end
-- Hammerspoon application watcher to handle app switching
hs.application.watcher.new(function(appName, eventType, appObject)
if eventType == hs.application.watcher.activated then
local bundleID = appObject:bundleID()
print("Activated app: " .. bundleID)
switchProfileForApp(bundleID)
end
end):start()
-- Cycle through profiles when pressing the "1" key on the mouse
hs.hotkey.bind({}, '1', function()
local frontmostApp = hs.application.frontmostApplication()
if frontmostApp then
local bundleID = frontmostApp:bundleID()
local profiles = appProfiles[bundleID] or generalProfiles
local currentProfile = lastUsedProfile[bundleID] or lastUsedGenericProfile
local index = hs.fnutils.indexOf(profiles, currentProfile)
if index then
local nextIndex = (index % #profiles) + 1
local nextProfile = profiles[nextIndex]
switchProfile(nextProfile)
if profiles == generalProfiles then
lastUsedGenericProfile = nextProfile
else
lastUsedProfile[bundleID] = nextProfile
end
end
end
end)](is:issue commenter:your_username)
Step 3: Create JSON Configuration
cd ~/.config/karabiner/assets/complex_modifications/
nano app_profile_switcher.json
{
"title": "App Profile Switcher",
"rules": [
{
"description": "App Profile Switching using '1' key on mouse keypad that is assigned 'f19'",
"manipulators": [
{
"conditions": [
{
"identifiers": [
{
"is_keyboard": true,
"product_id": 64007,
"vendor_id": 9639
}
],
"type": "device_if"
}
],
"from": {
"key_code": "f19",
"modifiers": {
"optional": [
"any"
]
}
},
"to_if_alone": [
{
"key_code": "f19"
}
],
"type": "basic"
}
]
}
]
}
Save JSON File (ctrl + o, enter, ctrl + x)
Apply configuration in Karabiner elements to each applicable profile under complex modifications by selecting "add predefined rule" and enabling "Cycle through profiles using the '1' key on the mouse"
Hi,
Kindly add support for profiles per app. For example, I have 2 profiles set in KE:
It would be nice to have KE switch between these 2 profiles dynamically based on which app is in foreground.
Basically, when I have Microsoft Word in focus, KE should switch the profile to "MS Word". Similarly, when I have iTerm2 in focus, KE should switch to the profile "iTerm2".