Compare commits

...

2 Commits

Author SHA1 Message Date
francop 75200ff664 Updated to reflect module changes 2026-05-16 22:42:29 -04:00
francop 73e5617176 Moved to modules 2026-05-16 22:42:02 -04:00
5 changed files with 196 additions and 79 deletions
+17
View File
@@ -0,0 +1,17 @@
{
"Work": {
"keepOpen": ["Slack", "Microsoft Teams", "Visual Studio Code", "Terminal", "Google Chrome"],
"close": ["Discord", "Steam", "Komga", "Kavita"],
"dimAlpha": 0.3
},
"Home": {
"keepOpen": ["Discord", "Steam", "Komga", "Kavita", "Plex"],
"close": ["Slack", "Microsoft Teams"],
"dimAlpha": 0.1
},
"Study": {
"keepOpen": ["AFFiNE", "Obsidian", "Anki", "Preview", "Safari"],
"close": ["Slack", "Microsoft Teams", "Discord", "Steam", "Instagram"],
"dimAlpha": 0.5
}
}
+21 -79
View File
@@ -1,111 +1,53 @@
-- Allow external apps like Raycast to execute custom Hammerspoon Lua functions
hs.allowAppleScript(true)
-- ========================================================================
-- HEADLESS WORKSPACE BACKGROUND ENGINE (FORCED AT BOOT)
-- ========================================================================
hs.allowAppleScript(true)
hs.menuIcon(false)
hs.dockIcon(false)
hs.ipc.cliInstall("/opt/homebrew")
hs.alert.show("Hammerspoon Headless Daemon Active", 2)
-- ~/.hammerspoon/init.lua
-- Load Config First
-- config = require("Config")
--
-- Load your HyperKey
-- Core Subsystems and Global Bindings
require("HyperKey")
require('SearchWindows')
require('Caffeine')
require('AppBorders')
-- CRITICAL FOR RAYCAST INTERACTION: Bind the return value to a global variable
-- IPC Bridges & Trackers
LayoutSelector = require('LayoutSelector')
-- require('System_Tweaks') -- Used for Time Machine Throttle Disable
-- require("Focus") -- Does not work with layout saver - Not needed if using Monocle - Focusdim is better than Monocle
-- require("FocusMode") -- Removed since I am using Focusdim
--
-- Network Center is currently disabled since menus are not working in Hammerspoon - Will re-enable once I can fix the menu issues
-- Network = require("NetworkCenter")
--
require("modules.mouseJiggle").start() -- used to trigger Focusdim
-- Load the window management module
-- Active Modules
require("modules.mouseJiggle").start()
local windowMgr = require("WindowManager")
local productivity = require("productivity")
-- For Affine
-- DEEP FOCUS MODULE (New Integration)
local focus = require("modules.focus")
-- Affine Note Engine Integration
local quickNote = require("affine_quick_note")
quickNote.init()
require("affine_clipper"):init()
-- Load Spoon Files
-- Spoons Engine & External Tool Integrations
hs.loadSpoon('SpoonInstall')
hs.loadSpoon('SpeedMenu')
hs.loadSpoon('BrewInfo')
-- ==========================================
-- SPOON CONFIGURATION
-- ==========================================
-- Run isolated Spoon setup configurations
require("modules.spoon_config")
---- SpeedMenu Config
if spoon.SpeedMenu then
-- Define the Fix Function (includes MAC and IPv6)
local function applyFullMenuFix()
local interface = spoon.SpeedMenu.interface or "en0"
local ssid = hs.wifi.currentNetwork() or "Disconnected"
local details = hs.network.interfaceDetails(interface)
local ipv4 = (details and details.IPv4) and details.IPv4.Addresses[1] or "N/A"
local ipv6 = (details and details.IPv6) and details.IPv6.Addresses[1] or "N/A"
-- Get MAC Address via shell
local macaddr = hs.execute('ifconfig ' .. interface .. ' | grep ether | awk \'{print $2}\''):gsub("%s+", "")
local menuitems = {
{ title = "SSID: " .. ssid, fn = function() hs.pasteboard.setContents(ssid) end },
{ title = "IPv4: " .. ipv4, fn = function() hs.pasteboard.setContents(ipv4) end },
{ title = "IPv6: " .. ipv6, fn = function() hs.pasteboard.setContents(ipv6) end },
{ title = "MAC: " .. macaddr, fn = function() hs.pasteboard.setContents(macaddr) end },
{ title = "-" },
{ title = "Rescan Network Interfaces", fn = function() spoon.SpeedMenu:rescan() end }
}
spoon.SpeedMenu.menubar:setMenu(menuitems)
end
-- Hook the rescan method
local oldRescan = spoon.SpeedMenu.rescan
spoon.SpeedMenu.rescan = function(self)
oldRescan(self)
applyFullMenuFix()
end
-- Toggle Logic (Starts as OFF)
local speedMenuRunning = false
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "W", function()
if speedMenuRunning then
spoon.SpeedMenu:stop()
hs.alert.show("SpeedMenu Stopped")
else
spoon.SpeedMenu:start() -- This puts it in the menu bar
applyFullMenuFix() -- This populates the data
hs.alert.show("SpeedMenu Started")
end
speedMenuRunning = not speedMenuRunning
end)
-- ========================================================================
-- RAYCAST / INTER-PROCESS COMMUNICATION (IPC) BRIDGE BINDINGS
-- ========================================================================
-- Expose the focus module methods globally so the hs CLI tool can call them
function ActivateDeepFocus(profileName)
return focus.activate(profileName)
end
---- SpeedMenu Config END
---- BrewInfo
if spoon.BrewInfo then
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "I", function()
spoon.BrewInfo:showBrewInfo()
end)
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "J", function()
spoon.BrewInfo:showBrewInfoCurSel()
end)
function ClearDeepFocus()
return focus.clear()
end
---- BrewInfo END
-- Boot Confirmation
hs.alert.show("Hammerspoon Config Reloaded")
+10
View File
@@ -0,0 +1,10 @@
local focus = require("modules.focus")
-- Expose clean functions globally for the hs CLI tool
function ActivateDeepFocus(profileName)
return focus.activate(profileName)
end
function ClearDeepFocus()
return focus.clear()
end
+88
View File
@@ -0,0 +1,88 @@
local M = {}
local focusCanvas = nil
local activeProfile = nil
local configPath = hs.configdir .. "/focus_profiles.json"
local function loadProfiles()
local file = io.open(configPath, "r")
if not file then
print("Error: Could not open focus_profiles.json")
return nil
end
local content = file:read("*a")
file:close()
return hs.json.decode(content)
end
local function manageApps(profileConfig)
for _, appName in ipairs(profileConfig.close) do
local app = hs.application.get(appName)
if app then app:kill() end
end
for _, appName in ipairs(profileConfig.keepOpen) do
hs.application.launchOrFocus(appName)
end
end
local function setFocusOverlay(alpha)
if focusCanvas then
focusCanvas:delete()
focusCanvas = nil
end
if not alpha or alpha == 0 then return end
local mainScreen = hs.screen.mainScreen()
local rect = mainScreen:frame()
focusCanvas = hs.canvas.new(rect)
focusCanvas:insertElement({
action = "fill",
type = "rectangle",
fillColor = { red = 0, green = 0, blue = 0, alpha = alpha }
})
focusCanvas:level(50)
focusCanvas:show()
local frontApp = hs.application.frontmostApplication()
if frontApp then
local win = frontApp:mainWindow()
if win then win:focus() end
end
end
function M.activate(profileName)
local profiles = loadProfiles()
if not profiles or not profiles[profileName] then
print("Error: Profile '" .. tostring(profileName) .. "' not found.")
return "Profile not found"
end
activeProfile = profileName
local currentProfileConfig = profiles[profileName]
manageApps(currentProfileConfig)
setFocusOverlay(currentProfileConfig.dimAlpha)
return "Activated " .. profileName .. " mode"
end
function M.clear()
setFocusOverlay(nil)
activeProfile = nil
return "Focus mode cleared"
end
hs.screen.watcher.new(function()
if activeProfile then
local profiles = loadProfiles()
if profiles and profiles[activeProfile] then
setFocusOverlay(profiles[activeProfile].dimAlpha)
end
end
end):start()
return M
+60
View File
@@ -0,0 +1,60 @@
-- ========================================================================
-- SPOON RUNTIME CONFIGURATION MODULE
-- ========================================================================
---- SpeedMenu Implementation
if spoon.SpeedMenu then
-- Define the Fix Function (includes MAC and IPv6 parsing via shell)
local function applyFullMenuFix()
local interface = spoon.SpeedMenu.interface or "en0"
local ssid = hs.wifi.currentNetwork() or "Disconnected"
local details = hs.network.interfaceDetails(interface)
local ipv4 = (details and details.IPv4) and details.IPv4.Addresses[1] or "N/A"
local ipv6 = (details and details.IPv6) and details.IPv6.Addresses[1] or "N/A"
-- Get MAC Address via native shell pipe
local macaddr = hs.execute('ifconfig ' .. interface .. ' | grep ether | awk \'{print $2}\''):gsub("%s+", "")
local menuitems = {
{ title = "SSID: " .. ssid, fn = function() hs.pasteboard.setContents(ssid) end },
{ title = "IPv4: " .. ipv4, fn = function() hs.pasteboard.setContents(ipv4) end },
{ title = "IPv6: " .. ipv6, fn = function() hs.pasteboard.setContents(ipv6) end },
{ title = "MAC: " .. macaddr, fn = function() hs.pasteboard.setContents(macaddr) end },
{ title = "-" },
{ title = "Rescan Network Interfaces", fn = function() spoon.SpeedMenu:rescan() end }
}
spoon.SpeedMenu.menubar:setMenu(menuitems)
end
-- Overwrite the baseline rescan hook cleanly
local oldRescan = spoon.SpeedMenu.rescan
spoon.SpeedMenu.rescan = function(self)
oldRescan(self)
applyFullMenuFix()
end
-- Toggle Engine State Manager
local speedMenuRunning = false
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "W", function()
if speedMenuRunning then
spoon.SpeedMenu:stop()
hs.alert.show("SpeedMenu Stopped")
else
spoon.SpeedMenu:start()
applyFullMenuFix()
hs.alert.show("SpeedMenu Started")
end
speedMenuRunning = not speedMenuRunning
end)
end
---- BrewInfo Implementation
if spoon.BrewInfo then
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "I", function()
spoon.BrewInfo:showBrewInfo()
end)
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "J", function()
spoon.BrewInfo:showBrewInfoCurSel()
end)
end