How to create spoon of hammerspoon in right way?

578 views Asked by At

I wrote a spoon script to control volume, but the hotkeys.bind method doesn't work, what is the problem?

Here is the init.lua of the spoon

-- === Volume ===

local obj={}
obj.__index = obj

-- Metadata
obj.name = "Volume"
obj.version = "1.0"
obj.license = "MIT - https://opensource.org/licenses/MIT"

obj.logger = hs.logger.new('Volume')

function obj:init()
end

function obj:changeVolume(diff)
   return function()
     local current = hs.audiodevice.defaultOutputDevice():volume()
     local new = math.min(100, math.max(0, math.floor(current + diff)))
     if new > 0 then
       hs.audiodevice.defaultOutputDevice():setMuted(false)
     end
     hs.alert.closeAll(0.0)
     hs.alert.show("Volume " .. new .. "%", {}, 0.5)
     hs.audiodevice.defaultOutputDevice():setVolume(new)
   end
 end

return obj

I loaded and used this spoon in ~/.hammerspoon/init.lua by

hs.loadSpoon("Volume")
hs.hotkey.bind({'cmd', 'alt'}, '[', function() spoon.Volume:changeVolume(-3) end)
hs.hotkey.bind({'cmd', 'alt'}, ']', function() spoon.Volume:changeVolume(3) end)
1

There are 1 answers

0
streetturtle On

When the changeVolume method is called it returns a function, but does not execute it. The only thing you need to do to make it work is to remove second line from top and bottom, this way when the function is called it will be executed:

function obj:changeVolume(diff)
    local current = hs.audiodevice.defaultOutputDevice():volume()
    local new = math.min(100, math.max(0, math.floor(current + diff)))
    if new > 0 then
        hs.audiodevice.defaultOutputDevice():setMuted(false)
    end
    hs.alert.closeAll(0.0)
    hs.alert.show("Volume " .. new .. "%", {}, 0.5)
    hs.audiodevice.defaultOutputDevice():setVolume(new)
 end

Note that the suggested way is to expose a :bindHotKeys() method. I'd recommend to make the changeVolume function local (local function changeVolume) and then expose inc() and dec() methods:

local function changeVolume(diff)
...
end

function obj:inc()
    changeVolume(3)
end

function obj:dec()
    changeVolume(-3)
end

function obj:bindHotkeys(mapping)
    local spec = {
        inc = hs.fnutils.partial(self.inc, self),
        dec = hs.fnutils.partial(self.dec, self),
      }
      hs.spoons.bindHotkeysToSpec(spec, mapping)
      return self
end