Today I installed some Spoons, and tried to list/enumerate them on the Console using
> hs.inspect(hs.spoons:list())
{}
If I load the spoon manually first...
> hs.loadSpoon("AClock")
2020-05-04 13:41:07: -- Loading Spoon: AClock
table: 0x600000a06940
> hs.inspect(hs.spoons:list())
{ {
loaded = true,
name = "AClock",
version = "1.0"
} }
I think I remember this used to work鈥擨s this expected?
Hmm, after a reboot, it's working as expected. 馃
Guess this is/was a fluke.
Ok, I updated the title - seems like if ~/.hammerspoon/Spoons is a symlink, then this behavior occurs. Loading spoons manually still works, but enumerating them with hs.inspect(hs.spoons:list()) fails to find anything beneath the symlinked folder.
I have seen similar behavior with symlinks in other environments...
If you look at /Applications/Hammerspoon.app/Contents/Resources/extensions/hs/spoons/init.lua and change line 161 from:
~lua
local _, dirobj = fs.dir(configdir .. "/Spoons")
~
to (note the addition of the trailing /):
~lua
local _, dirobj = fs.dir(configdir .. "/Spoons/")
~
and restarting Hammerspoon, does it work properly with symlinks?
Note that by changing the resource files for Hammerspoon, you may be prompted to re-enable Accessibility rights for Hammerspoon the next time the application is completely relaunched (i.e. quit the app completely and then launched again)... under System Preferences/Security & Privacy, you'll see Hammerspoon is still checked -- just uncheck it and recheck and it should clear up, if you see this behavior)
...and if that fails, you could try:
local spoonsPath = fs.pathToAbsolute(configdir .. "/Spoons/")
local _, dirobj = fs.dir(spoonsPath)
This is getting weirder... Thanks @latenitefilms and @asmagill for trying to help!
I don't know what caused this to breifly start working a few days ago, but it's broken again, even after several reboots. I've tested and ruled out that this is caused by the Spoons dir being a symlink or not. It fails reliably in both cases now.
The problem, at least on my systems (both running 10.15.4 + HS 0.9.78.5164) is that an extra parameter (a table object) being passed into the hs.spoons.list() function. This causes the onlyLoaded bool to _always_ evaluate to true ignoring the actual passed value. I added an print(inspect(onlyLoaded)) to the top of the function like this:
function module.list(onlyLoaded)
print(inspect(onlyLoaded)) <==
here's sample output from the console, with no spoons loaded:
> hs.inspect(hs.spoons:list())
2020-05-09 13:27:00: {
_keys = {},
bindHotkeysToSpec = <function 1>,
isInstalled = <function 2>,
isLoaded = <function 3>,
list = <function 4>,
newSpoon = <function 5>,
resourcePath = <function 6>,
scriptPath = <function 7>,
use = <function 8>
}
{}
I don't know _where_ this table param is coming from鈥攎y Lua skills are weak at best, but hopefully one of you will recognize it.
If I change extensions/spoons/init.lua#L160 and add an extra _ to "eat" the table being passed in, then everything works correctly again:
function module.list(onlyLoaded)
==> function module.list(_,onlyLoaded)
I'm sure this is an improper fix. I'd like to understand why the function is receiving an extra param and hopefully correct it at the source.
Any ideas?
My guess is you鈥檙e using hs.spoons:list() instead of hs.spoons.list()?
It also looks like the documentation is possibly wrong - saying method where it should be a function:
http://www.hammerspoon.org/docs/hs.spoons.html#list
Will have a proper look at the code in the morning unless @cmsj or @asmagill beats me to it.
Wow @latenitefilms Nice catch! Indeed, I was using : instead of .
What exactly does calling the function in this wayhs.spoons:list() do anyway? Still trying to understand what generated that table...
obj:f() is equivalent to obj.f(obj) and function A:f() is equivalent to function A.f(self). The empty table comes in because your trying to pass in an empty object.
@latenitefilms is right, all of the functions in hs.spoon are documented as methods, but they are not. Using . instead of : is the right way to go. Good spot!
Most helpful comment
@latenitefilms is right, all of the functions in hs.spoon are documented as methods, but they are not. Using
.instead of:is the right way to go. Good spot!