From 047d11653bcc2374cb1e27e53cf5f8df9d436197 Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sat, 28 Oct 2023 17:04:23 +0100 Subject: [PATCH] refactor(hammerspoon): improve URL handling setup, enabling host-specific setup --- hammerspoon/hosts/noct.lua | 57 +++++++++++++- hammerspoon/init.lua | 7 -- hammerspoon/url_handler.lua | 142 +++++++++++++++++++++++++++++++++++ hammerspoon/url_handling.lua | 79 ------------------- 4 files changed, 197 insertions(+), 88 deletions(-) create mode 100644 hammerspoon/url_handler.lua delete mode 100644 hammerspoon/url_handling.lua diff --git a/hammerspoon/hosts/noct.lua b/hammerspoon/hosts/noct.lua index 490f848..97003ee 100644 --- a/hammerspoon/hosts/noct.lua +++ b/hammerspoon/hosts/noct.lua @@ -1,8 +1,12 @@ local obj = {} -function obj.init() - local apptoggle = require('app_toggle') +-------------------------------------------------------------------------------- +-- Global Hotkeys +-------------------------------------------------------------------------------- +local apptoggle = require('app_toggle') + +local function init_hotkeys() apptoggle:bind({ 'cmd', 'alt', 'ctrl' }, 'A', { 'Activity Monitor' }) apptoggle:bind({ 'cmd', 'ctrl' }, '2', { 'ChatGPT' }) apptoggle:bind({ 'cmd', 'ctrl' }, '4', { 'FastGPT' }) @@ -24,4 +28,53 @@ function obj.init() ) end +-------------------------------------------------------------------------------- +-- URL Handling +-------------------------------------------------------------------------------- + +local uh = require('url_handler') + +local function init_url_handler() + local chromeProfiles = { + default = uh.chromeProfile("Default"), + work = uh.chromeProfile("Profile 1"), + } + + uh.default_handler = uh.browsers.safari + uh.url_patterns = { + { + { "%://github.com/krystal/", "%://%.github.com/krystal/" }, + uh.browsers.edge, nil, { "Slack" } + }, + { + { "%://meet.google.com/" }, + chromeProfiles.work, nil, { "Slack", "Calendar" } + } + } + -- uh.url_redir_decoders = { + -- { + -- "MS Teams links", + -- function(_, _, params, fullUrl) + -- if params.url then + -- return params.url + -- else + -- return fullUrl + -- end + -- end, + -- nil, true, "Microsoft Teams" + -- }, + -- } + + uh:init() +end + +-------------------------------------------------------------------------------- +-- Initialization +-------------------------------------------------------------------------------- + +function obj.init() + init_hotkeys() + init_url_handler() +end + return obj diff --git a/hammerspoon/init.lua b/hammerspoon/init.lua index 8c628c0..687bb9d 100644 --- a/hammerspoon/init.lua +++ b/hammerspoon/init.lua @@ -42,13 +42,6 @@ hostconfig:init() local wm = require('window_management') wm:init() --------------------------------------------------------------------------------- --- URL Handling --------------------------------------------------------------------------------- - -local wm = require('url_handling') -wm:init() - -------------------------------------------------------------------------------- -- The End -------------------------------------------------------------------------------- diff --git a/hammerspoon/url_handler.lua b/hammerspoon/url_handler.lua new file mode 100644 index 0000000..813ebb3 --- /dev/null +++ b/hammerspoon/url_handler.lua @@ -0,0 +1,142 @@ +-- luacheck: read_globals hs + +--- === url_handler === +--- +--- URL handler for Hammerspoon. This module wraps the URLDispatcher spoon with +--- a number of extra helper function to make it easier to configure. +--- +--- You will need to separately install the URLDispatcher spoon for this module +--- to work. + +hs.loadSpoon('URLDispatcher') +local obj = { + _url_dispatcher = spoon.URLDispatcher + +} + +--- url_handler.default_handler +--- Variable +--- The default handler for URLs that don't match any of the patterns. If this +--- is not nil, it will be set as default_handler on the URLDispatcher spoon. +obj.default_handler = nil + +--- url_handler.decode_slack_redir_urls +--- Variable +--- A boolean indicating whether to decode Slack redirect URLs. If this is not +--- nil, it will be set as decode_slack_redir_urls on the URLDispatcher spoon. +obj.decode_slack_redir_urls = nil + +--- url_handler.url_patterns +--- Variable +--- A table of URL patterns to match against. If this is not nil, it will be set +--- as url_patterns on the URLDispatcher spoon. +obj.url_patterns = nil + +--- url_handler.url_redir_decoders +--- Variable +--- A table of URL redirect decoders. If this is not nil, it will be set as +--- url_redir_decoders on the URLDispatcher spoon. +obj.url_redir_decoders = nil + +--- url_handler.browsers +--- Variable +--- A table of browser names and corresponding bundle IDs that can be used in +--- the url_patterns table. +obj.browsers = { + arc = 'com.arc.arc', + brave = 'com.brave.Browser', + camino = 'org.mozilla.camino', + chrome = 'com.google.Chrome', + chromium = 'org.chromium.Chromium', + edge = 'com.microsoft.edgemac', + firefox = 'org.mozilla.firefox', + flock = 'com.flock.Flock', + icab = 'de.icab.iCab', + maxthon = 'com.maxthon.Maxthon', + omniweb = 'com.omnigroup.OmniWeb5', + opera = 'com.operasoftware.Opera', + orion = 'com.orionbrowser.orion', + palemoon = 'com.palemoon.palemoon', + safari = 'com.apple.Safari', + seamonkey = 'org.mozilla.seamonkey', + tor = 'org.mozilla.tor browser', + vivaldi = 'com.vivaldi.Vivaldi', + waterfox = 'net.waterfox.waterfox', + yandex = 'ru.yandex.desktop.yandex-browser', +} + +--- url_handler.open(appID, url) +--- Function +--- Open url with the specified application bundle ID. This is a helper function +--- that's useful if you need to build custom functions to open URLs. +function obj.open(url, appID) + hs.application.launchOrFocusByBundleID(appID) + hs.urlevent.openURLWithBundle(url, appID) +end + +--- url_handler.appID(appPath) +--- Function +--- Returns the bundle ID for the specified application path. +function obj.appID(appPath) + local info = hs.application.infoForBundlePath(appPath) + if info then + return info['CFBundleIdentifier'] + end +end + +function obj._chromiumProfile(app, profile) + return function(url) + hs.task.new("/usr/bin/open", nil, { + "-n", + "-a", app, + "--args", + "--profile-directory=" .. profile, + url + }):start() + end +end + +--- url_handler.chromeProfile(profile) +--- Function +--- Returns a function that opens the specified URL in Google Chrome using the +--- given profile. +--- +--- This assumes that Microsoft Edge is already installed and available to use. +function obj.chromeProfile(profile) + return obj._chromiumProfile("Google Chrome", profile) +end + +--- url_handler.edgeProfile(profile) +--- Function +--- Returns a function that opens the specified URL in Microsoft Edge using the +--- given profile. +--- +--- This assumes that Microsoft Edge is already installed and available to use. +function obj.edgeProfile(profile) + return obj._chromiumProfile("Microsoft Edge", profile) +end + +--- url_handler.init() +--- Function +--- Initialize URL handler. This will set the default_handler, url_patterns, +--- and url_redir_decoders on the URLDispatcher spoon, followed by calling its +--- start() method. +function obj:init() + local keys = { + "default_handler", + "decode_slack_redir_urls", + "url_patterns", + "url_redir_decoders" + } + + for _, key in ipairs(keys) do + if self[key] ~= nil then + self._url_dispatcher[key] = self[key] + end + end + + self._url_dispatcher:start() +end + +-- the end +return obj diff --git a/hammerspoon/url_handling.lua b/hammerspoon/url_handling.lua deleted file mode 100644 index de07ee8..0000000 --- a/hammerspoon/url_handling.lua +++ /dev/null @@ -1,79 +0,0 @@ --- luacheck: read_globals hs - -hs.loadSpoon('URLDispatcher') - -local ud = spoon.URLDispatcher -local obj = {} - --- --- Helpers --- --- Borrowed from: --- https://github.com/zzamboni/dot-hammerspoon/blob/master/init.org - -local function appID(app) - if hs.application.infoForBundlePath(app) then - return hs.application.infoForBundlePath(app)['CFBundleIdentifier'] - end -end - -local function chromeProfile(profile) - return function(url) - hs.task.new("/usr/bin/open", nil, { - "-n", - "-a", "Google Chrome", - "--args", - "--profile-directory=" .. profile, - url - }):start() - end -end - --- --- Configuration --- - -function obj:init() - local browsers = { - arc = appID('/Applications/Arc.app'), - chrome = appID('/Applications/Google Chrome.app'), - edge = appID('/Applications/Microsoft Edge.app'), - firefox = appID('/Applications/Firefox.app'), - orion = appID('/Applications/Orion.app'), - safari = appID('/Applications/Safari.app') - } - local chromeProfiles = { - default = chromeProfile("Default"), - work = chromeProfile("Profile 1"), - } - - ud.default_handler = browsers.safari - ud.url_patterns = { - { - { "%://github.com/", "%://%.github.com/" }, - browsers.edge, nil, { "Slack" } - }, - { - { "%://meet.google.com/" }, - chromeProfiles.work, nil, { "Slack", "Calendar" } - } - } - ud.url_redir_decoders = { - -- { - -- "MS Teams links", - -- function(_, _, params, fullUrl) - -- if params.url then - -- return params.url - -- else - -- return fullUrl - -- end - -- end, - -- nil, true, "Microsoft Teams" - -- }, - } - - ud:start() -end - --- the end -return obj