hammerspoon icon indicating copy to clipboard operation
hammerspoon copied to clipboard

spaces.lua's search for Dock does not succeed on early startup

Open saagarjha opened this issue 1 year ago • 4 comments

Not sure when I started seeing this, perhaps in the first beta of 14.4? But this line of code fails for me when Hammerspoon opens on startup: https://github.com/Hammerspoon/hammerspoon/blob/56b5835dc1bf7bb430dfea3f1662379cccec0c82/extensions/spaces/spaces.lua#L57

Here's the error:

2024-02-07 01:20:17: *** ERROR: ...merspoon.app/Contents/Resources/extensions/hs/spaces.lua:57: attempt to index a nil value (field 'integer index')
stack traceback:
	...merspoon.app/Contents/Resources/extensions/hs/spaces.lua:57: in local 'getDockExitTemplates'
	...merspoon.app/Contents/Resources/extensions/hs/spaces.lua:77: in main chunk
	[C]: in function 'rawrequire'
	...poon.app/Contents/Resources/extensions/hs/_coresetup.lua:662: in function 'require'
	...n.app/Contents/Resources/extensions/hs/window_filter.lua:1530: in main chunk
	[C]: in function 'rawrequire'
	...poon.app/Contents/Resources/extensions/hs/_coresetup.lua:662: in function 'require'
	(...tail calls...)
	[C]: in function 'rawrequire'
	...poon.app/Contents/Resources/extensions/hs/_coresetup.lua:662: in function 'require'
	...merspoon.app/Contents/Resources/extensions/hs/window.lua:1027: in function <...merspoon.app/Contents/Resources/extensions/hs/window.lua:1025>
	(...tail calls...)
	/Users/saagarjha/.hammerspoon/shared.lua:1: in main chunk
	[C]: in function 'rawrequire'
	...poon.app/Contents/Resources/extensions/hs/_coresetup.lua:662: in function 'require'
	/Users/saagarjha/.hammerspoon/init.lua:21: in main chunk
	[C]: in function 'xpcall'
	...poon.app/Contents/Resources/extensions/hs/_coresetup.lua:723: in function 'hs._coresetup.setup'
	(...tail calls...)

If I reload the config it works as expected, so I assume whenever this runs is too early for this to return any results?

saagarjha avatar Feb 07 '24 09:02 saagarjha

Yeah, it's looking for a running instance of the Dock, so it will fail if Hammerspoon somehow manages to start before the Dock. But all it's actually doing with it at that point is trying to find the Dock app on disk, so I think it could probably be changed to:

    local path   = application.pathForBundleID("com.apple.dock") .. "/Contents/Resources"

(It does try to actually talk to the running Dock later on, to interact with Mission Control/Spaces - but the Dock is likely to be running by the time you're using any of those functions.)


If you want to try out that change, you can copy spaces.lua from Hammerspoon into ~/.hammerspoon/hs/spaces.lua and edit the line above into that copy. Or if you want to dynamically patch it, so that you still get any other updates to spaces.lua in new Hammerspoon versions, you can create ~/.hammerspoon/hs/spaces.lua with this code in it:

~/.hammerspoon/hs/spaces.lua (patching version)
local myName, myPath = ...
local pathToAbsolute = require 'hs.fs'.pathToAbsolute
local myAbsPath = pathToAbsolute(myPath)
for entry in package.path:gmatch '[^;]*' do
	local realPath = package.searchpath(myName, entry)
	if not realPath or pathToAbsolute(realPath) == myAbsPath then goto continue end
	local fn = load(coroutine.wrap(function()
		local yield = coroutine.yield
		
		local findStr = [[application.applicationsForBundleID("com.apple.dock")[1]:path()]]
		local replaceStr = [[application.pathForBundleID("com.apple.dock")]]
		
		local findPattern = findStr:gsub('%W', '%%%0')
		local replacePattern = replaceStr:gsub('%%', '%%%%')
		
		local didPatch = false
		for line in io.lines(realPath, 'L') do
			local fixedLine, nMatches = line:gsub(findPattern, replacePattern)
			yield(fixedLine)
			if nMatches > 0 then
				didPatch = true
			end
		end
		if not didPatch then
			print "Warning: couldn't patch spaces.lua!"
		end
	end), '@'..realPath, 't')
	do return fn(myName, realPath) end
	::continue::
end

Rhys-T avatar Feb 07 '24 17:02 Rhys-T

I've never run into a timing issue this tight, but pathForBundleID should work. At load time, it's looking for the specific verbiage that pages will be using in the Mission Control accessibility objects, so it's the location on disk that matters, not the running Dock itself.

As noted, the running Dock is important when you trigger it, but not at load time.

asmagill avatar Feb 08 '24 00:02 asmagill

Would I run into issues if I just edited the app itself for testing?

saagarjha avatar Feb 08 '24 10:02 saagarjha

@saagarjha nope, editing .lua files inside Hammerspoon.app is fine, they're ignored by Gatekeeper.

cmsj avatar Aug 05 '24 18:08 cmsj