diff --git a/.github/workflows/PR.yml b/.github/workflows/PR.yml index a8b1f939..e5ab8f93 100644 --- a/.github/workflows/PR.yml +++ b/.github/workflows/PR.yml @@ -25,10 +25,10 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Check-out the Spoons PR - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Check-out the Hammerspoon repository we need for doc building - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: repository: 'Hammerspoon/hammerspoon' path: 'hammerspoon' @@ -40,7 +40,7 @@ jobs: /usr/bin/python3 -m pip install -r requirements.txt # Find files modified by this PR - - uses: lots0logs/gh-action-get-changed-files@2.1.4 + - uses: lots0logs/gh-action-get-changed-files@2.2.2 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/Source/AClock.spoon/docs.json b/Source/AClock.spoon/docs.json index 4119951a..2047649f 100644 --- a/Source/AClock.spoon/docs.json +++ b/Source/AClock.spoon/docs.json @@ -13,7 +13,7 @@ "doc": "Hide AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "116", + "lineno": "130", "name": "hide", "notes": [], "parameters": [ @@ -51,7 +51,7 @@ "doc": "Show AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "97", + "lineno": "111", "name": "show", "notes": [], "parameters": [ @@ -70,7 +70,7 @@ "doc": "Show AClock for 4 seconds. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "133", + "lineno": "147", "name": "toggleShow", "notes": [], "parameters": [ @@ -87,7 +87,7 @@ "doc": "Show AClock. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "154", + "lineno": "168", "name": "toggleShowPersistent", "notes": [], "parameters": [ @@ -109,7 +109,7 @@ "doc": "Hide AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "116", + "lineno": "130", "name": "hide", "notes": [], "parameters": [ @@ -147,7 +147,7 @@ "doc": "Show AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "97", + "lineno": "111", "name": "show", "notes": [], "parameters": [ @@ -166,7 +166,7 @@ "doc": "Show AClock for 4 seconds. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "133", + "lineno": "147", "name": "toggleShow", "notes": [], "parameters": [ @@ -183,7 +183,7 @@ "doc": "Show AClock. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon//init.lua", - "lineno": "154", + "lineno": "168", "name": "toggleShowPersistent", "notes": [], "parameters": [ diff --git a/Source/AClock.spoon/init.lua b/Source/AClock.spoon/init.lua index 8d094c83..e046d880 100644 --- a/Source/AClock.spoon/init.lua +++ b/Source/AClock.spoon/init.lua @@ -60,6 +60,17 @@ for k, v in pairs(obj._attribs) do obj[k] = v end --- --- Returns: --- * The AClock object +function getframe(width, height) + local mainScreen = hs.screen.primaryScreen() + local mainRes = mainScreen:fullFrame() + return { + x = (mainRes.w - width) / 2, + y = (mainRes.h - height) / 2, + w = width, + h = height + } +end + function obj:init() if not self.canvas then self.canvas = hs.canvas.new({x=0, y=0, w=0, h=0}) end self.canvas[1] = { @@ -72,16 +83,19 @@ function obj:init() } local mainScreen = hs.screen.primaryScreen() local mainRes = mainScreen:fullFrame() - self.canvas:frame({ - x = (mainRes.w-self.width)/2, - y = (mainRes.h-self.height)/2, - w = self.width, - h = self.height, - }) + self.canvas:frame(getframe(self.width, self.height)) + self._screen_watcher = hs.screen.watcher.new(function() + self:update_canvas() + end) + self._screen_watcher:start() self._init_done = true return self end +function obj:update_canvas() + self.canvas:frame(getframe(self.width, self.height)) +end + function obj:update_clock_text() self.canvas[1].text = os.date(self.format) end diff --git a/Source/ArrangeDesktop.spoon/init.lua b/Source/ArrangeDesktop.spoon/init.lua index 09df850f..fef02702 100644 --- a/Source/ArrangeDesktop.spoon/init.lua +++ b/Source/ArrangeDesktop.spoon/init.lua @@ -202,7 +202,7 @@ function obj:createArrangement() return end - hs.dialog.blockAlert("We will now record each of your application windows.", "Each will window will flash into focus. The first focus on each monitor will prompt you to name the monitor.") + hs.dialog.blockAlert("We will now record each of your application windows.", "Each window will flash into focus. The first focus on each monitor will prompt you to name the monitor.") config[arrangementName] = obj:_buildArrangement(arrangementName) diff --git a/Source/AutoMuteOnSleep.spoon/docs.json b/Source/AutoMuteOnSleep.spoon/docs.json new file mode 100644 index 00000000..edaa4207 --- /dev/null +++ b/Source/AutoMuteOnSleep.spoon/docs.json @@ -0,0 +1,19 @@ +[ + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [], + "Variable": [], + "desc": "Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.", + "doc": "Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.\nUseful to avoid blasting sound when opening a Macbook in the public transport.\nNote: This is primarily intended for portable Mac devices, which have internal speakers.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip)", + "items": [], + "name": "AutoMuteOnSleep", + "stripped_doc": "Useful to avoid blasting sound when opening a Macbook in the public transport.\nNote: This is primarily intended for portable Mac devices, which have internal speakers.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip)", + "submodules": [], + "type": "Module" + } +] \ No newline at end of file diff --git a/Source/AutoMuteOnSleep.spoon/init.lua b/Source/AutoMuteOnSleep.spoon/init.lua new file mode 100644 index 00000000..b351a2c9 --- /dev/null +++ b/Source/AutoMuteOnSleep.spoon/init.lua @@ -0,0 +1,47 @@ +--- === AutoMuteOnSleep === +--- +--- Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep. +--- Useful to avoid blasting sound when opening a Macbook in the public transport. +--- Note: This is primarily intended for portable Mac devices, which have internal speakers. +--- +--- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip) + + +local obj={} +obj.__index = obj + +-- Metadata +obj.name = "AutoMuteOnSleep" +obj.version = "1.0" +obj.author = "devnoname120 fmtime then - -- print("creating " .. fname) + M.logger.i("creating " .. fname) local fd = io.open(fname, "w+") io.output(fd) M.processModule(module) io.close(fd) + else + M.logger.i("skipping " .. fname) end end end +function M.createWhenChanged(jsonDocs, prefix) + local mtime = hs.fs.attributes(jsonDocs, "modification") + local timestamp = options.timestamps[jsonDocs] + + if(timestamp == nil or mtime ~= timestamp) then + M.logger.i("reading "..jsonDocs) + M.create(jsonDocs, prefix) + options.timestamps[jsonDocs] = mtime + options.timestampsChanged = true + else + M.logger.i("skipping "..jsonDocs) + end +end + +function M.readTimestamps() + timestamps = hs.json.read(options.timestampsFilename) + + if timestamps then + options.timestamps = timestamps + end + + M.logger.d(hs.inspect(options.timestamps)) +end + +function M.writeTimestamps() + M.logger.d(hs.inspect(options.timestamps)) + if options.timestampsChanged then + hs.json.write(options.timestamps, options.timestampsFilename, true, true) + end +end + function M:init() + hs.fs.mkdir(options.annotations) + + M.readTimestamps() + -- Load hammerspoon docs - M.create(hs.docstrings_json_file) + M.createWhenChanged(hs.docstrings_json_file) -- Load Spoons for _, spoon in ipairs(hs.spoons.list()) do local doc = hs.configdir .. "/Spoons/" .. spoon.name .. ".spoon/docs.json" if hs.fs.attributes(doc, "modification") then - M.create(doc, "spoon.") + M.createWhenChanged(doc, "spoon.") end end + + M.writeTimestamps() + end return M diff --git a/Source/InputMethodIndicator.spoon/docs.json b/Source/InputMethodIndicator.spoon/docs.json new file mode 100644 index 00000000..5cab46ff --- /dev/null +++ b/Source/InputMethodIndicator.spoon/docs.json @@ -0,0 +1,127 @@ +[ + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "InputMethodIndicator:init()", + "desc": "init.", + "doc": "init.\n\nParameters:\n * None\n\nReturns:\n * The InputMethodIndicator object", + "examples": [], + "file": "Source/InputMethodIndicator.spoon//init.lua", + "lineno": "67", + "name": "init", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The InputMethodIndicator object" + ], + "signature": "InputMethodIndicator:init()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:start(config)", + "desc": "Start InputMethodIndicator.", + "doc": "Start InputMethodIndicator.\n\nParameters:\n * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse", + "examples": [], + "file": "Source/InputMethodIndicator.spoon//init.lua", + "lineno": "200", + "name": "start", + "notes": [], + "parameters": [ + " * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse" + ], + "returns": [], + "signature": "InputMethodIndicator:start(config)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:stop()", + "desc": "Stop InputMethodIndicator.", + "doc": "Stop InputMethodIndicator.\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputMethodIndicator.spoon//init.lua", + "lineno": "245", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputMethodIndicator:stop()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [], + "desc": "Show input method indicator in the current mouse position.", + "doc": "Show input method indicator in the current mouse position.\nIt is a small but noticable dot near the cursor.\nIt can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method.\nYou can use it as follows in the init.lua:\nhs.loadSpoon(\"InputMethodIndicator\")\nspoon.InputMethodIndicator:start(nil)\nnote: config parameter is a table, pass nil to use the default config\nthe default config is as follows:\n{\n ABCColor = \"#62C555\", -- the dot color when the input method is ABC\n LocalLanguageColor = \"#ED6A5E\", -- the dot color when the input method is not ABC\n mode = \"nearMouse\", -- the mode of the indicator\n showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed\n checkInterval = .01, -- seconds to check the input method\n dotSize = 6, -- the size of the dot\n deltaY=7, -- the distance between the dot and the center of the selection or mouse\n}\nthe mode can be \"nearMouse\",\"onChange\",\"adaptive\", the default mode is \"adaptive\"\n\"nearMouse\" means the indicator will always show near the mouse\n\"onChange\" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds\n\"adaptive\" means the indicator will show near the textarea when typing, otherwise it will show near the mouse\nNote: the \"adaptive\" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API", + "items": [ + { + "def": "InputMethodIndicator:init()", + "desc": "init.", + "doc": "init.\n\nParameters:\n * None\n\nReturns:\n * The InputMethodIndicator object", + "examples": [], + "file": "Source/InputMethodIndicator.spoon//init.lua", + "lineno": "67", + "name": "init", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The InputMethodIndicator object" + ], + "signature": "InputMethodIndicator:init()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:start(config)", + "desc": "Start InputMethodIndicator.", + "doc": "Start InputMethodIndicator.\n\nParameters:\n * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse", + "examples": [], + "file": "Source/InputMethodIndicator.spoon//init.lua", + "lineno": "200", + "name": "start", + "notes": [], + "parameters": [ + " * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse" + ], + "returns": [], + "signature": "InputMethodIndicator:start(config)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:stop()", + "desc": "Stop InputMethodIndicator.", + "doc": "Stop InputMethodIndicator.\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputMethodIndicator.spoon//init.lua", + "lineno": "245", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputMethodIndicator:stop()", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "InputMethodIndicator", + "stripped_doc": "It is a small but noticable dot near the cursor.\nIt can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method.\nYou can use it as follows in the init.lua:\nhs.loadSpoon(\"InputMethodIndicator\")\nspoon.InputMethodIndicator:start(nil)\nnote: config parameter is a table, pass nil to use the default config\nthe default config is as follows:\n{\n ABCColor = \"#62C555\", -- the dot color when the input method is ABC\n LocalLanguageColor = \"#ED6A5E\", -- the dot color when the input method is not ABC\n mode = \"nearMouse\", -- the mode of the indicator\n showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed\n checkInterval = .01, -- seconds to check the input method\n dotSize = 6, -- the size of the dot\n deltaY=7, -- the distance between the dot and the center of the selection or mouse\n}\nthe mode can be \"nearMouse\",\"onChange\",\"adaptive\", the default mode is \"adaptive\"\n\"nearMouse\" means the indicator will always show near the mouse\n\"onChange\" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds\n\"adaptive\" means the indicator will show near the textarea when typing, otherwise it will show near the mouse\nNote: the \"adaptive\" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API", + "submodules": [], + "type": "Module" + } +] \ No newline at end of file diff --git a/Source/InputMethodIndicator.spoon/init.lua b/Source/InputMethodIndicator.spoon/init.lua new file mode 100644 index 00000000..22051ec2 --- /dev/null +++ b/Source/InputMethodIndicator.spoon/init.lua @@ -0,0 +1,268 @@ +--- === InputMethodIndicator === +--- +--- Show input method indicator in the current mouse position. +--- It is a small but noticable dot near the cursor. +--- It can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method. +--- You can use it as follows in the init.lua: +--- hs.loadSpoon("InputMethodIndicator") +--- spoon.InputMethodIndicator:start(nil) +--- note: config parameter is a table, pass nil to use the default config +--- the default config is as follows: +--- { +--- ABCColor = "#62C555", -- the dot color when the input method is ABC +--- LocalLanguageColor = "#ED6A5E", -- the dot color when the input method is not ABC +--- mode = "nearMouse", -- the mode of the indicator +--- showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed +--- checkInterval = .01, -- seconds to check the input method +--- dotSize = 6, -- the size of the dot +--- deltaY=7, -- the distance between the dot and the center of the selection or mouse +--- } +--- the mode can be "nearMouse","onChange","adaptive", the default mode is "adaptive" +--- "nearMouse" means the indicator will always show near the mouse +--- "onChange" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds +--- "adaptive" means the indicator will show near the textarea when typing, otherwise it will show near the mouse +--- Note: the "adaptive" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API + +local obj = {} +local _store = {} +setmetatable(obj, { + __index = function(_, k) + return _store[k] + end, + __newindex = function(t, k, v) + rawset(_store, k, v) + if t._init_done then + if t._attribs[k] then + t:init() + end + end + end +}) +obj.__index = obj + +-- Metadata +obj.name = "InputMethodIndicator" +obj.version = "1.0" +obj.author = "lunaticsky <2013599@mail.nankai.edu.cn>" +obj.homepage = "https://github.com/Hammerspoon/Spoons" +obj.license = "MIT - https://opensource.org/licenses/MIT" + +local logger = hs.logger.new("InputMethodIndicator") +obj.logger = logger + +-- Defaults +obj._attribs = { + ABCColor = "#62C555", + LocalLanguageColor = "#ED6A5E", + mode = "adaptive", + showOnChangeDuration = 3, + checkInterval = .01, + dotSize = 6, + deltaY=7, +} +for k, v in pairs(obj._attribs) do + obj[k] = v +end + +--- InputMethodIndicator:init() +--- Method +--- init. +--- +--- Parameters: +--- * None +--- +--- Returns: +--- * The InputMethodIndicator object +function obj:init() + local mousePosition = hs.mouse.absolutePosition() + if not self.canvas then + self.canvas = hs.canvas.new({ + x = mousePosition.x - self.dotSize / 2, + y = mousePosition.y - 2*self.deltaY, + w = self.dotSize, + h = self.dotSize + }) + end + local sourceID = hs.keycodes.currentSourceID() + print(sourceID) + if (sourceID == "com.apple.keylayout.ABC") then + self.color = self.ABCColor + self.lastLayout = sourceID + else + self.color = self.LocalLanguageColor + self.lastLayout = sourceID + end + self.canvas[1] = { + action = "fill", + type = "circle", + fillColor = { + hex = self.color + }, + frame = { + x = 0, + y = 0, + h = self.dotSize, + w = self.dotSize + } + } + self._init_done = true + return self +end + +function obj:hideCanvasTimer() + return hs.timer.doAfter(self.showOnChangeDuration, function() + self.canvas:hide() + end) +end + +function obj:showCanvasOnChanged() + local sourceID = hs.keycodes.currentSourceID() + if (sourceID == self.lastLayout) then + return + end + self.setColor(self, sourceID) + self.canvas:show() + if not self.hideCanvasTimer:running() then + self.hideCanvasTimer:start() + else + self.hideCanvasTimer:stop() + self.hideCanvasTimer:start() + end +end +function obj:setColor(sourceID) + -- change the color of the circle according to the input layout + if (sourceID == "com.apple.keylayout.ABC") then + self.color = self.ABCColor + else + self.color = self.LocalLanguageColor + end + self.lastLayout = sourceID + self.canvas[1].fillColor = { + hex = self.color + } +end + +function obj:showNearMouse() + local cp = hs.mouse.absolutePosition() + -- change the position of the canvas + self.canvas:topLeft({ + x = cp.x - self.dotSize / 2, + y = cp.y - 15 + }) +end + +function obj:adaptiveChangePosition() + local systemWideElement = hs.axuielement.systemWideElement() + local focusedElement = systemWideElement.AXFocusedUIElement + if focusedElement then + local selectedRange = focusedElement.AXSelectedTextRange + if selectedRange then + local selectionBounds = focusedElement:parameterizedAttributeValue("AXBoundsForRange", selectedRange) + -- print the position and size of the selection,which is a table + if selectionBounds then + if selectionBounds.h == 0 or selectionBounds.y < 0 then + self:showNearMouse() + else + self.canvas:topLeft({ + x = selectionBounds.x - self.dotSize / 2, + y = selectionBounds.y - self.deltaY + }) + end + else + self:showNearMouse() + end + else + self:showNearMouse() + end + end +end + +function obj:adaptiveTimer() + return hs.timer.doEvery(self.checkInterval, function() + self:adaptiveChangePosition() + self:setColor(hs.keycodes.currentSourceID()) + end) +end + +function obj:showOnChangeTimer() + return hs.timer.doEvery(self.checkInterval, function() + self:adaptiveChangePosition() + self:showCanvasOnChanged() + end) +end + +function obj:showNearMouseTimer() + return hs.timer.doEvery(self.checkInterval, function() + self:showNearMouse() + self:setColor(hs.keycodes.currentSourceID()) + end) +end +--- InputMethodIndicator:start(config) +--- Method +--- Start InputMethodIndicator. +--- +--- Parameters: +--- * config - A table contains config options for the module +--- * ABCColor - the dot color when the input method is ABC +--- * LocalLanguageColor - the dot color when the input method is not ABC +--- * mode - the mode of the indicator +--- * showOnChangeDuration - seconds to show the indicator when the input method is changed +--- * checkInterval - seconds to check the input method +--- * dotSize - the size of the dot +--- * deltaY - the distance between the dot and the center of the selection or mouse +function obj:start(config) + -- check whether the config is a table + if config then + if type(config) ~= "table" then + hs.alert.show("Config must be a table") + logger.e("Config must be a table") + return + end + for k, v in pairs(config) do + if self[k] then + self[k] = v + else + logger.e("Invalid config key: " .. k) + end + end + end + if self.mode == "onChange" then + self.hideCanvasTimer = self:hideCanvasTimer() + self.showOnChangeTimer = self:showOnChangeTimer() + elseif self.mode == "adaptive" then + self.canvas:show() + self.adaptiveTimer = self:adaptiveTimer() + elseif self.mode == "nearMouse" then + self.canvas:show() + self.showNearMouseTimer = self:showNearMouseTimer() + else + hs.alert.show("Invalid mode") + logger.e("Invalid mode") + return + end +end + +--- InputMethodIndicator:stop() +--- Method +--- Stop InputMethodIndicator. +--- +--- Parameters: +--- * None +function obj:stop() + self.canvas:hide() + self.canvas = nil + if self.showOnChangeTimer then + self.showOnChangeTimer:stop() + self.showOnChangeTimer = nil + end + if self.adaptiveTimer then + self.adaptiveTimer:stop() + self.adaptiveTimer = nil + end + if self.showNearMouseTimer then + self.showNearMouseTimer:stop() + self.showNearMouseTimer=nil + end +end + +return obj diff --git a/Source/InputSourceSwitch.spoon/docs.json b/Source/InputSourceSwitch.spoon/docs.json new file mode 100644 index 00000000..9c93877c --- /dev/null +++ b/Source/InputSourceSwitch.spoon/docs.json @@ -0,0 +1,112 @@ +[ + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "InputSourceSwitch:setApplications()", + "desc": "Set that mapping the application name to the input source", + "doc": "Set that mapping the application name to the input source\n\nParameters:\n * applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:\n```\n{\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n}\n```", + "examples": [], + "file": "Source/InputSourceSwitch.spoon//init.lua", + "lineno": "80", + "name": "setApplications", + "notes": [], + "parameters": [ + " * applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: ``` { [\"WeChat\"] = \"Pinyin - Simplified\", [\"Mail\"] = \"ABC\" } ```" + ], + "returns": [], + "signature": "InputSourceSwitch:setApplications()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputSourceSwitch:start()", + "desc": "Start InputSourceSwitch", + "doc": "Start InputSourceSwitch\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputSourceSwitch.spoon//init.lua", + "lineno": "100", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputSourceSwitch:start()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ + { + "def": "InputSourceSwitch.applicationMap", + "desc": "Mapping the application name to the input source", + "doc": "Mapping the application name to the input source", + "file": "Source/InputSourceSwitch.spoon//init.lua", + "lineno": "75", + "name": "applicationMap", + "signature": "InputSourceSwitch.applicationMap", + "stripped_doc": "", + "type": "Variable" + } + ], + "desc": "Automatically switch the input source when switching applications.", + "doc": "Automatically switch the input source when switching applications.\n\nExample:\n```\nhs.loadSpoon(\"InputSourceSwitch\")\n\nspoon.InputSourceSwitch:setApplications({\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n})\n\nspoon.InputSourceSwitch:start()\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip)", + "items": [ + { + "def": "InputSourceSwitch.applicationMap", + "desc": "Mapping the application name to the input source", + "doc": "Mapping the application name to the input source", + "file": "Source/InputSourceSwitch.spoon//init.lua", + "lineno": "75", + "name": "applicationMap", + "signature": "InputSourceSwitch.applicationMap", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "InputSourceSwitch:setApplications()", + "desc": "Set that mapping the application name to the input source", + "doc": "Set that mapping the application name to the input source\n\nParameters:\n * applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:\n```\n{\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n}\n```", + "examples": [], + "file": "Source/InputSourceSwitch.spoon//init.lua", + "lineno": "80", + "name": "setApplications", + "notes": [], + "parameters": [ + " * applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: ``` { [\"WeChat\"] = \"Pinyin - Simplified\", [\"Mail\"] = \"ABC\" } ```" + ], + "returns": [], + "signature": "InputSourceSwitch:setApplications()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputSourceSwitch:start()", + "desc": "Start InputSourceSwitch", + "doc": "Start InputSourceSwitch\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputSourceSwitch.spoon//init.lua", + "lineno": "100", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputSourceSwitch:start()", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "InputSourceSwitch", + "stripped_doc": "\nExample:\n```\nhs.loadSpoon(\"InputSourceSwitch\")\n\nspoon.InputSourceSwitch:setApplications({\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n})\n\nspoon.InputSourceSwitch:start()\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip)", + "submodules": [], + "type": "Module" + } +] \ No newline at end of file diff --git a/Source/InputSourceSwitch.spoon/init.lua b/Source/InputSourceSwitch.spoon/init.lua new file mode 100644 index 00000000..d3814be4 --- /dev/null +++ b/Source/InputSourceSwitch.spoon/init.lua @@ -0,0 +1,113 @@ +--- === InputSourceSwitch === +--- +--- Automatically switch the input source when switching applications. +--- +--- Example: +--- ``` +--- hs.loadSpoon("InputSourceSwitch") +--- +--- spoon.InputSourceSwitch:setApplications({ +--- ["WeChat"] = "Pinyin - Simplified", +--- ["Mail"] = "ABC" +--- }) +--- +--- spoon.InputSourceSwitch:start() +--- ``` +--- +--- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip) + +local obj = {} +obj.__index = obj + +-- Metadata +obj.name = "InputSourceSwitch" +obj.version = "1.0" +obj.author = "eks5115 " +obj.homepage = "https://github.com/Hammerspoon/Spoons" +obj.license = "MIT - https://opensource.org/licenses/MIT" + +local log = hs.logger.new('InputSourceSwitch','debug') +log.d('Init') + +-- Internal function used to get enabled input sources +local function isLayout(layoutName) + local layouts = hs.keycodes.layouts() + for key, value in pairs(layouts) do + if (value == layoutName) then + return true + end + end + + return false +end + +local function isMethod(methodName) + local methods = hs.keycodes.methods() + for key, value in pairs(methods) do + if (value == methodName) then + return true + end + end + + return false +end + +local function setAppInputSource(appName, sourceName, event) + event = event or hs.window.filter.windowFocused + + hs.window.filter.new(appName):subscribe(event, function() + local r = true + + if (isLayout(sourceName)) then + r = hs.keycodes.setLayout(sourceName) + elseif isMethod(sourceName) then + r = hs.keycodes.setMethod(sourceName) + else + hs.alert.show(string.format('sourceName: %s is not layout or method', sourceName)) + end + + if (not r) then + hs.alert.show(string.format('set %s to %s failure', appName, sourceName)) + end + end) +end + +--- InputSourceSwitch.applicationMap +--- Variable +--- Mapping the application name to the input source +obj.applicationsMap = {} + +--- InputSourceSwitch:setApplications() +--- Method +--- Set that mapping the application name to the input source +--- +--- Parameters: +--- * applications - A table containing that mapping the application name to the input source +--- key is the application name and value is the input source name +--- example: +--- ``` +--- { +--- ["WeChat"] = "Pinyin - Simplified", +--- ["Mail"] = "ABC" +--- } +--- ``` +function obj:setApplications(applications) + for key, value in pairs(applications) do + obj.applicationsMap[key] = value + end +end + +--- InputSourceSwitch:start() +--- Method +--- Start InputSourceSwitch +--- +--- Parameters: +--- * None +function obj:start() + for k,v in pairs(self.applicationsMap) do + setAppInputSource(k, v) + end + return self +end + +return obj diff --git a/Source/Keychain.spoon/docs.json b/Source/Keychain.spoon/docs.json index 3ff47d7a..f25b9339 100644 --- a/Source/Keychain.spoon/docs.json +++ b/Source/Keychain.spoon/docs.json @@ -29,20 +29,15 @@ "def": "Keychain:addItem(options)", "desc": "Add generic password to keychain.", "doc": "Add generic password to keychain.\n\nParameters:\n * options is a table with values for what keys to try locate with.\n * password - the password\n * account - account name (required)\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment \n * label - label (defaults to service name)\n * service - service name (required)", + "examples": [], "file": "Source/Keychain.spoon//init.lua", "lineno": "139", "name": "addItem", + "notes": [], "parameters": [ - " * options is a table with values for what keys to try locate with.", - " * password - the password", - " * account - account name (required)", - " * creator - creator, must be 4 characters", - " * type - type, must be 4 characters", - " * kind - kind of item", - " * comment - comment ", - " * label - label (defaults to service name)", - " * service - service name (required)" + " * options is a table with values for what keys to try locate with.\n * password - the password\n * account - account name (required)\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment\n * label - label (defaults to service name)\n * service - service name (required)" ], + "returns": [], "signature": "Keychain:addItem(options)", "stripped_doc": "", "type": "Method" @@ -51,6 +46,7 @@ "def": "Keychain:getItem(options)", "desc": "Retrieve an item from the Login Keychain. Return nil if not found and otherwise a table with found data.", "doc": "Retrieve an item from the Login Keychain. Return nil if not found and otherwise a table with found data.\n\nParameters:\n * options is a table with values for what keys to try locate with.\n * account - account name\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment \n * label - label (defaults to service name)\n * service - service name\n\nNotes:\n * If multiple possibles matches just the first one is found.", + "examples": [], "file": "Source/Keychain.spoon//init.lua", "lineno": "82", "name": "getItem", @@ -58,15 +54,9 @@ " * If multiple possibles matches just the first one is found." ], "parameters": [ - " * options is a table with values for what keys to try locate with.", - " * account - account name", - " * creator - creator, must be 4 characters", - " * type - type, must be 4 characters", - " * kind - kind of item", - " * comment - comment ", - " * label - label (defaults to service name)", - " * service - service name" + " * options is a table with values for what keys to try locate with.\n * account - account name\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment\n * label - label (defaults to service name)\n * service - service name" ], + "returns": [], "signature": "Keychain:getItem(options)", "stripped_doc": "", "type": "Method" @@ -92,20 +82,15 @@ "def": "Keychain:addItem(options)", "desc": "Add generic password to keychain.", "doc": "Add generic password to keychain.\n\nParameters:\n * options is a table with values for what keys to try locate with.\n * password - the password\n * account - account name (required)\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment \n * label - label (defaults to service name)\n * service - service name (required)", + "examples": [], "file": "Source/Keychain.spoon//init.lua", "lineno": "139", "name": "addItem", + "notes": [], "parameters": [ - " * options is a table with values for what keys to try locate with.", - " * password - the password", - " * account - account name (required)", - " * creator - creator, must be 4 characters", - " * type - type, must be 4 characters", - " * kind - kind of item", - " * comment - comment ", - " * label - label (defaults to service name)", - " * service - service name (required)" + " * options is a table with values for what keys to try locate with.\n * password - the password\n * account - account name (required)\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment\n * label - label (defaults to service name)\n * service - service name (required)" ], + "returns": [], "signature": "Keychain:addItem(options)", "stripped_doc": "", "type": "Method" @@ -114,6 +99,7 @@ "def": "Keychain:getItem(options)", "desc": "Retrieve an item from the Login Keychain. Return nil if not found and otherwise a table with found data.", "doc": "Retrieve an item from the Login Keychain. Return nil if not found and otherwise a table with found data.\n\nParameters:\n * options is a table with values for what keys to try locate with.\n * account - account name\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment \n * label - label (defaults to service name)\n * service - service name\n\nNotes:\n * If multiple possibles matches just the first one is found.", + "examples": [], "file": "Source/Keychain.spoon//init.lua", "lineno": "82", "name": "getItem", @@ -121,15 +107,9 @@ " * If multiple possibles matches just the first one is found." ], "parameters": [ - " * options is a table with values for what keys to try locate with.", - " * account - account name", - " * creator - creator, must be 4 characters", - " * type - type, must be 4 characters", - " * kind - kind of item", - " * comment - comment ", - " * label - label (defaults to service name)", - " * service - service name" + " * options is a table with values for what keys to try locate with.\n * account - account name\n * creator - creator, must be 4 characters\n * type - type, must be 4 characters\n * kind - kind of item\n * comment - comment\n * label - label (defaults to service name)\n * service - service name" ], + "returns": [], "signature": "Keychain:getItem(options)", "stripped_doc": "", "type": "Method" diff --git a/Source/Keychain.spoon/init.lua b/Source/Keychain.spoon/init.lua index 08a0c5b3..0332ca6c 100644 --- a/Source/Keychain.spoon/init.lua +++ b/Source/Keychain.spoon/init.lua @@ -150,7 +150,7 @@ end --- * comment - comment --- * label - label (defaults to service name) --- * service - service name (required) -function obj:addPassword(options) +function obj:addItem(options) local cmd="/usr/bin/security add-generic-password" @@ -160,7 +160,6 @@ function obj:addPassword(options) end end - cmd = cmd .. "-w '" .. options.password .. "'" local handle = io.popen(cmd) local result = handle:read("*a") diff --git a/Source/LeftRightHotkey.spoon/docs.json b/Source/LeftRightHotkey.spoon/docs.json new file mode 100644 index 00000000..7068e1b6 --- /dev/null +++ b/Source/LeftRightHotkey.spoon/docs.json @@ -0,0 +1,291 @@ +[ + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create and enable a new hotkey with the specified left/right specific modifiers.", + "doc": "Create and enable a new hotkey with the specified left/right specific modifiers.\n\nParameters:\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new enabled hotkey with the specified left/right modifiers.\n\nNotes:\n * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "415", + "name": "bind", + "notes": [ + " * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`", + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here." + ], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "returns": [ + " * a new enabled hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:deleteAll(mods, key)", + "desc": "Deletes all previously set callbacks for a given keyboard combination", + "doc": "Deletes all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "326", + "name": "deleteAll", + "notes": [], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "returns": [ + " * None" + ], + "signature": "LeftRightHotkey:deleteAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:disableAll(mods, key)", + "desc": "Disables all previously set callbacks for a given keyboard combination", + "doc": "Disables all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "373", + "name": "disableAll", + "notes": [], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "returns": [ + " * None" + ], + "signature": "LeftRightHotkey:disableAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create a new hotkey with the specified left/right specific modifiers.", + "doc": "Create a new hotkey with the specified left/right specific modifiers.\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new, initially disabled, hotkey with the specified left/right modifiers.\n\nNotes:\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "263", + "name": "new", + "notes": [ + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here." + ], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "returns": [ + " * a new, initially disabled, hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:start() -> self", + "desc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this enables the use of hotkeys created by using this Spoon.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "444", + "name": "start", + "notes": [ + " * this enables the use of hotkeys created by using this Spoon." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:start() -> self", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:stop() -> self", + "desc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "471", + "name": "stop", + "notes": [ + " * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:stop() -> self", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [], + "desc": "This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.", + "doc": "This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.\n\nThis is accomplished by creating unactivated hotkeys for each definition and using an [hs.eventtap](hs.eventtap.html) watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the `bind` and `new` methods of this spoon.\n\nThe `LeftRightHotkeyObject` that is returned by [LeftRightHotkey:new](#new) and [LeftRightHotkey:bind](#bind) supports the following methods in a manner similar to the [hs.hotkey](hs.hotkey.html) equivalents:\n\n * `LeftRightHotkeyObject:enable()` -- enables the registered hotkey.\n * `LeftRightHotkeyObject:disable()` -- disables the registered hotkey.\n * `LeftRightHotkeyObject:delete()` -- deletes the registered hotkey.\n * `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)\n\nThe following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n\nThe modifiers table for any given hotkey is all inclusive; this means that if you specify `{ \"rShift\", \"lShift\" }` then *both* the left and right shift keys *must* be pressed to trigger the hotkey -- if you want either/or, then stick with [hs.hotkey](hs.hotkey.html).\n\nAlternatively, if you want to setup a hotkey when *either* command key is pressed with *only* the right shift, you would need to set up two hotkeys with this spoon:\n e.g. `LeftRightHotkey:bind({ \"rCmd\", \"rShift\" }, \"a\", myFunction)` *and* `LeftRightHotkey:bind({ \"lCmd\", \"rShift\" }, \"a\", myFunction)`\n\nThis spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:\n * like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.\n * behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through `hs.hotkey:enable()` -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.\n * a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue [LeftRightHotkey:start()](#start) to force the eventtap to be reset if necessary.\n * if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.\n\nLike all Spoons, don't forget to use the [LeftRightHotkey:start()](#start) method to activate the modifier key watcher.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip)", + "items": [ + { + "def": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create and enable a new hotkey with the specified left/right specific modifiers.", + "doc": "Create and enable a new hotkey with the specified left/right specific modifiers.\n\nParameters:\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new enabled hotkey with the specified left/right modifiers.\n\nNotes:\n * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "415", + "name": "bind", + "notes": [ + " * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`", + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here." + ], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "returns": [ + " * a new enabled hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:deleteAll(mods, key)", + "desc": "Deletes all previously set callbacks for a given keyboard combination", + "doc": "Deletes all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "326", + "name": "deleteAll", + "notes": [], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "returns": [ + " * None" + ], + "signature": "LeftRightHotkey:deleteAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:disableAll(mods, key)", + "desc": "Disables all previously set callbacks for a given keyboard combination", + "doc": "Disables all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "373", + "name": "disableAll", + "notes": [], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "returns": [ + " * None" + ], + "signature": "LeftRightHotkey:disableAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create a new hotkey with the specified left/right specific modifiers.", + "doc": "Create a new hotkey with the specified left/right specific modifiers.\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new, initially disabled, hotkey with the specified left/right modifiers.\n\nNotes:\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "263", + "name": "new", + "notes": [ + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here." + ], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "returns": [ + " * a new, initially disabled, hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:start() -> self", + "desc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this enables the use of hotkeys created by using this Spoon.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "444", + "name": "start", + "notes": [ + " * this enables the use of hotkeys created by using this Spoon." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:start() -> self", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:stop() -> self", + "desc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon//init.lua", + "lineno": "471", + "name": "stop", + "notes": [ + " * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:stop() -> self", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "LeftRightHotkey", + "stripped_doc": "\nThis is accomplished by creating unactivated hotkeys for each definition and using an [hs.eventtap](hs.eventtap.html) watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the `bind` and `new` methods of this spoon.\n\nThe `LeftRightHotkeyObject` that is returned by [LeftRightHotkey:new](#new) and [LeftRightHotkey:bind](#bind) supports the following methods in a manner similar to the [hs.hotkey](hs.hotkey.html) equivalents:\n\n * `LeftRightHotkeyObject:enable()` -- enables the registered hotkey.\n * `LeftRightHotkeyObject:disable()` -- disables the registered hotkey.\n * `LeftRightHotkeyObject:delete()` -- deletes the registered hotkey.\n * `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)\n\nThe following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n\nThe modifiers table for any given hotkey is all inclusive; this means that if you specify `{ \"rShift\", \"lShift\" }` then *both* the left and right shift keys *must* be pressed to trigger the hotkey -- if you want either/or, then stick with [hs.hotkey](hs.hotkey.html).\n\nAlternatively, if you want to setup a hotkey when *either* command key is pressed with *only* the right shift, you would need to set up two hotkeys with this spoon:\n e.g. `LeftRightHotkey:bind({ \"rCmd\", \"rShift\" }, \"a\", myFunction)` *and* `LeftRightHotkey:bind({ \"lCmd\", \"rShift\" }, \"a\", myFunction)`\n\nThis spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:\n * like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.\n * behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through `hs.hotkey:enable()` -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.\n * a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue [LeftRightHotkey:start()](#start) to force the eventtap to be reset if necessary.\n * if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.\n\nLike all Spoons, don't forget to use the [LeftRightHotkey:start()](#start) method to activate the modifier key watcher.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip)", + "submodules": [], + "type": "Module" + } +] \ No newline at end of file diff --git a/Source/LeftRightHotkey.spoon/init.lua b/Source/LeftRightHotkey.spoon/init.lua new file mode 100644 index 00000000..e1a55dd5 --- /dev/null +++ b/Source/LeftRightHotkey.spoon/init.lua @@ -0,0 +1,515 @@ +--- === LeftRightHotkey === +--- +--- This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free. +--- +--- This is accomplished by creating unactivated hotkeys for each definition and using an [hs.eventtap](hs.eventtap.html) watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the `bind` and `new` methods of this spoon. +--- +--- The `LeftRightHotkeyObject` that is returned by [LeftRightHotkey:new](#new) and [LeftRightHotkey:bind](#bind) supports the following methods in a manner similar to the [hs.hotkey](hs.hotkey.html) equivalents: +--- +--- * `LeftRightHotkeyObject:enable()` -- enables the registered hotkey. +--- * `LeftRightHotkeyObject:disable()` -- disables the registered hotkey. +--- * `LeftRightHotkeyObject:delete()` -- deletes the registered hotkey. +--- * `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false) +--- +--- The following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon: +--- * "lCmd", "lCommand", or "l⌘" for the left Command modifier +--- * "rCmd", "rCommand", or "r⌘" for the right Command modifier +--- * "lCtrl", "lControl" or "l⌃" for the left Control modifier +--- * "rCtrl", "rControl" or "r⌃" for the right Control modifier +--- * "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier +--- * "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier +--- * "lShift" or "l⇧" for the left Shift modifier +--- * "rShift" or "r⇧" for the right Shift modifier +--- +--- The modifiers table for any given hotkey is all inclusive; this means that if you specify `{ "rShift", "lShift" }` then *both* the left and right shift keys *must* be pressed to trigger the hotkey -- if you want either/or, then stick with [hs.hotkey](hs.hotkey.html). +--- +--- Alternatively, if you want to setup a hotkey when *either* command key is pressed with *only* the right shift, you would need to set up two hotkeys with this spoon: +--- e.g. `LeftRightHotkey:bind({ "rCmd", "rShift" }, "a", myFunction)` *and* `LeftRightHotkey:bind({ "lCmd", "rShift" }, "a", myFunction)` +--- +--- This spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following: +--- * like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely. +--- * behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through `hs.hotkey:enable()` -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed. +--- * a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue [LeftRightHotkey:start()](#start) to force the eventtap to be reset if necessary. +--- * if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above. +--- +--- Like all Spoons, don't forget to use the [LeftRightHotkey:start()](#start) method to activate the modifier key watcher. +--- +--- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip) + +local spoons = require("hs.spoons") +local log = require("hs.logger").new("LeftRightHotkey", require("hs.settings").get("LeftRightHotkey_logLevel") or "warning") + +local fnutils = require("hs.fnutils") +local hotkey = require("hs.hotkey") +local keycodes = require("hs.keycodes") +local timer = require("hs.timer") +local eventtap = require("hs.eventtap") +local etevent = eventtap.event + +local obj = { +-- Metadata + name = "LeftRightHotkey", + author = "A-Ron", + homepage = "https://github.com/Hammerspoon/Spoons", + license = "MIT - https://opensource.org/licenses/MIT", + spoonPath = spoons.scriptPath(), +} +-- version is outside of obj table definition to facilitate its auto detection by +-- external documentation generation scripts +obj.version = "0.1" + +-- defines the keys to display in object's __tostring metamethod; define here so subsequent +-- additions are not included in the output +local metadataKeys = {} ; for k, v in fnutils.sortByKeys(obj) do table.insert(metadataKeys, k) end + +obj.__index = obj + +---------- Local Functions And Variables ---------- + +local modiferBase = { + ["lcmd"] = "cmd", + ["rcmd"] = "cmd", + ["lshift"] = "shift", + ["rshift"] = "shift", + ["lalt"] = "alt", + ["ralt"] = "alt", + ["lctrl"] = "ctrl", + ["rctrl"] = "ctrl", +} + +local altMods = { + ["⇧"] = "shift", + ["opt"] = "alt", + ["option"] = "alt", + ["⌥"] = "alt", + ["⌘"] = "cmd", + ["command"] = "cmd", + ["⌃"] = "ctrl", + ["control"] = "ctrl", +} + +local modifierMasks = { + lcmd = 1 << 0, + rcmd = 1 << 1, + lshift = 1 << 2, + rshift = 1 << 3, + lalt = 1 << 4, + ralt = 1 << 5, + lctrl = 1 << 6, + rctrl = 1 << 7, +} + +local existantHotKeys = {} + +local queuedHotKeys = {} +for i = 1, (1 << 8) - 1, 1 do queuedHotKeys[i] = setmetatable({}, { __mode = "k" }) end + +-- copies flag tables so that if the user wants to reuse his tables, we don't +-- modify them +local shallowCopyTable = function(tbl) + local newTbl = {} + local key, value = next(tbl) + while key do + newTbl[key] = value + key, value = next(tbl, key) + end + return newTbl +end + +-- use lookup tables above to convert all flags to one format to simplify later checks +local normalizeModsTable = function(tbl) + local newTbl = shallowCopyTable(tbl) + for i, m in ipairs(newTbl) do + local mod = m:lower() + for k, v in pairs(altMods) do + local s, e = mod:find(k .. "$") + if s then + newTbl[i] = mod:sub(1, s - 1) .. v + break + end + end + newTbl[i] = newTbl[i]:lower() + end + return newTbl +end + +-- converts our modifiers to the actual modifiers sent to `hs.hotkey` +local convertModifiers = function(specifiedMods) + local actualMods, queueIndex = {}, 0 + + for _, v in pairs(specifiedMods) do + queueIndex = queueIndex | (modifierMasks[v] or 0) + local hotkeyModEquivalant = modiferBase[v] + if hotkeyModEquivalant then + table.insert(actualMods, hotkeyModEquivalant) + else + queueIndex = 0 + break + end + end + return actualMods, queueIndex +end + +-- eventtap and watchdog timer predefined so they stay local +local _flagWatcher, _watchTimer + +local enableAndDisableHotkeys = function(queueIndex) + local foundMatches = {} + for i, v in ipairs(queuedHotKeys) do + if i == queueIndex then + for key, _ in pairs(v) do + if key._enabled then + table.insert(foundMatches, key) +-- key._hotkey:enable() + end + end + else + for key, _ in pairs(v) do + if key._enabled then + key._hotkey:disable() + end + end + end + end + + if #foundMatches > 0 then + -- enable only the most recently created version for a given _keycode + -- in case of stacking + local enabled = {} + table.sort(foundMatches, function(a, b) return a._creationID > b._creationID end) + for _, key in ipairs(foundMatches) do + if not enabled[key._keycode] then + enabled[key._keycode] = true + key._hotkey:enable() + end + end + end +end + +-- respond to flag changes or (if ev is null) resynchronize +local flagChangeCallback = function(ev) + local rf = ev and ev:getRawEventData().CGEventData.flags + or eventtap.checkKeyboardModifiers(true)._raw + + local queueIndex = 0 + if rf & etevent.rawFlagMasks.deviceLeftAlternate > 0 then + queueIndex = queueIndex | modifierMasks.lalt + end + if rf & etevent.rawFlagMasks.deviceLeftCommand > 0 then + queueIndex = queueIndex | modifierMasks.lcmd + end + if rf & etevent.rawFlagMasks.deviceLeftControl > 0 then + queueIndex = queueIndex | modifierMasks.lctrl + end + if rf & etevent.rawFlagMasks.deviceLeftShift > 0 then + queueIndex = queueIndex | modifierMasks.lshift + end + if rf & etevent.rawFlagMasks.deviceRightAlternate > 0 then + queueIndex = queueIndex | modifierMasks.ralt + end + if rf & etevent.rawFlagMasks.deviceRightCommand > 0 then + queueIndex = queueIndex | modifierMasks.rcmd + end + if rf & etevent.rawFlagMasks.deviceRightControl > 0 then + queueIndex = queueIndex | modifierMasks.rctrl + end + if rf & etevent.rawFlagMasks.deviceRightShift > 0 then + queueIndex = queueIndex | modifierMasks.rshift + end +-- print("activating " .. tostring(queueIndex)) + + enableAndDisableHotkeys(queueIndex) +end + +-- checks that the flagwatcher is still running and synchronizes the callbacks +local checkFlagWatcher = function() + if not _flagWatcher:isEnabled() then + log.w("re-enabling flag watcher") + _flagWatcher:start() + flagChangeCallback(nil) + end +end + +-- define methods for our hotkey objects +local _LeftRightHotkeyObjMT = {} +_LeftRightHotkeyObjMT.__index = { + enable = function(self) + self._enabled = true + return self + end, + disable = function(self) + self._enabled = false + self._hotkey:disable() + return self + end, + delete = function(self) + self:disable() + existantHotKeys[self] = nil + collectgarbage() + return nil + end, + isEnabled = function(self) return self._enabled end, +} +_LeftRightHotkeyObjMT.__tostring = function(self) + return self._modDesc .. " " .. (keycodes.map[self._keycode] or ("unmapped:" .. tostring(self._keycode))) +end + +-- keeps track of creation order so we can enable only the latest enabled version +-- (i.e. stacking) +local definitionIndex = 0 + +---------- Spoon Methods ---------- + +--- LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject +--- Method +--- Create a new hotkey with the specified left/right specific modifiers. +--- +--- Parameters: +--- * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following: +--- * "lCmd", "lCommand", or "l⌘" for the left Command modifier +--- * "rCmd", "rCommand", or "r⌘" for the right Command modifier +--- * "lCtrl", "lControl" or "l⌃" for the left Control modifier +--- * "rCtrl", "rControl" or "r⌃" for the right Control modifier +--- * "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier +--- * "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier +--- * "lShift" or "l⇧" for the left Shift modifier +--- * "rShift" or "r⇧" for the right Shift modifier +--- * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number +--- * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown +--- * pressedfn - A function that will be called when the hotkey has been pressed, or nil +--- * releasedfn - A function that will be called when the hotkey has been released, or nil +--- * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil +--- +--- Returns: +--- * a new, initially disabled, hotkey with the specified left/right modifiers. +--- +--- Notes: +--- * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here. +obj.new = function(self, ...) + local args = { ... } + if self ~= obj then + table.insert(args, 1, self) + self = obj + end + local specifiedMods = normalizeModsTable(args[1]) + local actualMods, queueIndex = convertModifiers(specifiedMods) + + if queueIndex ~= 0 then + args[1] = actualMods + for i, v in ipairs(specifiedMods) do + specifiedMods[i] = v:sub(1,1) .. v:sub(2,2):upper() .. v:sub(3) + end + local key = args[2] + local keycode = keycodes.map[key] + if type(key) == "number" then keycode = key end +-- print(queueIndex, "actually " .. finspect(actualMods)) + local newObject = setmetatable({ + _modDesc = table.concat(specifiedMods, "+"), + _queueIndex = queueIndex, + _keycode = keycode, + _hotkey = hotkey.new(table.unpack(args)), + _enabled = false, + _creationID = definitionIndex, + }, _LeftRightHotkeyObjMT) + + -- used to determine creation order for stacking + definitionIndex = definitionIndex + 1 + + existantHotKeys[newObject] = true + queuedHotKeys[queueIndex][newObject] = true + return newObject + else + error("you must specifiy one or more of lcmd, rcmd, lshift, rshift, lalt, ralt, lctrl, rctrl", 2) + end +end + +--- LeftRightHotkey:deleteAll(mods, key) +--- Method +--- Deletes all previously set callbacks for a given keyboard combination +--- +--- Parameters: +--- * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following: +--- * "lCmd", "lCommand", or "l⌘" for the left Command modifier +--- * "rCmd", "rCommand", or "r⌘" for the right Command modifier +--- * "lCtrl", "lControl" or "l⌃" for the left Control modifier +--- * "rCtrl", "rControl" or "r⌃" for the right Control modifier +--- * "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier +--- * "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier +--- * "lShift" or "l⇧" for the left Shift modifier +--- * "rShift" or "r⇧" for the right Shift modifier +--- * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number +--- +--- Returns: +--- * None +obj.deleteAll = function(self, ...) + local args = { ... } + if self ~= obj then + table.insert(args, 1, self) + self = obj + end + local specifiedMods = normalizeModsTable(args[1]) + local _, queueIndex = convertModifiers(specifiedMods) + + if queueIndex ~= 0 then + local key = args[2] + local keycode = keycodes.map[key] + if type(key) == "number" then keycode = key end + + local foundMatches = {} + for k, v in pairs(existantHotKeys) do + if v._queueIndex == queueIndex and v._keycode == keycode then + table.insert(foundMatches, k) + end + end + -- this is so we don't remove items from existantHotKeys while iterating through it + for _, v in ipairs(foundMatches) do + v:delete() + end + else + error("you must specifiy one or more of lcmd, rcmd, lshift, rshift, lalt, ralt, lctrl, rctrl", 2) + end +end + +--- LeftRightHotkey:disableAll(mods, key) +--- Method +--- Disables all previously set callbacks for a given keyboard combination +--- +--- Parameters: +--- * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following: +--- * "lCmd", "lCommand", or "l⌘" for the left Command modifier +--- * "rCmd", "rCommand", or "r⌘" for the right Command modifier +--- * "lCtrl", "lControl" or "l⌃" for the left Control modifier +--- * "rCtrl", "rControl" or "r⌃" for the right Control modifier +--- * "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier +--- * "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier +--- * "lShift" or "l⇧" for the left Shift modifier +--- * "rShift" or "r⇧" for the right Shift modifier +--- * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number +--- +--- Returns: +--- * None +obj.disableAll = function(self, ...) + local args = { ... } + if self ~= obj then + table.insert(args, 1, self) + self = obj + end + local specifiedMods = normalizeModsTable(args[1]) + local _, queueIndex = convertModifiers(specifiedMods) + + if queueIndex ~= 0 then + local key = args[2] + local keycode = keycodes.map[key] + if type(key) == "number" then keycode = key end + + for k, v in pairs(existantHotKeys) do + if v._queueIndex == queueIndex and v._keycode == keycode then + k:disable() -- we don't need the temp table used in delete since we're just disabling + end + end + else + error("you must specifiy one or more of lcmd, rcmd, lshift, rshift, lalt, ralt, lctrl, rctrl", 2) + end +end + +--- LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject +--- Method +--- Create and enable a new hotkey with the specified left/right specific modifiers. +--- +--- Parameters: +--- Parameters: +--- * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following: +--- * "lCmd", "lCommand", or "l⌘" for the left Command modifier +--- * "rCmd", "rCommand", or "r⌘" for the right Command modifier +--- * "lCtrl", "lControl" or "l⌃" for the left Control modifier +--- * "rCtrl", "rControl" or "r⌃" for the right Control modifier +--- * "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier +--- * "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier +--- * "lShift" or "l⇧" for the left Shift modifier +--- * "rShift" or "r⇧" for the right Shift modifier +--- * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number +--- * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown +--- * pressedfn - A function that will be called when the hotkey has been pressed, or nil +--- * releasedfn - A function that will be called when the hotkey has been released, or nil +--- * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil +--- +--- Returns: +--- * a new enabled hotkey with the specified left/right modifiers. +--- +--- Notes: +--- * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()` +--- * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here. +obj.bind = function(...) return obj.new(...):enable() end + +--- LeftRightHotkey:start() -> self +--- Method +--- Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed. +--- +--- Parameters: +--- * None +--- +--- Returns: +--- * the LeftRightHotkey spoon object +--- +--- Notes: +--- * this enables the use of hotkeys created by using this Spoon. +obj.start = function(self) + -- in case called as function + if self ~= obj then self = obj end + if not _flagWatcher then + _flagWatcher = eventtap.new({ etevent.types.flagsChanged }, flagChangeCallback):start() + _watchTimer = timer.doEvery(1, checkFlagWatcher) +-- for debugging purposes, may go away + obj._flagWatcher = _flagWatcher + obj._watchTimer = _watchTimer + else + checkFlagWatcher() + end + return self +end + +--- LeftRightHotkey:stop() -> self +--- Method +--- Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed. +--- +--- Parameters: +--- * None +--- +--- Returns: +--- * the LeftRightHotkey spoon object +--- +--- Notes: +--- * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available. +obj.stop = function(self) + -- in case called as function + if self ~= obj then self = obj end + if _flagWatcher then + enableAndDisableHotkeys(0) + _flagWatcher:stop() + _flagWatcher = nil + _watchTimer:stop() + _watchTimer = nil +-- for debugging purposes, may go away + obj._flagWatcher = nil + obj._watchTimer = nil + end + return self +end + +-- Spoon Metadata definition and object return -- + +-- for debugging purposes, may go away +obj._queuedHotKeys = queuedHotKeys +obj._existantHotKeys = existantHotKeys + +return setmetatable(obj, { + -- more useful than "table: 0x????????????????" + __tostring = function(self) + local result, fieldSize = "", 0 + for i, v in ipairs(metadataKeys) do fieldSize = math.max(fieldSize, #v) end + for i, v in ipairs(metadataKeys) do + result = result .. string.format("%-"..tostring(fieldSize) .. "s %s\n", v, self[v]) + end + return result + end, +}) diff --git a/Source/MiddleClickDragScroll.spoon/docs.json b/Source/MiddleClickDragScroll.spoon/docs.json new file mode 100644 index 00000000..564af49a --- /dev/null +++ b/Source/MiddleClickDragScroll.spoon/docs.json @@ -0,0 +1,19 @@ +[ + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [], + "Variable": [], + "desc": "Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.", + "doc": "Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.\nEspecially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.\n\nNote: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position\nwhere the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.\n\n== Usage ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):start()\n```\n\nYou can temporarily stop the spoon by calling `MiddleClickDragScroll:stop()` and then restart it by calling `MiddleClickDragScroll:start()` again.\n\n== Configuration ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):configure{\n excludedApps = {\"Some App\", \"Other app\"}, -- Don't activate scrolling in apps with these names\n excludedWindows = {\"^Some Window Title$\"}, -- Don't activate scrolling in windows with these names (supports regex, for exact match, use \"^title$\")\n excludedUrls = {\"^https://geogebra.calculator$\"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)\n indicatorSize = 25, -- Size of the scrolling indicator in pixels\n indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.\n {\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n },\n startDistance = 15, -- Minimal distance to drag the mouse before scrolling is triggered.\n scrollMode = \"pixel\", -- Whether the scroll speed is in \"line\"s or \"pixel\"s. Scrolling by lines has smooting in some applications\n -- and therefore works with reduced frequency but it offers much less precise control.\n scrollFrequency = 0.01, -- How often to trigger scrolling (in seconds)\n scrollAccelaration = 30, -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.\n scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location.\n -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument\n -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).\n function(self, x)\n return (x ^ 2) / (self.scrollAccelaration ^ 2)\n end\n}:start()\n```\n\nUnspecified keys are unchanged. You can call `configure` multiple times to dynamically change it but changing `indicatorAttributes` and `indicatorSize` only works when `MiddleClickDragScroll` is stopped.\n\nInstead of `indicatorSize` and `indicatorAttributes`, you can also pass a custom canvas to `configure` or set it directly to have more control over the indicator style:\n\n```lua\n MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n }\n```\n\nFor more details, see: https://www.hammerspoon.org/docs/hs.canvas.html\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip)", + "items": [], + "name": "MiddleClickDragScroll", + "stripped_doc": "Especially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.\n\nNote: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position\nwhere the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.\n\n== Usage ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):start()\n```\n\nYou can temporarily stop the spoon by calling `MiddleClickDragScroll:stop()` and then restart it by calling `MiddleClickDragScroll:start()` again.\n\n== Configuration ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):configure{\n excludedApps = {\"Some App\", \"Other app\"}, -- Don't activate scrolling in apps with these names\n excludedWindows = {\"^Some Window Title$\"}, -- Don't activate scrolling in windows with these names (supports regex, for exact match, use \"^title$\")\n excludedUrls = {\"^https://geogebra.calculator$\"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)\n indicatorSize = 25, -- Size of the scrolling indicator in pixels\n indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.\n {\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n },\n startDistance = 15, -- Minimal distance to drag the mouse before scrolling is triggered.\n scrollMode = \"pixel\", -- Whether the scroll speed is in \"line\"s or \"pixel\"s. Scrolling by lines has smooting in some applications\n -- and therefore works with reduced frequency but it offers much less precise control.\n scrollFrequency = 0.01, -- How often to trigger scrolling (in seconds)\n scrollAccelaration = 30, -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.\n scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location.\n -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument\n -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).\n function(self, x)\n return (x ^ 2) / (self.scrollAccelaration ^ 2)\n end\n}:start()\n```\n\nUnspecified keys are unchanged. You can call `configure` multiple times to dynamically change it but changing `indicatorAttributes` and `indicatorSize` only works when `MiddleClickDragScroll` is stopped.\n\nInstead of `indicatorSize` and `indicatorAttributes`, you can also pass a custom canvas to `configure` or set it directly to have more control over the indicator style:\n\n```lua\n MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n }\n```\n\nFor more details, see: https://www.hammerspoon.org/docs/hs.canvas.html\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip)", + "submodules": [], + "type": "Module" + } +] \ No newline at end of file diff --git a/Source/MiddleClickDragScroll.spoon/init.lua b/Source/MiddleClickDragScroll.spoon/init.lua new file mode 100644 index 00000000..f4ab54bd --- /dev/null +++ b/Source/MiddleClickDragScroll.spoon/init.lua @@ -0,0 +1,261 @@ +--- === MiddleClickDragScroll === +--- +--- Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows. +--- Especially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse. +--- +--- Note: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position +--- where the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window. +--- +--- == Usage == +--- +--- ```lua +--- local MiddleClickDragScroll = hs.loadSpoon("MiddleClickDragScroll"):start() +--- ``` +--- +--- You can temporarily stop the spoon by calling `MiddleClickDragScroll:stop()` and then restart it by calling `MiddleClickDragScroll:start()` again. +--- +--- == Configuration == +--- +--- ```lua +--- local MiddleClickDragScroll = hs.loadSpoon("MiddleClickDragScroll"):configure{ +--- excludedApps = {"Some App", "Other app"}, -- Don't activate scrolling in apps with these names +--- excludedWindows = {"^Some Window Title$"}, -- Don't activate scrolling in windows with these names (supports regex, for exact match, use "^title$") +--- excludedUrls = {"^https://geogebra.calculator$"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger) +--- indicatorSize = 25, -- Size of the scrolling indicator in pixels +--- indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below. +--- { +--- type = "circle", +--- fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 }, +--- strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 }, +--- }, +--- startDistance = 15, -- Minimal distance to drag the mouse before scrolling is triggered. +--- scrollMode = "pixel", -- Whether the scroll speed is in "line"s or "pixel"s. Scrolling by lines has smooting in some applications +--- -- and therefore works with reduced frequency but it offers much less precise control. +--- scrollFrequency = 0.01, -- How often to trigger scrolling (in seconds) +--- scrollAccelaration = 30, -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster. +--- scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location. +--- -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument +--- -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting). +--- function(self, x) +--- return (x ^ 2) / (self.scrollAccelaration ^ 2) +--- end +--- }:start() +--- ``` +--- +--- Unspecified keys are unchanged. You can call `configure` multiple times to dynamically change it but changing `indicatorAttributes` and `indicatorSize` only works when `MiddleClickDragScroll` is stopped. +--- +--- Instead of `indicatorSize` and `indicatorAttributes`, you can also pass a custom canvas to `configure` or set it directly to have more control over the indicator style: +--- +--- ```lua +--- MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{ +--- type = "circle", +--- fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 }, +--- strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 }, +--- } +--- ``` +--- +--- For more details, see: https://www.hammerspoon.org/docs/hs.canvas.html +--- +--- Download: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip) + +local MiddleClickDragScroll = {} + +MiddleClickDragScroll.author = "Benedikt Werner <1benediktwerner@gmail.com>" +MiddleClickDragScroll.homepage = "https://github.com/benediktwerner/MiddleClickDragScroll.spoon" +MiddleClickDragScroll.license = "MIT" +MiddleClickDragScroll.name = "MiddleClickDragScroll" +MiddleClickDragScroll.version = "1.0.0" +MiddleClickDragScroll.spoon = hs.spoons.scriptPath() + +MiddleClickDragScroll.excludedApps = {} -- Don't activate scrolling in apps with these names +MiddleClickDragScroll.excludedWindows = {} -- Don't activate scrolling in windows with these names (supports regex) +MiddleClickDragScroll.excludedUrls = {} -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger) +MiddleClickDragScroll.indicatorSize = 25 -- Size of the scrolling indicator in pixels +MiddleClickDragScroll.indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas. +{ + type = "circle", + fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 }, + strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 }, +} +MiddleClickDragScroll.startDistance = 15 -- Minimal distance to drag the mouse before scrolling is triggered. +MiddleClickDragScroll.scrollMode = "pixel" -- Whether the scroll speed is in "line"s or "pixel"s. Scrolling by lines has smooting in some applications and therefore works with reduced frequency but it offers much less precise control. +MiddleClickDragScroll.scrollFrequency = 0.01 -- How often to trigger scrolling (in seconds) +MiddleClickDragScroll.scrollAccelaration = 30 -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster. +MiddleClickDragScroll.scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location. The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting) +function(self, x) + return (x ^ 2) / (self.scrollAccelaration ^ 2) +end + +local function signum(n) + if n > 0 then return 1 + elseif n < 0 then return -1 + else return 0 end +end + +local function getWindowUnderMouse() + -- Adapted from SkyRocket.spoon + -- Invoke `hs.application` because `hs.window.orderedWindows()` doesn't do it and breaks itself + local _ = hs.application + + local mousePos = hs.geometry.new(hs.mouse.absolutePosition()) + local screen = hs.mouse.getCurrentScreen() + + return hs.fnutils.find(hs.window.orderedWindows(), function(w) + return screen == w:screen() and mousePos:inside(w:frame()) + end) +end + +function MiddleClickDragScroll:init() + self.position = nil + self.isScrolling = false + self.timer = nil + + self.middleMouseDownEventTap = hs.eventtap.new({hs.eventtap.event.types.otherMouseDown}, self:handleMouseDown()) + self.middleMouseDraggedEventTap = hs.eventtap.new({hs.eventtap.event.types.otherMouseDragged}, self:handleMouseDragged()) + self.middleMouseUpEventTap = hs.eventtap.new({hs.eventtap.event.types.otherMouseUp}, self:handleMouseUp()) +end + +function MiddleClickDragScroll:handleMouseDown() + return function(event) + self.isScrolling = false + if self.timer ~= nil then + self.timer:stop() + self.timer = nil + end + + if event:getProperty(hs.eventtap.event.properties.mouseEventButtonNumber) ~= 2 then + return + end + + local window = getWindowUnderMouse() + if window == nil then return end + + local appTitle = window:application():title() + if hs.fnutils.some(self.excludedApps, function(a) return a == appTitle end) then return end + + local windowTitle = window:title() + if hs.fnutils.some(self.excludedWindows, function(w) return windowTitle:match(w) end) then return end + + if appTitle == "Safari" and #self.excludedUrls > 0 then + local _, url = hs.osascript.applescript('tell application "Safari" to return URL of current tab of front window') + if hs.fnutils.some(self.excludedUrls, function(u) return url:match(u) end) then return end + end + + if appTitle == "Google Chrome" and #self.excludedUrls > 0 then + local _, url = hs.osascript.applescript('tell application "Google Chrome" to return URL of active tab of front window') + if hs.fnutils.some(self.excludedUrls, function(u) return url:match(u) end) then return end + end + + self.startPos = event:location() + + return true + end +end + +function MiddleClickDragScroll:handleMouseDragged() + return function(event) + if event:getProperty(hs.eventtap.event.properties.mouseEventButtonNumber) ~= 2 or self.startPos == nil then + return + end + + local loc = event:location() + if loc == nil then + return true + end + + self.currPos = loc + + if self.isScrolling then + return true + end + + if (loc.x - self.startPos.x) ^ 2 + (loc.y - self.startPos.y) ^ 2 > self.startDistance ^ 2 then + self.isScrolling = true + local frame = self.canvas:frame() + self.canvas:topLeft{ x = self.startPos.x - frame.w / 2, y = self.startPos.y - frame.h / 2 }:show() + self.timer = hs.timer.doEvery(self.scrollFrequency, function(t) + local xDiff = self.startPos.x - self.currPos.x + local yDiff = self.startPos.y - self.currPos.y + hs.eventtap.scrollWheel( + { + math.floor(self:scrollSpeedFn(xDiff)) * signum(xDiff), + math.floor(self:scrollSpeedFn(yDiff)) * signum(yDiff), + }, + {}, + self.scrollMode + ) + end) + end + + return true + end +end + +function MiddleClickDragScroll:handleMouseUp() + return function(event) + if event:getProperty(hs.eventtap.event.properties.mouseEventButtonNumber) ~= 2 or self.startPos == nil then + return + end + + if self.timer ~= nil then + self.timer:stop() + self.timer = nil + end + + self.startPos = nil + self.canvas:hide() + + if not self.isScrolling then + self.middleMouseDownEventTap:stop() + self.middleMouseUpEventTap:stop() + hs.eventtap.middleClick(event:location(), 1) + self.middleMouseUpEventTap:start() + self.middleMouseDownEventTap:start() + end + + return true + end +end + +function MiddleClickDragScroll:configure(options) + self.excludedApps = options.excludedApps or self.excludedApps + self.excludedWindows = options.excludedWindows or self.excludedWindows + self.excludedUrls = options.excludedUrls or self.excludedUrls + self.startDistance = options.startDistance or self.startDistance + self.scrollMode = options.scrollMode or self.scrollMode + self.scrollFrequency = options.scrollFrequency or self.scrollFrequency + self.scrollSpeed = options.scrollSpeed or self.scrollSpeed + self.scrollSpeedFn = options.scrollSpeedFn or self.scrollSpeedFn + self.canvas = options.canvas or self.canvas + self.indicatorSize = options.indicatorSize or self.indicatorSize + self.indicatorAttributes = options.indicatorAttributes or self.indicatorAttributes + if options.indicatorSize or options.indicatorAttributes then + self.canvas = nil + end + return self +end + +function MiddleClickDragScroll:start() + if self.canvas == nil then + self.canvas = hs.canvas.new{ w = self.indicatorSize, h = self.indicatorSize } + self.canvas:insertElement(self.indicatorAttributes) + end + + self.middleMouseDownEventTap:start() + self.middleMouseDraggedEventTap:start() + self.middleMouseUpEventTap:start() + return self +end + +function MiddleClickDragScroll:stop() + self.middleMouseDownEventTap:stop() + self.middleMouseDraggedEventTap:stop() + self.middleMouseUpEventTap:stop() + return self +end + +function MiddleClickDragScroll:isEnabled() + return self.middleMouseDownEventTap:isEnabled() +end + +return MiddleClickDragScroll diff --git a/Source/ModalMgr.spoon/docs.json b/Source/ModalMgr.spoon/docs.json index f6b505bb..b762d345 100644 --- a/Source/ModalMgr.spoon/docs.json +++ b/Source/ModalMgr.spoon/docs.json @@ -11,12 +11,17 @@ "def": "ModalMgr:activate(idList, [trayColor], [showKeys])", "desc": "Activate all modal environment in `idList`.", "doc": "Activate all modal environment in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments\n * trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to `nil`.\n * showKeys - A optional boolean value to show all available keybindings, defaults to `nil`.", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "174", "name": "activate", + "notes": [], "parameters": [ " * idList - An table specifying IDs of modal environments", " * trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to `nil`.", " * showKeys - A optional boolean value to show all available keybindings, defaults to `nil`." ], + "returns": [], "signature": "ModalMgr:activate(idList, [trayColor], [showKeys])", "stripped_doc": "", "type": "Method" @@ -25,10 +30,15 @@ "def": "ModalMgr:deactivate(idList)", "desc": "Deactivate modal environments in `idList`.", "doc": "Deactivate modal environments in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "205", "name": "deactivate", + "notes": [], "parameters": [ " * idList - An table specifying IDs of modal environments" ], + "returns": [], "signature": "ModalMgr:deactivate(idList)", "stripped_doc": "", "type": "Method" @@ -36,8 +46,16 @@ { "def": "ModalMgr:deactivateAll()", "desc": "Deactivate all active modal environments.", - "doc": "Deactivate all active modal environments.\n", + "doc": "Deactivate all active modal environments.\n\nParameters:\n * None", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "224", "name": "deactivateAll", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "ModalMgr:deactivateAll()", "stripped_doc": "", "type": "Method" @@ -46,10 +64,15 @@ "def": "ModalMgr:new(id)", "desc": "Create a new modal keybindings environment", "doc": "Create a new modal keybindings environment\n\nParameters:\n * id - A string specifying ID of new modal keybindings", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "57", "name": "new", + "notes": [], "parameters": [ " * id - A string specifying ID of new modal keybindings" ], + "returns": [], "signature": "ModalMgr:new(id)", "stripped_doc": "", "type": "Method" @@ -58,11 +81,16 @@ "def": "ModalMgr:toggleCheatsheet([idList], [force])", "desc": "Toggle the cheatsheet display of current modal environments's keybindings.", "doc": "Toggle the cheatsheet display of current modal environments's keybindings.\n\nParameters:\n * iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.\n * force - A optional boolean value to force show cheatsheet, defaults to `nil` (automatically).", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "126", "name": "toggleCheatsheet", + "notes": [], "parameters": [ " * iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.", " * force - A optional boolean value to force show cheatsheet, defaults to `nil` (automatically)." ], + "returns": [], "signature": "ModalMgr:toggleCheatsheet([idList], [force])", "stripped_doc": "", "type": "Method" @@ -76,12 +104,17 @@ "def": "ModalMgr:activate(idList, [trayColor], [showKeys])", "desc": "Activate all modal environment in `idList`.", "doc": "Activate all modal environment in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments\n * trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to `nil`.\n * showKeys - A optional boolean value to show all available keybindings, defaults to `nil`.", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "174", "name": "activate", + "notes": [], "parameters": [ " * idList - An table specifying IDs of modal environments", " * trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to `nil`.", " * showKeys - A optional boolean value to show all available keybindings, defaults to `nil`." ], + "returns": [], "signature": "ModalMgr:activate(idList, [trayColor], [showKeys])", "stripped_doc": "", "type": "Method" @@ -90,10 +123,15 @@ "def": "ModalMgr:deactivate(idList)", "desc": "Deactivate modal environments in `idList`.", "doc": "Deactivate modal environments in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "205", "name": "deactivate", + "notes": [], "parameters": [ " * idList - An table specifying IDs of modal environments" ], + "returns": [], "signature": "ModalMgr:deactivate(idList)", "stripped_doc": "", "type": "Method" @@ -101,8 +139,16 @@ { "def": "ModalMgr:deactivateAll()", "desc": "Deactivate all active modal environments.", - "doc": "Deactivate all active modal environments.\n", + "doc": "Deactivate all active modal environments.\n\nParameters:\n * None", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "224", "name": "deactivateAll", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "ModalMgr:deactivateAll()", "stripped_doc": "", "type": "Method" @@ -111,10 +157,15 @@ "def": "ModalMgr:new(id)", "desc": "Create a new modal keybindings environment", "doc": "Create a new modal keybindings environment\n\nParameters:\n * id - A string specifying ID of new modal keybindings", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "57", "name": "new", + "notes": [], "parameters": [ " * id - A string specifying ID of new modal keybindings" ], + "returns": [], "signature": "ModalMgr:new(id)", "stripped_doc": "", "type": "Method" @@ -123,11 +174,16 @@ "def": "ModalMgr:toggleCheatsheet([idList], [force])", "desc": "Toggle the cheatsheet display of current modal environments's keybindings.", "doc": "Toggle the cheatsheet display of current modal environments's keybindings.\n\nParameters:\n * iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.\n * force - A optional boolean value to force show cheatsheet, defaults to `nil` (automatically).", + "examples": [], + "file": "Source/ModalMgr.spoon//init.lua", + "lineno": "126", "name": "toggleCheatsheet", + "notes": [], "parameters": [ " * iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.", " * force - A optional boolean value to force show cheatsheet, defaults to `nil` (automatically)." ], + "returns": [], "signature": "ModalMgr:toggleCheatsheet([idList], [force])", "stripped_doc": "", "type": "Method" diff --git a/Source/ModalMgr.spoon/init.lua b/Source/ModalMgr.spoon/init.lua index 22916c1f..f62d4656 100644 --- a/Source/ModalMgr.spoon/init.lua +++ b/Source/ModalMgr.spoon/init.lua @@ -20,6 +20,17 @@ obj.modal_list = {} obj.active_list = {} obj.supervisor = nil +-- customize width and height of Cheatsheet +obj.width_factor = 0.30 +obj.height_factor = 0.30 +-- minimum sizes +obj.min_width = 200 +obj.min_height = 200 + +-- alighment for right column +obj.alignmentRightColumn = 'right' +obj.fillByRow = false + function obj:init() hsupervisor_keys = hsupervisor_keys or {{"cmd", "shift", "ctrl"}, "Q"} obj.supervisor = hs.hotkey.modal.new(hsupervisor_keys[1], hsupervisor_keys[2], 'Initialize Modal Environment') @@ -54,6 +65,64 @@ function obj:new(id) obj.modal_list[id] = hs.hotkey.modal.new() end + +-- this function draws the text on the window +-- +-- by default, it fills by row +-- but it can be customized to fill by column +function insertIntoSheet(position, st, row, column, n) + local textAlign = "left" + local xpos + local ypos + -- height available for one item, in percentage + -- add one for a small margin of at least 1/2 element at the bottom + local h = 100 / (math.ceil(n*1.0/2) + 1) + local w = "47%" + local xposLeft = "3%" + local xposRight = "50%" + if obj.fillByRow then + if position %2 == 1 then + xpos = xposLeft + ypos = tostring(math.floor(h * position / 2)) .. "%" + else + -- this one goes to the right + textAlign = obj.alignmentRigthColumn + xpos = xposRight + ypos = tostring(math.floor(h * (position-1) / 2)) .. "%" + end + else + local actualPos + if position > math.ceil(n / 2) then + -- this one goes to the right + textAlign = obj.alignmentRightColumn + xpos = xposRight + actualPos = position - math.ceil(n*1.0/2) + else + xpos = xposLeft + actualPos = position + end + ypos = tostring(math.floor(actualPos * h)) .. "%" + end + +-- print(ypos, n, h) + obj.which_key[position + 1] = { + type = "text", + text = st, + textFont = "Courier-Bold", + textSize = 16, + textColor = {hex = "#2390FF", alpha = 1}, + textAlignment = textAlign, + frame = { + x = xpos, + y = ypos, + -- w = tostring((1 - 80 / (cres.w / 5 * 3)) / 2), + w = w, + h = tostring(math.floor(h)) .. "%" + } + } + +end + --- ModalMgr:toggleCheatsheet([idList], [force]) --- Method --- Toggle the cheatsheet display of current modal environments's keybindings. @@ -68,11 +137,14 @@ function obj:toggleCheatsheet(iterList, force) else local cscreen = hs.screen.mainScreen() local cres = cscreen:fullFrame() + + local framew = math.max(math.floor(cres.w * obj.width_factor),obj.min_width) + local frameh = math.max(math.floor(cres.h * obj.height_factor), obj.min_height) obj.which_key:frame({ - x = cres.x + cres.w / 5, - y = cres.y + cres.h / 5, - w = cres.w / 5 * 3, - h = cres.h / 5 * 3 + w = framew, + h = frameh, + x = cres.x + (cres.w - framew) /2, + y = cres.y + (cres.h - frameh) /2 }) local keys_pool = {} local tmplist = iterList or obj.active_list @@ -89,38 +161,11 @@ function obj:toggleCheatsheet(iterList, force) end end end - for idx, val in ipairs(keys_pool) do - if idx % 2 == 1 then - obj.which_key[idx + 1] = { - type = "text", - text = keys_pool[idx], - textFont = "Courier-Bold", - textSize = 16, - textColor = {hex = "#2390FF", alpha = 1}, - textAlignment = "left", - frame = { - x = tostring(40 / (cres.w / 5 * 3)), - y = tostring((30 + (idx - math.ceil(idx / 2)) * math.ceil((cres.h / 5 * 3 - 60) / #keys_pool) * 2) / (cres.h / 5 * 3)), - w = tostring((1 - 80 / (cres.w / 5 * 3)) / 2), - h = tostring(math.ceil((cres.h / 5 * 3 - 60) / #keys_pool) * 2 / (cres.h / 5 * 3)) - } - } - else - obj.which_key[idx + 1] = { - type = "text", - text = keys_pool[idx], - textFont = "Courier-Bold", - textSize = 16, - textColor = {hex = "#2390FF"}, - textAlignment = "right", - frame = { - x = "50%", - y = tostring((30 + (idx - math.ceil(idx / 2) - 1) * math.ceil((cres.h / 5 * 3 - 60) / #keys_pool) * 2) / (cres.h / 5 * 3)), - w = tostring((1 - 80 / (cres.w / 5 * 3)) / 2), - h = tostring(math.ceil((cres.h / 5 * 3 - 60) / #keys_pool) * 2 / (cres.h / 5 * 3)) - } - } - end + -- if obj.orderByColumn then + if true then + for idx, val in ipairs(keys_pool) do + insertIntoSheet(idx,val, idx, 0, #keys_pool) + end end obj.which_key:show() end diff --git a/Source/MouseFollowsFocus.spoon/docs.json b/Source/MouseFollowsFocus.spoon/docs.json index 17cb2c98..bdb2f014 100644 --- a/Source/MouseFollowsFocus.spoon/docs.json +++ b/Source/MouseFollowsFocus.spoon/docs.json @@ -9,12 +9,17 @@ "Method": [ { "def": "MouseFollowsFocus:configure(configuration)", - "desc": "Configures the spoon. There is currently nothing to configure.", - "doc": "Configures the spoon. There is currently nothing to configure.\n\nParameters:\n * configuration - :", + "desc": "Configures the spoon.", + "doc": "Configures the spoon.\n\nParameters:\n * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "29", "name": "configure", + "notes": [], "parameters": [ - " * configuration - :" + " * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:" ], + "returns": [], "signature": "MouseFollowsFocus:configure(configuration)", "stripped_doc": "", "type": "Method" @@ -22,9 +27,16 @@ { "def": "MouseFollowsFocus:start()", "desc": "Starts updating the mouse position when window focus changes", - "doc": "Starts updating the mouse position when window focus changes\n\nParameters:", + "doc": "Starts updating the mouse position when window focus changes\n\nParameters:\n * None", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "44", "name": "start", - "parameters": [], + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "MouseFollowsFocus:start()", "stripped_doc": "", "type": "Method" @@ -32,9 +44,16 @@ { "def": "MouseFollowsFocus:stop()", "desc": "Stops updating the mouse position when window focus changes", - "doc": "Stops updating the mouse position when window focus changes\n\nParameters:", + "doc": "Stops updating the mouse position when window focus changes\n\nParameters:\n * None", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "73", "name": "stop", - "parameters": [], + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "MouseFollowsFocus:stop()", "stripped_doc": "", "type": "Method" @@ -42,8 +61,16 @@ { "def": "MouseFollowsFocus:updateMouse(window)", "desc": "Moves the mouse to the center of the given window unless it's already inside the window", - "doc": "Moves the mouse to the center of the given window unless it's already inside the window", + "doc": "Moves the mouse to the center of the given window unless it's already inside the window\n\nParameters:\n * None", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "84", "name": "updateMouse", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "MouseFollowsFocus:updateMouse(window)", "stripped_doc": "", "type": "Method" @@ -54,6 +81,8 @@ "def": "MouseFollowsFocus.logger", "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "24", "name": "logger", "signature": "MouseFollowsFocus.logger", "stripped_doc": "", @@ -61,16 +90,21 @@ } ], "desc": "Set the mouse pointer to the center of the focused window whenever focus changes.", - "doc": "Set the mouse pointer to the center of the focused window whenever focus changes.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip)", + "doc": "Set the mouse pointer to the center of the focused window whenever focus changes.\n\nAdditionally, if focused window moves when no mouse buttons are pressed, set the\nmouse pointer to the new center. This is intended to work with other utilities\nwhich warp the focused window.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip)", "items": [ { "def": "MouseFollowsFocus:configure(configuration)", - "desc": "Configures the spoon. There is currently nothing to configure.", - "doc": "Configures the spoon. There is currently nothing to configure.\n\nParameters:\n * configuration - :", + "desc": "Configures the spoon.", + "doc": "Configures the spoon.\n\nParameters:\n * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "29", "name": "configure", + "notes": [], "parameters": [ - " * configuration - :" + " * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:" ], + "returns": [], "signature": "MouseFollowsFocus:configure(configuration)", "stripped_doc": "", "type": "Method" @@ -79,6 +113,8 @@ "def": "MouseFollowsFocus.logger", "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "24", "name": "logger", "signature": "MouseFollowsFocus.logger", "stripped_doc": "", @@ -87,9 +123,16 @@ { "def": "MouseFollowsFocus:start()", "desc": "Starts updating the mouse position when window focus changes", - "doc": "Starts updating the mouse position when window focus changes\n\nParameters:", + "doc": "Starts updating the mouse position when window focus changes\n\nParameters:\n * None", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "44", "name": "start", - "parameters": [], + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "MouseFollowsFocus:start()", "stripped_doc": "", "type": "Method" @@ -97,9 +140,16 @@ { "def": "MouseFollowsFocus:stop()", "desc": "Stops updating the mouse position when window focus changes", - "doc": "Stops updating the mouse position when window focus changes\n\nParameters:", + "doc": "Stops updating the mouse position when window focus changes\n\nParameters:\n * None", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "73", "name": "stop", - "parameters": [], + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "MouseFollowsFocus:stop()", "stripped_doc": "", "type": "Method" @@ -107,15 +157,23 @@ { "def": "MouseFollowsFocus:updateMouse(window)", "desc": "Moves the mouse to the center of the given window unless it's already inside the window", - "doc": "Moves the mouse to the center of the given window unless it's already inside the window", + "doc": "Moves the mouse to the center of the given window unless it's already inside the window\n\nParameters:\n * None", + "examples": [], + "file": "Source/MouseFollowsFocus.spoon//init.lua", + "lineno": "84", "name": "updateMouse", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], "signature": "MouseFollowsFocus:updateMouse(window)", "stripped_doc": "", "type": "Method" } ], "name": "MouseFollowsFocus", - "stripped_doc": "\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip)", + "stripped_doc": "\nAdditionally, if focused window moves when no mouse buttons are pressed, set the\nmouse pointer to the new center. This is intended to work with other utilities\nwhich warp the focused window.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MouseFollowsFocus.spoon.zip)", "submodules": [], "type": "Module" } diff --git a/Source/MouseFollowsFocus.spoon/init.lua b/Source/MouseFollowsFocus.spoon/init.lua index 854c441e..a6646483 100644 --- a/Source/MouseFollowsFocus.spoon/init.lua +++ b/Source/MouseFollowsFocus.spoon/init.lua @@ -17,6 +17,9 @@ obj.version = "0.1" obj.author = "Jason Felice " obj.homepage = "https://github.com/Hammerspoon/Spoons" obj.license = "MIT - https://opensource.org/licenses/MIT" +obj.onChangeOfScreenOnly = false +obj.onWindowMoved = false +obj.currentWindowScreen = nil --- MouseFollowsFocus.logger --- Variable @@ -25,11 +28,17 @@ obj.logger = hs.logger.new('MouseFollowsFocus') --- MouseFollowsFocus:configure(configuration) --- Method ---- Configures the spoon. There is currently nothing to configure. +--- Configures the spoon. --- --- Parameters: ---- * configuration - : +--- * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly: function obj:configure(configuration) + if configuration['onChangeOfScreenOnly'] then + self.onChangeOfScreenOnly = configuration['onChangeOfScreenOnly'] + end + if configuration['onWindowMoved'] then + self.onWindowMoved = configuration['onWindowMoved'] + end end --- MouseFollowsFocus:start() @@ -46,12 +55,15 @@ function obj:start() }) self.window_filter:subscribe({ hs.window.filter.windowFocused - }, function(window) - self:updateMouse(window) + }, function(window) + if self.onChangeOfScreenOnly and self.currentWindowScreen and self.currentWindowScreen:id() == window:screen():id() then return end + self:updateMouse(window) + self.currentWindowScreen = window:screen() end) self.window_filter:subscribe({ hs.window.filter.windowMoved }, function(window) + if not self.onWindowMoved then return end if window ~= hs.window.focusedWindow() then return end if #hs.mouse.getButtons() ~= 0 then return end self:updateMouse(window) diff --git a/Source/PaperWM.spoon/docs.json b/Source/PaperWM.spoon/docs.json new file mode 100644 index 00000000..bf217ce8 --- /dev/null +++ b/Source/PaperWM.spoon/docs.json @@ -0,0 +1,778 @@ +[ + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "PaperWM:addWindow(add_window)", + "desc": "Adds a window to layout and tiles.", + "doc": "Adds a window to layout and tiles.\n\nParameters:\n * add_window - An hs.window\n\nReturns:\n * The hs.spaces space for added window or nil if window not added.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "594", + "name": "addWindow", + "notes": [], + "parameters": [ + " * add_window - An hs.window" + ], + "returns": [ + " * The hs.spaces space for added window or nil if window not added." + ], + "signature": "PaperWM:addWindow(add_window)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:barfWindow()", + "desc": "Removes current window from column and places it to the right", + "doc": "Removes current window from column and places it to the right\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1026", + "name": "barfWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:barfWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.bindHotkeys(mapping)", + "desc": "Binds hotkeys for PaperWM", + "doc": "Binds hotkeys for PaperWM\n\nParameters:\n * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "275", + "name": "bindHotkeys", + "notes": [], + "parameters": [ + " * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9" + ], + "returns": [], + "signature": "PaperWM.bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:centerWindow()", + "desc": "Moves current window to center of screen, without resizing.", + "doc": "Moves current window to center of screen, without resizing.\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "860", + "name": "centerWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:centerWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:cycleWindowSize(direction)", + "desc": "Resizes current window by cycling through width or height ratios.", + "doc": "Resizes current window by cycling through width or height ratios.\n\nParameters:\n * direction - One of Direction { WIDTH, HEIGHT }", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "907", + "name": "cycleWindowSize", + "notes": [], + "parameters": [ + " * direction - One of Direction { WIDTH, HEIGHT }" + ], + "returns": [], + "signature": "PaperWM:cycleWindowSize(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:focusWindow(direction, focused_index)", + "desc": "Change focus to a nearby window", + "doc": "Change focus to a nearby window\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }\n * focused_index - The coordinates of the current window in the tiling layout\n\nReturns:\n * A boolean. True if a new window was focused. False if no nearby window\n was found in that direction.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "699", + "name": "focusWindow", + "notes": [], + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + " * focused_index - The coordinates of the current window in the tiling layout" + ], + "returns": [ + " * A boolean. True if a new window was focused. False if no nearby window", + " was found in that direction." + ], + "signature": "PaperWM:focusWindow(direction, focused_index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM::moveWindow(window, frame)", + "desc": "Resizes a window without triggering a windowMoved event", + "doc": "Resizes a window without triggering a windowMoved event\n\nParameters:\n * window - An hs.window\n * frame - An hs.geometry.rect for the windows new frame size.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1147", + "name": "moveWindow", + "notes": [], + "parameters": [ + " * window - An hs.window", + " * frame - An hs.geometry.rect for the windows new frame size." + ], + "returns": [], + "signature": "PaperWM::moveWindow(window, frame)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:moveWindowToSpace(index)", + "desc": "Moves the current window to a new Mission Control space", + "doc": "Moves the current window to a new Mission Control space\n\nParameters:\n * index - The space number", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1096", + "name": "moveWindowToSpace", + "notes": [], + "parameters": [ + " * index - The space number" + ], + "returns": [], + "signature": "PaperWM:moveWindowToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:refreshWindows()", + "desc": "Searches for all windows that match window filter.", + "doc": "Searches for all windows that match window filter.\n\nParameters:\n * None\n\nReturns:\n * A boolean, true if the layout needs to be re-tiled, false if no change.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "563", + "name": "refreshWindows", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * A boolean, true if the layout needs to be re-tiled, false if no change." + ], + "signature": "PaperWM:refreshWindows()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "desc": "Remove window from tiling layout", + "doc": "Remove window from tiling layout\n\nParameters:\n * remove_window - A hs.window to remove from tiling layout\n * skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.\n\nReturns:\n * The hs.spaces space for removed window.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "652", + "name": "remove_window", + "notes": [], + "parameters": [ + " * remove_window - A hs.window to remove from tiling layout", + " * skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed." + ], + "returns": [ + " * The hs.spaces space for removed window." + ], + "signature": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:setWindowFullWidth()", + "desc": "Resizes current window's width to width of screen, without adjusting height.", + "doc": "Resizes current window's width to width of screen, without adjusting height.\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "885", + "name": "setWindowFullWidth", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:setWindowFullWidth()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:slurpWindow()", + "desc": "Moves current window into column of windows to the left", + "doc": "Moves current window into column of windows to the left\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "961", + "name": "slurpWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:slurpWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:start()", + "desc": "Start automatic tiling of windows", + "doc": "Start automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "354", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The PaperWM object" + ], + "signature": "PaperWM:start()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:stop()", + "desc": "Stop automatic tiling of windows", + "doc": "Stop automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "391", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The PaperWM object" + ], + "signature": "PaperWM:stop()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:swapWindows(direction)", + "desc": "Swaps window postions between current window and window in specified direction.", + "doc": "Swaps window postions between current window and window in specified direction.\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "749", + "name": "swapWindows", + "notes": [], + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }" + ], + "returns": [], + "signature": "PaperWM:swapWindows(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:switchToSpace(index)", + "desc": "Switch to a Mission Control space", + "doc": "Switch to a Mission Control space\n\nParameters:\n * index - The space number", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1080", + "name": "switchToSpace", + "notes": [], + "parameters": [ + " * index - The space number" + ], + "returns": [], + "signature": "PaperWM:switchToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "desc": "Tile a column of windows", + "doc": "Tile a column of windows\n\nParameters:\n * windows - A list of hs.windows.\n * bounds - An hs.geometry.rect. The area for this column to fill.\n * h - The height for each window in column.\n * w - The width for each window in column.\n * id - A hs.window.id() for a specific window in column.\n * h4id - The height for a window matching id in column.\n\nNotes:\n * The h, w, id, and h4id parameters are optional. The height and width of\n all windows will be calculated and set to fill column bounds.\n * If bounds width is not specified, all windows in column will be resized\n to width of first window.\n\nReturns:\n * The width of the column", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "408", + "name": "tileColumn", + "notes": [ + " * The h, w, id, and h4id parameters are optional. The height and width of", + " all windows will be calculated and set to fill column bounds.", + " * If bounds width is not specified, all windows in column will be resized", + " to width of first window." + ], + "parameters": [ + " * windows - A list of hs.windows.", + " * bounds - An hs.geometry.rect. The area for this column to fill.", + " * h - The height for each window in column.", + " * w - The width for each window in column.", + " * id - A hs.window.id() for a specific window in column.", + " * h4id - The height for a window matching id in column." + ], + "returns": [ + " * The width of the column" + ], + "signature": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileSpace(space)", + "desc": "Tile all windows within a space", + "doc": "Tile all windows within a space\n\nParameters:\n * space - A hs.spaces space.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "460", + "name": "tileSpace", + "notes": [], + "parameters": [ + " * space - A hs.spaces space." + ], + "returns": [], + "signature": "PaperWM:tileSpace(space)", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ + { + "def": "PaperWM.default_hotkeys", + "desc": "Default hotkeys for moving / resizing windows", + "doc": "Default hotkeys for moving / resizing windows", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "111", + "name": "default_hotkeys", + "signature": "PaperWM.default_hotkeys", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.logger", + "desc": "Logger object. Can be accessed to set default log level.", + "doc": "Logger object. Can be accessed to set default log level.", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "165", + "name": "logger", + "signature": "PaperWM.logger", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_filter", + "desc": "Windows captured by this filter are automatically tiled and managed", + "doc": "Windows captured by this filter are automatically tiled and managed", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "150", + "name": "window_filter", + "signature": "PaperWM.window_filter", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_gap", + "desc": "Number of pixels between tiled windows", + "doc": "Number of pixels between tiled windows", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "160", + "name": "window_gap", + "signature": "PaperWM.window_gap", + "stripped_doc": "", + "type": "Variable" + } + ], + "desc": "A scrolling window manager. Inspired by PaperWM Gnome extension.", + "doc": "A scrolling window manager. Inspired by PaperWM Gnome extension.\n\n# Usage\n\n`PaperWM:start()` will begin automatically tiling new and existing windows.\n`PaperWM:stop()` will release control over windows.\n`PaperWM::bindHotkeys()` will move / resize windows using keyboard shortcuts.\n\nHere is an example Hammerspoon config:\n\n```\nPaperWM = hs.loadSpoon(\"PaperWM\")\nPaperWM:bindHotkeys({\n -- switch to a new focused window in tiled grid\n focus_left = {{\"ctrl\", \"alt\", \"cmd\"}, \"left\"},\n focus_right = {{\"ctrl\", \"alt\", \"cmd\"}, \"right\"},\n focus_up = {{\"ctrl\", \"alt\", \"cmd\"}, \"up\"},\n focus_down = {{\"ctrl\", \"alt\", \"cmd\"}, \"down\"},\n\n -- move windows around in tiled grid\n swap_left = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"left\"},\n swap_right = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"right\"},\n swap_up = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"up\"},\n swap_down = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"down\"},\n\n -- position and resize focused window\n center_window = {{\"ctrl\", \"alt\", \"cmd\"}, \"c\"},\n full_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"f\"},\n cycle_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"r\"},\n cycle_height = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"r\"},\n\n -- move focused window into / out of a column\n slurp_in = {{\"ctrl\", \"alt\", \"cmd\"}, \"i\"},\n barf_out = {{\"ctrl\", \"alt\", \"cmd\"}, \"o\"},\n\n -- switch to a new Mission Control space\n switch_space_1 = {{\"ctrl\", \"alt\", \"cmd\"}, \"1\"},\n switch_space_2 = {{\"ctrl\", \"alt\", \"cmd\"}, \"2\"},\n switch_space_3 = {{\"ctrl\", \"alt\", \"cmd\"}, \"3\"},\n switch_space_4 = {{\"ctrl\", \"alt\", \"cmd\"}, \"4\"},\n switch_space_5 = {{\"ctrl\", \"alt\", \"cmd\"}, \"5\"},\n switch_space_6 = {{\"ctrl\", \"alt\", \"cmd\"}, \"6\"},\n switch_space_7 = {{\"ctrl\", \"alt\", \"cmd\"}, \"7\"},\n switch_space_8 = {{\"ctrl\", \"alt\", \"cmd\"}, \"8\"},\n switch_space_9 = {{\"ctrl\", \"alt\", \"cmd\"}, \"9\"},\n\n -- move focused window to a new space and tile\n move_window_1 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"1\"},\n move_window_2 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"2\"},\n move_window_3 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"3\"},\n move_window_4 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"4\"},\n move_window_5 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"5\"},\n move_window_6 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"6\"},\n move_window_7 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"7\"},\n move_window_8 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"8\"},\n move_window_9 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"9\"}\n})\nPaperWM:start()\n```\n\nUse `PaperWM:bindHotkeys(PaperWM.default_hotkeys)` for defaults.\n\nSet `PaperWM.window_gap` to the number of pixels to space between windows and\nthe top and bottom screen edges.\n\nOverwrite `PaperWM.window_filter` to ignore specific applications. For example:\n\n```\nPaperWM.window_filter = PaperWM.window_filter:setAppFilter(\"Finder\", false)\nPaperWM:start() -- restart for new window filter to take effect\n```\n\n# Limitations\n\nUnder System Preferences -> Mission Control, unselect \"Automatically\nrearrange Spaces based on most recent use\" and select \"Displays have separate\nSpaces\".\n\nMacOS does not allow a window to be moved fully off-screen. Windows that would\nbe tiled off-screen are placed in a margin on the left and right edge of the\nscreen. They are still visible and clickable.\n\nIt's difficult to detect when a window is dragged from one space or screen to\nanother. Use the move_window_N commands to move windows between spaces and\nscreens.\n\nArrange screens vertically to prevent windows from bleeding into other screens.\n\n\nDownload: [https://github.com/mogenson/PaperWM.spoon](https://github.com/mogenson/PaperWM.spoon)", + "items": [ + { + "def": "PaperWM:addWindow(add_window)", + "desc": "Adds a window to layout and tiles.", + "doc": "Adds a window to layout and tiles.\n\nParameters:\n * add_window - An hs.window\n\nReturns:\n * The hs.spaces space for added window or nil if window not added.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "594", + "name": "addWindow", + "notes": [], + "parameters": [ + " * add_window - An hs.window" + ], + "returns": [ + " * The hs.spaces space for added window or nil if window not added." + ], + "signature": "PaperWM:addWindow(add_window)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:barfWindow()", + "desc": "Removes current window from column and places it to the right", + "doc": "Removes current window from column and places it to the right\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1026", + "name": "barfWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:barfWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.bindHotkeys(mapping)", + "desc": "Binds hotkeys for PaperWM", + "doc": "Binds hotkeys for PaperWM\n\nParameters:\n * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "275", + "name": "bindHotkeys", + "notes": [], + "parameters": [ + " * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9" + ], + "returns": [], + "signature": "PaperWM.bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:centerWindow()", + "desc": "Moves current window to center of screen, without resizing.", + "doc": "Moves current window to center of screen, without resizing.\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "860", + "name": "centerWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:centerWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:cycleWindowSize(direction)", + "desc": "Resizes current window by cycling through width or height ratios.", + "doc": "Resizes current window by cycling through width or height ratios.\n\nParameters:\n * direction - One of Direction { WIDTH, HEIGHT }", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "907", + "name": "cycleWindowSize", + "notes": [], + "parameters": [ + " * direction - One of Direction { WIDTH, HEIGHT }" + ], + "returns": [], + "signature": "PaperWM:cycleWindowSize(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.default_hotkeys", + "desc": "Default hotkeys for moving / resizing windows", + "doc": "Default hotkeys for moving / resizing windows", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "111", + "name": "default_hotkeys", + "signature": "PaperWM.default_hotkeys", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM:focusWindow(direction, focused_index)", + "desc": "Change focus to a nearby window", + "doc": "Change focus to a nearby window\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }\n * focused_index - The coordinates of the current window in the tiling layout\n\nReturns:\n * A boolean. True if a new window was focused. False if no nearby window\n was found in that direction.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "699", + "name": "focusWindow", + "notes": [], + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + " * focused_index - The coordinates of the current window in the tiling layout" + ], + "returns": [ + " * A boolean. True if a new window was focused. False if no nearby window", + " was found in that direction." + ], + "signature": "PaperWM:focusWindow(direction, focused_index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.logger", + "desc": "Logger object. Can be accessed to set default log level.", + "doc": "Logger object. Can be accessed to set default log level.", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "165", + "name": "logger", + "signature": "PaperWM.logger", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM::moveWindow(window, frame)", + "desc": "Resizes a window without triggering a windowMoved event", + "doc": "Resizes a window without triggering a windowMoved event\n\nParameters:\n * window - An hs.window\n * frame - An hs.geometry.rect for the windows new frame size.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1147", + "name": "moveWindow", + "notes": [], + "parameters": [ + " * window - An hs.window", + " * frame - An hs.geometry.rect for the windows new frame size." + ], + "returns": [], + "signature": "PaperWM::moveWindow(window, frame)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:moveWindowToSpace(index)", + "desc": "Moves the current window to a new Mission Control space", + "doc": "Moves the current window to a new Mission Control space\n\nParameters:\n * index - The space number", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1096", + "name": "moveWindowToSpace", + "notes": [], + "parameters": [ + " * index - The space number" + ], + "returns": [], + "signature": "PaperWM:moveWindowToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:refreshWindows()", + "desc": "Searches for all windows that match window filter.", + "doc": "Searches for all windows that match window filter.\n\nParameters:\n * None\n\nReturns:\n * A boolean, true if the layout needs to be re-tiled, false if no change.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "563", + "name": "refreshWindows", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * A boolean, true if the layout needs to be re-tiled, false if no change." + ], + "signature": "PaperWM:refreshWindows()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "desc": "Remove window from tiling layout", + "doc": "Remove window from tiling layout\n\nParameters:\n * remove_window - A hs.window to remove from tiling layout\n * skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.\n\nReturns:\n * The hs.spaces space for removed window.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "652", + "name": "remove_window", + "notes": [], + "parameters": [ + " * remove_window - A hs.window to remove from tiling layout", + " * skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed." + ], + "returns": [ + " * The hs.spaces space for removed window." + ], + "signature": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:setWindowFullWidth()", + "desc": "Resizes current window's width to width of screen, without adjusting height.", + "doc": "Resizes current window's width to width of screen, without adjusting height.\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "885", + "name": "setWindowFullWidth", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:setWindowFullWidth()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:slurpWindow()", + "desc": "Moves current window into column of windows to the left", + "doc": "Moves current window into column of windows to the left\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "961", + "name": "slurpWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:slurpWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:start()", + "desc": "Start automatic tiling of windows", + "doc": "Start automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "354", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The PaperWM object" + ], + "signature": "PaperWM:start()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:stop()", + "desc": "Stop automatic tiling of windows", + "doc": "Stop automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "391", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The PaperWM object" + ], + "signature": "PaperWM:stop()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:swapWindows(direction)", + "desc": "Swaps window postions between current window and window in specified direction.", + "doc": "Swaps window postions between current window and window in specified direction.\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "749", + "name": "swapWindows", + "notes": [], + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }" + ], + "returns": [], + "signature": "PaperWM:swapWindows(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:switchToSpace(index)", + "desc": "Switch to a Mission Control space", + "doc": "Switch to a Mission Control space\n\nParameters:\n * index - The space number", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "1080", + "name": "switchToSpace", + "notes": [], + "parameters": [ + " * index - The space number" + ], + "returns": [], + "signature": "PaperWM:switchToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "desc": "Tile a column of windows", + "doc": "Tile a column of windows\n\nParameters:\n * windows - A list of hs.windows.\n * bounds - An hs.geometry.rect. The area for this column to fill.\n * h - The height for each window in column.\n * w - The width for each window in column.\n * id - A hs.window.id() for a specific window in column.\n * h4id - The height for a window matching id in column.\n\nNotes:\n * The h, w, id, and h4id parameters are optional. The height and width of\n all windows will be calculated and set to fill column bounds.\n * If bounds width is not specified, all windows in column will be resized\n to width of first window.\n\nReturns:\n * The width of the column", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "408", + "name": "tileColumn", + "notes": [ + " * The h, w, id, and h4id parameters are optional. The height and width of", + " all windows will be calculated and set to fill column bounds.", + " * If bounds width is not specified, all windows in column will be resized", + " to width of first window." + ], + "parameters": [ + " * windows - A list of hs.windows.", + " * bounds - An hs.geometry.rect. The area for this column to fill.", + " * h - The height for each window in column.", + " * w - The width for each window in column.", + " * id - A hs.window.id() for a specific window in column.", + " * h4id - The height for a window matching id in column." + ], + "returns": [ + " * The width of the column" + ], + "signature": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileSpace(space)", + "desc": "Tile all windows within a space", + "doc": "Tile all windows within a space\n\nParameters:\n * space - A hs.spaces space.", + "examples": [], + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "460", + "name": "tileSpace", + "notes": [], + "parameters": [ + " * space - A hs.spaces space." + ], + "returns": [], + "signature": "PaperWM:tileSpace(space)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.window_filter", + "desc": "Windows captured by this filter are automatically tiled and managed", + "doc": "Windows captured by this filter are automatically tiled and managed", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "150", + "name": "window_filter", + "signature": "PaperWM.window_filter", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_gap", + "desc": "Number of pixels between tiled windows", + "doc": "Number of pixels between tiled windows", + "file": "Source/PaperWM.spoon//init.lua", + "lineno": "160", + "name": "window_gap", + "signature": "PaperWM.window_gap", + "stripped_doc": "", + "type": "Variable" + } + ], + "name": "PaperWM", + "stripped_doc": "\n# Usage\n\n`PaperWM:start()` will begin automatically tiling new and existing windows.\n`PaperWM:stop()` will release control over windows.\n`PaperWM::bindHotkeys()` will move / resize windows using keyboard shortcuts.\n\nHere is an example Hammerspoon config:\n\n```\nPaperWM = hs.loadSpoon(\"PaperWM\")\nPaperWM:bindHotkeys({\n -- switch to a new focused window in tiled grid\n focus_left = {{\"ctrl\", \"alt\", \"cmd\"}, \"left\"},\n focus_right = {{\"ctrl\", \"alt\", \"cmd\"}, \"right\"},\n focus_up = {{\"ctrl\", \"alt\", \"cmd\"}, \"up\"},\n focus_down = {{\"ctrl\", \"alt\", \"cmd\"}, \"down\"},\n\n -- move windows around in tiled grid\n swap_left = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"left\"},\n swap_right = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"right\"},\n swap_up = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"up\"},\n swap_down = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"down\"},\n\n -- position and resize focused window\n center_window = {{\"ctrl\", \"alt\", \"cmd\"}, \"c\"},\n full_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"f\"},\n cycle_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"r\"},\n cycle_height = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"r\"},\n\n -- move focused window into / out of a column\n slurp_in = {{\"ctrl\", \"alt\", \"cmd\"}, \"i\"},\n barf_out = {{\"ctrl\", \"alt\", \"cmd\"}, \"o\"},\n\n -- switch to a new Mission Control space\n switch_space_1 = {{\"ctrl\", \"alt\", \"cmd\"}, \"1\"},\n switch_space_2 = {{\"ctrl\", \"alt\", \"cmd\"}, \"2\"},\n switch_space_3 = {{\"ctrl\", \"alt\", \"cmd\"}, \"3\"},\n switch_space_4 = {{\"ctrl\", \"alt\", \"cmd\"}, \"4\"},\n switch_space_5 = {{\"ctrl\", \"alt\", \"cmd\"}, \"5\"},\n switch_space_6 = {{\"ctrl\", \"alt\", \"cmd\"}, \"6\"},\n switch_space_7 = {{\"ctrl\", \"alt\", \"cmd\"}, \"7\"},\n switch_space_8 = {{\"ctrl\", \"alt\", \"cmd\"}, \"8\"},\n switch_space_9 = {{\"ctrl\", \"alt\", \"cmd\"}, \"9\"},\n\n -- move focused window to a new space and tile\n move_window_1 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"1\"},\n move_window_2 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"2\"},\n move_window_3 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"3\"},\n move_window_4 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"4\"},\n move_window_5 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"5\"},\n move_window_6 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"6\"},\n move_window_7 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"7\"},\n move_window_8 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"8\"},\n move_window_9 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"9\"}\n})\nPaperWM:start()\n```\n\nUse `PaperWM:bindHotkeys(PaperWM.default_hotkeys)` for defaults.\n\nSet `PaperWM.window_gap` to the number of pixels to space between windows and\nthe top and bottom screen edges.\n\nOverwrite `PaperWM.window_filter` to ignore specific applications. For example:\n\n```\nPaperWM.window_filter = PaperWM.window_filter:setAppFilter(\"Finder\", false)\nPaperWM:start() -- restart for new window filter to take effect\n```\n\n# Limitations\n\nUnder System Preferences -> Mission Control, unselect \"Automatically\nrearrange Spaces based on most recent use\" and select \"Displays have separate\nSpaces\".\n\nMacOS does not allow a window to be moved fully off-screen. Windows that would\nbe tiled off-screen are placed in a margin on the left and right edge of the\nscreen. They are still visible and clickable.\n\nIt's difficult to detect when a window is dragged from one space or screen to\nanother. Use the move_window_N commands to move windows between spaces and\nscreens.\n\nArrange screens vertically to prevent windows from bleeding into other screens.\n\n\nDownload: [https://github.com/mogenson/PaperWM.spoon](https://github.com/mogenson/PaperWM.spoon)", + "submodules": [], + "type": "Module" + } +] \ No newline at end of file diff --git a/Source/PaperWM.spoon/init.lua b/Source/PaperWM.spoon/init.lua new file mode 100644 index 00000000..819b9be2 --- /dev/null +++ b/Source/PaperWM.spoon/init.lua @@ -0,0 +1,1176 @@ +--- === PaperWM === +--- +--- A scrolling window manager. Inspired by PaperWM Gnome extension. +--- +--- # Usage +--- +--- `PaperWM:start()` will begin automatically tiling new and existing windows. +--- `PaperWM:stop()` will release control over windows. +--- `PaperWM::bindHotkeys()` will move / resize windows using keyboard shortcuts. +--- +--- Here is an example Hammerspoon config: +--- +--- ``` +--- PaperWM = hs.loadSpoon("PaperWM") +--- PaperWM:bindHotkeys({ +--- -- switch to a new focused window in tiled grid +--- focus_left = {{"ctrl", "alt", "cmd"}, "left"}, +--- focus_right = {{"ctrl", "alt", "cmd"}, "right"}, +--- focus_up = {{"ctrl", "alt", "cmd"}, "up"}, +--- focus_down = {{"ctrl", "alt", "cmd"}, "down"}, +--- +--- -- move windows around in tiled grid +--- swap_left = {{"ctrl", "alt", "cmd", "shift"}, "left"}, +--- swap_right = {{"ctrl", "alt", "cmd", "shift"}, "right"}, +--- swap_up = {{"ctrl", "alt", "cmd", "shift"}, "up"}, +--- swap_down = {{"ctrl", "alt", "cmd", "shift"}, "down"}, +--- +--- -- position and resize focused window +--- center_window = {{"ctrl", "alt", "cmd"}, "c"}, +--- full_width = {{"ctrl", "alt", "cmd"}, "f"}, +--- cycle_width = {{"ctrl", "alt", "cmd"}, "r"}, +--- cycle_height = {{"ctrl", "alt", "cmd", "shift"}, "r"}, +--- +--- -- move focused window into / out of a column +--- slurp_in = {{"ctrl", "alt", "cmd"}, "i"}, +--- barf_out = {{"ctrl", "alt", "cmd"}, "o"}, +--- +--- -- switch to a new Mission Control space +--- switch_space_1 = {{"ctrl", "alt", "cmd"}, "1"}, +--- switch_space_2 = {{"ctrl", "alt", "cmd"}, "2"}, +--- switch_space_3 = {{"ctrl", "alt", "cmd"}, "3"}, +--- switch_space_4 = {{"ctrl", "alt", "cmd"}, "4"}, +--- switch_space_5 = {{"ctrl", "alt", "cmd"}, "5"}, +--- switch_space_6 = {{"ctrl", "alt", "cmd"}, "6"}, +--- switch_space_7 = {{"ctrl", "alt", "cmd"}, "7"}, +--- switch_space_8 = {{"ctrl", "alt", "cmd"}, "8"}, +--- switch_space_9 = {{"ctrl", "alt", "cmd"}, "9"}, +--- +--- -- move focused window to a new space and tile +--- move_window_1 = {{"ctrl", "alt", "cmd", "shift"}, "1"}, +--- move_window_2 = {{"ctrl", "alt", "cmd", "shift"}, "2"}, +--- move_window_3 = {{"ctrl", "alt", "cmd", "shift"}, "3"}, +--- move_window_4 = {{"ctrl", "alt", "cmd", "shift"}, "4"}, +--- move_window_5 = {{"ctrl", "alt", "cmd", "shift"}, "5"}, +--- move_window_6 = {{"ctrl", "alt", "cmd", "shift"}, "6"}, +--- move_window_7 = {{"ctrl", "alt", "cmd", "shift"}, "7"}, +--- move_window_8 = {{"ctrl", "alt", "cmd", "shift"}, "8"}, +--- move_window_9 = {{"ctrl", "alt", "cmd", "shift"}, "9"} +--- }) +--- PaperWM:start() +--- ``` +--- +--- Use `PaperWM:bindHotkeys(PaperWM.default_hotkeys)` for defaults. +--- +--- Set `PaperWM.window_gap` to the number of pixels to space between windows and +--- the top and bottom screen edges. +--- +--- Overwrite `PaperWM.window_filter` to ignore specific applications. For example: +--- +--- ``` +--- PaperWM.window_filter = PaperWM.window_filter:setAppFilter("Finder", false) +--- PaperWM:start() -- restart for new window filter to take effect +--- ``` +--- +--- # Limitations +--- +--- Under System Preferences -> Mission Control, unselect "Automatically +--- rearrange Spaces based on most recent use" and select "Displays have separate +--- Spaces". +--- +--- MacOS does not allow a window to be moved fully off-screen. Windows that would-- +--- be tiled off-screen are placed in a margin on the left and right edge of the +--- screen. They are still visible and clickable. +--- +--- It's difficult to detect when a window is dragged from one space or screen to +--- another. Use the move_window_N commands to move windows between spaces and +--- screens. +--- +--- Arrange screens vertically to prevent windows from bleeding into other screens. +--- +--- +--- Download: [https://github.com/mogenson/PaperWM.spoon](https://github.com/mogenson/PaperWM.spoon) +local WindowFilter = hs.window.filter +local Window = hs.window +local Spaces = hs.spaces +local Screen = hs.screen +local DoAfter = hs.timer.doAfter +local Rect = hs.geometry.rect +local Watcher = hs.uielement.watcher + +local PaperWM = {} +PaperWM.__index = PaperWM + +-- Metadata +PaperWM.name = "PaperWM" +PaperWM.version = "0.4" +PaperWM.author = "Michael Mogenson" +PaperWM.homepage = "https://github.com/mogenson/PaperWM.spoon" +PaperWM.license = "MIT - https://opensource.org/licenses/MIT" + +--- PaperWM.default_hotkeys +--- Variable +--- Default hotkeys for moving / resizing windows +PaperWM.default_hotkeys = { + stop_events = { { "ctrl", "alt", "cmd", "shift" }, "q" }, + focus_left = { { "ctrl", "alt", "cmd" }, "left" }, + focus_right = { { "ctrl", "alt", "cmd" }, "right" }, + focus_up = { { "ctrl", "alt", "cmd" }, "up" }, + focus_down = { { "ctrl", "alt", "cmd" }, "down" }, + swap_left = { { "ctrl", "alt", "cmd", "shift" }, "left" }, + swap_right = { { "ctrl", "alt", "cmd", "shift" }, "right" }, + swap_up = { { "ctrl", "alt", "cmd", "shift" }, "up" }, + swap_down = { { "ctrl", "alt", "cmd", "shift" }, "down" }, + center_window = { { "ctrl", "alt", "cmd" }, "c" }, + full_width = { { "ctrl", "alt", "cmd" }, "f" }, + cycle_width = { { "ctrl", "alt", "cmd" }, "r" }, + cycle_height = { { "ctrl", "alt", "cmd", "shift" }, "r" }, + slurp_in = { { "ctrl", "alt", "cmd" }, "i" }, + barf_out = { { "ctrl", "alt", "cmd" }, "o" }, + switch_space_1 = { { "ctrl", "alt", "cmd" }, "1" }, + switch_space_2 = { { "ctrl", "alt", "cmd" }, "2" }, + switch_space_3 = { { "ctrl", "alt", "cmd" }, "3" }, + switch_space_4 = { { "ctrl", "alt", "cmd" }, "4" }, + switch_space_5 = { { "ctrl", "alt", "cmd" }, "5" }, + switch_space_6 = { { "ctrl", "alt", "cmd" }, "6" }, + switch_space_7 = { { "ctrl", "alt", "cmd" }, "7" }, + switch_space_8 = { { "ctrl", "alt", "cmd" }, "8" }, + switch_space_9 = { { "ctrl", "alt", "cmd" }, "9" }, + move_window_1 = { { "ctrl", "alt", "cmd", "shift" }, "1" }, + move_window_2 = { { "ctrl", "alt", "cmd", "shift" }, "2" }, + move_window_3 = { { "ctrl", "alt", "cmd", "shift" }, "3" }, + move_window_4 = { { "ctrl", "alt", "cmd", "shift" }, "4" }, + move_window_5 = { { "ctrl", "alt", "cmd", "shift" }, "5" }, + move_window_6 = { { "ctrl", "alt", "cmd", "shift" }, "6" }, + move_window_7 = { { "ctrl", "alt", "cmd", "shift" }, "7" }, + move_window_8 = { { "ctrl", "alt", "cmd", "shift" }, "8" }, + move_window_9 = { { "ctrl", "alt", "cmd", "shift" }, "9" } +} + +--- PaperWM.window_filter +--- Variable +--- Windows captured by this filter are automatically tiled and managed +PaperWM.window_filter = WindowFilter.new():setOverrideFilter({ + visible = true, + fullscreen = false, + hasTitlebar = true, + allowRoles = "AXStandardWindow" +}) + +--- PaperWM.window_gap +--- Variable +--- Number of pixels between tiled windows +PaperWM.window_gap = 8 + +--- PaperWM.logger +--- Variable +--- Logger object. Can be accessed to set default log level. +PaperWM.logger = hs.logger.new(PaperWM.name) + +-- constants +local Direction = { + LEFT = -1, + RIGHT = 1, + UP = -2, + DOWN = 2, + WIDTH = 3, + HEIGHT = 4 +} + +-- array of windows sorted from left to right +local window_list = {} -- 3D array of tiles in order of [space][x][y] +local index_table = {} -- dictionary of {space, x, y} with window id for keys +local ui_watchers = {} -- dictionary of uielement watchers with window id for keys + +-- current focused window +local focused_window = nil + +local function getSpace(index) + local layout = Spaces.allSpaces() + for _, screen in ipairs(Screen.allScreens()) do + local screen_uuid = screen:getUUID() + local num_spaces = #layout[screen_uuid] + if num_spaces >= index then return layout[screen_uuid][index] end + index = index - num_spaces + end +end + +local function getFirstVisibleWindow(columns, screen) + local x = screen:frame().x + for _, windows in ipairs(columns or {}) do + local window = windows[1] -- take first window in column + if window:frame().x >= x then return window end + end +end + +local function getColumn(space, col) return (window_list[space] or {})[col] end + +local function getWindow(space, col, row) + return (getColumn(space, col) or {})[row] +end + +local function getCanvas(screen) + local screen_frame = screen:frame() + return Rect(screen_frame.x + PaperWM.window_gap, + screen_frame.y + PaperWM.window_gap, + screen_frame.w - (2 * PaperWM.window_gap), + screen_frame.h - (2 * PaperWM.window_gap)) +end + +local function updateIndexTable(space, column) + local columns = window_list[space] or {} + for col = column, #columns do + for row, window in ipairs(getColumn(space, col)) do + index_table[window:id()] = { space = space, col = col, row = row } + end + end +end + +local pending_window = nil +local function windowEventHandler(window, event, self) + self.logger.df("%s for %s", event, window) + local space = nil + + --[[ When a new window is created, We first get a windowVisible event but + without a Space. Next we receive a windowFocused event for the window, but + this also sometimes lacks a Space. Our approach is to store the window + pending a Space in the pending_window variable and set a timer to try to add + the window again later. Also schedule the windowFocused handler to run later + after the window was added ]] + -- + + if event == "windowFocused" then + if pending_window and window == pending_window then + DoAfter(Window.animationDuration, + function() + windowEventHandler(window, event, self) + end) + return + end + focused_window = window + space = Spaces.windowSpaces(window)[1] + elseif event == "windowVisible" or event == "windowUnfullscreened" then + space = self:addWindow(window) + if pending_window and window == pending_window then + pending_window = nil -- tried to add window for the second time + elseif not space then + pending_window = window + DoAfter(Window.animationDuration, + function() + windowEventHandler(window, event, self) + end) + return + end + elseif event == "windowNotVisible" then + self:removeWindow(window) -- destroyed windows don't have a space + elseif event == "windowFullscreened" then + space = self:removeWindow(window, true) -- don't focus new window if fullscreened + elseif event == "AXWindowMoved" or event == "AXWindowResized" then + space = Spaces.windowSpaces(window)[1] + end + + if space then self:tileSpace(space) end +end + +--- PaperWM.bindHotkeys(mapping) +--- Method +--- Binds hotkeys for PaperWM +--- +--- Parameters: +--- * mapping - A table containing hotkey modifer/key details for the following items: +--- * stop_events - Stop automatic tiling +--- * focus_left - Focus window to left of current window +--- * focus_right - Focus window to right of current window +--- * focus_up - Focus window to up of current window +--- * focus_down - Focus window to down of current window +--- * swap_left - Swap positions of window to the left and current window +--- * swap_right - Swap positions of window to the right and current window +--- * swap_up - Swap positions of window above and current window +--- * swap_down - Swap positions of window below and current window +--- * center_window - Move current window to center of screen +--- * full_width - Resize width of current window to width of screen +--- * cycle_width - Toggle through preset window widths +--- * cycle_height - Toggle through preset window heights +--- * slurp_in - Move current window into column to the left +--- * barf_out - Remove current window from column and place to the right +--- * switch_space_1 - Switch to Mission Control space 1 +--- * switch_space_2 - Switch to Mission Control space 2 +--- * switch_space_3 - Switch to Mission Control space 3 +--- * switch_space_4 - Switch to Mission Control space 4 +--- * switch_space_5 - Switch to Mission Control space 5 +--- * switch_space_6 - Switch to Mission Control space 6 +--- * switch_space_7 - Switch to Mission Control space 7 +--- * switch_space_8 - Switch to Mission Control space 8 +--- * switch_space_9 - Switch to Mission Control space 9 +--- * move_window_1 - Move current window to Mission Control space 1 +--- * move_window_2 - Move current window to Mission Control space 2 +--- * move_window_3 - Move current window to Mission Control space 3 +--- * move_window_4 - Move current window to Mission Control space 4 +--- * move_window_5 - Move current window to Mission Control space 5 +--- * move_window_6 - Move current window to Mission Control space 6 +--- * move_window_7 - Move current window to Mission Control space 7 +--- * move_window_8 - Move current window to Mission Control space 8 +--- * move_window_9 - Move current window to Mission Control space 9 +function PaperWM:bindHotkeys(mapping) + local partial = hs.fnutils.partial + local spec = { + stop_events = partial(self.stop, self), + focus_left = partial(self.focusWindow, self, Direction.LEFT), + focus_right = partial(self.focusWindow, self, Direction.RIGHT), + focus_up = partial(self.focusWindow, self, Direction.UP), + focus_down = partial(self.focusWindow, self, Direction.DOWN), + swap_left = partial(self.swapWindows, self, Direction.LEFT), + swap_right = partial(self.swapWindows, self, Direction.RIGHT), + swap_up = partial(self.swapWindows, self, Direction.UP), + swap_down = partial(self.swapWindows, self, Direction.DOWN), + center_window = partial(self.centerWindow, self), + full_width = partial(self.setWindowFullWidth, self), + cycle_width = partial(self.cycleWindowSize, self, Direction.WIDTH), + cycle_height = partial(self.cycleWindowSize, self, Direction.HEIGHT), + slurp_in = partial(self.slurpWindow, self), + barf_out = partial(self.barfWindow, self), + switch_space_1 = partial(self.switchToSpace, self, 1), + switch_space_2 = partial(self.switchToSpace, self, 2), + switch_space_3 = partial(self.switchToSpace, self, 3), + switch_space_4 = partial(self.switchToSpace, self, 4), + switch_space_5 = partial(self.switchToSpace, self, 5), + switch_space_6 = partial(self.switchToSpace, self, 6), + switch_space_7 = partial(self.switchToSpace, self, 7), + switch_space_8 = partial(self.switchToSpace, self, 8), + switch_space_9 = partial(self.switchToSpace, self, 9), + move_window_1 = partial(self.moveWindowToSpace, self, 1), + move_window_2 = partial(self.moveWindowToSpace, self, 2), + move_window_3 = partial(self.moveWindowToSpace, self, 3), + move_window_4 = partial(self.moveWindowToSpace, self, 4), + move_window_5 = partial(self.moveWindowToSpace, self, 5), + move_window_6 = partial(self.moveWindowToSpace, self, 6), + move_window_7 = partial(self.moveWindowToSpace, self, 7), + move_window_8 = partial(self.moveWindowToSpace, self, 8), + move_window_9 = partial(self.moveWindowToSpace, self, 9) + } + hs.spoons.bindHotkeysToSpec(spec, mapping) +end + +--- PaperWM:start() +--- Method +--- Start automatic tiling of windows +--- +--- Parameters: +--- * None +--- +--- Returns: +--- * The PaperWM object +function PaperWM:start() + -- check for some settings + if not Spaces.screensHaveSeparateSpaces() then + self.logger.e( + "please check 'Displays have separate Spaces' in System Preferences -> Mission Control") + end + + -- clear state + window_list = {} + index_table = {} + ui_watchers = {} + + -- populate window list, index table, and ui_watchers + self:refreshWindows() + + -- set initial layout + for space, _ in pairs(window_list) do self:tileSpace(space) end + + -- listen for window events + self.window_filter:subscribe({ + WindowFilter.windowFocused, WindowFilter.windowVisible, + WindowFilter.windowNotVisible, WindowFilter.windowFullscreened, + WindowFilter.windowUnfullscreened + }, function(window, _, event) windowEventHandler(window, event, self) end) + + return self +end + +--- PaperWM:stop() +--- Method +--- Stop automatic tiling of windows +--- +--- Parameters: +--- * None +--- +--- Returns: +--- * The PaperWM object +function PaperWM:stop() + -- stop events + self.window_filter:unsubscribeAll() + for _, watcher in pairs(ui_watchers) do watcher:stop() end + + return self +end + +--- PaperWM:tileColumn(windows, bounds, h, w, id, h4id) +--- Method +--- Tile a column of windows +--- +--- Parameters: +--- * windows - A list of hs.windows. +--- * bounds - An hs.geometry.rect. The area for this column to fill. +--- * h - The height for each window in column. +--- * w - The width for each window in column. +--- * id - A hs.window.id() for a specific window in column. +--- * h4id - The height for a window matching id in column. +--- +--- Notes: +--- * The h, w, id, and h4id parameters are optional. The height and width of +--- all windows will be calculated and set to fill column bounds. +--- * If bounds width is not specified, all windows in column will be resized +--- to width of first window. +--- +--- Returns: +--- * The width of the column +function PaperWM:tileColumn(windows, bounds, h, w, id, h4id) + local last_window, frame + for _, window in ipairs(windows) do + frame = window:frame() + w = w or frame.w -- take given width or width of first window + if bounds.x then -- set either left or right x coord + frame.x = bounds.x + elseif bounds.x2 then + frame.x = bounds.x2 - w + end + if h then -- set height if given + if id and h4id and window:id() == id then + frame.h = h4id -- use this height for window with id + else + frame.h = h -- use this height for all other windows + end + end + frame.y = bounds.y + frame.w = w + frame.y2 = math.min(frame.y2, bounds.y2) -- don't overflow bottom of bounds + self:moveWindow(window, frame) + bounds.y = math.min(frame.y2 + self.window_gap, bounds.y2) + last_window = window + end + -- expand last window height to bottom + if frame.y2 ~= bounds.y2 then + frame.y2 = bounds.y2 + self:moveWindow(last_window, frame) + end + return w -- return width of column +end + +--- PaperWM:tileSpace(space) +--- Method +--- Tile all windows within a space +--- +--- Parameters: +--- * space - A hs.spaces space. +function PaperWM:tileSpace(space) + -- MacOS doesn't allow windows to be moved off screen + -- stack windows in a visible margin on either side + local screen_margin = 40 + + if not space or Spaces.spaceType(space) ~= "user" then + self.logger.e("current space invalid") + return + end + + -- find screen for space + local screen = Screen(Spaces.spaceDisplay(space)) + if not screen then + self.logger.e("no screen for space") + return + end + + -- if focused window is in space, tile from that + focused_window = focused_window or Window.focusedWindow() + local anchor_window = (focused_window and + (Spaces.windowSpaces(focused_window)[1] == space)) and + focused_window or + getFirstVisibleWindow(window_list[space], screen) + + if not anchor_window then + self.logger.e("no anchor window in space") + return + end + + local anchor_index = index_table[anchor_window:id()] + if not anchor_index then + self.logger.e("anchor index not found") + if self:addWindow(anchor_window) == space then + self.logger.d("added missing window") + anchor_index = index_table[anchor_window:id()] + else + return -- bail + end + end + + -- get some global coordinates + local screen_frame = screen:frame() + local left_margin = screen_frame.x + screen_margin + local right_margin = screen_frame.x2 - screen_margin + local canvas = getCanvas(screen) + + -- make sure anchor window is on screen + local anchor_frame = anchor_window:frame() + anchor_frame.x = math.max(anchor_frame.x, canvas.x) + anchor_frame.w = math.min(anchor_frame.w, canvas.w) + anchor_frame.h = math.min(anchor_frame.h, canvas.h) + if anchor_frame.x2 > canvas.x2 then + anchor_frame.x = canvas.x2 - anchor_frame.w + end + + -- adjust anchor window column + local column = getColumn(space, anchor_index.col) + if not column then + self.logger.e("no anchor window column") + return + end + + -- TODO: need a minimum window height + if #column == 1 then + anchor_frame.y, anchor_frame.h = canvas.y, canvas.h + self:moveWindow(anchor_window, anchor_frame) + else + local n = #column - 1 -- number of other windows in column + local h = + math.max(0, canvas.h - anchor_frame.h - (n * self.window_gap)) // n + local bounds = { + x = anchor_frame.x, + x2 = nil, + y = canvas.y, + y2 = canvas.y2 + } + self:tileColumn(column, bounds, h, anchor_frame.w, anchor_window:id(), + anchor_frame.h) + end + + -- tile windows from anchor right + local x = math.min(anchor_frame.x2 + self.window_gap, right_margin) + for col = anchor_index.col + 1, #(window_list[space] or {}) do + local bounds = { x = x, x2 = nil, y = canvas.y, y2 = canvas.y2 } + local column_width = self:tileColumn(getColumn(space, col), bounds) + x = math.min(x + column_width + self.window_gap, right_margin) + end + + -- tile windows from anchor left + local x2 = math.max(anchor_frame.x - self.window_gap, left_margin) + for col = anchor_index.col - 1, 1, -1 do + local bounds = { x = nil, x2 = x2, y = canvas.y, y2 = canvas.y2 } + local column_width = self:tileColumn(getColumn(space, col), bounds) + x2 = math.max(x2 - column_width - self.window_gap, left_margin) + end +end + +--- PaperWM:refreshWindows() +--- Method +--- Searches for all windows that match window filter. +--- +--- Parameters: +--- * None +--- +--- Returns: +--- * A boolean, true if the layout needs to be re-tiled, false if no change. +function PaperWM:refreshWindows() + -- get all windows across spaces + local all_windows = self.window_filter:getWindows() + + local refresh_needed = false + for _, window in ipairs(all_windows) do + local index = index_table[window:id()] + if not index then + -- add window + self:addWindow(window) + refresh_needed = true + elseif index.space ~= Spaces.windowSpaces(window)[1] then + -- move to window list in new space + self:removeWindow(window) + self:addWindow(window) + refresh_needed = true + end + end + + return refresh_needed +end + +--- PaperWM:addWindow(add_window) +--- Method +--- Adds a window to layout and tiles. +--- +--- Parameters: +--- * add_window - An hs.window +--- +--- Returns: +--- * The hs.spaces space for added window or nil if window not added. +function PaperWM:addWindow(add_window) + -- check if window is already in window list + if index_table[add_window:id()] then return end + + local space = Spaces.windowSpaces(add_window)[1] + if not space then + self.logger.e("add window does not have a space") + return + end + if not window_list[space] then window_list[space] = {} end + + -- find where to insert window + local add_column = 1 + + -- when addWindow() is called from a window created event: + -- focused_window from previous window focused event will not be add_window + -- hs.window.focusedWindow() will return add_window + -- new window focused event for add_window has not happened yet + if focused_window and + ((index_table[focused_window:id()] or {}).space == space) and + (focused_window:id() ~= add_window:id()) then + add_column = index_table[focused_window:id()].col + 1 -- insert to the right + else + local x = add_window:frame().center.x + for col, windows in ipairs(window_list[space]) do + if x < windows[1]:frame().center.x then + add_column = col + break + end + end + end + + -- add window + table.insert(window_list[space], add_column, { add_window }) + + -- update index table + updateIndexTable(space, add_column) + + -- subscribe to window moved events + local watcher = add_window:newWatcher( + function(window, event, _, self) + windowEventHandler(window, event, self) + end, self) + watcher:start({ Watcher.windowMoved, Watcher.windowResized }) + ui_watchers[add_window:id()] = watcher + + return space +end + +--- PaperWM:remove_window(remove_window, skip_new_window_focus) +--- Method +--- Remove window from tiling layout +--- +--- Parameters: +--- * remove_window - A hs.window to remove from tiling layout +--- * skip_new_window_focus - A boolean. True if a nearby window should not be +--- focused after current window is removed. +--- +--- Returns: +--- * The hs.spaces space for removed window. +function PaperWM:removeWindow(remove_window, skip_new_window_focus) + -- get index of window + local remove_index = index_table[remove_window:id()] + if not remove_index then + self.logger.e("remove index not found") + return + end + + if not skip_new_window_focus then -- find nearby window to focus + for _, direction in ipairs({ + Direction.DOWN, Direction.UP, Direction.LEFT, Direction.RIGHT + }) do if self:focusWindow(direction, remove_index) then break end end + end + + -- remove window + table.remove(window_list[remove_index.space][remove_index.col], + remove_index.row) + if #window_list[remove_index.space][remove_index.col] == 0 then + table.remove(window_list[remove_index.space], remove_index.col) + end + + -- remove watcher + ui_watchers[remove_window:id()] = nil + + -- update index table + index_table[remove_window:id()] = nil + updateIndexTable(remove_index.space, remove_index.col) + + -- remove if space is empty + if #window_list[remove_index.space] == 0 then + window_list[remove_index.space] = nil + end + + return remove_index.space -- return space for removed window +end + +--- PaperWM:focusWindow(direction, focused_index) +--- Method +--- Change focus to a nearby window +--- +--- Parameters: +--- * direction - One of Direction { LEFT, RIGHT, DOWN, UP } +--- * focused_index - The coordinates of the current window in the tiling layout +--- +--- Returns: +--- * A boolean. True if a new window was focused. False if no nearby window +--- was found in that direction. +function PaperWM:focusWindow(direction, focused_index) + if not focused_index then + -- get current focused window + focused_window = focused_window or Window.focusedWindow() + if not focused_window then return false end + + -- get focused window index + focused_index = index_table[focused_window:id()] + end + + if not focused_index then + self.logger.e("focused index not found") + return false + end + + -- get new focused window + local new_focused_window + if direction == Direction.LEFT or direction == Direction.RIGHT then + -- walk down column, looking for match in neighbor column + for row = focused_index.row, 1, -1 do + new_focused_window = getWindow(focused_index.space, + focused_index.col + direction, row) + if new_focused_window then break end + end + elseif direction == Direction.UP or direction == Direction.DOWN then + new_focused_window = getWindow(focused_index.space, focused_index.col, + focused_index.row + (direction // 2)) + end + + if not new_focused_window then + self.logger.d("new focused window not found") + return false + end + + -- focus new window, windowFocused event will be emited immediately + new_focused_window:focus() + return true +end + +--- PaperWM:swapWindows(direction) +--- Method +--- Swaps window postions between current window and window in specified direction. +--- +--- Parameters: +--- * direction - One of Direction { LEFT, RIGHT, DOWN, UP } +function PaperWM:swapWindows(direction) + -- use focused window as source window + focused_window = focused_window or Window.focusedWindow() + if not focused_window then return end + + -- get focused window index + local focused_index = index_table[focused_window:id()] + if not focused_index then + self.logger.e("focused index not found") + return + end + + if direction == Direction.LEFT or direction == Direction.RIGHT then + -- get target windows + local target_index = { col = focused_index.col + direction } + local target_column = window_list[focused_index.space][target_index.col] + if not target_column then + self.logger.d("target column not found") + return + end + + -- swap place in window list + local focused_column = + window_list[focused_index.space][focused_index.col] + window_list[focused_index.space][target_index.col] = focused_column + window_list[focused_index.space][focused_index.col] = target_column + + -- update index table + for row, window in ipairs(target_column) do + index_table[window:id()] = { + space = focused_index.space, + col = focused_index.col, + row = row + } + end + for row, window in ipairs(focused_column) do + index_table[window:id()] = { + space = focused_index.space, + col = target_index.col, + row = row + } + end + + -- swap frames + local focused_frame = focused_window:frame() + local target_frame = target_column[1]:frame() + if direction == Direction.LEFT then + focused_frame.x = target_frame.x + target_frame.x = focused_frame.x2 + self.window_gap + else -- Direction.RIGHT + target_frame.x = focused_frame.x + focused_frame.x = target_frame.x2 + self.window_gap + end + for _, window in ipairs(target_column) do + local frame = window:frame() + frame.x = target_frame.x + self:moveWindow(window, frame) + end + for _, window in ipairs(focused_column) do + local frame = window:frame() + frame.x = focused_frame.x + self:moveWindow(window, frame) + end + elseif direction == Direction.UP or direction == Direction.DOWN then + -- get target window + local target_index = { + space = focused_index.space, + col = focused_index.col, + row = focused_index.row + (direction // 2) + } + local target_window = getWindow(target_index.space, target_index.col, + target_index.row) + if not target_window then + self.logger.d("target window not found") + return + end + + -- swap places in window list + window_list[target_index.space][target_index.col][target_index.row] = + focused_window + window_list[focused_index.space][focused_index.col][focused_index.row] = + target_window + + -- update index table + index_table[target_window:id()] = focused_index + index_table[focused_window:id()] = target_index + + -- swap frames + local focused_frame = focused_window:frame() + local target_frame = target_window:frame() + if direction == Direction.UP then + focused_frame.y = target_frame.y + target_frame.y = focused_frame.y2 + self.window_gap + else -- Direction.DOWN + target_frame.y = focused_frame.y + focused_frame.y = target_frame.y2 + self.window_gap + end + self:moveWindow(focused_window, focused_frame) + self:moveWindow(target_window, target_frame) + end + + -- update layout + self:tileSpace(focused_index.space) +end + +--- PaperWM:centerWindow() +--- Method +--- Moves current window to center of screen, without resizing. +--- +--- Parameters: +--- * None +function PaperWM:centerWindow() + -- get current focused window + focused_window = focused_window or Window.focusedWindow() + if not focused_window then return end + + -- get global coordinates + local focused_frame = focused_window:frame() + local screen_frame = focused_window:screen():frame() + + -- center window + focused_frame.x = screen_frame.x + (screen_frame.w // 2) - + (focused_frame.w // 2) + self:moveWindow(focused_window, focused_frame) + + -- update layout + local space = Spaces.windowSpaces(focused_window)[1] + self:tileSpace(space) +end + +--- PaperWM:setWindowFullWidth() +--- Method +--- Resizes current window's width to width of screen, without adjusting height. +--- +--- Parameters: +--- * None +function PaperWM:setWindowFullWidth() + -- get current focused window + focused_window = focused_window or Window.focusedWindow() + if not focused_window then return end + + -- fullscreen window width + local canvas = getCanvas(focused_window:screen()) + local focused_frame = focused_window:frame() + focused_frame.x, focused_frame.w = canvas.x, canvas.w + self:moveWindow(focused_window, focused_frame) + + -- update layout + local space = Spaces.windowSpaces(focused_window)[1] + self:tileSpace(space) +end + +--- PaperWM:cycleWindowSize(direction) +--- Method +--- Resizes current window by cycling through width or height ratios. +--- +--- Parameters: +--- * direction - One of Direction { WIDTH, HEIGHT } +function PaperWM:cycleWindowSize(direction) + -- get current focused window + focused_window = focused_window or Window.focusedWindow() + if not focused_window then return end + + local function findNewSize(area_size, frame_size) + -- calculate pixel widths from ratios + local sizes = { 0.38195, 0.5, 0.61804 } + for index, size in ipairs(sizes) do + sizes[index] = size * area_size + end + + -- find new size + local new_size = sizes[1] + for _, size in ipairs(sizes) do + if size > frame_size + 10 then + new_size = size + break + end + end + + return new_size + end + + local canvas = getCanvas(focused_window:screen()) + local focused_frame = focused_window:frame() + + if direction == Direction.WIDTH then + local new_width = findNewSize(canvas.w, focused_frame.w) + focused_frame.x = focused_frame.x + ((focused_frame.w - new_width) // 2) + focused_frame.w = new_width + elseif direction == Direction.HEIGHT then + local new_height = findNewSize(canvas.h, focused_frame.h) + focused_frame.y = math.max(canvas.y, focused_frame.y + + ((focused_frame.h - new_height) // 2)) + focused_frame.h = new_height + focused_frame.y = focused_frame.y - + math.max(0, focused_frame.y2 - canvas.y2) + end + + -- apply new size + self:moveWindow(focused_window, focused_frame) + + -- update layout + local space = Spaces.windowSpaces(focused_window)[1] + self:tileSpace(space) +end + +--- PaperWM:slurpWindow() +--- Method +--- Moves current window into column of windows to the left +--- +--- Parameters: +--- * None +function PaperWM:slurpWindow() + -- TODO paperwm behavior: + -- add top window from column to the right to bottom of current column + -- if no colum to the right and current window is only window in current column, + -- add current window to bottom of column to the left + + -- get current focused window + focused_window = focused_window or Window.focusedWindow() + if not focused_window then return end + + -- get window index + local focused_index = index_table[focused_window:id()] + if not focused_index then + self.logger.e("focused index not found") + return + end + + -- get column to left + local column = window_list[focused_index.space][focused_index.col - 1] + if not column then + self.logger.d("column not found") + return + end + + -- remove window + table.remove(window_list[focused_index.space][focused_index.col], + focused_index.row) + if #window_list[focused_index.space][focused_index.col] == 0 then + table.remove(window_list[focused_index.space], focused_index.col) + end + + -- append to end of column + table.insert(column, focused_window) + + -- update index table + local num_windows = #column + index_table[focused_window:id()] = { + space = focused_index.space, + col = focused_index.col - 1, + row = num_windows + } + updateIndexTable(focused_index.space, focused_index.col) + + -- adjust window frames + local canvas = getCanvas(focused_window:screen()) + local bounds = { + x = column[1]:frame().x, + x2 = nil, + y = canvas.y, + y2 = canvas.y2 + } + local h = math.max(0, canvas.h - ((num_windows - 1) * self.window_gap)) // + num_windows + self:tileColumn(column, bounds, h) + + -- update layout + self:tileSpace(focused_index.space) +end + +--- PaperWM:barfWindow() +--- Method +--- Removes current window from column and places it to the right +--- +--- Parameters: +--- * None +function PaperWM:barfWindow() + -- TODO paperwm behavior: + -- remove bottom window of current column + -- place window into a new column to the right-- + + -- get current focused window + focused_window = focused_window or Window.focusedWindow() + if not focused_window then return end + + -- get window index + local focused_index = index_table[focused_window:id()] + if not focused_index then + self.logger.e("focused index not found") + return + end + + -- get column + local column = window_list[focused_index.space][focused_index.col] + if #column == 1 then + self.logger.d("only window in column") + return + end + + -- remove window and insert in new column + table.remove(column, focused_index.row) + table.insert(window_list[focused_index.space], focused_index.col + 1, + { focused_window }) + + -- update index table + updateIndexTable(focused_index.space, focused_index.col) + + -- adjust window frames + local num_windows = #column + local canvas = getCanvas(focused_window:screen()) + local focused_frame = focused_window:frame() + local bounds = { x = focused_frame.x, x2 = nil, y = canvas.y, y2 = canvas.y2 } + local h = math.max(0, canvas.h - ((num_windows - 1) * self.window_gap)) // + num_windows + focused_frame.y = canvas.y + focused_frame.x = focused_frame.x2 + self.window_gap + focused_frame.h = canvas.h + self:moveWindow(focused_window, focused_frame) + self:tileColumn(column, bounds, h) + + -- update layout + self:tileSpace(focused_index.space) +end + +--- PaperWM:switchToSpace(index) +--- Method +--- Switch to a Mission Control space +--- +--- Parameters: +--- * index - The space number +function PaperWM:switchToSpace(index) + local space = getSpace(index) + if not space then + self.logger.d("space not found") + return + end + + Spaces.gotoSpace(space) +end + +--- PaperWM:moveWindowToSpace(index) +--- Method +--- Moves the current window to a new Mission Control space +--- +--- Parameters: +--- * index - The space number +function PaperWM:moveWindowToSpace(index) + focused_window = focused_window or Window.focusedWindow() + if not focused_window then + self.logger.d("focused window not found") + return + end + + local focused_index = index_table[focused_window:id()] + if not focused_index then + self.logger.e("focused index not found") + return + end + + local new_space = getSpace(index) + if not new_space then + self.logger.d("space not found") + return + end + + if Spaces.spaceType(new_space) ~= "user" then + self.logger.d("space is invalid") + return + end + + local screen = Screen(Spaces.spaceDisplay(new_space)) + if not screen then + self.logger.d("screen not found") + return + end + + -- cache a local copy, removeWindow() will clear global focused_window + local focused_window = focused_window + local old_space = self:removeWindow(focused_window) + if not old_space then + self.logger.e("can't remove focused window") + return + end + + Spaces.moveWindowToSpace(focused_window, new_space) + self:addWindow(focused_window) + self:tileSpace(old_space) + self:tileSpace(new_space) + Spaces.gotoSpace(new_space) +end + +--- PaperWM::moveWindow(window, frame) +--- Method +--- Resizes a window without triggering a windowMoved event +--- +--- Parameters: +--- * window - An hs.window +--- * frame - An hs.geometry.rect for the windows new frame size. +function PaperWM:moveWindow(window, frame) + -- greater than 0.017 hs.window animation step time + local padding = 0.02 + + local watcher = ui_watchers[window:id()] + if not watcher then + self.logger.e("window does not have ui watcher") + return + end + + if frame == window:frame() then + self.logger.v("no change in window frame") + return + end + + watcher:stop() + window:setFrame(frame) + DoAfter(Window.animationDuration + padding, function() + watcher:start({ Watcher.windowMoved, Watcher.windowResized }) + end) +end + +return PaperWM diff --git a/Source/Seal.spoon/init.lua b/Source/Seal.spoon/init.lua index c520d756..30813ba1 100644 --- a/Source/Seal.spoon/init.lua +++ b/Source/Seal.spoon/init.lua @@ -301,9 +301,9 @@ function obj.choicesCallback() end query_words = table.concat(query_words, " ") -- First get any direct command matches - for command,cmdInfo in pairs(obj.commands) do + for _,cmdInfo in pairs(obj.commands) do cmd_fn = cmdInfo["fn"] - if cmd:lower() == command:lower() then + if cmd:lower() == cmdInfo["cmd"]:lower() then if (query_words or "") == "" then query_words = ".*" end diff --git a/Source/TimeMachineProgress.spoon/docs.json b/Source/TimeMachineProgress.spoon/docs.json index cbaef2ac..b6ae931c 100644 --- a/Source/TimeMachineProgress.spoon/docs.json +++ b/Source/TimeMachineProgress.spoon/docs.json @@ -30,7 +30,7 @@ "doc": "Starts the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon//init.lua", - "lineno": "203", + "lineno": "207", "name": "start", "notes": [], "parameters": [ @@ -49,7 +49,7 @@ "doc": "Stops the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon//init.lua", - "lineno": "221", + "lineno": "225", "name": "stop", "notes": [], "parameters": [ @@ -163,7 +163,7 @@ "doc": "Starts the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon//init.lua", - "lineno": "203", + "lineno": "207", "name": "start", "notes": [], "parameters": [ @@ -182,7 +182,7 @@ "doc": "Stops the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon//init.lua", - "lineno": "221", + "lineno": "225", "name": "stop", "notes": [], "parameters": [ diff --git a/Source/TimeMachineProgress.spoon/init.lua b/Source/TimeMachineProgress.spoon/init.lua index a650ab6d..e8e02a62 100644 --- a/Source/TimeMachineProgress.spoon/init.lua +++ b/Source/TimeMachineProgress.spoon/init.lua @@ -13,7 +13,7 @@ obj.__index = obj -- Metadata obj.name = "TimeMachineProgress" -obj.version = "0.1" +obj.version = "0.2" obj.author = "Diego Zamboni " obj.homepage = "https://github.com/Hammerspoon/Spoons" obj.license = "MIT - https://opensource.org/licenses/MIT" @@ -132,7 +132,7 @@ function obj:refresh() -- Identify special states: preparing backup and stopping backup. local stopping = (data['Stopping'] == '1') - local preparing = (not stopping) and (data['Percent'] == '-1' or data['Percent'] == '0') + local preparing = (not stopping) and (data['Percent'] == '-1' or data['Percent'] == '0' or not data['Progress']) -- Depending on macOS version the 'Progress' data may be stored in a -- subitem, we promote it to the top level @@ -148,7 +148,11 @@ function obj:refresh() topmenu = tooltip elseif preparing then title = "(prep)" - tooltip = "Preparing Backup…" + if (data['BackupPhase']) then + tooltip = data['BackupPhase']:gsub("(%l)(%u)", "%1 %2") + else + tooltip = "Preparing Backup…" + end topmenu = tooltip else title = string.format("%.2f%%", tonumber(data['Percent'])*100) diff --git a/Spoons/AClock.spoon.zip b/Spoons/AClock.spoon.zip index 93bf3b59..242cf59e 100644 Binary files a/Spoons/AClock.spoon.zip and b/Spoons/AClock.spoon.zip differ diff --git a/Spoons/ArrangeDesktop.spoon.zip b/Spoons/ArrangeDesktop.spoon.zip index be4d6495..0c9b5cfd 100644 Binary files a/Spoons/ArrangeDesktop.spoon.zip and b/Spoons/ArrangeDesktop.spoon.zip differ diff --git a/Spoons/AutoMuteOnSleep.spoon.zip b/Spoons/AutoMuteOnSleep.spoon.zip new file mode 100644 index 00000000..20826a2f Binary files /dev/null and b/Spoons/AutoMuteOnSleep.spoon.zip differ diff --git a/Spoons/EmmyLua.spoon.zip b/Spoons/EmmyLua.spoon.zip index bba097a0..951620dd 100644 Binary files a/Spoons/EmmyLua.spoon.zip and b/Spoons/EmmyLua.spoon.zip differ diff --git a/Spoons/InputMethodIndicator.spoon.zip b/Spoons/InputMethodIndicator.spoon.zip new file mode 100644 index 00000000..dcbf8da6 Binary files /dev/null and b/Spoons/InputMethodIndicator.spoon.zip differ diff --git a/Spoons/InputSourceSwitch.spoon.zip b/Spoons/InputSourceSwitch.spoon.zip new file mode 100644 index 00000000..a01fe646 Binary files /dev/null and b/Spoons/InputSourceSwitch.spoon.zip differ diff --git a/Spoons/Keychain.spoon.zip b/Spoons/Keychain.spoon.zip index 34360fd9..b274a60a 100644 Binary files a/Spoons/Keychain.spoon.zip and b/Spoons/Keychain.spoon.zip differ diff --git a/Spoons/LeftRightHotkey.spoon.zip b/Spoons/LeftRightHotkey.spoon.zip new file mode 100644 index 00000000..b16e539d Binary files /dev/null and b/Spoons/LeftRightHotkey.spoon.zip differ diff --git a/Spoons/MiddleClickDragScroll.spoon.zip b/Spoons/MiddleClickDragScroll.spoon.zip new file mode 100644 index 00000000..b5b9f96b Binary files /dev/null and b/Spoons/MiddleClickDragScroll.spoon.zip differ diff --git a/Spoons/ModalMgr.spoon.zip b/Spoons/ModalMgr.spoon.zip index 18b12c77..7a95b4fd 100644 Binary files a/Spoons/ModalMgr.spoon.zip and b/Spoons/ModalMgr.spoon.zip differ diff --git a/Spoons/MouseFollowsFocus.spoon.zip b/Spoons/MouseFollowsFocus.spoon.zip index 05c872cb..8903c115 100644 Binary files a/Spoons/MouseFollowsFocus.spoon.zip and b/Spoons/MouseFollowsFocus.spoon.zip differ diff --git a/Spoons/PaperWM.spoon.zip b/Spoons/PaperWM.spoon.zip new file mode 100644 index 00000000..deefc4c8 Binary files /dev/null and b/Spoons/PaperWM.spoon.zip differ diff --git a/Spoons/Seal.spoon.zip b/Spoons/Seal.spoon.zip index a730189a..2cab1890 100644 Binary files a/Spoons/Seal.spoon.zip and b/Spoons/Seal.spoon.zip differ diff --git a/Spoons/TimeMachineProgress.spoon.zip b/Spoons/TimeMachineProgress.spoon.zip index 779ccb55..6cc8885c 100644 Binary files a/Spoons/TimeMachineProgress.spoon.zip and b/Spoons/TimeMachineProgress.spoon.zip differ diff --git a/docs/AClock.html b/docs/AClock.html index ac175efa..2e898afe 100644 --- a/docs/AClock.html +++ b/docs/AClock.html @@ -75,7 +75,7 @@
hide
Source - Source/AClock.spoon/init.lua line 116 + Source/AClock.spoon/init.lua line 130 @@ -149,7 +149,7 @@
show
Source - Source/AClock.spoon/init.lua line 97 + Source/AClock.spoon/init.lua line 111 @@ -183,7 +183,7 @@
toggleShow
Source - Source/AClock.spoon/init.lua line 133 + Source/AClock.spoon/init.lua line 147 @@ -217,7 +217,7 @@
toggleShowPersistent
Source - Source/AClock.spoon/init.lua line 154 + Source/AClock.spoon/init.lua line 168 diff --git a/docs/AutoMuteOnSleep.html b/docs/AutoMuteOnSleep.html new file mode 100644 index 00000000..ef68fb2d --- /dev/null +++ b/docs/AutoMuteOnSleep.html @@ -0,0 +1,29 @@ + + + + Hammerspoon docs: AutoMuteOnSleep + + + + +
+

docs » AutoMuteOnSleep

+

Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep. +Useful to avoid blasting sound when opening a Macbook in the public transport. +Note: This is primarily intended for portable Mac devices, which have internal speakers.

+

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip

+ +
+

API Overview

+
    +
+

API Documentation

+ + \ No newline at end of file diff --git a/docs/EmmyLua.html b/docs/EmmyLua.html index bf87fb03..b9c739f8 100644 --- a/docs/EmmyLua.html +++ b/docs/EmmyLua.html @@ -26,9 +26,9 @@

docs » EmmyLua

To start using this annotations library, add the annotations folder to your workspace. for lua-languag-server:

-
{
-  "Lua.workspace.library": ["/Users/YOUR_USERNAME/.hammerspoon/Spoons/EmmyLua.spoon/annotations"]
-}
+
{
+  "Lua.workspace.library": ["/Users/YOUR_USERNAME/.hammerspoon/Spoons/EmmyLua.spoon/annotations"]
+}
 

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/EmmyLua.spoon.zip

diff --git a/docs/InputMethodIndicator.html b/docs/InputMethodIndicator.html new file mode 100644 index 00000000..65b25ce0 --- /dev/null +++ b/docs/InputMethodIndicator.html @@ -0,0 +1,168 @@ + + + + Hammerspoon docs: InputMethodIndicator + + + + +
+

docs » InputMethodIndicator

+

Show input method indicator in the current mouse position. +It is a small but noticable dot near the cursor. +It can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method. +You can use it as follows in the init.lua: +hs.loadSpoon("InputMethodIndicator") +spoon.InputMethodIndicator:start(nil) +note: config parameter is a table, pass nil to use the default config +the default config is as follows: +{ + ABCColor = "#62C555", -- the dot color when the input method is ABC + LocalLanguageColor = "#ED6A5E", -- the dot color when the input method is not ABC + mode = "nearMouse", -- the mode of the indicator + showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed + checkInterval = .01, -- seconds to check the input method + dotSize = 6, -- the size of the dot + deltaY=7, -- the distance between the dot and the center of the selection or mouse +} +the mode can be "nearMouse","onChange","adaptive", the default mode is "adaptive" +"nearMouse" means the indicator will always show near the mouse +"onChange" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds +"adaptive" means the indicator will show near the textarea when typing, otherwise it will show near the mouse +Note: the "adaptive" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API

+ +
+

API Overview

+
    +
  • Methods - API calls which can only be made on an object returned by a constructor
  • + +
+

API Documentation

+

Methods

+
+ +
init
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureInputMethodIndicator:init()
TypeMethod
Description

init.

+
Parameters
    +
  • None
  • +
+
Returns
    +
  • The InputMethodIndicator object
  • +
+
SourceSource/InputMethodIndicator.spoon/init.lua line 67
+
+
+ +
start
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureInputMethodIndicator:start(config)
TypeMethod
Description

Start InputMethodIndicator.

+
Parameters
    +
  • config - A table contains config options for the module
      +
    • ABCColor - the dot color when the input method is ABC
    • +
    • LocalLanguageColor - the dot color when the input method is not ABC
    • +
    • mode - the mode of the indicator
    • +
    • showOnChangeDuration - seconds to show the indicator when the input method is changed
    • +
    • checkInterval - seconds to check the input method
    • +
    • dotSize - the size of the dot
    • +
    • deltaY - the distance between the dot and the center of the selection or mouse
    • +
    +
  • +
+
Returns
SourceSource/InputMethodIndicator.spoon/init.lua line 200
+
+
+ +
stop
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureInputMethodIndicator:stop()
TypeMethod
Description

Stop InputMethodIndicator.

+
Parameters
    +
  • None
  • +
+
Returns
SourceSource/InputMethodIndicator.spoon/init.lua line 245
+
+ + \ No newline at end of file diff --git a/docs/InputSourceSwitch.html b/docs/InputSourceSwitch.html new file mode 100644 index 00000000..944295c9 --- /dev/null +++ b/docs/InputSourceSwitch.html @@ -0,0 +1,140 @@ + + + + Hammerspoon docs: InputSourceSwitch + + + + +
+

docs » InputSourceSwitch

+

Automatically switch the input source when switching applications.

+

Example:

+ +
hs.loadSpoon("InputSourceSwitch")
+
+spoon.InputSourceSwitch:setApplications({
+    ["WeChat"] = "Pinyin - Simplified",
+    ["Mail"] = "ABC"
+})
+
+spoon.InputSourceSwitch:start()
+
+

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip

+ +
+

API Overview

+
    +
  • Variables - Configurable values
  • + +
  • Methods - API calls which can only be made on an object returned by a constructor
  • + +
+

API Documentation

+

Variables

+
+ +
applicationMap
+ + + + + + + + + + + + + + + + + +
SignatureInputSourceSwitch.applicationMap
TypeVariable
Description

Mapping the application name to the input source

+
SourceSource/InputSourceSwitch.spoon/init.lua line 75
+
+

Methods

+
+ +
setApplications
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureInputSourceSwitch:setApplications()
TypeMethod
Description

Set that mapping the application name to the input source

+
Parameters
    +
  • applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: { ["WeChat"] = "Pinyin - Simplified", ["Mail"] = "ABC" }
  • +
+
Returns
SourceSource/InputSourceSwitch.spoon/init.lua line 80
+
+
+ +
start
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureInputSourceSwitch:start()
TypeMethod
Description

Start InputSourceSwitch

+
Parameters
    +
  • None
  • +
+
Returns
SourceSource/InputSourceSwitch.spoon/init.lua line 100
+
+ + \ No newline at end of file diff --git a/docs/LeftRightHotkey.html b/docs/LeftRightHotkey.html new file mode 100644 index 00000000..1fbd7613 --- /dev/null +++ b/docs/LeftRightHotkey.html @@ -0,0 +1,372 @@ + + + + Hammerspoon docs: LeftRightHotkey + + + + +
+

docs » LeftRightHotkey

+

This spoon addresses a limitation within the hs.hotkey module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.

+

This is accomplished by creating unactivated hotkeys for each definition and using an hs.eventtap watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the bind and new methods of this spoon.

+

The LeftRightHotkeyObject that is returned by LeftRightHotkey:new and LeftRightHotkey:bind supports the following methods in a manner similar to the hs.hotkey equivalents:

+
    +
  • LeftRightHotkeyObject:enable() -- enables the registered hotkey.
  • +
  • LeftRightHotkeyObject:disable() -- disables the registered hotkey.
  • +
  • LeftRightHotkeyObject:delete() -- deletes the registered hotkey.
  • +
  • `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)
  • +
+

The following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:

+
    +
  • "lCmd", "lCommand", or "l⌘" for the left Command modifier
  • +
  • "rCmd", "rCommand", or "r⌘" for the right Command modifier
  • +
  • "lCtrl", "lControl" or "l⌃" for the left Control modifier
  • +
  • "rCtrl", "rControl" or "r⌃" for the right Control modifier
  • +
  • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
  • +
  • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
  • +
  • "lShift" or "l⇧" for the left Shift modifier
  • +
  • "rShift" or "r⇧" for the right Shift modifier
  • +
+

The modifiers table for any given hotkey is all inclusive; this means that if you specify { "rShift", "lShift" } then both the left and right shift keys must be pressed to trigger the hotkey -- if you want either/or, then stick with hs.hotkey.

+

Alternatively, if you want to setup a hotkey when either command key is pressed with only the right shift, you would need to set up two hotkeys with this spoon: + e.g. LeftRightHotkey:bind({ "rCmd", "rShift" }, "a", myFunction) and LeftRightHotkey:bind({ "lCmd", "rShift" }, "a", myFunction)

+

This spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:

+
    +
  • like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.
  • +
  • behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through hs.hotkey:enable() -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.
      +
    • a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue LeftRightHotkey:start() to force the eventtap to be reset if necessary.
    • +
    • if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.
    • +
    +
  • +
+

Like all Spoons, don't forget to use the LeftRightHotkey:start() method to activate the modifier key watcher.

+

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip

+ +
+

API Overview

+ +

API Documentation

+

Methods

+
+ +
bind
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureLeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject
TypeMethod
Description

Create and enable a new hotkey with the specified left/right specific modifiers.

+
Parameters
    +
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      +
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • +
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • +
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • +
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • +
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • +
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • +
    • "lShift" or "l⇧" for the left Shift modifier
    • +
    • "rShift" or "r⇧" for the right Shift modifier
    • +
    +
  • +
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • +
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • +
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • +
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • +
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • +
+
Returns
    +
  • a new enabled hotkey with the specified left/right modifiers.
  • +
+
Notes
    +
  • This function is just a wrapper that performs LeftRightHotkey:new(...):enable()
  • +
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.bind as is and any caveats or considerations outlined there also apply here.
  • +
+
SourceSource/LeftRightHotkey.spoon/init.lua line 415
+
+
+ +
deleteAll
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureLeftRightHotkey:deleteAll(mods, key)
TypeMethod
Description

Deletes all previously set callbacks for a given keyboard combination

+
Parameters
    +
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      +
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • +
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • +
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • +
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • +
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • +
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • +
    • "lShift" or "l⇧" for the left Shift modifier
    • +
    • "rShift" or "r⇧" for the right Shift modifier
    • +
    +
  • +
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • +
+
Returns
    +
  • None
  • +
+
SourceSource/LeftRightHotkey.spoon/init.lua line 326
+
+
+ +
disableAll
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureLeftRightHotkey:disableAll(mods, key)
TypeMethod
Description

Disables all previously set callbacks for a given keyboard combination

+
Parameters
    +
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      +
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • +
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • +
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • +
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • +
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • +
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • +
    • "lShift" or "l⇧" for the left Shift modifier
    • +
    • "rShift" or "r⇧" for the right Shift modifier
    • +
    +
  • +
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • +
+
Returns
    +
  • None
  • +
+
SourceSource/LeftRightHotkey.spoon/init.lua line 373
+
+
+ +
new
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureLeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject
TypeMethod
Description

Create a new hotkey with the specified left/right specific modifiers.

+
Parameters
    +
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      +
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • +
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • +
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • +
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • +
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • +
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • +
    • "lShift" or "l⇧" for the left Shift modifier
    • +
    • "rShift" or "r⇧" for the right Shift modifier
    • +
    +
  • +
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • +
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • +
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • +
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • +
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • +
+
Returns
    +
  • a new, initially disabled, hotkey with the specified left/right modifiers.
  • +
+
Notes
    +
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.new as is and any caveats or considerations outlined there also apply here.
  • +
+
SourceSource/LeftRightHotkey.spoon/init.lua line 263
+
+
+ +
start
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureLeftRightHotkey:start() -> self
TypeMethod
Description

Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

+
Parameters
    +
  • None
  • +
+
Returns
    +
  • the LeftRightHotkey spoon object
  • +
+
Notes
    +
  • this enables the use of hotkeys created by using this Spoon.
  • +
+
SourceSource/LeftRightHotkey.spoon/init.lua line 444
+
+
+ +
stop
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SignatureLeftRightHotkey:stop() -> self
TypeMethod
Description

Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

+
Parameters
    +
  • None
  • +
+
Returns
    +
  • the LeftRightHotkey spoon object
  • +
+
Notes
    +
  • this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with hs.hotkey directly will still be available.
  • +
+
SourceSource/LeftRightHotkey.spoon/init.lua line 471
+
+ + \ No newline at end of file diff --git a/docs/MiddleClickDragScroll.html b/docs/MiddleClickDragScroll.html new file mode 100644 index 00000000..2aad9ebb --- /dev/null +++ b/docs/MiddleClickDragScroll.html @@ -0,0 +1,68 @@ + + + + Hammerspoon docs: MiddleClickDragScroll + + + + +
+

docs » MiddleClickDragScroll

+

Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows. +Especially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.

+

Note: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position +where the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.

+

== Usage ==

+
local MiddleClickDragScroll = hs.loadSpoon("MiddleClickDragScroll"):start()
+
+

You can temporarily stop the spoon by calling MiddleClickDragScroll:stop() and then restart it by calling MiddleClickDragScroll:start() again.

+

== Configuration ==

+
local MiddleClickDragScroll = hs.loadSpoon("MiddleClickDragScroll"):configure{
+  excludedApps = {"Some App", "Other app"},         -- Don't activate scrolling in apps with these names
+  excludedWindows = {"^Some Window Title$"},        -- Don't activate scrolling in windows with these names (supports regex, for exact match, use "^title$")
+  excludedUrls = {"^https://geogebra.calculator$"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)
+  indicatorSize = 25,   -- Size of the scrolling indicator in pixels
+  indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.
+  {
+    type = "circle",
+    fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },
+    strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },
+  },
+  startDistance = 15,       -- Minimal distance to drag the mouse before scrolling is triggered.
+  scrollMode = "pixel",     -- Whether the scroll speed is in "line"s or "pixel"s. Scrolling by lines has smooting in some applications
+                            -- and therefore works with reduced frequency but it offers much less precise control.
+  scrollFrequency = 0.01,   -- How often to trigger scrolling (in seconds)
+  scrollAccelaration = 30,  -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.
+  scrollSpeedFn =           -- How scrolling accelerates based on the mouse distance from the initial location.
+                            -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument
+                            -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).
+  function(self, x)
+    return (x ^ 2) / (self.scrollAccelaration ^ 2)
+  end
+}:start()
+
+

Unspecified keys are unchanged. You can call configure multiple times to dynamically change it but changing indicatorAttributes and indicatorSize only works when MiddleClickDragScroll is stopped.

+

Instead of indicatorSize and indicatorAttributes, you can also pass a custom canvas to configure or set it directly to have more control over the indicator style:

+
MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{
+    type = "circle",
+    fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },
+    strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },
+  }
+
+

For more details, see: https://www.hammerspoon.org/docs/hs.canvas.html

+

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip

+ +
+

API Overview

+
    +
+

API Documentation

+ + \ No newline at end of file diff --git a/docs/ModalMgr.html b/docs/ModalMgr.html index d1a405dc..b16b53a1 100644 --- a/docs/ModalMgr.html +++ b/docs/ModalMgr.html @@ -64,7 +64,7 @@
activate
Source - Source/ModalMgr.spoon/init.lua line 129 + Source/ModalMgr.spoon/init.lua line 174 @@ -98,7 +98,7 @@
deactivate
Source - Source/ModalMgr.spoon/init.lua line 160 + Source/ModalMgr.spoon/init.lua line 205 @@ -132,7 +132,7 @@
deactivateAll
Source - Source/ModalMgr.spoon/init.lua line 179 + Source/ModalMgr.spoon/init.lua line 224 @@ -166,7 +166,7 @@
new
Source - Source/ModalMgr.spoon/init.lua line 46 + Source/ModalMgr.spoon/init.lua line 57 @@ -201,7 +201,7 @@
toggleCheatsheet
Source - Source/ModalMgr.spoon/init.lua line 57 + Source/ModalMgr.spoon/init.lua line 126 diff --git a/docs/MouseFollowsFocus.html b/docs/MouseFollowsFocus.html index ddd545f7..cbfc13ec 100644 --- a/docs/MouseFollowsFocus.html +++ b/docs/MouseFollowsFocus.html @@ -57,7 +57,7 @@
logger
Source - Source/MouseFollowsFocus.spoon/init.lua line 21 + Source/MouseFollowsFocus.spoon/init.lua line 24 @@ -76,13 +76,13 @@
configure
Description -

Configures the spoon. There is currently nothing to configure.

+

Configures the spoon.

Parameters
    -
  • configuration - :
  • +
  • configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:
@@ -92,7 +92,7 @@
configure
Source - Source/MouseFollowsFocus.spoon/init.lua line 26 + Source/MouseFollowsFocus.spoon/init.lua line 29 @@ -126,7 +126,7 @@
start
Source - Source/MouseFollowsFocus.spoon/init.lua line 35 + Source/MouseFollowsFocus.spoon/init.lua line 44 @@ -160,7 +160,7 @@
stop
Source - Source/MouseFollowsFocus.spoon/init.lua line 61 + Source/MouseFollowsFocus.spoon/init.lua line 73 @@ -194,7 +194,7 @@
updateMouse
Source - Source/MouseFollowsFocus.spoon/init.lua line 72 + Source/MouseFollowsFocus.spoon/init.lua line 84 diff --git a/docs/PaperWM.html b/docs/PaperWM.html new file mode 100644 index 00000000..c250194f --- /dev/null +++ b/docs/PaperWM.html @@ -0,0 +1,909 @@ + + + + Hammerspoon docs: PaperWM + + + + +
+

docs » PaperWM

+

A scrolling window manager. Inspired by PaperWM Gnome extension.

+

Usage

+

PaperWM:start() will begin automatically tiling new and existing windows. +PaperWM:stop() will release control over windows. +PaperWM::bindHotkeys() will move / resize windows using keyboard shortcuts.

+

Here is an example Hammerspoon config:

+ +
PaperWM = hs.loadSpoon("PaperWM")
+PaperWM:bindHotkeys({
+    -- switch to a new focused window in tiled grid
+    focus_left  = {{"ctrl", "alt", "cmd"}, "left"},
+    focus_right = {{"ctrl", "alt", "cmd"}, "right"},
+    focus_up    = {{"ctrl", "alt", "cmd"}, "up"},
+    focus_down  = {{"ctrl", "alt", "cmd"}, "down"},
+
+    -- move windows around in tiled grid
+    swap_left  = {{"ctrl", "alt", "cmd", "shift"}, "left"},
+    swap_right = {{"ctrl", "alt", "cmd", "shift"}, "right"},
+    swap_up    = {{"ctrl", "alt", "cmd", "shift"}, "up"},
+    swap_down  = {{"ctrl", "alt", "cmd", "shift"}, "down"},
+
+    -- position and resize focused window
+    center_window = {{"ctrl", "alt", "cmd"}, "c"},
+    full_width    = {{"ctrl", "alt", "cmd"}, "f"},
+    cycle_width   = {{"ctrl", "alt", "cmd"}, "r"},
+    cycle_height  = {{"ctrl", "alt", "cmd", "shift"}, "r"},
+
+    -- move focused window into / out of a column
+    slurp_in = {{"ctrl", "alt", "cmd"}, "i"},
+    barf_out = {{"ctrl", "alt", "cmd"}, "o"},
+
+    -- switch to a new Mission Control space
+    switch_space_1 = {{"ctrl", "alt", "cmd"}, "1"},
+    switch_space_2 = {{"ctrl", "alt", "cmd"}, "2"},
+    switch_space_3 = {{"ctrl", "alt", "cmd"}, "3"},
+    switch_space_4 = {{"ctrl", "alt", "cmd"}, "4"},
+    switch_space_5 = {{"ctrl", "alt", "cmd"}, "5"},
+    switch_space_6 = {{"ctrl", "alt", "cmd"}, "6"},
+    switch_space_7 = {{"ctrl", "alt", "cmd"}, "7"},
+    switch_space_8 = {{"ctrl", "alt", "cmd"}, "8"},
+    switch_space_9 = {{"ctrl", "alt", "cmd"}, "9"},
+
+    -- move focused window to a new space and tile
+    move_window_1 = {{"ctrl", "alt", "cmd", "shift"}, "1"},
+    move_window_2 = {{"ctrl", "alt", "cmd", "shift"}, "2"},
+    move_window_3 = {{"ctrl", "alt", "cmd", "shift"}, "3"},
+    move_window_4 = {{"ctrl", "alt", "cmd", "shift"}, "4"},
+    move_window_5 = {{"ctrl", "alt", "cmd", "shift"}, "5"},
+    move_window_6 = {{"ctrl", "alt", "cmd", "shift"}, "6"},
+    move_window_7 = {{"ctrl", "alt", "cmd", "shift"}, "7"},
+    move_window_8 = {{"ctrl", "alt", "cmd", "shift"}, "8"},
+    move_window_9 = {{"ctrl", "alt", "cmd", "shift"}, "9"}
+})
+PaperWM:start()
+
+

Use PaperWM:bindHotkeys(PaperWM.default_hotkeys) for defaults.

+

Set PaperWM.window_gap to the number of pixels to space between windows and +the top and bottom screen edges.

+

Overwrite PaperWM.window_filter to ignore specific applications. For example:

+ +
PaperWM.window_filter = PaperWM.window_filter:setAppFilter("Finder", false)
+PaperWM:start() -- restart for new window filter to take effect
+
+

Limitations

+

Under System Preferences -> Mission Control, unselect "Automatically +rearrange Spaces based on most recent use" and select "Displays have separate +Spaces".

+

MacOS does not allow a window to be moved fully off-screen. Windows that would +be tiled off-screen are placed in a margin on the left and right edge of the +screen. They are still visible and clickable.

+

It's difficult to detect when a window is dragged from one space or screen to +another. Use the move_window_N commands to move windows between spaces and +screens.

+

Arrange screens vertically to prevent windows from bleeding into other screens.

+

Download: https://github.com/mogenson/PaperWM.spoon

+ +
+

API Overview

+ +

API Documentation

+

Variables

+
+ +
default_hotkeys
+ + + + + + + + + + + + + + + + + +
SignaturePaperWM.default_hotkeys
TypeVariable
Description

Default hotkeys for moving / resizing windows

+
SourceSource/PaperWM.spoon/init.lua line 111
+
+
+ +
logger
+ + + + + + + + + + + + + + + + + +
SignaturePaperWM.logger
TypeVariable
Description

Logger object. Can be accessed to set default log level.

+
SourceSource/PaperWM.spoon/init.lua line 165
+
+
+ +
window_filter
+ + + + + + + + + + + + + + + + + +
SignaturePaperWM.window_filter
TypeVariable
Description

Windows captured by this filter are automatically tiled and managed

+
SourceSource/PaperWM.spoon/init.lua line 150
+
+
+ +
window_gap
+ + + + + + + + + + + + + + + + + +
SignaturePaperWM.window_gap
TypeVariable
Description

Number of pixels between tiled windows

+
SourceSource/PaperWM.spoon/init.lua line 160
+
+

Methods

+
+ +
addWindow
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:addWindow(add_window)
TypeMethod
Description

Adds a window to layout and tiles.

+
Parameters
    +
  • add_window - An hs.window
  • +
+
Returns
    +
  • The hs.spaces space for added window or nil if window not added.
  • +
+
SourceSource/PaperWM.spoon/init.lua line 594
+
+
+ +
barfWindow
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:barfWindow()
TypeMethod
Description

Removes current window from column and places it to the right

+
Parameters
    +
  • None
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 1026
+
+
+ +
bindHotkeys
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM.bindHotkeys(mapping)
TypeMethod
Description

Binds hotkeys for PaperWM

+
Parameters
    +
  • mapping - A table containing hotkey modifer/key details for the following items:
      +
    • stop_events - Stop automatic tiling
    • +
    • focus_left - Focus window to left of current window
    • +
    • focus_right - Focus window to right of current window
    • +
    • focus_up - Focus window to up of current window
    • +
    • focus_down - Focus window to down of current window
    • +
    • swap_left - Swap positions of window to the left and current window
    • +
    • swap_right - Swap positions of window to the right and current window
    • +
    • swap_up - Swap positions of window above and current window
    • +
    • swap_down - Swap positions of window below and current window
    • +
    • center_window - Move current window to center of screen
    • +
    • full_width - Resize width of current window to width of screen
    • +
    • cycle_width - Toggle through preset window widths
    • +
    • cycle_height - Toggle through preset window heights
    • +
    • slurp_in - Move current window into column to the left
    • +
    • barf_out - Remove current window from column and place to the right
    • +
    • switch_space_1 - Switch to Mission Control space 1
    • +
    • switch_space_2 - Switch to Mission Control space 2
    • +
    • switch_space_3 - Switch to Mission Control space 3
    • +
    • switch_space_4 - Switch to Mission Control space 4
    • +
    • switch_space_5 - Switch to Mission Control space 5
    • +
    • switch_space_6 - Switch to Mission Control space 6
    • +
    • switch_space_7 - Switch to Mission Control space 7
    • +
    • switch_space_8 - Switch to Mission Control space 8
    • +
    • switch_space_9 - Switch to Mission Control space 9
    • +
    • move_window_1 - Move current window to Mission Control space 1
    • +
    • move_window_2 - Move current window to Mission Control space 2
    • +
    • move_window_3 - Move current window to Mission Control space 3
    • +
    • move_window_4 - Move current window to Mission Control space 4
    • +
    • move_window_5 - Move current window to Mission Control space 5
    • +
    • move_window_6 - Move current window to Mission Control space 6
    • +
    • move_window_7 - Move current window to Mission Control space 7
    • +
    • move_window_8 - Move current window to Mission Control space 8
    • +
    • move_window_9 - Move current window to Mission Control space 9
    • +
    +
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 275
+
+
+ +
centerWindow
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:centerWindow()
TypeMethod
Description

Moves current window to center of screen, without resizing.

+
Parameters
    +
  • None
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 860
+
+
+ +
cycleWindowSize
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:cycleWindowSize(direction)
TypeMethod
Description

Resizes current window by cycling through width or height ratios.

+
Parameters
    +
  • direction - One of Direction { WIDTH, HEIGHT }
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 907
+
+
+ +
focusWindow
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:focusWindow(direction, focused_index)
TypeMethod
Description

Change focus to a nearby window

+
Parameters
    +
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • +
  • focused_index - The coordinates of the current window in the tiling layout
  • +
+
Returns
    +
  • A boolean. True if a new window was focused. False if no nearby window +was found in that direction.
  • +
+
SourceSource/PaperWM.spoon/init.lua line 699
+
+
+ +
moveWindow
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM::moveWindow(window, frame)
TypeMethod
Description

Resizes a window without triggering a windowMoved event

+
Parameters
    +
  • window - An hs.window
  • +
  • frame - An hs.geometry.rect for the windows new frame size.
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 1147
+
+
+ +
moveWindowToSpace
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:moveWindowToSpace(index)
TypeMethod
Description

Moves the current window to a new Mission Control space

+
Parameters
    +
  • index - The space number
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 1096
+
+
+ +
refreshWindows
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:refreshWindows()
TypeMethod
Description

Searches for all windows that match window filter.

+
Parameters
    +
  • None
  • +
+
Returns
    +
  • A boolean, true if the layout needs to be re-tiled, false if no change.
  • +
+
SourceSource/PaperWM.spoon/init.lua line 563
+
+
+ +
remove_window
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:remove_window(remove_window, skip_new_window_focus)
TypeMethod
Description

Remove window from tiling layout

+
Parameters
    +
  • remove_window - A hs.window to remove from tiling layout
  • +
  • skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed.
  • +
+
Returns
    +
  • The hs.spaces space for removed window.
  • +
+
SourceSource/PaperWM.spoon/init.lua line 652
+
+
+ +
setWindowFullWidth
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:setWindowFullWidth()
TypeMethod
Description

Resizes current window's width to width of screen, without adjusting height.

+
Parameters
    +
  • None
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 885
+
+
+ +
slurpWindow
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:slurpWindow()
TypeMethod
Description

Moves current window into column of windows to the left

+
Parameters
    +
  • None
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 961
+
+
+ +
start
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:start()
TypeMethod
Description

Start automatic tiling of windows

+
Parameters
    +
  • None
  • +
+
Returns
    +
  • The PaperWM object
  • +
+
SourceSource/PaperWM.spoon/init.lua line 354
+
+
+ +
stop
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:stop()
TypeMethod
Description

Stop automatic tiling of windows

+
Parameters
    +
  • None
  • +
+
Returns
    +
  • The PaperWM object
  • +
+
SourceSource/PaperWM.spoon/init.lua line 391
+
+
+ +
swapWindows
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:swapWindows(direction)
TypeMethod
Description

Swaps window postions between current window and window in specified direction.

+
Parameters
    +
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 749
+
+
+ +
switchToSpace
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:switchToSpace(index)
TypeMethod
Description

Switch to a Mission Control space

+
Parameters
    +
  • index - The space number
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 1080
+
+
+ +
tileColumn
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:tileColumn(windows, bounds, h, w, id, h4id)
TypeMethod
Description

Tile a column of windows

+
Parameters
    +
  • windows - A list of hs.windows.
  • +
  • bounds - An hs.geometry.rect. The area for this column to fill.
  • +
  • h - The height for each window in column.
  • +
  • w - The width for each window in column.
  • +
  • id - A hs.window.id() for a specific window in column.
  • +
  • h4id - The height for a window matching id in column.
  • +
+
Returns
    +
  • The width of the column
  • +
+
Notes
    +
  • The h, w, id, and h4id parameters are optional. The height and width of +all windows will be calculated and set to fill column bounds.
  • +
  • If bounds width is not specified, all windows in column will be resized +to width of first window.
  • +
+
SourceSource/PaperWM.spoon/init.lua line 408
+
+
+ +
tileSpace
+ + + + + + + + + + + + + + + + + + + + + + + + + +
SignaturePaperWM:tileSpace(space)
TypeMethod
Description

Tile all windows within a space

+
Parameters
    +
  • space - A hs.spaces space.
  • +
+
Returns
SourceSource/PaperWM.spoon/init.lua line 460
+
+ + \ No newline at end of file diff --git a/docs/TimeMachineProgress.html b/docs/TimeMachineProgress.html index 6d7438ab..626e5399 100644 --- a/docs/TimeMachineProgress.html +++ b/docs/TimeMachineProgress.html @@ -183,7 +183,7 @@
start
Source - Source/TimeMachineProgress.spoon/init.lua line 203 + Source/TimeMachineProgress.spoon/init.lua line 207 @@ -220,7 +220,7 @@
stop
Source - Source/TimeMachineProgress.spoon/init.lua line 221 + Source/TimeMachineProgress.spoon/init.lua line 225 diff --git a/docs/docs.json b/docs/docs.json index ccfaede9..cbf7a926 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -13,7 +13,7 @@ "doc": "Hide AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "116", + "lineno": "130", "name": "hide", "notes": [], "parameters": [ @@ -51,7 +51,7 @@ "doc": "Show AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "97", + "lineno": "111", "name": "show", "notes": [], "parameters": [ @@ -70,7 +70,7 @@ "doc": "Show AClock for 4 seconds. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "133", + "lineno": "147", "name": "toggleShow", "notes": [], "parameters": [ @@ -87,7 +87,7 @@ "doc": "Show AClock. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "154", + "lineno": "168", "name": "toggleShowPersistent", "notes": [], "parameters": [ @@ -109,7 +109,7 @@ "doc": "Hide AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "116", + "lineno": "130", "name": "hide", "notes": [], "parameters": [ @@ -147,7 +147,7 @@ "doc": "Show AClock.\n\nParameters:\n * None\n\nReturns:\n * The AClock object", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "97", + "lineno": "111", "name": "show", "notes": [], "parameters": [ @@ -166,7 +166,7 @@ "doc": "Show AClock for 4 seconds. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "133", + "lineno": "147", "name": "toggleShow", "notes": [], "parameters": [ @@ -183,7 +183,7 @@ "doc": "Show AClock. If already showing, hide it.\n\nParameters:\n * None", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "154", + "lineno": "168", "name": "toggleShowPersistent", "notes": [], "parameters": [ @@ -845,6 +845,23 @@ "submodules": [], "type": "Module" }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [], + "Variable": [], + "desc": "Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.", + "doc": "Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.\nUseful to avoid blasting sound when opening a Macbook in the public transport.\nNote: This is primarily intended for portable Mac devices, which have internal speakers.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip)", + "items": [], + "name": "AutoMuteOnSleep", + "stripped_doc": "Useful to avoid blasting sound when opening a Macbook in the public transport.\nNote: This is primarily intended for portable Mac devices, which have internal speakers.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip)", + "submodules": [], + "type": "Module" + }, { "Command": [], "Constant": [], @@ -6765,6 +6782,241 @@ "submodules": [], "type": "Module" }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "InputMethodIndicator:init()", + "desc": "init.", + "doc": "init.\n\nParameters:\n * None\n\nReturns:\n * The InputMethodIndicator object", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "67", + "name": "init", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The InputMethodIndicator object" + ], + "signature": "InputMethodIndicator:init()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:start(config)", + "desc": "Start InputMethodIndicator.", + "doc": "Start InputMethodIndicator.\n\nParameters:\n * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "200", + "name": "start", + "notes": [], + "parameters": [ + " * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse" + ], + "returns": [], + "signature": "InputMethodIndicator:start(config)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:stop()", + "desc": "Stop InputMethodIndicator.", + "doc": "Stop InputMethodIndicator.\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "245", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputMethodIndicator:stop()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [], + "desc": "Show input method indicator in the current mouse position.", + "doc": "Show input method indicator in the current mouse position.\nIt is a small but noticable dot near the cursor.\nIt can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method.\nYou can use it as follows in the init.lua:\nhs.loadSpoon(\"InputMethodIndicator\")\nspoon.InputMethodIndicator:start(nil)\nnote: config parameter is a table, pass nil to use the default config\nthe default config is as follows:\n{\n ABCColor = \"#62C555\", -- the dot color when the input method is ABC\n LocalLanguageColor = \"#ED6A5E\", -- the dot color when the input method is not ABC\n mode = \"nearMouse\", -- the mode of the indicator\n showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed\n checkInterval = .01, -- seconds to check the input method\n dotSize = 6, -- the size of the dot\n deltaY=7, -- the distance between the dot and the center of the selection or mouse\n}\nthe mode can be \"nearMouse\",\"onChange\",\"adaptive\", the default mode is \"adaptive\"\n\"nearMouse\" means the indicator will always show near the mouse\n\"onChange\" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds\n\"adaptive\" means the indicator will show near the textarea when typing, otherwise it will show near the mouse\nNote: the \"adaptive\" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API", + "items": [ + { + "def": "InputMethodIndicator:init()", + "desc": "init.", + "doc": "init.\n\nParameters:\n * None\n\nReturns:\n * The InputMethodIndicator object", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "67", + "name": "init", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The InputMethodIndicator object" + ], + "signature": "InputMethodIndicator:init()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:start(config)", + "desc": "Start InputMethodIndicator.", + "doc": "Start InputMethodIndicator.\n\nParameters:\n * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "200", + "name": "start", + "notes": [], + "parameters": [ + " * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse" + ], + "returns": [], + "signature": "InputMethodIndicator:start(config)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:stop()", + "desc": "Stop InputMethodIndicator.", + "doc": "Stop InputMethodIndicator.\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "245", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputMethodIndicator:stop()", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "InputMethodIndicator", + "stripped_doc": "It is a small but noticable dot near the cursor.\nIt can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method.\nYou can use it as follows in the init.lua:\nhs.loadSpoon(\"InputMethodIndicator\")\nspoon.InputMethodIndicator:start(nil)\nnote: config parameter is a table, pass nil to use the default config\nthe default config is as follows:\n{\n ABCColor = \"#62C555\", -- the dot color when the input method is ABC\n LocalLanguageColor = \"#ED6A5E\", -- the dot color when the input method is not ABC\n mode = \"nearMouse\", -- the mode of the indicator\n showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed\n checkInterval = .01, -- seconds to check the input method\n dotSize = 6, -- the size of the dot\n deltaY=7, -- the distance between the dot and the center of the selection or mouse\n}\nthe mode can be \"nearMouse\",\"onChange\",\"adaptive\", the default mode is \"adaptive\"\n\"nearMouse\" means the indicator will always show near the mouse\n\"onChange\" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds\n\"adaptive\" means the indicator will show near the textarea when typing, otherwise it will show near the mouse\nNote: the \"adaptive\" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API", + "submodules": [], + "type": "Module" + }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "InputSourceSwitch:setApplications()", + "desc": "Set that mapping the application name to the input source", + "doc": "Set that mapping the application name to the input source\n\nParameters:\n * applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:\n```\n{\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n}\n```", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "80", + "name": "setApplications", + "notes": [], + "parameters": [ + " * applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: ``` { [\"WeChat\"] = \"Pinyin - Simplified\", [\"Mail\"] = \"ABC\" } ```" + ], + "returns": [], + "signature": "InputSourceSwitch:setApplications()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputSourceSwitch:start()", + "desc": "Start InputSourceSwitch", + "doc": "Start InputSourceSwitch\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "100", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputSourceSwitch:start()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ + { + "def": "InputSourceSwitch.applicationMap", + "desc": "Mapping the application name to the input source", + "doc": "Mapping the application name to the input source", + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "75", + "name": "applicationMap", + "signature": "InputSourceSwitch.applicationMap", + "stripped_doc": "", + "type": "Variable" + } + ], + "desc": "Automatically switch the input source when switching applications.", + "doc": "Automatically switch the input source when switching applications.\n\nExample:\n```\nhs.loadSpoon(\"InputSourceSwitch\")\n\nspoon.InputSourceSwitch:setApplications({\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n})\n\nspoon.InputSourceSwitch:start()\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip)", + "items": [ + { + "def": "InputSourceSwitch.applicationMap", + "desc": "Mapping the application name to the input source", + "doc": "Mapping the application name to the input source", + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "75", + "name": "applicationMap", + "signature": "InputSourceSwitch.applicationMap", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "InputSourceSwitch:setApplications()", + "desc": "Set that mapping the application name to the input source", + "doc": "Set that mapping the application name to the input source\n\nParameters:\n * applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:\n```\n{\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n}\n```", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "80", + "name": "setApplications", + "notes": [], + "parameters": [ + " * applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: ``` { [\"WeChat\"] = \"Pinyin - Simplified\", [\"Mail\"] = \"ABC\" } ```" + ], + "returns": [], + "signature": "InputSourceSwitch:setApplications()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputSourceSwitch:start()", + "desc": "Start InputSourceSwitch", + "doc": "Start InputSourceSwitch\n\nParameters:\n * None", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "100", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "InputSourceSwitch:start()", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "InputSourceSwitch", + "stripped_doc": "\nExample:\n```\nhs.loadSpoon(\"InputSourceSwitch\")\n\nspoon.InputSourceSwitch:setApplications({\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n})\n\nspoon.InputSourceSwitch:start()\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip)", + "submodules": [], + "type": "Module" + }, { "Command": [], "Constant": [], @@ -7612,90 +7864,379 @@ "Function": [], "Method": [ { - "def": "LookupSelection:bindHotkeys(mapping)", - "desc": "Binds hotkeys for LookupSelection", - "doc": "Binds hotkeys for LookupSelection\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help\n\nNotes:\n * Sample value for `mapping`:\n```\n {\n lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },\n neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },\n hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },\n }\n```", + "def": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create and enable a new hotkey with the specified left/right specific modifiers.", + "doc": "Create and enable a new hotkey with the specified left/right specific modifiers.\n\nParameters:\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new enabled hotkey with the specified left/right modifiers.\n\nNotes:\n * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here.", "examples": [], - "file": "Source/LookupSelection.spoon/init.lua", - "lineno": "93", - "name": "bindHotkeys", + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "415", + "name": "bind", "notes": [ - " * Sample value for `mapping`:", - "```", - " {", - " lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },", - " neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },", - " hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },", - " }", - "```" + " * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`", + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here." ], "parameters": [ - " * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help" + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" ], - "returns": [], - "signature": "LookupSelection:bindHotkeys(mapping)", + "returns": [ + " * a new enabled hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", "stripped_doc": "", "type": "Method" }, { - "def": "LookupSelection:openLexicon()", - "desc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages", - "doc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages\n\nParameters:\n * None\n\nReturns:\n * The LookupSelection object", + "def": "LeftRightHotkey:deleteAll(mods, key)", + "desc": "Deletes all previously set callbacks for a given keyboard combination", + "doc": "Deletes all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", "examples": [], - "file": "Source/LookupSelection.spoon/init.lua", - "lineno": "58", - "name": "openLexicon", + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "326", + "name": "deleteAll", "notes": [], "parameters": [ - " * None" + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" ], "returns": [ - " * The LookupSelection object" + " * None" ], - "signature": "LookupSelection:openLexicon()", + "signature": "LeftRightHotkey:deleteAll(mods, key)", "stripped_doc": "", "type": "Method" - } - ], - "Variable": [ - { - "def": "LookupSelection.logger", - "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", - "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", - "file": "Source/LookupSelection.spoon/init.lua", - "lineno": "42", - "name": "logger", - "signature": "LookupSelection.logger", - "stripped_doc": "", - "type": "Variable" - } - ], - "desc": "Show a popup window with the currently selected word in lexicon, notes, online help", - "doc": "Show a popup window with the currently selected word in lexicon, notes, online help\n\nThe spoon uses hs.urlevent.openURL(\"dict://\" .. text) \n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LookupSelection.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LookupSelection.spoon.zip)", - "items": [ + }, { - "def": "LookupSelection:bindHotkeys(mapping)", - "desc": "Binds hotkeys for LookupSelection", - "doc": "Binds hotkeys for LookupSelection\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help\n\nNotes:\n * Sample value for `mapping`:\n```\n {\n lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },\n neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },\n hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },\n }\n```", + "def": "LeftRightHotkey:disableAll(mods, key)", + "desc": "Disables all previously set callbacks for a given keyboard combination", + "doc": "Disables all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", "examples": [], - "file": "Source/LookupSelection.spoon/init.lua", - "lineno": "93", - "name": "bindHotkeys", - "notes": [ - " * Sample value for `mapping`:", - "```", - " {", - " lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },", - " neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },", - " hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },", - " }", - "```" - ], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "373", + "name": "disableAll", + "notes": [], "parameters": [ - " * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help" + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" ], - "returns": [], - "signature": "LookupSelection:bindHotkeys(mapping)", + "returns": [ + " * None" + ], + "signature": "LeftRightHotkey:disableAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create a new hotkey with the specified left/right specific modifiers.", + "doc": "Create a new hotkey with the specified left/right specific modifiers.\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new, initially disabled, hotkey with the specified left/right modifiers.\n\nNotes:\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "263", + "name": "new", + "notes": [ + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here." + ], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "returns": [ + " * a new, initially disabled, hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:start() -> self", + "desc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this enables the use of hotkeys created by using this Spoon.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "444", + "name": "start", + "notes": [ + " * this enables the use of hotkeys created by using this Spoon." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:start() -> self", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:stop() -> self", + "desc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "471", + "name": "stop", + "notes": [ + " * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:stop() -> self", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [], + "desc": "This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.", + "doc": "This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.\n\nThis is accomplished by creating unactivated hotkeys for each definition and using an [hs.eventtap](hs.eventtap.html) watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the `bind` and `new` methods of this spoon.\n\nThe `LeftRightHotkeyObject` that is returned by [LeftRightHotkey:new](#new) and [LeftRightHotkey:bind](#bind) supports the following methods in a manner similar to the [hs.hotkey](hs.hotkey.html) equivalents:\n\n * `LeftRightHotkeyObject:enable()` -- enables the registered hotkey.\n * `LeftRightHotkeyObject:disable()` -- disables the registered hotkey.\n * `LeftRightHotkeyObject:delete()` -- deletes the registered hotkey.\n * `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)\n\nThe following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n\nThe modifiers table for any given hotkey is all inclusive; this means that if you specify `{ \"rShift\", \"lShift\" }` then *both* the left and right shift keys *must* be pressed to trigger the hotkey -- if you want either/or, then stick with [hs.hotkey](hs.hotkey.html).\n\nAlternatively, if you want to setup a hotkey when *either* command key is pressed with *only* the right shift, you would need to set up two hotkeys with this spoon:\n e.g. `LeftRightHotkey:bind({ \"rCmd\", \"rShift\" }, \"a\", myFunction)` *and* `LeftRightHotkey:bind({ \"lCmd\", \"rShift\" }, \"a\", myFunction)`\n\nThis spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:\n * like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.\n * behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through `hs.hotkey:enable()` -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.\n * a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue [LeftRightHotkey:start()](#start) to force the eventtap to be reset if necessary.\n * if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.\n\nLike all Spoons, don't forget to use the [LeftRightHotkey:start()](#start) method to activate the modifier key watcher.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip)", + "items": [ + { + "def": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create and enable a new hotkey with the specified left/right specific modifiers.", + "doc": "Create and enable a new hotkey with the specified left/right specific modifiers.\n\nParameters:\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new enabled hotkey with the specified left/right modifiers.\n\nNotes:\n * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "415", + "name": "bind", + "notes": [ + " * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`", + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here." + ], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "returns": [ + " * a new enabled hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:deleteAll(mods, key)", + "desc": "Deletes all previously set callbacks for a given keyboard combination", + "doc": "Deletes all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "326", + "name": "deleteAll", + "notes": [], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "returns": [ + " * None" + ], + "signature": "LeftRightHotkey:deleteAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:disableAll(mods, key)", + "desc": "Disables all previously set callbacks for a given keyboard combination", + "doc": "Disables all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "373", + "name": "disableAll", + "notes": [], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "returns": [ + " * None" + ], + "signature": "LeftRightHotkey:disableAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create a new hotkey with the specified left/right specific modifiers.", + "doc": "Create a new hotkey with the specified left/right specific modifiers.\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new, initially disabled, hotkey with the specified left/right modifiers.\n\nNotes:\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "263", + "name": "new", + "notes": [ + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here." + ], + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "returns": [ + " * a new, initially disabled, hotkey with the specified left/right modifiers." + ], + "signature": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:start() -> self", + "desc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this enables the use of hotkeys created by using this Spoon.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "444", + "name": "start", + "notes": [ + " * this enables the use of hotkeys created by using this Spoon." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:start() -> self", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:stop() -> self", + "desc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "doc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available.", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "471", + "name": "stop", + "notes": [ + " * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available." + ], + "parameters": [ + " * None" + ], + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "signature": "LeftRightHotkey:stop() -> self", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "LeftRightHotkey", + "stripped_doc": "\nThis is accomplished by creating unactivated hotkeys for each definition and using an [hs.eventtap](hs.eventtap.html) watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the `bind` and `new` methods of this spoon.\n\nThe `LeftRightHotkeyObject` that is returned by [LeftRightHotkey:new](#new) and [LeftRightHotkey:bind](#bind) supports the following methods in a manner similar to the [hs.hotkey](hs.hotkey.html) equivalents:\n\n * `LeftRightHotkeyObject:enable()` -- enables the registered hotkey.\n * `LeftRightHotkeyObject:disable()` -- disables the registered hotkey.\n * `LeftRightHotkeyObject:delete()` -- deletes the registered hotkey.\n * `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)\n\nThe following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n\nThe modifiers table for any given hotkey is all inclusive; this means that if you specify `{ \"rShift\", \"lShift\" }` then *both* the left and right shift keys *must* be pressed to trigger the hotkey -- if you want either/or, then stick with [hs.hotkey](hs.hotkey.html).\n\nAlternatively, if you want to setup a hotkey when *either* command key is pressed with *only* the right shift, you would need to set up two hotkeys with this spoon:\n e.g. `LeftRightHotkey:bind({ \"rCmd\", \"rShift\" }, \"a\", myFunction)` *and* `LeftRightHotkey:bind({ \"lCmd\", \"rShift\" }, \"a\", myFunction)`\n\nThis spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:\n * like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.\n * behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through `hs.hotkey:enable()` -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.\n * a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue [LeftRightHotkey:start()](#start) to force the eventtap to be reset if necessary.\n * if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.\n\nLike all Spoons, don't forget to use the [LeftRightHotkey:start()](#start) method to activate the modifier key watcher.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip)", + "submodules": [], + "type": "Module" + }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "LookupSelection:bindHotkeys(mapping)", + "desc": "Binds hotkeys for LookupSelection", + "doc": "Binds hotkeys for LookupSelection\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help\n\nNotes:\n * Sample value for `mapping`:\n```\n {\n lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },\n neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },\n hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },\n }\n```", + "examples": [], + "file": "Source/LookupSelection.spoon/init.lua", + "lineno": "93", + "name": "bindHotkeys", + "notes": [ + " * Sample value for `mapping`:", + "```", + " {", + " lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },", + " neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },", + " hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },", + " }", + "```" + ], + "parameters": [ + " * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help" + ], + "returns": [], + "signature": "LookupSelection:bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LookupSelection:openLexicon()", + "desc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages", + "doc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages\n\nParameters:\n * None\n\nReturns:\n * The LookupSelection object", + "examples": [], + "file": "Source/LookupSelection.spoon/init.lua", + "lineno": "58", + "name": "openLexicon", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The LookupSelection object" + ], + "signature": "LookupSelection:openLexicon()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ + { + "def": "LookupSelection.logger", + "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", + "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", + "file": "Source/LookupSelection.spoon/init.lua", + "lineno": "42", + "name": "logger", + "signature": "LookupSelection.logger", + "stripped_doc": "", + "type": "Variable" + } + ], + "desc": "Show a popup window with the currently selected word in lexicon, notes, online help", + "doc": "Show a popup window with the currently selected word in lexicon, notes, online help\n\nThe spoon uses hs.urlevent.openURL(\"dict://\" .. text) \n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LookupSelection.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LookupSelection.spoon.zip)", + "items": [ + { + "def": "LookupSelection:bindHotkeys(mapping)", + "desc": "Binds hotkeys for LookupSelection", + "doc": "Binds hotkeys for LookupSelection\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help\n\nNotes:\n * Sample value for `mapping`:\n```\n {\n lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },\n neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },\n hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },\n }\n```", + "examples": [], + "file": "Source/LookupSelection.spoon/init.lua", + "lineno": "93", + "name": "bindHotkeys", + "notes": [ + " * Sample value for `mapping`:", + "```", + " {", + " lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },", + " neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },", + " hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },", + " }", + "```" + ], + "parameters": [ + " * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help" + ], + "returns": [], + "signature": "LookupSelection:bindHotkeys(mapping)", "stripped_doc": "", "type": "Method" }, @@ -8186,6 +8727,23 @@ "submodules": [], "type": "Module" }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [], + "Variable": [], + "desc": "Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.", + "doc": "Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.\nEspecially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.\n\nNote: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position\nwhere the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.\n\n== Usage ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):start()\n```\n\nYou can temporarily stop the spoon by calling `MiddleClickDragScroll:stop()` and then restart it by calling `MiddleClickDragScroll:start()` again.\n\n== Configuration ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):configure{\n excludedApps = {\"Some App\", \"Other app\"}, -- Don't activate scrolling in apps with these names\n excludedWindows = {\"^Some Window Title$\"}, -- Don't activate scrolling in windows with these names (supports regex, for exact match, use \"^title$\")\n excludedUrls = {\"^https://geogebra.calculator$\"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)\n indicatorSize = 25, -- Size of the scrolling indicator in pixels\n indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.\n {\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n },\n startDistance = 15, -- Minimal distance to drag the mouse before scrolling is triggered.\n scrollMode = \"pixel\", -- Whether the scroll speed is in \"line\"s or \"pixel\"s. Scrolling by lines has smooting in some applications\n -- and therefore works with reduced frequency but it offers much less precise control.\n scrollFrequency = 0.01, -- How often to trigger scrolling (in seconds)\n scrollAccelaration = 30, -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.\n scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location.\n -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument\n -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).\n function(self, x)\n return (x ^ 2) / (self.scrollAccelaration ^ 2)\n end\n}:start()\n```\n\nUnspecified keys are unchanged. You can call `configure` multiple times to dynamically change it but changing `indicatorAttributes` and `indicatorSize` only works when `MiddleClickDragScroll` is stopped.\n\nInstead of `indicatorSize` and `indicatorAttributes`, you can also pass a custom canvas to `configure` or set it directly to have more control over the indicator style:\n\n```lua\n MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n }\n```\n\nFor more details, see: https://www.hammerspoon.org/docs/hs.canvas.html\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip)", + "items": [], + "name": "MiddleClickDragScroll", + "stripped_doc": "Especially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.\n\nNote: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position\nwhere the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.\n\n== Usage ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):start()\n```\n\nYou can temporarily stop the spoon by calling `MiddleClickDragScroll:stop()` and then restart it by calling `MiddleClickDragScroll:start()` again.\n\n== Configuration ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):configure{\n excludedApps = {\"Some App\", \"Other app\"}, -- Don't activate scrolling in apps with these names\n excludedWindows = {\"^Some Window Title$\"}, -- Don't activate scrolling in windows with these names (supports regex, for exact match, use \"^title$\")\n excludedUrls = {\"^https://geogebra.calculator$\"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)\n indicatorSize = 25, -- Size of the scrolling indicator in pixels\n indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.\n {\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n },\n startDistance = 15, -- Minimal distance to drag the mouse before scrolling is triggered.\n scrollMode = \"pixel\", -- Whether the scroll speed is in \"line\"s or \"pixel\"s. Scrolling by lines has smooting in some applications\n -- and therefore works with reduced frequency but it offers much less precise control.\n scrollFrequency = 0.01, -- How often to trigger scrolling (in seconds)\n scrollAccelaration = 30, -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.\n scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location.\n -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument\n -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).\n function(self, x)\n return (x ^ 2) / (self.scrollAccelaration ^ 2)\n end\n}:start()\n```\n\nUnspecified keys are unchanged. You can call `configure` multiple times to dynamically change it but changing `indicatorAttributes` and `indicatorSize` only works when `MiddleClickDragScroll` is stopped.\n\nInstead of `indicatorSize` and `indicatorAttributes`, you can also pass a custom canvas to `configure` or set it directly to have more control over the indicator style:\n\n```lua\n MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n }\n```\n\nFor more details, see: https://www.hammerspoon.org/docs/hs.canvas.html\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip)", + "submodules": [], + "type": "Module" + }, { "Command": [], "Constant": [], @@ -8360,7 +8918,7 @@ "doc": "Activate all modal environment in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments\n * trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to `nil`.\n * showKeys - A optional boolean value to show all available keybindings, defaults to `nil`.", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "129", + "lineno": "174", "name": "activate", "notes": [], "parameters": [ @@ -8379,7 +8937,7 @@ "doc": "Deactivate modal environments in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "160", + "lineno": "205", "name": "deactivate", "notes": [], "parameters": [ @@ -8396,7 +8954,7 @@ "doc": "Deactivate all active modal environments.\n\nParameters:\n * None", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "179", + "lineno": "224", "name": "deactivateAll", "notes": [], "parameters": [ @@ -8413,7 +8971,7 @@ "doc": "Create a new modal keybindings environment\n\nParameters:\n * id - A string specifying ID of new modal keybindings", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "46", + "lineno": "57", "name": "new", "notes": [], "parameters": [ @@ -8430,7 +8988,7 @@ "doc": "Toggle the cheatsheet display of current modal environments's keybindings.\n\nParameters:\n * iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.\n * force - A optional boolean value to force show cheatsheet, defaults to `nil` (automatically).", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "57", + "lineno": "126", "name": "toggleCheatsheet", "notes": [], "parameters": [ @@ -8453,7 +9011,7 @@ "doc": "Activate all modal environment in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments\n * trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to `nil`.\n * showKeys - A optional boolean value to show all available keybindings, defaults to `nil`.", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "129", + "lineno": "174", "name": "activate", "notes": [], "parameters": [ @@ -8472,7 +9030,7 @@ "doc": "Deactivate modal environments in `idList`.\n\nParameters:\n * idList - An table specifying IDs of modal environments", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "160", + "lineno": "205", "name": "deactivate", "notes": [], "parameters": [ @@ -8489,7 +9047,7 @@ "doc": "Deactivate all active modal environments.\n\nParameters:\n * None", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "179", + "lineno": "224", "name": "deactivateAll", "notes": [], "parameters": [ @@ -8506,7 +9064,7 @@ "doc": "Create a new modal keybindings environment\n\nParameters:\n * id - A string specifying ID of new modal keybindings", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "46", + "lineno": "57", "name": "new", "notes": [], "parameters": [ @@ -8523,7 +9081,7 @@ "doc": "Toggle the cheatsheet display of current modal environments's keybindings.\n\nParameters:\n * iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.\n * force - A optional boolean value to force show cheatsheet, defaults to `nil` (automatically).", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "57", + "lineno": "126", "name": "toggleCheatsheet", "notes": [], "parameters": [ @@ -9105,15 +9663,15 @@ "Method": [ { "def": "MouseFollowsFocus:configure(configuration)", - "desc": "Configures the spoon. There is currently nothing to configure.", - "doc": "Configures the spoon. There is currently nothing to configure.\n\nParameters:\n * configuration - :", + "desc": "Configures the spoon.", + "doc": "Configures the spoon.\n\nParameters:\n * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "26", + "lineno": "29", "name": "configure", "notes": [], "parameters": [ - " * configuration - :" + " * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:" ], "returns": [], "signature": "MouseFollowsFocus:configure(configuration)", @@ -9126,7 +9684,7 @@ "doc": "Starts updating the mouse position when window focus changes\n\nParameters:\n * None", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "35", + "lineno": "44", "name": "start", "notes": [], "parameters": [ @@ -9143,7 +9701,7 @@ "doc": "Stops updating the mouse position when window focus changes\n\nParameters:\n * None", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "61", + "lineno": "73", "name": "stop", "notes": [], "parameters": [ @@ -9160,7 +9718,7 @@ "doc": "Moves the mouse to the center of the given window unless it's already inside the window\n\nParameters:\n * None", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "72", + "lineno": "84", "name": "updateMouse", "notes": [], "parameters": [ @@ -9178,7 +9736,7 @@ "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "21", + "lineno": "24", "name": "logger", "signature": "MouseFollowsFocus.logger", "stripped_doc": "", @@ -9190,15 +9748,15 @@ "items": [ { "def": "MouseFollowsFocus:configure(configuration)", - "desc": "Configures the spoon. There is currently nothing to configure.", - "doc": "Configures the spoon. There is currently nothing to configure.\n\nParameters:\n * configuration - :", + "desc": "Configures the spoon.", + "doc": "Configures the spoon.\n\nParameters:\n * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "26", + "lineno": "29", "name": "configure", "notes": [], "parameters": [ - " * configuration - :" + " * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:" ], "returns": [], "signature": "MouseFollowsFocus:configure(configuration)", @@ -9210,7 +9768,7 @@ "desc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "21", + "lineno": "24", "name": "logger", "signature": "MouseFollowsFocus.logger", "stripped_doc": "", @@ -9222,7 +9780,7 @@ "doc": "Starts updating the mouse position when window focus changes\n\nParameters:\n * None", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "35", + "lineno": "44", "name": "start", "notes": [], "parameters": [ @@ -9239,7 +9797,7 @@ "doc": "Stops updating the mouse position when window focus changes\n\nParameters:\n * None", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "61", + "lineno": "73", "name": "stop", "notes": [], "parameters": [ @@ -9256,7 +9814,7 @@ "doc": "Moves the mouse to the center of the given window unless it's already inside the window\n\nParameters:\n * None", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "72", + "lineno": "84", "name": "updateMouse", "notes": [], "parameters": [ @@ -9676,283 +10234,1059 @@ "doc": "Control OBS and react to its events, via the obs-websocket plugin.\n\nInstall and configure the obs-websocket plugin first from [their project](https://github.com/obsproject/obs-websocket/releases)\n\nNote: This Spoon will only work with Hammerspoon 0.9.100 or later.\n\nNote: This Spoon will only work with obs-websocket 5.0.1 or later, which also requires OBS Studio v27 or later.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip)\n\nExample:\n```\n-- This example will start OBS, connect to it, and then start streaming once connected\nobs = hs.loadSpoon(\"OBS\")\nobsCallback = function(eventType, eventIntent, eventData)\n print(eventType)\n print(eventIntent)\n print(hs.inspect(eventData))\n\n if eventType == \"SpoonOBSConnected\" then\n obs:request(\"StartStream\")\n end\nend\nobs:init(obsCallback, \"localhost\", 4444, \"password\")\nobs:start()\n```", "items": [ { - "def": "OBS:addEventSubsciption(event)", - "desc": "Adds an event subscription", - "doc": "Adds an event subscription\n\nParameters:\n * `event` - The event to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * If you wish to add multiple event subscriptions you can use the `|` operator to combine them, e.g. `spoon.OBS:addEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`", + "def": "OBS:addEventSubsciption(event)", + "desc": "Adds an event subscription", + "doc": "Adds an event subscription\n\nParameters:\n * `event` - The event to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * If you wish to add multiple event subscriptions you can use the `|` operator to combine them, e.g. `spoon.OBS:addEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "309", + "name": "addEventSubsciption", + "notes": [ + " * If you wish to add multiple event subscriptions you can use the `|` operator to combine them, e.g. `spoon.OBS:addEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`" + ], + "parameters": [ + " * `event` - The event to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + ], + "returns": [ + " * None" + ], + "signature": "OBS:addEventSubsciption(event)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS.eventSubscriptionValues", + "desc": "A table of the possible values for the `eventSubscriptions` parameter to [OBS:init()](#init)", + "doc": "A table of the possible values for the `eventSubscriptions` parameter to [OBS:init()](#init)\n\nNotes:\n * The keys are:\n * `None` - No events\n * `General` - General events\n * `Config` - Configuration events\n * `Scenes` - Scene events\n * `Inputs` - Input events\n * `Transitions` - Transition events\n * `Filters` - Filter events\n * `Outputs` - Output events\n * `SceneItems` - Scene item events\n * `MediaInputs` - Media input events\n * `Vendors` - Vendor events\n * `UI` - UI events\n * `All` - All of the above events\n * `InputVolumeMeters` - Input volume meter events\n * `InputActiveStateChanged` - Input active state changed events\n * `InputShowStateChanged` - Input show state changed events\n * `SceneItemTransformChanged` - Scene item transform changed events\n * For more information about these event categories and the events they contain, see the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)\n * To combine these as a bitmask, use boolean operators, e.g. `OBS.eventSubscriptionValues.General | OBS.eventSubscriptionValues.Scenes`\n * The final four values are considered \"high volume\" events, so are not included in `OBS.eventSubscriptionValues.All` by default", + "file": "Source/OBS.spoon/init.lua", + "lineno": "58", + "name": "eventSubscriptionValues", + "notes": [ + " * The keys are:", + " * `None` - No events", + " * `General` - General events", + " * `Config` - Configuration events", + " * `Scenes` - Scene events", + " * `Inputs` - Input events", + " * `Transitions` - Transition events", + " * `Filters` - Filter events", + " * `Outputs` - Output events", + " * `SceneItems` - Scene item events", + " * `MediaInputs` - Media input events", + " * `Vendors` - Vendor events", + " * `UI` - UI events", + " * `All` - All of the above events", + " * `InputVolumeMeters` - Input volume meter events", + " * `InputActiveStateChanged` - Input active state changed events", + " * `InputShowStateChanged` - Input show state changed events", + " * `SceneItemTransformChanged` - Scene item transform changed events", + " * For more information about these event categories and the events they contain, see the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)", + " * To combine these as a bitmask, use boolean operators, e.g. `OBS.eventSubscriptionValues.General | OBS.eventSubscriptionValues.Scenes`", + " * The final four values are considered \"high volume\" events, so are not included in `OBS.eventSubscriptionValues.All` by default" + ], + "signature": "OBS.eventSubscriptionValues", + "stripped_doc": "", + "type": "Constant" + }, + { + "def": "OBS:init(eventCallback, host, port[, password, eventSubscriptions])", + "desc": "Initialisation method", + "doc": "Initialisation method\n\nParameters:\n * `eventCallback` - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:\n * `eventType` - The type of event, e.g. `StudioModeStateChanged`\n * `eventIntent` - The event subscription value that caused this event to be sent, e.g. `OBS.eventSubscriptionValues.General`\n * `eventData` - A table containing the event data, e.g. `{ \"studioModeEnabled\": true }`\n * `host` - The hostname or IP address of the machine running OBS\n * `port` - The port number that obs-websocket is listening on\n * `password` - An optional password string that obs-websocket is configured to use\n * `eventSubscriptions` - An optional number containing the bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * This method does not connect to OBS, it just sets up the connection parameters for later use\n * By default, no events are subscribed to, so you will need to set `eventSubscriptions` to something useful if you want to receive events\n * If you do not wish to supply an `eventCallback`, pass `nil` instead\n * The events that OBS can produce are documented in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)\n * There are some additional values for `eventType`, specific to this Spoon:\n * `SpoonOBSConnected` - This event is sent when the websocket connection to OBS is established. All other fields will be `nil`.\n * `SpoonOBSDisconnected` - This event is sent when the websocket connection to OBS is lost. All other fields will be nil. Return false to inhibit automatic reconnection.\n * `SpoonRequestResponse` - This event is sent to pass replies to requests made via [OBS:request()](#request). Its `eventIntent` will be nil and the format of its `eventData` table will be:\n * `requestId` - The ID of the request that this is a reply to\n * `requestType` - The request type that was made\n * `requestStatus` - A table containing:\n * `result` - A bool, `true` if the request succeeded, otherwise `false`\n * `code` - A number containing the response code\n * `comment` - An optional string that may contain additional information about the response\n * `responseData` - An table that contains the response data, if any\n * `SpoonBatchRequestResponse` - This event is sent to pass replies to batch requests made via [OBS:requestBatch()](#requestBatch). Its `eventIntent` will be nil and the format of its `eventData` table will be:\n * `requestId` - The ID of the request batch that this is a reply to\n * `results` - A table containing the results of each request in the batch. Each entry in the table will be a table with the same format as `SpoonRequestResponse`", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "117", + "name": "init", + "notes": [ + " * This method does not connect to OBS, it just sets up the connection parameters for later use", + " * By default, no events are subscribed to, so you will need to set `eventSubscriptions` to something useful if you want to receive events", + " * If you do not wish to supply an `eventCallback`, pass `nil` instead", + " * The events that OBS can produce are documented in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)", + " * There are some additional values for `eventType`, specific to this Spoon:", + " * `SpoonOBSConnected` - This event is sent when the websocket connection to OBS is established. All other fields will be `nil`.", + " * `SpoonOBSDisconnected` - This event is sent when the websocket connection to OBS is lost. All other fields will be nil. Return false to inhibit automatic reconnection.", + " * `SpoonRequestResponse` - This event is sent to pass replies to requests made via [OBS:request()](#request). Its `eventIntent` will be nil and the format of its `eventData` table will be:", + " * `requestId` - The ID of the request that this is a reply to", + " * `requestType` - The request type that was made", + " * `requestStatus` - A table containing:", + " * `result` - A bool, `true` if the request succeeded, otherwise `false`", + " * `code` - A number containing the response code", + " * `comment` - An optional string that may contain additional information about the response", + " * `responseData` - An table that contains the response data, if any", + " * `SpoonBatchRequestResponse` - This event is sent to pass replies to batch requests made via [OBS:requestBatch()](#requestBatch). Its `eventIntent` will be nil and the format of its `eventData` table will be:", + " * `requestId` - The ID of the request batch that this is a reply to", + " * `results` - A table containing the results of each request in the batch. Each entry in the table will be a table with the same format as `SpoonRequestResponse`" + ], + "parameters": [ + " * `eventCallback` - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:\n * `eventType` - The type of event, e.g. `StudioModeStateChanged`\n * `eventIntent` - The event subscription value that caused this event to be sent, e.g. `OBS.eventSubscriptionValues.General`\n * `eventData` - A table containing the event data, e.g. `{ \"studioModeEnabled\": true }`", + " * `host` - The hostname or IP address of the machine running OBS", + " * `port` - The port number that obs-websocket is listening on", + " * `password` - An optional password string that obs-websocket is configured to use", + " * `eventSubscriptions` - An optional number containing the bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + ], + "returns": [ + " * None" + ], + "signature": "OBS:init(eventCallback, host, port[, password, eventSubscriptions])", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:reconnectDelay", + "desc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", + "doc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", + "file": "Source/OBS.spoon/init.lua", + "lineno": "112", + "name": "reconnectDelay", + "signature": "OBS:reconnectDelay", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "OBS:removeEventSubsciption(event)", + "desc": "Removes an event subscription", + "doc": "Removes an event subscription\n\nParameters:\n * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "326", + "name": "removeEventSubsciption", + "notes": [ + " * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`" + ], + "parameters": [ + " * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + ], + "returns": [ + " * None" + ], + "signature": "OBS:removeEventSubsciption(event)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:request(requestType[, requestData[, requestId]])", + "desc": "Sends a request to OBS", + "doc": "Sends a request to OBS\n\nParameters:\n * `requestType` - A string containing the type of request to send\n * `requestData` - An optional table containing the data to send with the request, or nil\n * `requestId` - An optional string containing the ID of the request\n\nReturns:\n * The `requestId` that was sent\n\nNotes:\n * If `requestId` is not specified then a random UUID will be generated.\n * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.\n * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "343", + "name": "request", + "notes": [ + " * If `requestId` is not specified then a random UUID will be generated.", + " * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.", + " * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)" + ], + "parameters": [ + " * `requestType` - A string containing the type of request to send", + " * `requestData` - An optional table containing the data to send with the request, or nil", + " * `requestId` - An optional string containing the ID of the request" + ], + "returns": [ + " * The `requestId` that was sent" + ], + "signature": "OBS:request(requestType[, requestData[, requestId]])", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:requestBatch(requests[, haltOnFailure])", + "desc": "Sends a batch of requests to OBS", + "doc": "Sends a batch of requests to OBS\n\nParameters:\n * `requests` - A table containing the requests to send\n * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false\n\nReturns:\n * The `requestId` that was sent for the batch\n\nNotes:\n * Each request should be a table with the keys:\n * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)\n * `requestData` - An optional table containing the data to send with the request, or `nil`\n * `requestId` - An optional string containing a unique ID for the request\n * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID\n\nExample:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "377", + "name": "requestBatch", + "notes": [ + " * Each request should be a table with the keys:", + " * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)", + " * `requestData` - An optional table containing the data to send with the request, or `nil`", + " * `requestId` - An optional string containing a unique ID for the request", + " * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID", + "", + "Example:", + "```lua", + "spoon.OBS:requestBatch({", + " {[\"requestType\"] = \"StartVirtualCam\"},", + " {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}", + "})", + "```" + ], + "parameters": [ + " * `requests` - A table containing the requests to send", + " * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false" + ], + "returns": [ + " * The `requestId` that was sent for the batch" + ], + "signature": "OBS:requestBatch(requests[, haltOnFailure])", + "stripped_doc": "Example:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", + "type": "Method" + }, + { + "def": "OBS:setLogLevel(level)", + "desc": "Sets the logging level for the OBS Spoon", + "doc": "Sets the logging level for the OBS Spoon\n\nParameters:\n * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values\n\nReturns:\n * None", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "419", + "name": "setLogLevel", + "notes": [], + "parameters": [ + " * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values" + ], + "returns": [ + " * None" + ], + "signature": "OBS:setLogLevel(level)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:shouldReconnect", + "desc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", + "doc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", + "file": "Source/OBS.spoon/init.lua", + "lineno": "105", + "name": "shouldReconnect", + "signature": "OBS:shouldReconnect", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "OBS:start()", + "desc": "Connects to OBS", + "doc": "Connects to OBS\n\nParameters:\n * None\n\nReturns:\n * None", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "161", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * None" + ], + "signature": "OBS:start()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:stop()", + "desc": "Disconnects from OBS", + "doc": "Disconnects from OBS\n\nParameters:\n * None\n\nReturns:\n * None", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "274", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * None" + ], + "signature": "OBS:stop()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:updateEventSubscriptions(eventSubscriptions)", + "desc": "Updates the event subscriptions", + "doc": "Updates the event subscriptions\n\nParameters:\n * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "289", + "name": "updateEventSubscriptions", + "notes": [], + "parameters": [ + " * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + ], + "returns": [ + " * None" + ], + "signature": "OBS:updateEventSubscriptions(eventSubscriptions)", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "OBS", + "stripped_doc": "\nInstall and configure the obs-websocket plugin first from [their project](https://github.com/obsproject/obs-websocket/releases)\n\nNote: This Spoon will only work with Hammerspoon 0.9.100 or later.\n\nNote: This Spoon will only work with obs-websocket 5.0.1 or later, which also requires OBS Studio v27 or later.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip)\n\nExample:\n```\n-- This example will start OBS, connect to it, and then start streaming once connected\nobs = hs.loadSpoon(\"OBS\")\nobsCallback = function(eventType, eventIntent, eventData)\n print(eventType)\n print(eventIntent)\n print(hs.inspect(eventData))\n\n if eventType == \"SpoonOBSConnected\" then\n obs:request(\"StartStream\")\n end\nend\nobs:init(obsCallback, \"localhost\", 4444, \"password\")\nobs:start()\n```", + "submodules": [], + "type": "Module" + }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "PaperWM:addWindow(add_window)", + "desc": "Adds a window to layout and tiles.", + "doc": "Adds a window to layout and tiles.\n\nParameters:\n * add_window - An hs.window\n\nReturns:\n * The hs.spaces space for added window or nil if window not added.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "594", + "name": "addWindow", + "notes": [], + "parameters": [ + " * add_window - An hs.window" + ], + "returns": [ + " * The hs.spaces space for added window or nil if window not added." + ], + "signature": "PaperWM:addWindow(add_window)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:barfWindow()", + "desc": "Removes current window from column and places it to the right", + "doc": "Removes current window from column and places it to the right\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1026", + "name": "barfWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:barfWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.bindHotkeys(mapping)", + "desc": "Binds hotkeys for PaperWM", + "doc": "Binds hotkeys for PaperWM\n\nParameters:\n * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "275", + "name": "bindHotkeys", + "notes": [], + "parameters": [ + " * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9" + ], + "returns": [], + "signature": "PaperWM.bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:centerWindow()", + "desc": "Moves current window to center of screen, without resizing.", + "doc": "Moves current window to center of screen, without resizing.\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "860", + "name": "centerWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:centerWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:cycleWindowSize(direction)", + "desc": "Resizes current window by cycling through width or height ratios.", + "doc": "Resizes current window by cycling through width or height ratios.\n\nParameters:\n * direction - One of Direction { WIDTH, HEIGHT }", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "907", + "name": "cycleWindowSize", + "notes": [], + "parameters": [ + " * direction - One of Direction { WIDTH, HEIGHT }" + ], + "returns": [], + "signature": "PaperWM:cycleWindowSize(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:focusWindow(direction, focused_index)", + "desc": "Change focus to a nearby window", + "doc": "Change focus to a nearby window\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }\n * focused_index - The coordinates of the current window in the tiling layout\n\nReturns:\n * A boolean. True if a new window was focused. False if no nearby window\n was found in that direction.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "699", + "name": "focusWindow", + "notes": [], + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + " * focused_index - The coordinates of the current window in the tiling layout" + ], + "returns": [ + " * A boolean. True if a new window was focused. False if no nearby window", + " was found in that direction." + ], + "signature": "PaperWM:focusWindow(direction, focused_index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM::moveWindow(window, frame)", + "desc": "Resizes a window without triggering a windowMoved event", + "doc": "Resizes a window without triggering a windowMoved event\n\nParameters:\n * window - An hs.window\n * frame - An hs.geometry.rect for the windows new frame size.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1147", + "name": "moveWindow", + "notes": [], + "parameters": [ + " * window - An hs.window", + " * frame - An hs.geometry.rect for the windows new frame size." + ], + "returns": [], + "signature": "PaperWM::moveWindow(window, frame)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:moveWindowToSpace(index)", + "desc": "Moves the current window to a new Mission Control space", + "doc": "Moves the current window to a new Mission Control space\n\nParameters:\n * index - The space number", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1096", + "name": "moveWindowToSpace", + "notes": [], + "parameters": [ + " * index - The space number" + ], + "returns": [], + "signature": "PaperWM:moveWindowToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:refreshWindows()", + "desc": "Searches for all windows that match window filter.", + "doc": "Searches for all windows that match window filter.\n\nParameters:\n * None\n\nReturns:\n * A boolean, true if the layout needs to be re-tiled, false if no change.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "563", + "name": "refreshWindows", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * A boolean, true if the layout needs to be re-tiled, false if no change." + ], + "signature": "PaperWM:refreshWindows()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "desc": "Remove window from tiling layout", + "doc": "Remove window from tiling layout\n\nParameters:\n * remove_window - A hs.window to remove from tiling layout\n * skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.\n\nReturns:\n * The hs.spaces space for removed window.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "652", + "name": "remove_window", + "notes": [], + "parameters": [ + " * remove_window - A hs.window to remove from tiling layout", + " * skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed." + ], + "returns": [ + " * The hs.spaces space for removed window." + ], + "signature": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:setWindowFullWidth()", + "desc": "Resizes current window's width to width of screen, without adjusting height.", + "doc": "Resizes current window's width to width of screen, without adjusting height.\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "885", + "name": "setWindowFullWidth", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:setWindowFullWidth()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:slurpWindow()", + "desc": "Moves current window into column of windows to the left", + "doc": "Moves current window into column of windows to the left\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "961", + "name": "slurpWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:slurpWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:start()", + "desc": "Start automatic tiling of windows", + "doc": "Start automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "354", + "name": "start", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The PaperWM object" + ], + "signature": "PaperWM:start()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:stop()", + "desc": "Stop automatic tiling of windows", + "doc": "Stop automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "391", + "name": "stop", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [ + " * The PaperWM object" + ], + "signature": "PaperWM:stop()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:swapWindows(direction)", + "desc": "Swaps window postions between current window and window in specified direction.", + "doc": "Swaps window postions between current window and window in specified direction.\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "749", + "name": "swapWindows", + "notes": [], + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }" + ], + "returns": [], + "signature": "PaperWM:swapWindows(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:switchToSpace(index)", + "desc": "Switch to a Mission Control space", + "doc": "Switch to a Mission Control space\n\nParameters:\n * index - The space number", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1080", + "name": "switchToSpace", + "notes": [], + "parameters": [ + " * index - The space number" + ], + "returns": [], + "signature": "PaperWM:switchToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "desc": "Tile a column of windows", + "doc": "Tile a column of windows\n\nParameters:\n * windows - A list of hs.windows.\n * bounds - An hs.geometry.rect. The area for this column to fill.\n * h - The height for each window in column.\n * w - The width for each window in column.\n * id - A hs.window.id() for a specific window in column.\n * h4id - The height for a window matching id in column.\n\nNotes:\n * The h, w, id, and h4id parameters are optional. The height and width of\n all windows will be calculated and set to fill column bounds.\n * If bounds width is not specified, all windows in column will be resized\n to width of first window.\n\nReturns:\n * The width of the column", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "408", + "name": "tileColumn", + "notes": [ + " * The h, w, id, and h4id parameters are optional. The height and width of", + " all windows will be calculated and set to fill column bounds.", + " * If bounds width is not specified, all windows in column will be resized", + " to width of first window." + ], + "parameters": [ + " * windows - A list of hs.windows.", + " * bounds - An hs.geometry.rect. The area for this column to fill.", + " * h - The height for each window in column.", + " * w - The width for each window in column.", + " * id - A hs.window.id() for a specific window in column.", + " * h4id - The height for a window matching id in column." + ], + "returns": [ + " * The width of the column" + ], + "signature": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileSpace(space)", + "desc": "Tile all windows within a space", + "doc": "Tile all windows within a space\n\nParameters:\n * space - A hs.spaces space.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "460", + "name": "tileSpace", + "notes": [], + "parameters": [ + " * space - A hs.spaces space." + ], + "returns": [], + "signature": "PaperWM:tileSpace(space)", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ + { + "def": "PaperWM.default_hotkeys", + "desc": "Default hotkeys for moving / resizing windows", + "doc": "Default hotkeys for moving / resizing windows", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "111", + "name": "default_hotkeys", + "signature": "PaperWM.default_hotkeys", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.logger", + "desc": "Logger object. Can be accessed to set default log level.", + "doc": "Logger object. Can be accessed to set default log level.", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "165", + "name": "logger", + "signature": "PaperWM.logger", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_filter", + "desc": "Windows captured by this filter are automatically tiled and managed", + "doc": "Windows captured by this filter are automatically tiled and managed", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "150", + "name": "window_filter", + "signature": "PaperWM.window_filter", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_gap", + "desc": "Number of pixels between tiled windows", + "doc": "Number of pixels between tiled windows", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "160", + "name": "window_gap", + "signature": "PaperWM.window_gap", + "stripped_doc": "", + "type": "Variable" + } + ], + "desc": "A scrolling window manager. Inspired by PaperWM Gnome extension.", + "doc": "A scrolling window manager. Inspired by PaperWM Gnome extension.\n\n# Usage\n\n`PaperWM:start()` will begin automatically tiling new and existing windows.\n`PaperWM:stop()` will release control over windows.\n`PaperWM::bindHotkeys()` will move / resize windows using keyboard shortcuts.\n\nHere is an example Hammerspoon config:\n\n```\nPaperWM = hs.loadSpoon(\"PaperWM\")\nPaperWM:bindHotkeys({\n -- switch to a new focused window in tiled grid\n focus_left = {{\"ctrl\", \"alt\", \"cmd\"}, \"left\"},\n focus_right = {{\"ctrl\", \"alt\", \"cmd\"}, \"right\"},\n focus_up = {{\"ctrl\", \"alt\", \"cmd\"}, \"up\"},\n focus_down = {{\"ctrl\", \"alt\", \"cmd\"}, \"down\"},\n\n -- move windows around in tiled grid\n swap_left = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"left\"},\n swap_right = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"right\"},\n swap_up = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"up\"},\n swap_down = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"down\"},\n\n -- position and resize focused window\n center_window = {{\"ctrl\", \"alt\", \"cmd\"}, \"c\"},\n full_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"f\"},\n cycle_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"r\"},\n cycle_height = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"r\"},\n\n -- move focused window into / out of a column\n slurp_in = {{\"ctrl\", \"alt\", \"cmd\"}, \"i\"},\n barf_out = {{\"ctrl\", \"alt\", \"cmd\"}, \"o\"},\n\n -- switch to a new Mission Control space\n switch_space_1 = {{\"ctrl\", \"alt\", \"cmd\"}, \"1\"},\n switch_space_2 = {{\"ctrl\", \"alt\", \"cmd\"}, \"2\"},\n switch_space_3 = {{\"ctrl\", \"alt\", \"cmd\"}, \"3\"},\n switch_space_4 = {{\"ctrl\", \"alt\", \"cmd\"}, \"4\"},\n switch_space_5 = {{\"ctrl\", \"alt\", \"cmd\"}, \"5\"},\n switch_space_6 = {{\"ctrl\", \"alt\", \"cmd\"}, \"6\"},\n switch_space_7 = {{\"ctrl\", \"alt\", \"cmd\"}, \"7\"},\n switch_space_8 = {{\"ctrl\", \"alt\", \"cmd\"}, \"8\"},\n switch_space_9 = {{\"ctrl\", \"alt\", \"cmd\"}, \"9\"},\n\n -- move focused window to a new space and tile\n move_window_1 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"1\"},\n move_window_2 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"2\"},\n move_window_3 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"3\"},\n move_window_4 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"4\"},\n move_window_5 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"5\"},\n move_window_6 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"6\"},\n move_window_7 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"7\"},\n move_window_8 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"8\"},\n move_window_9 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"9\"}\n})\nPaperWM:start()\n```\n\nUse `PaperWM:bindHotkeys(PaperWM.default_hotkeys)` for defaults.\n\nSet `PaperWM.window_gap` to the number of pixels to space between windows and\nthe top and bottom screen edges.\n\nOverwrite `PaperWM.window_filter` to ignore specific applications. For example:\n\n```\nPaperWM.window_filter = PaperWM.window_filter:setAppFilter(\"Finder\", false)\nPaperWM:start() -- restart for new window filter to take effect\n```\n\n# Limitations\n\nUnder System Preferences -> Mission Control, unselect \"Automatically\nrearrange Spaces based on most recent use\" and select \"Displays have separate\nSpaces\".\n\nMacOS does not allow a window to be moved fully off-screen. Windows that would\nbe tiled off-screen are placed in a margin on the left and right edge of the\nscreen. They are still visible and clickable.\n\nIt's difficult to detect when a window is dragged from one space or screen to\nanother. Use the move_window_N commands to move windows between spaces and\nscreens.\n\nArrange screens vertically to prevent windows from bleeding into other screens.\n\n\nDownload: [https://github.com/mogenson/PaperWM.spoon](https://github.com/mogenson/PaperWM.spoon)", + "items": [ + { + "def": "PaperWM:addWindow(add_window)", + "desc": "Adds a window to layout and tiles.", + "doc": "Adds a window to layout and tiles.\n\nParameters:\n * add_window - An hs.window\n\nReturns:\n * The hs.spaces space for added window or nil if window not added.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "594", + "name": "addWindow", + "notes": [], + "parameters": [ + " * add_window - An hs.window" + ], + "returns": [ + " * The hs.spaces space for added window or nil if window not added." + ], + "signature": "PaperWM:addWindow(add_window)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:barfWindow()", + "desc": "Removes current window from column and places it to the right", + "doc": "Removes current window from column and places it to the right\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1026", + "name": "barfWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:barfWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.bindHotkeys(mapping)", + "desc": "Binds hotkeys for PaperWM", + "doc": "Binds hotkeys for PaperWM\n\nParameters:\n * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "275", + "name": "bindHotkeys", + "notes": [], + "parameters": [ + " * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9" + ], + "returns": [], + "signature": "PaperWM.bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:centerWindow()", + "desc": "Moves current window to center of screen, without resizing.", + "doc": "Moves current window to center of screen, without resizing.\n\nParameters:\n * None", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "309", - "name": "addEventSubsciption", - "notes": [ - " * If you wish to add multiple event subscriptions you can use the `|` operator to combine them, e.g. `spoon.OBS:addEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`" - ], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "860", + "name": "centerWindow", + "notes": [], "parameters": [ - " * `event` - The event to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" - ], - "returns": [ " * None" ], - "signature": "OBS:addEventSubsciption(event)", + "returns": [], + "signature": "PaperWM:centerWindow()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS.eventSubscriptionValues", - "desc": "A table of the possible values for the `eventSubscriptions` parameter to [OBS:init()](#init)", - "doc": "A table of the possible values for the `eventSubscriptions` parameter to [OBS:init()](#init)\n\nNotes:\n * The keys are:\n * `None` - No events\n * `General` - General events\n * `Config` - Configuration events\n * `Scenes` - Scene events\n * `Inputs` - Input events\n * `Transitions` - Transition events\n * `Filters` - Filter events\n * `Outputs` - Output events\n * `SceneItems` - Scene item events\n * `MediaInputs` - Media input events\n * `Vendors` - Vendor events\n * `UI` - UI events\n * `All` - All of the above events\n * `InputVolumeMeters` - Input volume meter events\n * `InputActiveStateChanged` - Input active state changed events\n * `InputShowStateChanged` - Input show state changed events\n * `SceneItemTransformChanged` - Scene item transform changed events\n * For more information about these event categories and the events they contain, see the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)\n * To combine these as a bitmask, use boolean operators, e.g. `OBS.eventSubscriptionValues.General | OBS.eventSubscriptionValues.Scenes`\n * The final four values are considered \"high volume\" events, so are not included in `OBS.eventSubscriptionValues.All` by default", - "file": "Source/OBS.spoon/init.lua", - "lineno": "58", - "name": "eventSubscriptionValues", - "notes": [ - " * The keys are:", - " * `None` - No events", - " * `General` - General events", - " * `Config` - Configuration events", - " * `Scenes` - Scene events", - " * `Inputs` - Input events", - " * `Transitions` - Transition events", - " * `Filters` - Filter events", - " * `Outputs` - Output events", - " * `SceneItems` - Scene item events", - " * `MediaInputs` - Media input events", - " * `Vendors` - Vendor events", - " * `UI` - UI events", - " * `All` - All of the above events", - " * `InputVolumeMeters` - Input volume meter events", - " * `InputActiveStateChanged` - Input active state changed events", - " * `InputShowStateChanged` - Input show state changed events", - " * `SceneItemTransformChanged` - Scene item transform changed events", - " * For more information about these event categories and the events they contain, see the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)", - " * To combine these as a bitmask, use boolean operators, e.g. `OBS.eventSubscriptionValues.General | OBS.eventSubscriptionValues.Scenes`", - " * The final four values are considered \"high volume\" events, so are not included in `OBS.eventSubscriptionValues.All` by default" + "def": "PaperWM:cycleWindowSize(direction)", + "desc": "Resizes current window by cycling through width or height ratios.", + "doc": "Resizes current window by cycling through width or height ratios.\n\nParameters:\n * direction - One of Direction { WIDTH, HEIGHT }", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "907", + "name": "cycleWindowSize", + "notes": [], + "parameters": [ + " * direction - One of Direction { WIDTH, HEIGHT }" ], - "signature": "OBS.eventSubscriptionValues", + "returns": [], + "signature": "PaperWM:cycleWindowSize(direction)", "stripped_doc": "", - "type": "Constant" + "type": "Method" }, { - "def": "OBS:init(eventCallback, host, port[, password, eventSubscriptions])", - "desc": "Initialisation method", - "doc": "Initialisation method\n\nParameters:\n * `eventCallback` - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:\n * `eventType` - The type of event, e.g. `StudioModeStateChanged`\n * `eventIntent` - The event subscription value that caused this event to be sent, e.g. `OBS.eventSubscriptionValues.General`\n * `eventData` - A table containing the event data, e.g. `{ \"studioModeEnabled\": true }`\n * `host` - The hostname or IP address of the machine running OBS\n * `port` - The port number that obs-websocket is listening on\n * `password` - An optional password string that obs-websocket is configured to use\n * `eventSubscriptions` - An optional number containing the bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * This method does not connect to OBS, it just sets up the connection parameters for later use\n * By default, no events are subscribed to, so you will need to set `eventSubscriptions` to something useful if you want to receive events\n * If you do not wish to supply an `eventCallback`, pass `nil` instead\n * The events that OBS can produce are documented in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)\n * There are some additional values for `eventType`, specific to this Spoon:\n * `SpoonOBSConnected` - This event is sent when the websocket connection to OBS is established. All other fields will be `nil`.\n * `SpoonOBSDisconnected` - This event is sent when the websocket connection to OBS is lost. All other fields will be nil. Return false to inhibit automatic reconnection.\n * `SpoonRequestResponse` - This event is sent to pass replies to requests made via [OBS:request()](#request). Its `eventIntent` will be nil and the format of its `eventData` table will be:\n * `requestId` - The ID of the request that this is a reply to\n * `requestType` - The request type that was made\n * `requestStatus` - A table containing:\n * `result` - A bool, `true` if the request succeeded, otherwise `false`\n * `code` - A number containing the response code\n * `comment` - An optional string that may contain additional information about the response\n * `responseData` - An table that contains the response data, if any\n * `SpoonBatchRequestResponse` - This event is sent to pass replies to batch requests made via [OBS:requestBatch()](#requestBatch). Its `eventIntent` will be nil and the format of its `eventData` table will be:\n * `requestId` - The ID of the request batch that this is a reply to\n * `results` - A table containing the results of each request in the batch. Each entry in the table will be a table with the same format as `SpoonRequestResponse`", + "def": "PaperWM.default_hotkeys", + "desc": "Default hotkeys for moving / resizing windows", + "doc": "Default hotkeys for moving / resizing windows", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "111", + "name": "default_hotkeys", + "signature": "PaperWM.default_hotkeys", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM:focusWindow(direction, focused_index)", + "desc": "Change focus to a nearby window", + "doc": "Change focus to a nearby window\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }\n * focused_index - The coordinates of the current window in the tiling layout\n\nReturns:\n * A boolean. True if a new window was focused. False if no nearby window\n was found in that direction.", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "117", - "name": "init", - "notes": [ - " * This method does not connect to OBS, it just sets up the connection parameters for later use", - " * By default, no events are subscribed to, so you will need to set `eventSubscriptions` to something useful if you want to receive events", - " * If you do not wish to supply an `eventCallback`, pass `nil` instead", - " * The events that OBS can produce are documented in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#events)", - " * There are some additional values for `eventType`, specific to this Spoon:", - " * `SpoonOBSConnected` - This event is sent when the websocket connection to OBS is established. All other fields will be `nil`.", - " * `SpoonOBSDisconnected` - This event is sent when the websocket connection to OBS is lost. All other fields will be nil. Return false to inhibit automatic reconnection.", - " * `SpoonRequestResponse` - This event is sent to pass replies to requests made via [OBS:request()](#request). Its `eventIntent` will be nil and the format of its `eventData` table will be:", - " * `requestId` - The ID of the request that this is a reply to", - " * `requestType` - The request type that was made", - " * `requestStatus` - A table containing:", - " * `result` - A bool, `true` if the request succeeded, otherwise `false`", - " * `code` - A number containing the response code", - " * `comment` - An optional string that may contain additional information about the response", - " * `responseData` - An table that contains the response data, if any", - " * `SpoonBatchRequestResponse` - This event is sent to pass replies to batch requests made via [OBS:requestBatch()](#requestBatch). Its `eventIntent` will be nil and the format of its `eventData` table will be:", - " * `requestId` - The ID of the request batch that this is a reply to", - " * `results` - A table containing the results of each request in the batch. Each entry in the table will be a table with the same format as `SpoonRequestResponse`" - ], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "699", + "name": "focusWindow", + "notes": [], "parameters": [ - " * `eventCallback` - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:\n * `eventType` - The type of event, e.g. `StudioModeStateChanged`\n * `eventIntent` - The event subscription value that caused this event to be sent, e.g. `OBS.eventSubscriptionValues.General`\n * `eventData` - A table containing the event data, e.g. `{ \"studioModeEnabled\": true }`", - " * `host` - The hostname or IP address of the machine running OBS", - " * `port` - The port number that obs-websocket is listening on", - " * `password` - An optional password string that obs-websocket is configured to use", - " * `eventSubscriptions` - An optional number containing the bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + " * focused_index - The coordinates of the current window in the tiling layout" ], "returns": [ - " * None" + " * A boolean. True if a new window was focused. False if no nearby window", + " was found in that direction." ], - "signature": "OBS:init(eventCallback, host, port[, password, eventSubscriptions])", + "signature": "PaperWM:focusWindow(direction, focused_index)", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:reconnectDelay", - "desc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", - "doc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", - "file": "Source/OBS.spoon/init.lua", - "lineno": "112", - "name": "reconnectDelay", - "signature": "OBS:reconnectDelay", + "def": "PaperWM.logger", + "desc": "Logger object. Can be accessed to set default log level.", + "doc": "Logger object. Can be accessed to set default log level.", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "165", + "name": "logger", + "signature": "PaperWM.logger", "stripped_doc": "", "type": "Variable" }, { - "def": "OBS:removeEventSubsciption(event)", - "desc": "Removes an event subscription", - "doc": "Removes an event subscription\n\nParameters:\n * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`", + "def": "PaperWM::moveWindow(window, frame)", + "desc": "Resizes a window without triggering a windowMoved event", + "doc": "Resizes a window without triggering a windowMoved event\n\nParameters:\n * window - An hs.window\n * frame - An hs.geometry.rect for the windows new frame size.", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "326", - "name": "removeEventSubsciption", - "notes": [ - " * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`" - ], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1147", + "name": "moveWindow", + "notes": [], "parameters": [ - " * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + " * window - An hs.window", + " * frame - An hs.geometry.rect for the windows new frame size." ], - "returns": [ - " * None" - ], - "signature": "OBS:removeEventSubsciption(event)", + "returns": [], + "signature": "PaperWM::moveWindow(window, frame)", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:request(requestType[, requestData[, requestId]])", - "desc": "Sends a request to OBS", - "doc": "Sends a request to OBS\n\nParameters:\n * `requestType` - A string containing the type of request to send\n * `requestData` - An optional table containing the data to send with the request, or nil\n * `requestId` - An optional string containing the ID of the request\n\nReturns:\n * The `requestId` that was sent\n\nNotes:\n * If `requestId` is not specified then a random UUID will be generated.\n * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.\n * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)", + "def": "PaperWM:moveWindowToSpace(index)", + "desc": "Moves the current window to a new Mission Control space", + "doc": "Moves the current window to a new Mission Control space\n\nParameters:\n * index - The space number", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "343", - "name": "request", - "notes": [ - " * If `requestId` is not specified then a random UUID will be generated.", - " * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.", - " * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)" + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1096", + "name": "moveWindowToSpace", + "notes": [], + "parameters": [ + " * index - The space number" ], + "returns": [], + "signature": "PaperWM:moveWindowToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:refreshWindows()", + "desc": "Searches for all windows that match window filter.", + "doc": "Searches for all windows that match window filter.\n\nParameters:\n * None\n\nReturns:\n * A boolean, true if the layout needs to be re-tiled, false if no change.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "563", + "name": "refreshWindows", + "notes": [], "parameters": [ - " * `requestType` - A string containing the type of request to send", - " * `requestData` - An optional table containing the data to send with the request, or nil", - " * `requestId` - An optional string containing the ID of the request" + " * None" ], "returns": [ - " * The `requestId` that was sent" + " * A boolean, true if the layout needs to be re-tiled, false if no change." ], - "signature": "OBS:request(requestType[, requestData[, requestId]])", + "signature": "PaperWM:refreshWindows()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:requestBatch(requests[, haltOnFailure])", - "desc": "Sends a batch of requests to OBS", - "doc": "Sends a batch of requests to OBS\n\nParameters:\n * `requests` - A table containing the requests to send\n * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false\n\nReturns:\n * The `requestId` that was sent for the batch\n\nNotes:\n * Each request should be a table with the keys:\n * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)\n * `requestData` - An optional table containing the data to send with the request, or `nil`\n * `requestId` - An optional string containing a unique ID for the request\n * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID\n\nExample:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", + "def": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "desc": "Remove window from tiling layout", + "doc": "Remove window from tiling layout\n\nParameters:\n * remove_window - A hs.window to remove from tiling layout\n * skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.\n\nReturns:\n * The hs.spaces space for removed window.", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "377", - "name": "requestBatch", - "notes": [ - " * Each request should be a table with the keys:", - " * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)", - " * `requestData` - An optional table containing the data to send with the request, or `nil`", - " * `requestId` - An optional string containing a unique ID for the request", - " * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID", - "", - "Example:", - "```lua", - "spoon.OBS:requestBatch({", - " {[\"requestType\"] = \"StartVirtualCam\"},", - " {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}", - "})", - "```" - ], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "652", + "name": "remove_window", + "notes": [], "parameters": [ - " * `requests` - A table containing the requests to send", - " * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false" + " * remove_window - A hs.window to remove from tiling layout", + " * skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed." ], "returns": [ - " * The `requestId` that was sent for the batch" + " * The hs.spaces space for removed window." ], - "signature": "OBS:requestBatch(requests[, haltOnFailure])", - "stripped_doc": "Example:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", + "signature": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "stripped_doc": "", "type": "Method" }, { - "def": "OBS:setLogLevel(level)", - "desc": "Sets the logging level for the OBS Spoon", - "doc": "Sets the logging level for the OBS Spoon\n\nParameters:\n * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values\n\nReturns:\n * None", + "def": "PaperWM:setWindowFullWidth()", + "desc": "Resizes current window's width to width of screen, without adjusting height.", + "doc": "Resizes current window's width to width of screen, without adjusting height.\n\nParameters:\n * None", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "419", - "name": "setLogLevel", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "885", + "name": "setWindowFullWidth", "notes": [], "parameters": [ - " * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values" - ], - "returns": [ " * None" ], - "signature": "OBS:setLogLevel(level)", + "returns": [], + "signature": "PaperWM:setWindowFullWidth()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:shouldReconnect", - "desc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", - "doc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", - "file": "Source/OBS.spoon/init.lua", - "lineno": "105", - "name": "shouldReconnect", - "signature": "OBS:shouldReconnect", + "def": "PaperWM:slurpWindow()", + "desc": "Moves current window into column of windows to the left", + "doc": "Moves current window into column of windows to the left\n\nParameters:\n * None", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "961", + "name": "slurpWindow", + "notes": [], + "parameters": [ + " * None" + ], + "returns": [], + "signature": "PaperWM:slurpWindow()", "stripped_doc": "", - "type": "Variable" + "type": "Method" }, { - "def": "OBS:start()", - "desc": "Connects to OBS", - "doc": "Connects to OBS\n\nParameters:\n * None\n\nReturns:\n * None", + "def": "PaperWM:start()", + "desc": "Start automatic tiling of windows", + "doc": "Start automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "161", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "354", "name": "start", "notes": [], "parameters": [ " * None" ], "returns": [ - " * None" + " * The PaperWM object" ], - "signature": "OBS:start()", + "signature": "PaperWM:start()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:stop()", - "desc": "Disconnects from OBS", - "doc": "Disconnects from OBS\n\nParameters:\n * None\n\nReturns:\n * None", + "def": "PaperWM:stop()", + "desc": "Stop automatic tiling of windows", + "doc": "Stop automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "274", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "391", "name": "stop", "notes": [], "parameters": [ " * None" ], "returns": [ - " * None" + " * The PaperWM object" ], - "signature": "OBS:stop()", + "signature": "PaperWM:stop()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:updateEventSubscriptions(eventSubscriptions)", - "desc": "Updates the event subscriptions", - "doc": "Updates the event subscriptions\n\nParameters:\n * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None", + "def": "PaperWM:swapWindows(direction)", + "desc": "Swaps window postions between current window and window in specified direction.", + "doc": "Swaps window postions between current window and window in specified direction.\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "289", - "name": "updateEventSubscriptions", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "749", + "name": "swapWindows", "notes": [], "parameters": [ - " * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }" + ], + "returns": [], + "signature": "PaperWM:swapWindows(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:switchToSpace(index)", + "desc": "Switch to a Mission Control space", + "doc": "Switch to a Mission Control space\n\nParameters:\n * index - The space number", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1080", + "name": "switchToSpace", + "notes": [], + "parameters": [ + " * index - The space number" + ], + "returns": [], + "signature": "PaperWM:switchToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "desc": "Tile a column of windows", + "doc": "Tile a column of windows\n\nParameters:\n * windows - A list of hs.windows.\n * bounds - An hs.geometry.rect. The area for this column to fill.\n * h - The height for each window in column.\n * w - The width for each window in column.\n * id - A hs.window.id() for a specific window in column.\n * h4id - The height for a window matching id in column.\n\nNotes:\n * The h, w, id, and h4id parameters are optional. The height and width of\n all windows will be calculated and set to fill column bounds.\n * If bounds width is not specified, all windows in column will be resized\n to width of first window.\n\nReturns:\n * The width of the column", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "408", + "name": "tileColumn", + "notes": [ + " * The h, w, id, and h4id parameters are optional. The height and width of", + " all windows will be calculated and set to fill column bounds.", + " * If bounds width is not specified, all windows in column will be resized", + " to width of first window." + ], + "parameters": [ + " * windows - A list of hs.windows.", + " * bounds - An hs.geometry.rect. The area for this column to fill.", + " * h - The height for each window in column.", + " * w - The width for each window in column.", + " * id - A hs.window.id() for a specific window in column.", + " * h4id - The height for a window matching id in column." ], "returns": [ - " * None" + " * The width of the column" ], - "signature": "OBS:updateEventSubscriptions(eventSubscriptions)", + "signature": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileSpace(space)", + "desc": "Tile all windows within a space", + "doc": "Tile all windows within a space\n\nParameters:\n * space - A hs.spaces space.", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "460", + "name": "tileSpace", + "notes": [], + "parameters": [ + " * space - A hs.spaces space." + ], + "returns": [], + "signature": "PaperWM:tileSpace(space)", "stripped_doc": "", "type": "Method" + }, + { + "def": "PaperWM.window_filter", + "desc": "Windows captured by this filter are automatically tiled and managed", + "doc": "Windows captured by this filter are automatically tiled and managed", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "150", + "name": "window_filter", + "signature": "PaperWM.window_filter", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_gap", + "desc": "Number of pixels between tiled windows", + "doc": "Number of pixels between tiled windows", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "160", + "name": "window_gap", + "signature": "PaperWM.window_gap", + "stripped_doc": "", + "type": "Variable" } ], - "name": "OBS", - "stripped_doc": "\nInstall and configure the obs-websocket plugin first from [their project](https://github.com/obsproject/obs-websocket/releases)\n\nNote: This Spoon will only work with Hammerspoon 0.9.100 or later.\n\nNote: This Spoon will only work with obs-websocket 5.0.1 or later, which also requires OBS Studio v27 or later.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip)\n\nExample:\n```\n-- This example will start OBS, connect to it, and then start streaming once connected\nobs = hs.loadSpoon(\"OBS\")\nobsCallback = function(eventType, eventIntent, eventData)\n print(eventType)\n print(eventIntent)\n print(hs.inspect(eventData))\n\n if eventType == \"SpoonOBSConnected\" then\n obs:request(\"StartStream\")\n end\nend\nobs:init(obsCallback, \"localhost\", 4444, \"password\")\nobs:start()\n```", + "name": "PaperWM", + "stripped_doc": "\n# Usage\n\n`PaperWM:start()` will begin automatically tiling new and existing windows.\n`PaperWM:stop()` will release control over windows.\n`PaperWM::bindHotkeys()` will move / resize windows using keyboard shortcuts.\n\nHere is an example Hammerspoon config:\n\n```\nPaperWM = hs.loadSpoon(\"PaperWM\")\nPaperWM:bindHotkeys({\n -- switch to a new focused window in tiled grid\n focus_left = {{\"ctrl\", \"alt\", \"cmd\"}, \"left\"},\n focus_right = {{\"ctrl\", \"alt\", \"cmd\"}, \"right\"},\n focus_up = {{\"ctrl\", \"alt\", \"cmd\"}, \"up\"},\n focus_down = {{\"ctrl\", \"alt\", \"cmd\"}, \"down\"},\n\n -- move windows around in tiled grid\n swap_left = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"left\"},\n swap_right = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"right\"},\n swap_up = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"up\"},\n swap_down = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"down\"},\n\n -- position and resize focused window\n center_window = {{\"ctrl\", \"alt\", \"cmd\"}, \"c\"},\n full_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"f\"},\n cycle_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"r\"},\n cycle_height = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"r\"},\n\n -- move focused window into / out of a column\n slurp_in = {{\"ctrl\", \"alt\", \"cmd\"}, \"i\"},\n barf_out = {{\"ctrl\", \"alt\", \"cmd\"}, \"o\"},\n\n -- switch to a new Mission Control space\n switch_space_1 = {{\"ctrl\", \"alt\", \"cmd\"}, \"1\"},\n switch_space_2 = {{\"ctrl\", \"alt\", \"cmd\"}, \"2\"},\n switch_space_3 = {{\"ctrl\", \"alt\", \"cmd\"}, \"3\"},\n switch_space_4 = {{\"ctrl\", \"alt\", \"cmd\"}, \"4\"},\n switch_space_5 = {{\"ctrl\", \"alt\", \"cmd\"}, \"5\"},\n switch_space_6 = {{\"ctrl\", \"alt\", \"cmd\"}, \"6\"},\n switch_space_7 = {{\"ctrl\", \"alt\", \"cmd\"}, \"7\"},\n switch_space_8 = {{\"ctrl\", \"alt\", \"cmd\"}, \"8\"},\n switch_space_9 = {{\"ctrl\", \"alt\", \"cmd\"}, \"9\"},\n\n -- move focused window to a new space and tile\n move_window_1 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"1\"},\n move_window_2 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"2\"},\n move_window_3 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"3\"},\n move_window_4 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"4\"},\n move_window_5 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"5\"},\n move_window_6 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"6\"},\n move_window_7 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"7\"},\n move_window_8 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"8\"},\n move_window_9 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"9\"}\n})\nPaperWM:start()\n```\n\nUse `PaperWM:bindHotkeys(PaperWM.default_hotkeys)` for defaults.\n\nSet `PaperWM.window_gap` to the number of pixels to space between windows and\nthe top and bottom screen edges.\n\nOverwrite `PaperWM.window_filter` to ignore specific applications. For example:\n\n```\nPaperWM.window_filter = PaperWM.window_filter:setAppFilter(\"Finder\", false)\nPaperWM:start() -- restart for new window filter to take effect\n```\n\n# Limitations\n\nUnder System Preferences -> Mission Control, unselect \"Automatically\nrearrange Spaces based on most recent use\" and select \"Displays have separate\nSpaces\".\n\nMacOS does not allow a window to be moved fully off-screen. Windows that would\nbe tiled off-screen are placed in a margin on the left and right edge of the\nscreen. They are still visible and clickable.\n\nIt's difficult to detect when a window is dragged from one space or screen to\nanother. Use the move_window_N commands to move windows between spaces and\nscreens.\n\nArrange screens vertically to prevent windows from bleeding into other screens.\n\n\nDownload: [https://github.com/mogenson/PaperWM.spoon](https://github.com/mogenson/PaperWM.spoon)", "submodules": [], "type": "Module" }, @@ -15761,7 +17095,7 @@ "doc": "Starts the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "203", + "lineno": "207", "name": "start", "notes": [], "parameters": [ @@ -15780,7 +17114,7 @@ "doc": "Stops the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "221", + "lineno": "225", "name": "stop", "notes": [], "parameters": [ @@ -15894,7 +17228,7 @@ "doc": "Starts the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "203", + "lineno": "207", "name": "start", "notes": [], "parameters": [ @@ -15913,7 +17247,7 @@ "doc": "Stops the indicator\n\nParameters:\n * None\n\nReturns:\n * The TimeMachineProgress object", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "221", + "lineno": "225", "name": "stop", "notes": [], "parameters": [ diff --git a/docs/docs_index.json b/docs/docs_index.json index 3d07f39c..cd5edcf7 100644 --- a/docs/docs_index.json +++ b/docs/docs_index.json @@ -155,6 +155,11 @@ "name": "createTask", "type": "Method" }, + { + "desc": "Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.", + "name": "AutoMuteOnSleep", + "type": "Module" + }, { "desc": "Use Bing daily picture as your wallpaper, automatically.", "name": "BingDaily", @@ -1285,6 +1290,52 @@ "name": "show", "type": "Method" }, + { + "desc": "Show input method indicator in the current mouse position.", + "name": "InputMethodIndicator", + "type": "Module" + }, + { + "desc": "init.", + "module": "InputMethodIndicator", + "name": "init", + "type": "Method" + }, + { + "desc": "Start InputMethodIndicator.", + "module": "InputMethodIndicator", + "name": "start", + "type": "Method" + }, + { + "desc": "Stop InputMethodIndicator.", + "module": "InputMethodIndicator", + "name": "stop", + "type": "Method" + }, + { + "desc": "Automatically switch the input source when switching applications.", + "name": "InputSourceSwitch", + "type": "Module" + }, + { + "desc": "Mapping the application name to the input source", + "module": "InputSourceSwitch", + "name": "applicationMap", + "type": "Variable" + }, + { + "desc": "Set that mapping the application name to the input source", + "module": "InputSourceSwitch", + "name": "setApplications", + "type": "Method" + }, + { + "desc": "Start InputSourceSwitch", + "module": "InputSourceSwitch", + "name": "start", + "type": "Method" + }, { "desc": "Get and Add items from Keychain. Provides no hotkeys and maintains no state", "name": "Keychain", @@ -1444,6 +1495,47 @@ "name": "stop", "type": "Method" }, + { + "desc": "This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.", + "name": "LeftRightHotkey", + "type": "Module" + }, + { + "desc": "Create and enable a new hotkey with the specified left/right specific modifiers.", + "module": "LeftRightHotkey", + "name": "bind", + "type": "Method" + }, + { + "desc": "Deletes all previously set callbacks for a given keyboard combination", + "module": "LeftRightHotkey", + "name": "deleteAll", + "type": "Method" + }, + { + "desc": "Disables all previously set callbacks for a given keyboard combination", + "module": "LeftRightHotkey", + "name": "disableAll", + "type": "Method" + }, + { + "desc": "Create a new hotkey with the specified left/right specific modifiers.", + "module": "LeftRightHotkey", + "name": "new", + "type": "Method" + }, + { + "desc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "module": "LeftRightHotkey", + "name": "start", + "type": "Method" + }, + { + "desc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "module": "LeftRightHotkey", + "name": "stop", + "type": "Method" + }, { "desc": "Show a popup window with the currently selected word in lexicon, notes, online help", "name": "LookupSelection", @@ -1549,6 +1641,11 @@ "name": "toggleMicMute", "type": "Method" }, + { + "desc": "Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.", + "name": "MiddleClickDragScroll", + "type": "Module" + }, { "desc": "With this script you will be able to move the window in halves and in corners using your keyboard and mainly using arrows. You would also be able to resize them by thirds, quarters, or halves.", "name": "MiroWindowsManager", @@ -1737,7 +1834,7 @@ "type": "Variable" }, { - "desc": "Configures the spoon. There is currently nothing to configure.", + "desc": "Configures the spoon.", "module": "MouseFollowsFocus", "name": "configure", "type": "Method" @@ -1859,6 +1956,143 @@ "name": "updateEventSubscriptions", "type": "Method" }, + { + "desc": "A scrolling window manager. Inspired by PaperWM Gnome extension.", + "name": "PaperWM", + "type": "Module" + }, + { + "desc": "Default hotkeys for moving / resizing windows", + "module": "PaperWM", + "name": "default_hotkeys", + "type": "Variable" + }, + { + "desc": "Logger object. Can be accessed to set default log level.", + "module": "PaperWM", + "name": "logger", + "type": "Variable" + }, + { + "desc": "Windows captured by this filter are automatically tiled and managed", + "module": "PaperWM", + "name": "window_filter", + "type": "Variable" + }, + { + "desc": "Number of pixels between tiled windows", + "module": "PaperWM", + "name": "window_gap", + "type": "Variable" + }, + { + "desc": "Adds a window to layout and tiles.", + "module": "PaperWM", + "name": "addWindow", + "type": "Method" + }, + { + "desc": "Removes current window from column and places it to the right", + "module": "PaperWM", + "name": "barfWindow", + "type": "Method" + }, + { + "desc": "Binds hotkeys for PaperWM", + "module": "PaperWM", + "name": "bindHotkeys", + "type": "Method" + }, + { + "desc": "Moves current window to center of screen, without resizing.", + "module": "PaperWM", + "name": "centerWindow", + "type": "Method" + }, + { + "desc": "Resizes current window by cycling through width or height ratios.", + "module": "PaperWM", + "name": "cycleWindowSize", + "type": "Method" + }, + { + "desc": "Change focus to a nearby window", + "module": "PaperWM", + "name": "focusWindow", + "type": "Method" + }, + { + "desc": "Resizes a window without triggering a windowMoved event", + "module": "PaperWM", + "name": "moveWindow", + "type": "Method" + }, + { + "desc": "Moves the current window to a new Mission Control space", + "module": "PaperWM", + "name": "moveWindowToSpace", + "type": "Method" + }, + { + "desc": "Searches for all windows that match window filter.", + "module": "PaperWM", + "name": "refreshWindows", + "type": "Method" + }, + { + "desc": "Remove window from tiling layout", + "module": "PaperWM", + "name": "remove_window", + "type": "Method" + }, + { + "desc": "Resizes current window's width to width of screen, without adjusting height.", + "module": "PaperWM", + "name": "setWindowFullWidth", + "type": "Method" + }, + { + "desc": "Moves current window into column of windows to the left", + "module": "PaperWM", + "name": "slurpWindow", + "type": "Method" + }, + { + "desc": "Start automatic tiling of windows", + "module": "PaperWM", + "name": "start", + "type": "Method" + }, + { + "desc": "Stop automatic tiling of windows", + "module": "PaperWM", + "name": "stop", + "type": "Method" + }, + { + "desc": "Swaps window postions between current window and window in specified direction.", + "module": "PaperWM", + "name": "swapWindows", + "type": "Method" + }, + { + "desc": "Switch to a Mission Control space", + "module": "PaperWM", + "name": "switchToSpace", + "type": "Method" + }, + { + "desc": "Tile a column of windows", + "module": "PaperWM", + "name": "tileColumn", + "type": "Method" + }, + { + "desc": "Tile all windows within a space", + "module": "PaperWM", + "name": "tileSpace", + "type": "Method" + }, { "desc": "Generate a password and copy to the clipboard.", "name": "PasswordGenerator", diff --git a/docs/index.html b/docs/index.html index 66379d2e..ad1daf48 100644 --- a/docs/index.html +++ b/docs/index.html @@ -97,6 +97,11 @@

API documentation

Asana

Simple spoon that creates a new task in Asana with a given name in a given workspace.

+ + + + AutoMuteOnSleep +

Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.

@@ -237,6 +242,16 @@

API documentation

HSKeybindings

Display Keybindings registered with bindHotkeys() and Spoons

+ + + + InputMethodIndicator +

Show input method indicator in the current mouse position.

+ + + + InputSourceSwitch +

Automatically switch the input source when switching applications.

@@ -252,6 +267,11 @@

API documentation

Leanpub

Spoon to track and notify about Leanpub builds.

+ + + + LeftRightHotkey +

This spoon addresses a limitation within the hs.hotkey module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.

@@ -267,6 +287,11 @@

API documentation

MicMute

Microphone Mute Toggle and status indicator

+ + + + MiddleClickDragScroll +

Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.

@@ -307,6 +332,11 @@

API documentation

OBS

Control OBS and react to its events, via the obs-websocket plugin.

+ + + + PaperWM +

A scrolling window manager. Inspired by PaperWM Gnome extension.

diff --git a/docs/templated_docs.json b/docs/templated_docs.json index 751990a2..9a5db9e1 100644 --- a/docs/templated_docs.json +++ b/docs/templated_docs.json @@ -16,7 +16,7 @@ "doc_gfm": "

Hide AClock.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The AClock object
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "116", + "lineno": "130", "name": "hide", "notes": [], "notes_gfm": "", @@ -66,7 +66,7 @@ "doc_gfm": "

Show AClock.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The AClock object
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "97", + "lineno": "111", "name": "show", "notes": [], "notes_gfm": "", @@ -91,7 +91,7 @@ "doc_gfm": "

Show AClock for 4 seconds. If already showing, hide it.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "133", + "lineno": "147", "name": "toggleShow", "notes": [], "notes_gfm": "", @@ -114,7 +114,7 @@ "doc_gfm": "

Show AClock. If already showing, hide it.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "154", + "lineno": "168", "name": "toggleShowPersistent", "notes": [], "notes_gfm": "", @@ -144,7 +144,7 @@ "doc_gfm": "

Hide AClock.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The AClock object
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "116", + "lineno": "130", "name": "hide", "notes": [], "notes_gfm": "", @@ -194,7 +194,7 @@ "doc_gfm": "

Show AClock.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The AClock object
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "97", + "lineno": "111", "name": "show", "notes": [], "notes_gfm": "", @@ -219,7 +219,7 @@ "doc_gfm": "

Show AClock for 4 seconds. If already showing, hide it.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "133", + "lineno": "147", "name": "toggleShow", "notes": [], "notes_gfm": "", @@ -242,7 +242,7 @@ "doc_gfm": "

Show AClock. If already showing, hide it.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/AClock.spoon/init.lua", - "lineno": "154", + "lineno": "168", "name": "toggleShowPersistent", "notes": [], "notes_gfm": "", @@ -1081,6 +1081,25 @@ "submodules": [], "type": "Module" }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [], + "Variable": [], + "desc": "Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.", + "desc_gfm": "

Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.

\n", + "doc": "Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.\nUseful to avoid blasting sound when opening a Macbook in the public transport.\nNote: This is primarily intended for portable Mac devices, which have internal speakers.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip)", + "doc_gfm": "

Automatically set to 0 the volume of all output audio devices except Bluetooth devices when Mac goes to sleep.\nUseful to avoid blasting sound when opening a Macbook in the public transport.\nNote: This is primarily intended for portable Mac devices, which have internal speakers.

\n

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip

\n", + "items": [], + "name": "AutoMuteOnSleep", + "stripped_doc": "Useful to avoid blasting sound when opening a Macbook in the public transport.\nNote: This is primarily intended for portable Mac devices, which have internal speakers.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/AutoMuteOnSleep.spoon.zip)", + "submodules": [], + "type": "Module" + }, { "Command": [], "Constant": [], @@ -5817,7 +5836,7 @@ "desc": "Thie plugin generates EmmyLua annotations for Hammerspoon and any installed Spoons", "desc_gfm": "

Thie plugin generates EmmyLua annotations for Hammerspoon and any installed Spoons

\n", "doc": "Thie plugin generates EmmyLua annotations for Hammerspoon and any installed Spoons\nunder ~/.hammerspoon/Spoons/EmmyLua.spoon/annotations.\nAnnotations will only be generated if they don't exist yet or are out of date.\n\nNote: Load this Spoon before any pathwatchers are defined to avoid unintended behaviour (for example multiple reloads when the annotions are created).\n\nIn order to get auto completion in your editor, you need to have one of the following LSP servers properly configured:\n* [lua-language-server](https://github.com/sumneko/lua-language-server) (recommended)\n* [EmmyLua-LanguageServer](https://github.com/EmmyLua/EmmyLua-LanguageServer)\n\nTo start using this annotations library, add the annotations folder to your workspace.\nfor lua-languag-server:\n\n```json\n{\n \"Lua.workspace.library\": [\"/Users/YOUR_USERNAME/.hammerspoon/Spoons/EmmyLua.spoon/annotations\"]\n}\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/EmmyLua.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/EmmyLua.spoon.zip)", - "doc_gfm": "

Thie plugin generates EmmyLua annotations for Hammerspoon and any installed Spoons\nunder ~/.hammerspoon/Spoons/EmmyLua.spoon/annotations.\nAnnotations will only be generated if they don't exist yet or are out of date.

\n

Note: Load this Spoon before any pathwatchers are defined to avoid unintended behaviour (for example multiple reloads when the annotions are created).

\n

In order to get auto completion in your editor, you need to have one of the following LSP servers properly configured:

\n\n

To start using this annotations library, add the annotations folder to your workspace.\nfor lua-languag-server:

\n
{\n  "Lua.workspace.library": ["/Users/YOUR_USERNAME/.hammerspoon/Spoons/EmmyLua.spoon/annotations"]\n}\n
\n

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/EmmyLua.spoon.zip

\n", + "doc_gfm": "

Thie plugin generates EmmyLua annotations for Hammerspoon and any installed Spoons\nunder ~/.hammerspoon/Spoons/EmmyLua.spoon/annotations.\nAnnotations will only be generated if they don't exist yet or are out of date.

\n

Note: Load this Spoon before any pathwatchers are defined to avoid unintended behaviour (for example multiple reloads when the annotions are created).

\n

In order to get auto completion in your editor, you need to have one of the following LSP servers properly configured:

\n\n

To start using this annotations library, add the annotations folder to your workspace.\nfor lua-languag-server:

\n
{\n  "Lua.workspace.library": ["/Users/YOUR_USERNAME/.hammerspoon/Spoons/EmmyLua.spoon/annotations"]\n}\n
\n

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/EmmyLua.spoon.zip

\n", "items": [], "name": "EmmyLua", "stripped_doc": "under ~/.hammerspoon/Spoons/EmmyLua.spoon/annotations.\nAnnotations will only be generated if they don't exist yet or are out of date.\n\nNote: Load this Spoon before any pathwatchers are defined to avoid unintended behaviour (for example multiple reloads when the annotions are created).\n\nIn order to get auto completion in your editor, you need to have one of the following LSP servers properly configured:\n* [lua-language-server](https://github.com/sumneko/lua-language-server) (recommended)\n* [EmmyLua-LanguageServer](https://github.com/EmmyLua/EmmyLua-LanguageServer)\n\nTo start using this annotations library, add the annotations folder to your workspace.\nfor lua-languag-server:\n\n```json\n{\n \"Lua.workspace.library\": [\"/Users/YOUR_USERNAME/.hammerspoon/Spoons/EmmyLua.spoon/annotations\"]\n}\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/EmmyLua.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/EmmyLua.spoon.zip)", @@ -8633,6 +8652,311 @@ "submodules": [], "type": "Module" }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "InputMethodIndicator:init()", + "def_gfm": "InputMethodIndicator:init()", + "desc": "init.", + "desc_gfm": "

init.

\n", + "doc": "init.\n\nParameters:\n * None\n\nReturns:\n * The InputMethodIndicator object", + "doc_gfm": "

init.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The InputMethodIndicator object
  • \n
\n", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "67", + "name": "init", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * The InputMethodIndicator object" + ], + "returns_gfm": "
    \n
  • The InputMethodIndicator object
  • \n
\n", + "signature": "InputMethodIndicator:init()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:start(config)", + "def_gfm": "InputMethodIndicator:start(config)", + "desc": "Start InputMethodIndicator.", + "desc_gfm": "

Start InputMethodIndicator.

\n", + "doc": "Start InputMethodIndicator.\n\nParameters:\n * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse", + "doc_gfm": "

Start InputMethodIndicator.

\n

Parameters:

\n
    \n
  • config - A table contains config options for the module
      \n
    • ABCColor - the dot color when the input method is ABC
    • \n
    • LocalLanguageColor - the dot color when the input method is not ABC
    • \n
    • mode - the mode of the indicator
    • \n
    • showOnChangeDuration - seconds to show the indicator when the input method is changed
    • \n
    • checkInterval - seconds to check the input method
    • \n
    • dotSize - the size of the dot
    • \n
    • deltaY - the distance between the dot and the center of the selection or mouse
    • \n
    \n
  • \n
\n", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "200", + "name": "start", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse" + ], + "parameters_gfm": "
    \n
  • config - A table contains config options for the module
      \n
    • ABCColor - the dot color when the input method is ABC
    • \n
    • LocalLanguageColor - the dot color when the input method is not ABC
    • \n
    • mode - the mode of the indicator
    • \n
    • showOnChangeDuration - seconds to show the indicator when the input method is changed
    • \n
    • checkInterval - seconds to check the input method
    • \n
    • dotSize - the size of the dot
    • \n
    • deltaY - the distance between the dot and the center of the selection or mouse
    • \n
    \n
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputMethodIndicator:start(config)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:stop()", + "def_gfm": "InputMethodIndicator:stop()", + "desc": "Stop InputMethodIndicator.", + "desc_gfm": "

Stop InputMethodIndicator.

\n", + "doc": "Stop InputMethodIndicator.\n\nParameters:\n * None", + "doc_gfm": "

Stop InputMethodIndicator.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "245", + "name": "stop", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputMethodIndicator:stop()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [], + "desc": "Show input method indicator in the current mouse position.", + "desc_gfm": "

Show input method indicator in the current mouse position.

\n", + "doc": "Show input method indicator in the current mouse position.\nIt is a small but noticable dot near the cursor.\nIt can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method.\nYou can use it as follows in the init.lua:\nhs.loadSpoon(\"InputMethodIndicator\")\nspoon.InputMethodIndicator:start(nil)\nnote: config parameter is a table, pass nil to use the default config\nthe default config is as follows:\n{\n ABCColor = \"#62C555\", -- the dot color when the input method is ABC\n LocalLanguageColor = \"#ED6A5E\", -- the dot color when the input method is not ABC\n mode = \"nearMouse\", -- the mode of the indicator\n showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed\n checkInterval = .01, -- seconds to check the input method\n dotSize = 6, -- the size of the dot\n deltaY=7, -- the distance between the dot and the center of the selection or mouse\n}\nthe mode can be \"nearMouse\",\"onChange\",\"adaptive\", the default mode is \"adaptive\"\n\"nearMouse\" means the indicator will always show near the mouse\n\"onChange\" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds\n\"adaptive\" means the indicator will show near the textarea when typing, otherwise it will show near the mouse\nNote: the \"adaptive\" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API", + "doc_gfm": "

Show input method indicator in the current mouse position.\nIt is a small but noticable dot near the cursor.\nIt can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method.\nYou can use it as follows in the init.lua:\nhs.loadSpoon("InputMethodIndicator")\nspoon.InputMethodIndicator:start(nil)\nnote: config parameter is a table, pass nil to use the default config\nthe default config is as follows:\n{\n ABCColor = "#62C555", -- the dot color when the input method is ABC\n LocalLanguageColor = "#ED6A5E", -- the dot color when the input method is not ABC\n mode = "nearMouse", -- the mode of the indicator\n showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed\n checkInterval = .01, -- seconds to check the input method\n dotSize = 6, -- the size of the dot\n deltaY=7, -- the distance between the dot and the center of the selection or mouse\n}\nthe mode can be "nearMouse","onChange","adaptive", the default mode is "adaptive"\n"nearMouse" means the indicator will always show near the mouse\n"onChange" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds\n"adaptive" means the indicator will show near the textarea when typing, otherwise it will show near the mouse\nNote: the "adaptive" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API

\n", + "items": [ + { + "def": "InputMethodIndicator:init()", + "def_gfm": "InputMethodIndicator:init()", + "desc": "init.", + "desc_gfm": "

init.

\n", + "doc": "init.\n\nParameters:\n * None\n\nReturns:\n * The InputMethodIndicator object", + "doc_gfm": "

init.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The InputMethodIndicator object
  • \n
\n", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "67", + "name": "init", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * The InputMethodIndicator object" + ], + "returns_gfm": "
    \n
  • The InputMethodIndicator object
  • \n
\n", + "signature": "InputMethodIndicator:init()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:start(config)", + "def_gfm": "InputMethodIndicator:start(config)", + "desc": "Start InputMethodIndicator.", + "desc_gfm": "

Start InputMethodIndicator.

\n", + "doc": "Start InputMethodIndicator.\n\nParameters:\n * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse", + "doc_gfm": "

Start InputMethodIndicator.

\n

Parameters:

\n
    \n
  • config - A table contains config options for the module
      \n
    • ABCColor - the dot color when the input method is ABC
    • \n
    • LocalLanguageColor - the dot color when the input method is not ABC
    • \n
    • mode - the mode of the indicator
    • \n
    • showOnChangeDuration - seconds to show the indicator when the input method is changed
    • \n
    • checkInterval - seconds to check the input method
    • \n
    • dotSize - the size of the dot
    • \n
    • deltaY - the distance between the dot and the center of the selection or mouse
    • \n
    \n
  • \n
\n", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "200", + "name": "start", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * config - A table contains config options for the module\n * ABCColor - the dot color when the input method is ABC\n * LocalLanguageColor - the dot color when the input method is not ABC\n * mode - the mode of the indicator\n * showOnChangeDuration - seconds to show the indicator when the input method is changed\n * checkInterval - seconds to check the input method\n * dotSize - the size of the dot\n * deltaY - the distance between the dot and the center of the selection or mouse" + ], + "parameters_gfm": "
    \n
  • config - A table contains config options for the module
      \n
    • ABCColor - the dot color when the input method is ABC
    • \n
    • LocalLanguageColor - the dot color when the input method is not ABC
    • \n
    • mode - the mode of the indicator
    • \n
    • showOnChangeDuration - seconds to show the indicator when the input method is changed
    • \n
    • checkInterval - seconds to check the input method
    • \n
    • dotSize - the size of the dot
    • \n
    • deltaY - the distance between the dot and the center of the selection or mouse
    • \n
    \n
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputMethodIndicator:start(config)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputMethodIndicator:stop()", + "def_gfm": "InputMethodIndicator:stop()", + "desc": "Stop InputMethodIndicator.", + "desc_gfm": "

Stop InputMethodIndicator.

\n", + "doc": "Stop InputMethodIndicator.\n\nParameters:\n * None", + "doc_gfm": "

Stop InputMethodIndicator.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/InputMethodIndicator.spoon/init.lua", + "lineno": "245", + "name": "stop", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputMethodIndicator:stop()", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "InputMethodIndicator", + "stripped_doc": "It is a small but noticable dot near the cursor.\nIt can be very useful when you are using a non-ABC input method and often needs to switch between ABC and the non-ABC input method.\nYou can use it as follows in the init.lua:\nhs.loadSpoon(\"InputMethodIndicator\")\nspoon.InputMethodIndicator:start(nil)\nnote: config parameter is a table, pass nil to use the default config\nthe default config is as follows:\n{\n ABCColor = \"#62C555\", -- the dot color when the input method is ABC\n LocalLanguageColor = \"#ED6A5E\", -- the dot color when the input method is not ABC\n mode = \"nearMouse\", -- the mode of the indicator\n showOnChangeDuration = 3, -- seconds to show the indicator when the input method is changed\n checkInterval = .01, -- seconds to check the input method\n dotSize = 6, -- the size of the dot\n deltaY=7, -- the distance between the dot and the center of the selection or mouse\n}\nthe mode can be \"nearMouse\",\"onChange\",\"adaptive\", the default mode is \"adaptive\"\n\"nearMouse\" means the indicator will always show near the mouse\n\"onChange\" means the indicator will show when the input method is changed and hide after showOnChangeDuration seconds\n\"adaptive\" means the indicator will show near the textarea when typing, otherwise it will show near the mouse\nNote: the \"adaptive\" mode is not perfect, it may not work in some apps because of the limitation of the accessibility API", + "submodules": [], + "type": "Module" + }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "InputSourceSwitch:setApplications()", + "def_gfm": "InputSourceSwitch:setApplications()", + "desc": "Set that mapping the application name to the input source", + "desc_gfm": "

Set that mapping the application name to the input source

\n", + "doc": "Set that mapping the application name to the input source\n\nParameters:\n * applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:\n```\n{\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n}\n```", + "doc_gfm": "

Set that mapping the application name to the input source

\n

Parameters:

\n
    \n
  • applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:
  • \n
\n\n
{\n    ["WeChat"] = "Pinyin - Simplified",\n    ["Mail"] = "ABC"\n}\n
\n", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "80", + "name": "setApplications", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: ``` { [\"WeChat\"] = \"Pinyin - Simplified\", [\"Mail\"] = \"ABC\" } ```" + ], + "parameters_gfm": "
    \n
  • applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: { ["WeChat"] = "Pinyin - Simplified", ["Mail"] = "ABC" }
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputSourceSwitch:setApplications()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputSourceSwitch:start()", + "def_gfm": "InputSourceSwitch:start()", + "desc": "Start InputSourceSwitch", + "desc_gfm": "

Start InputSourceSwitch

\n", + "doc": "Start InputSourceSwitch\n\nParameters:\n * None", + "doc_gfm": "

Start InputSourceSwitch

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "100", + "name": "start", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputSourceSwitch:start()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ + { + "def": "InputSourceSwitch.applicationMap", + "def_gfm": "InputSourceSwitch.applicationMap", + "desc": "Mapping the application name to the input source", + "desc_gfm": "

Mapping the application name to the input source

\n", + "doc": "Mapping the application name to the input source", + "doc_gfm": "

Mapping the application name to the input source

\n", + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "75", + "name": "applicationMap", + "signature": "InputSourceSwitch.applicationMap", + "stripped_doc": "", + "type": "Variable" + } + ], + "desc": "Automatically switch the input source when switching applications.", + "desc_gfm": "

Automatically switch the input source when switching applications.

\n", + "doc": "Automatically switch the input source when switching applications.\n\nExample:\n```\nhs.loadSpoon(\"InputSourceSwitch\")\n\nspoon.InputSourceSwitch:setApplications({\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n})\n\nspoon.InputSourceSwitch:start()\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip)", + "doc_gfm": "

Automatically switch the input source when switching applications.

\n

Example:

\n\n
hs.loadSpoon("InputSourceSwitch")\n\nspoon.InputSourceSwitch:setApplications({\n    ["WeChat"] = "Pinyin - Simplified",\n    ["Mail"] = "ABC"\n})\n\nspoon.InputSourceSwitch:start()\n
\n

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip

\n", + "items": [ + { + "def": "InputSourceSwitch.applicationMap", + "def_gfm": "InputSourceSwitch.applicationMap", + "desc": "Mapping the application name to the input source", + "desc_gfm": "

Mapping the application name to the input source

\n", + "doc": "Mapping the application name to the input source", + "doc_gfm": "

Mapping the application name to the input source

\n", + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "75", + "name": "applicationMap", + "signature": "InputSourceSwitch.applicationMap", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "InputSourceSwitch:setApplications()", + "def_gfm": "InputSourceSwitch:setApplications()", + "desc": "Set that mapping the application name to the input source", + "desc_gfm": "

Set that mapping the application name to the input source

\n", + "doc": "Set that mapping the application name to the input source\n\nParameters:\n * applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:\n```\n{\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n}\n```", + "doc_gfm": "

Set that mapping the application name to the input source

\n

Parameters:

\n
    \n
  • applications - A table containing that mapping the application name to the input source\n key is the application name and value is the input source name\n example:
  • \n
\n\n
{\n    ["WeChat"] = "Pinyin - Simplified",\n    ["Mail"] = "ABC"\n}\n
\n", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "80", + "name": "setApplications", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: ``` { [\"WeChat\"] = \"Pinyin - Simplified\", [\"Mail\"] = \"ABC\" } ```" + ], + "parameters_gfm": "
    \n
  • applications - A table containing that mapping the application name to the input source key is the application name and value is the input source name example: { ["WeChat"] = "Pinyin - Simplified", ["Mail"] = "ABC" }
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputSourceSwitch:setApplications()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "InputSourceSwitch:start()", + "def_gfm": "InputSourceSwitch:start()", + "desc": "Start InputSourceSwitch", + "desc_gfm": "

Start InputSourceSwitch

\n", + "doc": "Start InputSourceSwitch\n\nParameters:\n * None", + "doc_gfm": "

Start InputSourceSwitch

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/InputSourceSwitch.spoon/init.lua", + "lineno": "100", + "name": "start", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "InputSourceSwitch:start()", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "InputSourceSwitch", + "stripped_doc": "\nExample:\n```\nhs.loadSpoon(\"InputSourceSwitch\")\n\nspoon.InputSourceSwitch:setApplications({\n [\"WeChat\"] = \"Pinyin - Simplified\",\n [\"Mail\"] = \"ABC\"\n})\n\nspoon.InputSourceSwitch:start()\n```\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/InputSourceSwitch.spoon.zip)", + "submodules": [], + "type": "Module" + }, { "Command": [], "Constant": [], @@ -9724,64 +10048,427 @@ "Function": [], "Method": [ { - "def": "LookupSelection:bindHotkeys(mapping)", - "def_gfm": "LookupSelection:bindHotkeys(mapping)", - "desc": "Binds hotkeys for LookupSelection", - "desc_gfm": "

Binds hotkeys for LookupSelection

\n", - "doc": "Binds hotkeys for LookupSelection\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help\n\nNotes:\n * Sample value for `mapping`:\n```\n {\n lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },\n neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },\n hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },\n }\n```", - "doc_gfm": "

Binds hotkeys for LookupSelection

\n

Parameters:

\n
    \n
  • mapping - A table containing hotkey modifier/key details for the following items:
  • \n
  • lexicon - open in lexicon app
  • \n
  • neue_notiz - create new note in notes app
  • \n
  • hsdocs - display online help
  • \n
\n

Notes:

\n
    \n
  • Sample value for mapping:
  • \n
\n\n
 {\n    lexicon = { { "ctrl", "alt", "cmd" }, "L" },\n    neue_notiz = { { "ctrl", "alt", "cmd" }, "N" },\n    hsdocs = { { "ctrl", "alt", "cmd" }, "H" },\n }\n
\n", + "def": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "def_gfm": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create and enable a new hotkey with the specified left/right specific modifiers.", + "desc_gfm": "

Create and enable a new hotkey with the specified left/right specific modifiers.

\n", + "doc": "Create and enable a new hotkey with the specified left/right specific modifiers.\n\nParameters:\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new enabled hotkey with the specified left/right modifiers.\n\nNotes:\n * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here.", + "doc_gfm": "

Create and enable a new hotkey with the specified left/right specific modifiers.

\n

Parameters:\nParameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n

Returns:

\n
    \n
  • a new enabled hotkey with the specified left/right modifiers.
  • \n
\n

Notes:

\n
    \n
  • This function is just a wrapper that performs LeftRightHotkey:new(...):enable()
  • \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.bind as is and any caveats or considerations outlined there also apply here.
  • \n
\n", "examples": [], - "file": "Source/LookupSelection.spoon/init.lua", - "lineno": "93", - "name": "bindHotkeys", + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "415", + "name": "bind", "notes": [ - " * Sample value for `mapping`:", - "```", - " {", - " lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },", - " neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },", - " hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },", - " }", - "```" + " * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`", + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here." ], - "notes_gfm": "
    \n
  • Sample value for mapping:
  • \n
\n\n
 {\n    lexicon = { { "ctrl", "alt", "cmd" }, "L" },\n    neue_notiz = { { "ctrl", "alt", "cmd" }, "N" },\n    hsdocs = { { "ctrl", "alt", "cmd" }, "H" },\n }\n
\n", + "notes_gfm": "
    \n
  • This function is just a wrapper that performs LeftRightHotkey:new(...):enable()
  • \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.bind as is and any caveats or considerations outlined there also apply here.
  • \n
\n", "parameters": [ - " * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help" + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" ], - "parameters_gfm": "
    \n
  • mapping - A table containing hotkey modifier/key details for the following items:
      \n
    • lexicon - open in lexicon app
    • \n
    • neue_notiz - create new note in notes app
    • \n
    • hsdocs - display online help
    • \n
    \n
  • \n
\n", - "returns": [], - "returns_gfm": "", - "signature": "LookupSelection:bindHotkeys(mapping)", + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n", + "returns": [ + " * a new enabled hotkey with the specified left/right modifiers." + ], + "returns_gfm": "
    \n
  • a new enabled hotkey with the specified left/right modifiers.
  • \n
\n", + "signature": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", "stripped_doc": "", "type": "Method" }, { - "def": "LookupSelection:openLexicon()", - "def_gfm": "LookupSelection:openLexicon()", - "desc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages", - "desc_gfm": "

Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages

\n", - "doc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages\n\nParameters:\n * None\n\nReturns:\n * The LookupSelection object", - "doc_gfm": "

Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The LookupSelection object
  • \n
\n", + "def": "LeftRightHotkey:deleteAll(mods, key)", + "def_gfm": "LeftRightHotkey:deleteAll(mods, key)", + "desc": "Deletes all previously set callbacks for a given keyboard combination", + "desc_gfm": "

Deletes all previously set callbacks for a given keyboard combination

\n", + "doc": "Deletes all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "doc_gfm": "

Deletes all previously set callbacks for a given keyboard combination

\n

Parameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", "examples": [], - "file": "Source/LookupSelection.spoon/init.lua", - "lineno": "58", - "name": "openLexicon", + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "326", + "name": "deleteAll", "notes": [], "notes_gfm": "", "parameters": [ - " * None" + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" ], - "parameters_gfm": "
    \n
  • None
  • \n
\n", + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n", "returns": [ - " * The LookupSelection object" + " * None" ], - "returns_gfm": "
    \n
  • The LookupSelection object
  • \n
\n", - "signature": "LookupSelection:openLexicon()", + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "LeftRightHotkey:deleteAll(mods, key)", "stripped_doc": "", "type": "Method" - } - ], - "Variable": [ + }, + { + "def": "LeftRightHotkey:disableAll(mods, key)", + "def_gfm": "LeftRightHotkey:disableAll(mods, key)", + "desc": "Disables all previously set callbacks for a given keyboard combination", + "desc_gfm": "

Disables all previously set callbacks for a given keyboard combination

\n", + "doc": "Disables all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "doc_gfm": "

Disables all previously set callbacks for a given keyboard combination

\n

Parameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "373", + "name": "disableAll", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "LeftRightHotkey:disableAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "def_gfm": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create a new hotkey with the specified left/right specific modifiers.", + "desc_gfm": "

Create a new hotkey with the specified left/right specific modifiers.

\n", + "doc": "Create a new hotkey with the specified left/right specific modifiers.\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new, initially disabled, hotkey with the specified left/right modifiers.\n\nNotes:\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here.", + "doc_gfm": "

Create a new hotkey with the specified left/right specific modifiers.

\n

Parameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n

Returns:

\n
    \n
  • a new, initially disabled, hotkey with the specified left/right modifiers.
  • \n
\n

Notes:

\n
    \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.new as is and any caveats or considerations outlined there also apply here.
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "263", + "name": "new", + "notes": [ + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here." + ], + "notes_gfm": "
    \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.new as is and any caveats or considerations outlined there also apply here.
  • \n
\n", + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n", + "returns": [ + " * a new, initially disabled, hotkey with the specified left/right modifiers." + ], + "returns_gfm": "
    \n
  • a new, initially disabled, hotkey with the specified left/right modifiers.
  • \n
\n", + "signature": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:start() -> self", + "def_gfm": "LeftRightHotkey:start() -> self", + "desc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "desc_gfm": "

Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n", + "doc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this enables the use of hotkeys created by using this Spoon.", + "doc_gfm": "

Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • the LeftRightHotkey spoon object
  • \n
\n

Notes:

\n
    \n
  • this enables the use of hotkeys created by using this Spoon.
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "444", + "name": "start", + "notes": [ + " * this enables the use of hotkeys created by using this Spoon." + ], + "notes_gfm": "
    \n
  • this enables the use of hotkeys created by using this Spoon.
  • \n
\n", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "returns_gfm": "
    \n
  • the LeftRightHotkey spoon object
  • \n
\n", + "signature": "LeftRightHotkey:start() -> self", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:stop() -> self", + "def_gfm": "LeftRightHotkey:stop() -> self", + "desc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "desc_gfm": "

Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n", + "doc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available.", + "doc_gfm": "

Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • the LeftRightHotkey spoon object
  • \n
\n

Notes:

\n
    \n
  • this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with hs.hotkey directly will still be available.
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "471", + "name": "stop", + "notes": [ + " * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available." + ], + "notes_gfm": "
    \n
  • this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with hs.hotkey directly will still be available.
  • \n
\n", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "returns_gfm": "
    \n
  • the LeftRightHotkey spoon object
  • \n
\n", + "signature": "LeftRightHotkey:stop() -> self", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [], + "desc": "This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.", + "desc_gfm": "

This spoon addresses a limitation within the hs.hotkey module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.

\n", + "doc": "This spoon addresses a limitation within the [hs.hotkey](hs.hotkey.html) module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.\n\nThis is accomplished by creating unactivated hotkeys for each definition and using an [hs.eventtap](hs.eventtap.html) watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the `bind` and `new` methods of this spoon.\n\nThe `LeftRightHotkeyObject` that is returned by [LeftRightHotkey:new](#new) and [LeftRightHotkey:bind](#bind) supports the following methods in a manner similar to the [hs.hotkey](hs.hotkey.html) equivalents:\n\n * `LeftRightHotkeyObject:enable()` -- enables the registered hotkey.\n * `LeftRightHotkeyObject:disable()` -- disables the registered hotkey.\n * `LeftRightHotkeyObject:delete()` -- deletes the registered hotkey.\n * `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)\n\nThe following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n\nThe modifiers table for any given hotkey is all inclusive; this means that if you specify `{ \"rShift\", \"lShift\" }` then *both* the left and right shift keys *must* be pressed to trigger the hotkey -- if you want either/or, then stick with [hs.hotkey](hs.hotkey.html).\n\nAlternatively, if you want to setup a hotkey when *either* command key is pressed with *only* the right shift, you would need to set up two hotkeys with this spoon:\n e.g. `LeftRightHotkey:bind({ \"rCmd\", \"rShift\" }, \"a\", myFunction)` *and* `LeftRightHotkey:bind({ \"lCmd\", \"rShift\" }, \"a\", myFunction)`\n\nThis spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:\n * like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.\n * behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through `hs.hotkey:enable()` -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.\n * a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue [LeftRightHotkey:start()](#start) to force the eventtap to be reset if necessary.\n * if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.\n\nLike all Spoons, don't forget to use the [LeftRightHotkey:start()](#start) method to activate the modifier key watcher.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip)", + "doc_gfm": "

This spoon addresses a limitation within the hs.hotkey module that allows the creation of hotkeys bound to specific left or right keyboard modifiers while leaving the other side free.

\n

This is accomplished by creating unactivated hotkeys for each definition and using an hs.eventtap watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the bind and new methods of this spoon.

\n

The LeftRightHotkeyObject that is returned by LeftRightHotkey:new and LeftRightHotkey:bind supports the following methods in a manner similar to the hs.hotkey equivalents:

\n
    \n
  • LeftRightHotkeyObject:enable() -- enables the registered hotkey.
  • \n
  • LeftRightHotkeyObject:disable() -- disables the registered hotkey.
  • \n
  • LeftRightHotkeyObject:delete() -- deletes the registered hotkey.
  • \n
  • `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)
  • \n
\n

The following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:

\n
    \n
  • "lCmd", "lCommand", or "l⌘" for the left Command modifier
  • \n
  • "rCmd", "rCommand", or "r⌘" for the right Command modifier
  • \n
  • "lCtrl", "lControl" or "l⌃" for the left Control modifier
  • \n
  • "rCtrl", "rControl" or "r⌃" for the right Control modifier
  • \n
  • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
  • \n
  • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
  • \n
  • "lShift" or "l⇧" for the left Shift modifier
  • \n
  • "rShift" or "r⇧" for the right Shift modifier
  • \n
\n

The modifiers table for any given hotkey is all inclusive; this means that if you specify { "rShift", "lShift" } then both the left and right shift keys must be pressed to trigger the hotkey -- if you want either/or, then stick with hs.hotkey.

\n

Alternatively, if you want to setup a hotkey when either command key is pressed with only the right shift, you would need to set up two hotkeys with this spoon:\n e.g. LeftRightHotkey:bind({ "rCmd", "rShift" }, "a", myFunction) and LeftRightHotkey:bind({ "lCmd", "rShift" }, "a", myFunction)

\n

This spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:

\n
    \n
  • like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.
  • \n
  • behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through hs.hotkey:enable() -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.
      \n
    • a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue LeftRightHotkey:start() to force the eventtap to be reset if necessary.
    • \n
    • if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.
    • \n
    \n
  • \n
\n

Like all Spoons, don't forget to use the LeftRightHotkey:start() method to activate the modifier key watcher.

\n

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip

\n", + "items": [ + { + "def": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "def_gfm": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create and enable a new hotkey with the specified left/right specific modifiers.", + "desc_gfm": "

Create and enable a new hotkey with the specified left/right specific modifiers.

\n", + "doc": "Create and enable a new hotkey with the specified left/right specific modifiers.\n\nParameters:\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new enabled hotkey with the specified left/right modifiers.\n\nNotes:\n * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here.", + "doc_gfm": "

Create and enable a new hotkey with the specified left/right specific modifiers.

\n

Parameters:\nParameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n

Returns:

\n
    \n
  • a new enabled hotkey with the specified left/right modifiers.
  • \n
\n

Notes:

\n
    \n
  • This function is just a wrapper that performs LeftRightHotkey:new(...):enable()
  • \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.bind as is and any caveats or considerations outlined there also apply here.
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "415", + "name": "bind", + "notes": [ + " * This function is just a wrapper that performs `LeftRightHotkey:new(...):enable()`", + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.bind](hs.hotkey.html#bind) as is and any caveats or considerations outlined there also apply here." + ], + "notes_gfm": "
    \n
  • This function is just a wrapper that performs LeftRightHotkey:new(...):enable()
  • \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.bind as is and any caveats or considerations outlined there also apply here.
  • \n
\n", + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n", + "returns": [ + " * a new enabled hotkey with the specified left/right modifiers." + ], + "returns_gfm": "
    \n
  • a new enabled hotkey with the specified left/right modifiers.
  • \n
\n", + "signature": "LeftRightHotkey:bind(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:deleteAll(mods, key)", + "def_gfm": "LeftRightHotkey:deleteAll(mods, key)", + "desc": "Deletes all previously set callbacks for a given keyboard combination", + "desc_gfm": "

Deletes all previously set callbacks for a given keyboard combination

\n", + "doc": "Deletes all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "doc_gfm": "

Deletes all previously set callbacks for a given keyboard combination

\n

Parameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "326", + "name": "deleteAll", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "LeftRightHotkey:deleteAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:disableAll(mods, key)", + "def_gfm": "LeftRightHotkey:disableAll(mods, key)", + "desc": "Disables all previously set callbacks for a given keyboard combination", + "desc_gfm": "

Disables all previously set callbacks for a given keyboard combination

\n", + "doc": "Disables all previously set callbacks for a given keyboard combination\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n\nReturns:\n * None", + "doc_gfm": "

Disables all previously set callbacks for a given keyboard combination

\n

Parameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "373", + "name": "disableAll", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number" + ], + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "LeftRightHotkey:disableAll(mods, key)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "def_gfm": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "desc": "Create a new hotkey with the specified left/right specific modifiers.", + "desc_gfm": "

Create a new hotkey with the specified left/right specific modifiers.

\n", + "doc": "Create a new hotkey with the specified left/right specific modifiers.\n\nParameters:\n * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number\n * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown\n * pressedfn - A function that will be called when the hotkey has been pressed, or nil\n * releasedfn - A function that will be called when the hotkey has been released, or nil\n * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil\n\nReturns:\n * a new, initially disabled, hotkey with the specified left/right modifiers.\n\nNotes:\n * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here.", + "doc_gfm": "

Create a new hotkey with the specified left/right specific modifiers.

\n

Parameters:

\n
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n

Returns:

\n
    \n
  • a new, initially disabled, hotkey with the specified left/right modifiers.
  • \n
\n

Notes:

\n
    \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.new as is and any caveats or considerations outlined there also apply here.
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "263", + "name": "new", + "notes": [ + " * The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to [hs.hotkey.new](hs.hotkey.html#new) as is and any caveats or considerations outlined there also apply here." + ], + "notes_gfm": "
    \n
  • The modifiers table is adjusted for use when conditionally activating the appropriate hotkeys based on the current modifiers in effect, but the other arguments are passed to hs.hotkey.new as is and any caveats or considerations outlined there also apply here.
  • \n
\n", + "parameters": [ + " * mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier", + " * key - A string containing the name of a keyboard key (as found in [hs.keycodes.map](hs.keycodes.html#map) ), or a raw keycode number", + " * message - (optional) A string containing a message to be displayed via [hs.alert()](hs.alert.html) when the hotkey has been triggered; if omitted, no alert will be shown", + " * pressedfn - A function that will be called when the hotkey has been pressed, or nil", + " * releasedfn - A function that will be called when the hotkey has been released, or nil", + " * repeatfn - A function that will be called when a pressed hotkey is repeating, or nil" + ], + "parameters_gfm": "
    \n
  • mods - A table containing as elements the keyboard modifiers required, which should be one or more of the following:
      \n
    • "lCmd", "lCommand", or "l⌘" for the left Command modifier
    • \n
    • "rCmd", "rCommand", or "r⌘" for the right Command modifier
    • \n
    • "lCtrl", "lControl" or "l⌃" for the left Control modifier
    • \n
    • "rCtrl", "rControl" or "r⌃" for the right Control modifier
    • \n
    • "lAlt", "lOpt", "lOption" or "l⌥" for the left Option modifier
    • \n
    • "rAlt", "rOpt", "rOption" or "r⌥" for the right Option modifier
    • \n
    • "lShift" or "l⇧" for the left Shift modifier
    • \n
    • "rShift" or "r⇧" for the right Shift modifier
    • \n
    \n
  • \n
  • key - A string containing the name of a keyboard key (as found in hs.keycodes.map ), or a raw keycode number
  • \n
  • message - (optional) A string containing a message to be displayed via hs.alert() when the hotkey has been triggered; if omitted, no alert will be shown
  • \n
  • pressedfn - A function that will be called when the hotkey has been pressed, or nil
  • \n
  • releasedfn - A function that will be called when the hotkey has been released, or nil
  • \n
  • repeatfn - A function that will be called when a pressed hotkey is repeating, or nil
  • \n
\n", + "returns": [ + " * a new, initially disabled, hotkey with the specified left/right modifiers." + ], + "returns_gfm": "
    \n
  • a new, initially disabled, hotkey with the specified left/right modifiers.
  • \n
\n", + "signature": "LeftRightHotkey:new(mods, key, [message,] pressedfn, releasedfn, repeatfn) -> LeftRightHotkeyObject", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:start() -> self", + "def_gfm": "LeftRightHotkey:start() -> self", + "desc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "desc_gfm": "

Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n", + "doc": "Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this enables the use of hotkeys created by using this Spoon.", + "doc_gfm": "

Starts watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • the LeftRightHotkey spoon object
  • \n
\n

Notes:

\n
    \n
  • this enables the use of hotkeys created by using this Spoon.
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "444", + "name": "start", + "notes": [ + " * this enables the use of hotkeys created by using this Spoon." + ], + "notes_gfm": "
    \n
  • this enables the use of hotkeys created by using this Spoon.
  • \n
\n", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "returns_gfm": "
    \n
  • the LeftRightHotkey spoon object
  • \n
\n", + "signature": "LeftRightHotkey:start() -> self", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LeftRightHotkey:stop() -> self", + "def_gfm": "LeftRightHotkey:stop() -> self", + "desc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.", + "desc_gfm": "

Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n", + "doc": "Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.\n\nParameters:\n * None\n\nReturns:\n * the LeftRightHotkey spoon object\n\nNotes:\n * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available.", + "doc_gfm": "

Stops watching for flag (modifier key) change events that can determine if the right or left modifiers have been pressed.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • the LeftRightHotkey spoon object
  • \n
\n

Notes:

\n
    \n
  • this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with hs.hotkey directly will still be available.
  • \n
\n", + "examples": [], + "file": "Source/LeftRightHotkey.spoon/init.lua", + "lineno": "471", + "name": "stop", + "notes": [ + " * this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with [hs.hotkey](hs.hotkey.html) directly will still be available." + ], + "notes_gfm": "
    \n
  • this will implicitly disable all hotkeys created by using this Spoon -- only those hotkeys which are defined with hs.hotkey directly will still be available.
  • \n
\n", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * the LeftRightHotkey spoon object" + ], + "returns_gfm": "
    \n
  • the LeftRightHotkey spoon object
  • \n
\n", + "signature": "LeftRightHotkey:stop() -> self", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "LeftRightHotkey", + "stripped_doc": "\nThis is accomplished by creating unactivated hotkeys for each definition and using an [hs.eventtap](hs.eventtap.html) watcher to detect when modifier keys are pressed and conditionally activating only those hotkeys which correspond to the left or right modifiers currently active as specified by the `bind` and `new` methods of this spoon.\n\nThe `LeftRightHotkeyObject` that is returned by [LeftRightHotkey:new](#new) and [LeftRightHotkey:bind](#bind) supports the following methods in a manner similar to the [hs.hotkey](hs.hotkey.html) equivalents:\n\n * `LeftRightHotkeyObject:enable()` -- enables the registered hotkey.\n * `LeftRightHotkeyObject:disable()` -- disables the registered hotkey.\n * `LeftRightHotkeyObject:delete()` -- deletes the registered hotkey.\n * `LeftRightHotkeyObject:isEnabled() -- returns a boolean value specifying whether the hotkey is currently enabled (true) or disabled (false)\n\nThe following modifiers are recognized by this spoon in the modifier table when setting up hotkeys with this spoon:\n * \"lCmd\", \"lCommand\", or \"l⌘\" for the left Command modifier\n * \"rCmd\", \"rCommand\", or \"r⌘\" for the right Command modifier\n * \"lCtrl\", \"lControl\" or \"l⌃\" for the left Control modifier\n * \"rCtrl\", \"rControl\" or \"r⌃\" for the right Control modifier\n * \"lAlt\", \"lOpt\", \"lOption\" or \"l⌥\" for the left Option modifier\n * \"rAlt\", \"rOpt\", \"rOption\" or \"r⌥\" for the right Option modifier\n * \"lShift\" or \"l⇧\" for the left Shift modifier\n * \"rShift\" or \"r⇧\" for the right Shift modifier\n\nThe modifiers table for any given hotkey is all inclusive; this means that if you specify `{ \"rShift\", \"lShift\" }` then *both* the left and right shift keys *must* be pressed to trigger the hotkey -- if you want either/or, then stick with [hs.hotkey](hs.hotkey.html).\n\nAlternatively, if you want to setup a hotkey when *either* command key is pressed with *only* the right shift, you would need to set up two hotkeys with this spoon:\n e.g. `LeftRightHotkey:bind({ \"rCmd\", \"rShift\" }, \"a\", myFunction)` *and* `LeftRightHotkey:bind({ \"lCmd\", \"rShift\" }, \"a\", myFunction)`\n\nThis spoon works by using an eventtap to detect flag changes (modifier keys) and when they change, the appropriate hotkeys are enabled or disabled. This means that you should be aware of the following:\n * like all eventtaps, if the Hammerspoon application is particularly busy with some other task, it is possible for the flag change to be missed or for the macOS to disable the eventtap entirely.\n * behind the scenes, when a given set of flag changes occur that match a defined hotkey, the hotkey is actually enabled through `hs.hotkey:enable()` -- this means that in truth, either side's modifiers would trigger the callback. Under normal circumstances this won't be noticed because as soon as you switch to the alternate side's modifier, the flag change event will be detected and the hotkey will be disabled. However, as noted above, if Hammerspoon is particularly busy, it is possible for this event to be missed.\n * a timer runs (once this Spoon has been started the first time) which will check to see if the eventtap has been internally disabled and re-enable it if necessary; alternatively you can re-issue [LeftRightHotkey:start()](#start) to force the eventtap to be reset if necessary.\n * if your hotkeys seem out of sync, try pressing and releasing any modifier key -- this will reset the enabled/disabled hotkeys if a previous flag change was missed, but the eventtap is still running or has been reset by one of the methods described above.\n\nLike all Spoons, don't forget to use the [LeftRightHotkey:start()](#start) method to activate the modifier key watcher.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/LeftRightHotkey.spoon.zip)", + "submodules": [], + "type": "Module" + }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "LookupSelection:bindHotkeys(mapping)", + "def_gfm": "LookupSelection:bindHotkeys(mapping)", + "desc": "Binds hotkeys for LookupSelection", + "desc_gfm": "

Binds hotkeys for LookupSelection

\n", + "doc": "Binds hotkeys for LookupSelection\n\nParameters:\n * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help\n\nNotes:\n * Sample value for `mapping`:\n```\n {\n lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },\n neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },\n hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },\n }\n```", + "doc_gfm": "

Binds hotkeys for LookupSelection

\n

Parameters:

\n
    \n
  • mapping - A table containing hotkey modifier/key details for the following items:
  • \n
  • lexicon - open in lexicon app
  • \n
  • neue_notiz - create new note in notes app
  • \n
  • hsdocs - display online help
  • \n
\n

Notes:

\n
    \n
  • Sample value for mapping:
  • \n
\n\n
 {\n    lexicon = { { "ctrl", "alt", "cmd" }, "L" },\n    neue_notiz = { { "ctrl", "alt", "cmd" }, "N" },\n    hsdocs = { { "ctrl", "alt", "cmd" }, "H" },\n }\n
\n", + "examples": [], + "file": "Source/LookupSelection.spoon/init.lua", + "lineno": "93", + "name": "bindHotkeys", + "notes": [ + " * Sample value for `mapping`:", + "```", + " {", + " lexicon = { { \"ctrl\", \"alt\", \"cmd\" }, \"L\" },", + " neue_notiz = { { \"ctrl\", \"alt\", \"cmd\" }, \"N\" },", + " hsdocs = { { \"ctrl\", \"alt\", \"cmd\" }, \"H\" },", + " }", + "```" + ], + "notes_gfm": "
    \n
  • Sample value for mapping:
  • \n
\n\n
 {\n    lexicon = { { "ctrl", "alt", "cmd" }, "L" },\n    neue_notiz = { { "ctrl", "alt", "cmd" }, "N" },\n    hsdocs = { { "ctrl", "alt", "cmd" }, "H" },\n }\n
\n", + "parameters": [ + " * mapping - A table containing hotkey modifier/key details for the following items:\n * `lexicon` - open in lexicon app\n * `neue_notiz` - create new note in notes app\n * `hsdocs` - display online help" + ], + "parameters_gfm": "
    \n
  • mapping - A table containing hotkey modifier/key details for the following items:
      \n
    • lexicon - open in lexicon app
    • \n
    • neue_notiz - create new note in notes app
    • \n
    • hsdocs - display online help
    • \n
    \n
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "LookupSelection:bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "LookupSelection:openLexicon()", + "def_gfm": "LookupSelection:openLexicon()", + "desc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages", + "desc_gfm": "

Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages

\n", + "doc": "Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages\n\nParameters:\n * None\n\nReturns:\n * The LookupSelection object", + "doc_gfm": "

Get the current selected text in the frontmost window and display a translation popup with the translation between the specified languages

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The LookupSelection object
  • \n
\n", + "examples": [], + "file": "Source/LookupSelection.spoon/init.lua", + "lineno": "58", + "name": "openLexicon", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * The LookupSelection object" + ], + "returns_gfm": "
    \n
  • The LookupSelection object
  • \n
\n", + "signature": "LookupSelection:openLexicon()", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ { "def": "LookupSelection.logger", "def_gfm": "LookupSelection.logger", @@ -10446,6 +11133,25 @@ "submodules": [], "type": "Module" }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [], + "Variable": [], + "desc": "Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.", + "desc_gfm": "

Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.

\n", + "doc": "Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.\nEspecially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.\n\nNote: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position\nwhere the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.\n\n== Usage ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):start()\n```\n\nYou can temporarily stop the spoon by calling `MiddleClickDragScroll:stop()` and then restart it by calling `MiddleClickDragScroll:start()` again.\n\n== Configuration ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):configure{\n excludedApps = {\"Some App\", \"Other app\"}, -- Don't activate scrolling in apps with these names\n excludedWindows = {\"^Some Window Title$\"}, -- Don't activate scrolling in windows with these names (supports regex, for exact match, use \"^title$\")\n excludedUrls = {\"^https://geogebra.calculator$\"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)\n indicatorSize = 25, -- Size of the scrolling indicator in pixels\n indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.\n {\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n },\n startDistance = 15, -- Minimal distance to drag the mouse before scrolling is triggered.\n scrollMode = \"pixel\", -- Whether the scroll speed is in \"line\"s or \"pixel\"s. Scrolling by lines has smooting in some applications\n -- and therefore works with reduced frequency but it offers much less precise control.\n scrollFrequency = 0.01, -- How often to trigger scrolling (in seconds)\n scrollAccelaration = 30, -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.\n scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location.\n -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument\n -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).\n function(self, x)\n return (x ^ 2) / (self.scrollAccelaration ^ 2)\n end\n}:start()\n```\n\nUnspecified keys are unchanged. You can call `configure` multiple times to dynamically change it but changing `indicatorAttributes` and `indicatorSize` only works when `MiddleClickDragScroll` is stopped.\n\nInstead of `indicatorSize` and `indicatorAttributes`, you can also pass a custom canvas to `configure` or set it directly to have more control over the indicator style:\n\n```lua\n MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n }\n```\n\nFor more details, see: https://www.hammerspoon.org/docs/hs.canvas.html\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip)", + "doc_gfm": "

Allows scrolling by holding down the middle mouse button and dragging it, the same as it works on Windows.\nEspecially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.

\n

Note: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position\nwhere the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.

\n

== Usage ==

\n
local MiddleClickDragScroll = hs.loadSpoon("MiddleClickDragScroll"):start()\n
\n

You can temporarily stop the spoon by calling MiddleClickDragScroll:stop() and then restart it by calling MiddleClickDragScroll:start() again.

\n

== Configuration ==

\n
local MiddleClickDragScroll = hs.loadSpoon("MiddleClickDragScroll"):configure{\n  excludedApps = {"Some App", "Other app"},         -- Don't activate scrolling in apps with these names\n  excludedWindows = {"^Some Window Title$"},        -- Don't activate scrolling in windows with these names (supports regex, for exact match, use "^title$")\n  excludedUrls = {"^https://geogebra.calculator$"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)\n  indicatorSize = 25,   -- Size of the scrolling indicator in pixels\n  indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.\n  {\n    type = "circle",\n    fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n    strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n  },\n  startDistance = 15,       -- Minimal distance to drag the mouse before scrolling is triggered.\n  scrollMode = "pixel",     -- Whether the scroll speed is in "line"s or "pixel"s. Scrolling by lines has smooting in some applications\n                            -- and therefore works with reduced frequency but it offers much less precise control.\n  scrollFrequency = 0.01,   -- How often to trigger scrolling (in seconds)\n  scrollAccelaration = 30,  -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.\n  scrollSpeedFn =           -- How scrolling accelerates based on the mouse distance from the initial location.\n                            -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument\n                            -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).\n  function(self, x)\n    return (x ^ 2) / (self.scrollAccelaration ^ 2)\n  end\n}:start()\n
\n

Unspecified keys are unchanged. You can call configure multiple times to dynamically change it but changing indicatorAttributes and indicatorSize only works when MiddleClickDragScroll is stopped.

\n

Instead of indicatorSize and indicatorAttributes, you can also pass a custom canvas to configure or set it directly to have more control over the indicator style:

\n
MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{\n    type = "circle",\n    fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n    strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n  }\n
\n

For more details, see: https://www.hammerspoon.org/docs/hs.canvas.html

\n

Download: https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip

\n", + "items": [], + "name": "MiddleClickDragScroll", + "stripped_doc": "Especially useful to quickly scroll to the top or bottom of a page, if you don't have a Magic Mouse.\n\nNote: Due to OS limitations, it always scrolls the window currently below the mouse, not the window below the position\nwhere the dragging started, like it works on Windows. You therefore need to take some care to stay inside the window.\n\n== Usage ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):start()\n```\n\nYou can temporarily stop the spoon by calling `MiddleClickDragScroll:stop()` and then restart it by calling `MiddleClickDragScroll:start()` again.\n\n== Configuration ==\n\n```lua\nlocal MiddleClickDragScroll = hs.loadSpoon(\"MiddleClickDragScroll\"):configure{\n excludedApps = {\"Some App\", \"Other app\"}, -- Don't activate scrolling in apps with these names\n excludedWindows = {\"^Some Window Title$\"}, -- Don't activate scrolling in windows with these names (supports regex, for exact match, use \"^title$\")\n excludedUrls = {\"^https://geogebra.calculator$\"}, -- Don't activate scrolling when the active window is on these URLs (supports regex, only works in Chrome and Safari, asks for extra permissions on first trigger)\n indicatorSize = 25, -- Size of the scrolling indicator in pixels\n indicatorAttributes = -- Attributes of the scrolling indicator. Takes any specified on https://www.hammerspoon.org/docs/hs.canvas.html#attributes. Alternatively, you can pass a custom canvas, see the explenation below.\n {\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n },\n startDistance = 15, -- Minimal distance to drag the mouse before scrolling is triggered.\n scrollMode = \"pixel\", -- Whether the scroll speed is in \"line\"s or \"pixel\"s. Scrolling by lines has smooting in some applications\n -- and therefore works with reduced frequency but it offers much less precise control.\n scrollFrequency = 0.01, -- How often to trigger scrolling (in seconds)\n scrollAccelaration = 30, -- How fast scrolling accelerates based on the mouse distance from the initial location. Larger is faster.\n scrollSpeedFn = -- How scrolling accelerates based on the mouse distance from the initial location.\n -- The default is dist^2 / scrollAcceleration^2. You can pass a custom function that recieves `self` as the first argument\n -- and the absolute distance as the second and returns the resulting speed (in pixels or lines, depending on the scrollMode setting).\n function(self, x)\n return (x ^ 2) / (self.scrollAccelaration ^ 2)\n end\n}:start()\n```\n\nUnspecified keys are unchanged. You can call `configure` multiple times to dynamically change it but changing `indicatorAttributes` and `indicatorSize` only works when `MiddleClickDragScroll` is stopped.\n\nInstead of `indicatorSize` and `indicatorAttributes`, you can also pass a custom canvas to `configure` or set it directly to have more control over the indicator style:\n\n```lua\n MiddleClickDragScroll.canvas = hs.canvas.new{ w = 25, h = 25}:insertElement{\n type = \"circle\",\n fillColor = { red = 0, green = 0, blue = 0, alpha = 0.3 },\n strokeColor = { red = 1, green = 1, blue = 1, alpha = 0.5 },\n }\n```\n\nFor more details, see: https://www.hammerspoon.org/docs/hs.canvas.html\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/MiddleClickDragScroll.spoon.zip)", + "submodules": [], + "type": "Module" + }, { "Command": [], "Constant": [], @@ -10659,7 +11365,7 @@ "doc_gfm": "

Activate all modal environment in idList.

\n

Parameters:

\n
    \n
  • idList - An table specifying IDs of modal environments
  • \n
  • trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to nil.
  • \n
  • showKeys - A optional boolean value to show all available keybindings, defaults to nil.
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "129", + "lineno": "174", "name": "activate", "notes": [], "notes_gfm": "", @@ -10684,7 +11390,7 @@ "doc_gfm": "

Deactivate modal environments in idList.

\n

Parameters:

\n
    \n
  • idList - An table specifying IDs of modal environments
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "160", + "lineno": "205", "name": "deactivate", "notes": [], "notes_gfm": "", @@ -10707,7 +11413,7 @@ "doc_gfm": "

Deactivate all active modal environments.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "179", + "lineno": "224", "name": "deactivateAll", "notes": [], "notes_gfm": "", @@ -10730,7 +11436,7 @@ "doc_gfm": "

Create a new modal keybindings environment

\n

Parameters:

\n
    \n
  • id - A string specifying ID of new modal keybindings
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "46", + "lineno": "57", "name": "new", "notes": [], "notes_gfm": "", @@ -10753,7 +11459,7 @@ "doc_gfm": "

Toggle the cheatsheet display of current modal environments's keybindings.

\n

Parameters:

\n
    \n
  • iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.
  • \n
  • force - A optional boolean value to force show cheatsheet, defaults to nil (automatically).
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "57", + "lineno": "126", "name": "toggleCheatsheet", "notes": [], "notes_gfm": "", @@ -10784,7 +11490,7 @@ "doc_gfm": "

Activate all modal environment in idList.

\n

Parameters:

\n
    \n
  • idList - An table specifying IDs of modal environments
  • \n
  • trayColor - An optional string (e.g. #000000) specifying the color of modalTray, defaults to nil.
  • \n
  • showKeys - A optional boolean value to show all available keybindings, defaults to nil.
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "129", + "lineno": "174", "name": "activate", "notes": [], "notes_gfm": "", @@ -10809,7 +11515,7 @@ "doc_gfm": "

Deactivate modal environments in idList.

\n

Parameters:

\n
    \n
  • idList - An table specifying IDs of modal environments
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "160", + "lineno": "205", "name": "deactivate", "notes": [], "notes_gfm": "", @@ -10832,7 +11538,7 @@ "doc_gfm": "

Deactivate all active modal environments.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "179", + "lineno": "224", "name": "deactivateAll", "notes": [], "notes_gfm": "", @@ -10855,7 +11561,7 @@ "doc_gfm": "

Create a new modal keybindings environment

\n

Parameters:

\n
    \n
  • id - A string specifying ID of new modal keybindings
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "46", + "lineno": "57", "name": "new", "notes": [], "notes_gfm": "", @@ -10878,7 +11584,7 @@ "doc_gfm": "

Toggle the cheatsheet display of current modal environments's keybindings.

\n

Parameters:

\n
    \n
  • iterList - An table specifying IDs of modal environments or active_list. Optional, defaults to all active environments.
  • \n
  • force - A optional boolean value to force show cheatsheet, defaults to nil (automatically).
  • \n
\n", "examples": [], "file": "Source/ModalMgr.spoon/init.lua", - "lineno": "57", + "lineno": "126", "name": "toggleCheatsheet", "notes": [], "notes_gfm": "", @@ -11612,20 +12318,20 @@ { "def": "MouseFollowsFocus:configure(configuration)", "def_gfm": "MouseFollowsFocus:configure(configuration)", - "desc": "Configures the spoon. There is currently nothing to configure.", - "desc_gfm": "

Configures the spoon. There is currently nothing to configure.

\n", - "doc": "Configures the spoon. There is currently nothing to configure.\n\nParameters:\n * configuration - :", - "doc_gfm": "

Configures the spoon. There is currently nothing to configure.

\n

Parameters:

\n
    \n
  • configuration - :
  • \n
\n", + "desc": "Configures the spoon.", + "desc_gfm": "

Configures the spoon.

\n", + "doc": "Configures the spoon.\n\nParameters:\n * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:", + "doc_gfm": "

Configures the spoon.

\n

Parameters:

\n
    \n
  • configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "26", + "lineno": "29", "name": "configure", "notes": [], "notes_gfm": "", "parameters": [ - " * configuration - :" + " * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:" ], - "parameters_gfm": "
    \n
  • configuration - :
  • \n
\n", + "parameters_gfm": "
    \n
  • configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:
  • \n
\n", "returns": [], "returns_gfm": "", "signature": "MouseFollowsFocus:configure(configuration)", @@ -11641,7 +12347,7 @@ "doc_gfm": "

Starts updating the mouse position when window focus changes

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "35", + "lineno": "44", "name": "start", "notes": [], "notes_gfm": "", @@ -11664,7 +12370,7 @@ "doc_gfm": "

Stops updating the mouse position when window focus changes

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "61", + "lineno": "73", "name": "stop", "notes": [], "notes_gfm": "", @@ -11687,7 +12393,7 @@ "doc_gfm": "

Moves the mouse to the center of the given window unless it's already inside the window

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "72", + "lineno": "84", "name": "updateMouse", "notes": [], "notes_gfm": "", @@ -11711,7 +12417,7 @@ "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "doc_gfm": "

Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.

\n", "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "21", + "lineno": "24", "name": "logger", "signature": "MouseFollowsFocus.logger", "stripped_doc": "", @@ -11726,20 +12432,20 @@ { "def": "MouseFollowsFocus:configure(configuration)", "def_gfm": "MouseFollowsFocus:configure(configuration)", - "desc": "Configures the spoon. There is currently nothing to configure.", - "desc_gfm": "

Configures the spoon. There is currently nothing to configure.

\n", - "doc": "Configures the spoon. There is currently nothing to configure.\n\nParameters:\n * configuration - :", - "doc_gfm": "

Configures the spoon. There is currently nothing to configure.

\n

Parameters:

\n
    \n
  • configuration - :
  • \n
\n", + "desc": "Configures the spoon.", + "desc_gfm": "

Configures the spoon.

\n", + "doc": "Configures the spoon.\n\nParameters:\n * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:", + "doc_gfm": "

Configures the spoon.

\n

Parameters:

\n
    \n
  • configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "26", + "lineno": "29", "name": "configure", "notes": [], "notes_gfm": "", "parameters": [ - " * configuration - :" + " * configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:" ], - "parameters_gfm": "
    \n
  • configuration - :
  • \n
\n", + "parameters_gfm": "
    \n
  • configuration - a table containing the settings for onWindowMoved or onChangeOfScreenOnly:
  • \n
\n", "returns": [], "returns_gfm": "", "signature": "MouseFollowsFocus:configure(configuration)", @@ -11754,7 +12460,7 @@ "doc": "Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.", "doc_gfm": "

Logger object used within the Spoon. Can be accessed to set the default log level for the messages coming from the Spoon.

\n", "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "21", + "lineno": "24", "name": "logger", "signature": "MouseFollowsFocus.logger", "stripped_doc": "", @@ -11769,7 +12475,7 @@ "doc_gfm": "

Starts updating the mouse position when window focus changes

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "35", + "lineno": "44", "name": "start", "notes": [], "notes_gfm": "", @@ -11792,7 +12498,7 @@ "doc_gfm": "

Stops updating the mouse position when window focus changes

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "61", + "lineno": "73", "name": "stop", "notes": [], "notes_gfm": "", @@ -11815,7 +12521,7 @@ "doc_gfm": "

Moves the mouse to the center of the given window unless it's already inside the window

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], "file": "Source/MouseFollowsFocus.spoon/init.lua", - "lineno": "72", + "lineno": "84", "name": "updateMouse", "notes": [], "notes_gfm": "", @@ -12427,184 +13133,1095 @@ " * `requestId` - The ID of the request batch that this is a reply to", " * `results` - A table containing the results of each request in the batch. Each entry in the table will be a table with the same format as `SpoonRequestResponse`" ], - "notes_gfm": "
    \n
  • This method does not connect to OBS, it just sets up the connection parameters for later use
  • \n
  • By default, no events are subscribed to, so you will need to set eventSubscriptions to something useful if you want to receive events
  • \n
  • If you do not wish to supply an eventCallback, pass nil instead
  • \n
  • The events that OBS can produce are documented in the obs-websocket documentation
  • \n
  • There are some additional values for eventType, specific to this Spoon:
      \n
    • SpoonOBSConnected - This event is sent when the websocket connection to OBS is established. All other fields will be nil.
    • \n
    • SpoonOBSDisconnected - This event is sent when the websocket connection to OBS is lost. All other fields will be nil. Return false to inhibit automatic reconnection.
    • \n
    • SpoonRequestResponse - This event is sent to pass replies to requests made via OBS:request(). Its eventIntent will be nil and the format of its eventData table will be:
        \n
      • requestId - The ID of the request that this is a reply to
      • \n
      • requestType - The request type that was made
      • \n
      • requestStatus - A table containing:
          \n
        • result - A bool, true if the request succeeded, otherwise false
        • \n
        • code - A number containing the response code
        • \n
        • comment - An optional string that may contain additional information about the response
        • \n
        \n
      • \n
      • responseData - An table that contains the response data, if any
      • \n
      \n
    • \n
    • SpoonBatchRequestResponse - This event is sent to pass replies to batch requests made via OBS:requestBatch(). Its eventIntent will be nil and the format of its eventData table will be:
        \n
      • requestId - The ID of the request batch that this is a reply to
      • \n
      • results - A table containing the results of each request in the batch. Each entry in the table will be a table with the same format as SpoonRequestResponse
      • \n
      \n
    • \n
    \n
  • \n
\n", + "notes_gfm": "
    \n
  • This method does not connect to OBS, it just sets up the connection parameters for later use
  • \n
  • By default, no events are subscribed to, so you will need to set eventSubscriptions to something useful if you want to receive events
  • \n
  • If you do not wish to supply an eventCallback, pass nil instead
  • \n
  • The events that OBS can produce are documented in the obs-websocket documentation
  • \n
  • There are some additional values for eventType, specific to this Spoon:
      \n
    • SpoonOBSConnected - This event is sent when the websocket connection to OBS is established. All other fields will be nil.
    • \n
    • SpoonOBSDisconnected - This event is sent when the websocket connection to OBS is lost. All other fields will be nil. Return false to inhibit automatic reconnection.
    • \n
    • SpoonRequestResponse - This event is sent to pass replies to requests made via OBS:request(). Its eventIntent will be nil and the format of its eventData table will be:
        \n
      • requestId - The ID of the request that this is a reply to
      • \n
      • requestType - The request type that was made
      • \n
      • requestStatus - A table containing:
          \n
        • result - A bool, true if the request succeeded, otherwise false
        • \n
        • code - A number containing the response code
        • \n
        • comment - An optional string that may contain additional information about the response
        • \n
        \n
      • \n
      • responseData - An table that contains the response data, if any
      • \n
      \n
    • \n
    • SpoonBatchRequestResponse - This event is sent to pass replies to batch requests made via OBS:requestBatch(). Its eventIntent will be nil and the format of its eventData table will be:
        \n
      • requestId - The ID of the request batch that this is a reply to
      • \n
      • results - A table containing the results of each request in the batch. Each entry in the table will be a table with the same format as SpoonRequestResponse
      • \n
      \n
    • \n
    \n
  • \n
\n", + "parameters": [ + " * `eventCallback` - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:\n * `eventType` - The type of event, e.g. `StudioModeStateChanged`\n * `eventIntent` - The event subscription value that caused this event to be sent, e.g. `OBS.eventSubscriptionValues.General`\n * `eventData` - A table containing the event data, e.g. `{ \"studioModeEnabled\": true }`", + " * `host` - The hostname or IP address of the machine running OBS", + " * `port` - The port number that obs-websocket is listening on", + " * `password` - An optional password string that obs-websocket is configured to use", + " * `eventSubscriptions` - An optional number containing the bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + ], + "parameters_gfm": "
    \n
  • eventCallback - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:
      \n
    • eventType - The type of event, e.g. StudioModeStateChanged
    • \n
    • eventIntent - The event subscription value that caused this event to be sent, e.g. OBS.eventSubscriptionValues.General
    • \n
    • eventData - A table containing the event data, e.g. { "studioModeEnabled": true }
    • \n
    \n
  • \n
  • host - The hostname or IP address of the machine running OBS
  • \n
  • port - The port number that obs-websocket is listening on
  • \n
  • password - An optional password string that obs-websocket is configured to use
  • \n
  • eventSubscriptions - An optional number containing the bitmask of the events to subscribe to, see OBS.eventSubscriptionValues
  • \n
\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "OBS:init(eventCallback, host, port[, password, eventSubscriptions])", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:reconnectDelay", + "def_gfm": "OBS:reconnectDelay", + "desc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", + "desc_gfm": "

Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to 5

\n", + "doc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", + "doc_gfm": "

Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to 5

\n", + "file": "Source/OBS.spoon/init.lua", + "lineno": "112", + "name": "reconnectDelay", + "signature": "OBS:reconnectDelay", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "OBS:removeEventSubsciption(event)", + "def_gfm": "OBS:removeEventSubsciption(event)", + "desc": "Removes an event subscription", + "desc_gfm": "

Removes an event subscription

\n", + "doc": "Removes an event subscription\n\nParameters:\n * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`", + "doc_gfm": "

Removes an event subscription

\n

Parameters:

\n\n

Returns:

\n
    \n
  • None
  • \n
\n

Notes:

\n
    \n
  • If you wish to remove multiple event subscriptions you can use the & operator to combine them, e.g. spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)
  • \n
\n", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "326", + "name": "removeEventSubsciption", + "notes": [ + " * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`" + ], + "notes_gfm": "
    \n
  • If you wish to remove multiple event subscriptions you can use the & operator to combine them, e.g. spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)
  • \n
\n", + "parameters": [ + " * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + ], + "parameters_gfm": "\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "OBS:removeEventSubsciption(event)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:request(requestType[, requestData[, requestId]])", + "def_gfm": "OBS:request(requestType[, requestData[, requestId]])", + "desc": "Sends a request to OBS", + "desc_gfm": "

Sends a request to OBS

\n", + "doc": "Sends a request to OBS\n\nParameters:\n * `requestType` - A string containing the type of request to send\n * `requestData` - An optional table containing the data to send with the request, or nil\n * `requestId` - An optional string containing the ID of the request\n\nReturns:\n * The `requestId` that was sent\n\nNotes:\n * If `requestId` is not specified then a random UUID will be generated.\n * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.\n * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)", + "doc_gfm": "

Sends a request to OBS

\n

Parameters:

\n
    \n
  • requestType - A string containing the type of request to send
  • \n
  • requestData - An optional table containing the data to send with the request, or nil
  • \n
  • requestId - An optional string containing the ID of the request
  • \n
\n

Returns:

\n
    \n
  • The requestId that was sent
  • \n
\n

Notes:

\n
    \n
  • If requestId is not specified then a random UUID will be generated.
  • \n
  • The requestId will be passed to your event callback (provided to OBS:init()) when the response is received.
  • \n
  • Values for requestType can be found in the obs-websocket documentation
  • \n
\n", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "343", + "name": "request", + "notes": [ + " * If `requestId` is not specified then a random UUID will be generated.", + " * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.", + " * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)" + ], + "notes_gfm": "
    \n
  • If requestId is not specified then a random UUID will be generated.
  • \n
  • The requestId will be passed to your event callback (provided to OBS:init()) when the response is received.
  • \n
  • Values for requestType can be found in the obs-websocket documentation
  • \n
\n", + "parameters": [ + " * `requestType` - A string containing the type of request to send", + " * `requestData` - An optional table containing the data to send with the request, or nil", + " * `requestId` - An optional string containing the ID of the request" + ], + "parameters_gfm": "
    \n
  • requestType - A string containing the type of request to send
  • \n
  • requestData - An optional table containing the data to send with the request, or nil
  • \n
  • requestId - An optional string containing the ID of the request
  • \n
\n", + "returns": [ + " * The `requestId` that was sent" + ], + "returns_gfm": "
    \n
  • The requestId that was sent
  • \n
\n", + "signature": "OBS:request(requestType[, requestData[, requestId]])", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:requestBatch(requests[, haltOnFailure])", + "def_gfm": "OBS:requestBatch(requests[, haltOnFailure])", + "desc": "Sends a batch of requests to OBS", + "desc_gfm": "

Sends a batch of requests to OBS

\n", + "doc": "Sends a batch of requests to OBS\n\nParameters:\n * `requests` - A table containing the requests to send\n * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false\n\nReturns:\n * The `requestId` that was sent for the batch\n\nNotes:\n * Each request should be a table with the keys:\n * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)\n * `requestData` - An optional table containing the data to send with the request, or `nil`\n * `requestId` - An optional string containing a unique ID for the request\n * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID\n\nExample:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", + "doc_gfm": "

Sends a batch of requests to OBS

\n

Parameters:

\n
    \n
  • requests - A table containing the requests to send
  • \n
  • haltOnFailure - An optional boolean indicating whether to halt the batch if a request fails, defaults to false
  • \n
\n

Returns:

\n
    \n
  • The requestId that was sent for the batch
  • \n
\n

Notes:

\n
    \n
  • Each request should be a table with the keys:
      \n
    • requestType - A string containing the type of request to send, see OBS:request()
    • \n
    • requestData - An optional table containing the data to send with the request, or nil
    • \n
    • requestId - An optional string containing a unique ID for the request
    • \n
    \n
  • \n
  • Unlike OBS:request() the requestId is an auto-generated UUID
  • \n
\n

Example:

\n
spoon.OBS:requestBatch({\n {["requestType"] = "StartVirtualCam"},\n {["requestType"] = "SetCurrentProgramScene", ["requestData"] = { ["sceneName"] = "FancyScene" }}\n})\n
\n", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "377", + "name": "requestBatch", + "notes": [ + " * Each request should be a table with the keys:", + " * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)", + " * `requestData` - An optional table containing the data to send with the request, or `nil`", + " * `requestId` - An optional string containing a unique ID for the request", + " * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID", + "", + "Example:", + "```lua", + "spoon.OBS:requestBatch({", + " {[\"requestType\"] = \"StartVirtualCam\"},", + " {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}", + "})", + "```" + ], + "notes_gfm": "
    \n
  • Each request should be a table with the keys:
      \n
    • requestType - A string containing the type of request to send, see OBS:request()
    • \n
    • requestData - An optional table containing the data to send with the request, or nil
    • \n
    • requestId - An optional string containing a unique ID for the request
    • \n
    \n
  • \n
  • Unlike OBS:request() the requestId is an auto-generated UUID
  • \n
\n

Example:

\n
spoon.OBS:requestBatch({\n {["requestType"] = "StartVirtualCam"},\n {["requestType"] = "SetCurrentProgramScene", ["requestData"] = { ["sceneName"] = "FancyScene" }}\n})\n
\n", + "parameters": [ + " * `requests` - A table containing the requests to send", + " * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false" + ], + "parameters_gfm": "
    \n
  • requests - A table containing the requests to send
  • \n
  • haltOnFailure - An optional boolean indicating whether to halt the batch if a request fails, defaults to false
  • \n
\n", + "returns": [ + " * The `requestId` that was sent for the batch" + ], + "returns_gfm": "
    \n
  • The requestId that was sent for the batch
  • \n
\n", + "signature": "OBS:requestBatch(requests[, haltOnFailure])", + "stripped_doc": "Example:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", + "type": "Method" + }, + { + "def": "OBS:setLogLevel(level)", + "def_gfm": "OBS:setLogLevel(level)", + "desc": "Sets the logging level for the OBS Spoon", + "desc_gfm": "

Sets the logging level for the OBS Spoon

\n", + "doc": "Sets the logging level for the OBS Spoon\n\nParameters:\n * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values\n\nReturns:\n * None", + "doc_gfm": "

Sets the logging level for the OBS Spoon

\n

Parameters:

\n\n

Returns:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "419", + "name": "setLogLevel", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values" + ], + "parameters_gfm": "\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "OBS:setLogLevel(level)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:shouldReconnect", + "def_gfm": "OBS:shouldReconnect", + "desc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", + "desc_gfm": "

Controls whether the websocket connection should be re-established if it is lost. Defaults to true

\n", + "doc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", + "doc_gfm": "

Controls whether the websocket connection should be re-established if it is lost. Defaults to true

\n", + "file": "Source/OBS.spoon/init.lua", + "lineno": "105", + "name": "shouldReconnect", + "signature": "OBS:shouldReconnect", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "OBS:start()", + "def_gfm": "OBS:start()", + "desc": "Connects to OBS", + "desc_gfm": "

Connects to OBS

\n", + "doc": "Connects to OBS\n\nParameters:\n * None\n\nReturns:\n * None", + "doc_gfm": "

Connects to OBS

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "161", + "name": "start", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "OBS:start()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:stop()", + "def_gfm": "OBS:stop()", + "desc": "Disconnects from OBS", + "desc_gfm": "

Disconnects from OBS

\n", + "doc": "Disconnects from OBS\n\nParameters:\n * None\n\nReturns:\n * None", + "doc_gfm": "

Disconnects from OBS

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "274", + "name": "stop", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "OBS:stop()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "OBS:updateEventSubscriptions(eventSubscriptions)", + "def_gfm": "OBS:updateEventSubscriptions(eventSubscriptions)", + "desc": "Updates the event subscriptions", + "desc_gfm": "

Updates the event subscriptions

\n", + "doc": "Updates the event subscriptions\n\nParameters:\n * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None", + "doc_gfm": "

Updates the event subscriptions

\n

Parameters:

\n\n

Returns:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/OBS.spoon/init.lua", + "lineno": "289", + "name": "updateEventSubscriptions", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + ], + "parameters_gfm": "\n", + "returns": [ + " * None" + ], + "returns_gfm": "
    \n
  • None
  • \n
\n", + "signature": "OBS:updateEventSubscriptions(eventSubscriptions)", + "stripped_doc": "", + "type": "Method" + } + ], + "name": "OBS", + "stripped_doc": "\nInstall and configure the obs-websocket plugin first from [their project](https://github.com/obsproject/obs-websocket/releases)\n\nNote: This Spoon will only work with Hammerspoon 0.9.100 or later.\n\nNote: This Spoon will only work with obs-websocket 5.0.1 or later, which also requires OBS Studio v27 or later.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip)\n\nExample:\n```\n-- This example will start OBS, connect to it, and then start streaming once connected\nobs = hs.loadSpoon(\"OBS\")\nobsCallback = function(eventType, eventIntent, eventData)\n print(eventType)\n print(eventIntent)\n print(hs.inspect(eventData))\n\n if eventType == \"SpoonOBSConnected\" then\n obs:request(\"StartStream\")\n end\nend\nobs:init(obsCallback, \"localhost\", 4444, \"password\")\nobs:start()\n```", + "submodules": [], + "type": "Module" + }, + { + "Command": [], + "Constant": [], + "Constructor": [], + "Deprecated": [], + "Field": [], + "Function": [], + "Method": [ + { + "def": "PaperWM:addWindow(add_window)", + "def_gfm": "PaperWM:addWindow(add_window)", + "desc": "Adds a window to layout and tiles.", + "desc_gfm": "

Adds a window to layout and tiles.

\n", + "doc": "Adds a window to layout and tiles.\n\nParameters:\n * add_window - An hs.window\n\nReturns:\n * The hs.spaces space for added window or nil if window not added.", + "doc_gfm": "

Adds a window to layout and tiles.

\n

Parameters:

\n
    \n
  • add_window - An hs.window
  • \n
\n

Returns:

\n
    \n
  • The hs.spaces space for added window or nil if window not added.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "594", + "name": "addWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * add_window - An hs.window" + ], + "parameters_gfm": "
    \n
  • add_window - An hs.window
  • \n
\n", + "returns": [ + " * The hs.spaces space for added window or nil if window not added." + ], + "returns_gfm": "
    \n
  • The hs.spaces space for added window or nil if window not added.
  • \n
\n", + "signature": "PaperWM:addWindow(add_window)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:barfWindow()", + "def_gfm": "PaperWM:barfWindow()", + "desc": "Removes current window from column and places it to the right", + "desc_gfm": "

Removes current window from column and places it to the right

\n", + "doc": "Removes current window from column and places it to the right\n\nParameters:\n * None", + "doc_gfm": "

Removes current window from column and places it to the right

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1026", + "name": "barfWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:barfWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.bindHotkeys(mapping)", + "def_gfm": "PaperWM.bindHotkeys(mapping)", + "desc": "Binds hotkeys for PaperWM", + "desc_gfm": "

Binds hotkeys for PaperWM

\n", + "doc": "Binds hotkeys for PaperWM\n\nParameters:\n * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9", + "doc_gfm": "

Binds hotkeys for PaperWM

\n

Parameters:

\n
    \n
  • mapping - A table containing hotkey modifer/key details for the following items:
  • \n
  • stop_events - Stop automatic tiling
  • \n
  • focus_left - Focus window to left of current window
  • \n
  • focus_right - Focus window to right of current window
  • \n
  • focus_up - Focus window to up of current window
  • \n
  • focus_down - Focus window to down of current window
  • \n
  • swap_left - Swap positions of window to the left and current window
  • \n
  • swap_right - Swap positions of window to the right and current window
  • \n
  • swap_up - Swap positions of window above and current window
  • \n
  • swap_down - Swap positions of window below and current window
  • \n
  • center_window - Move current window to center of screen
  • \n
  • full_width - Resize width of current window to width of screen
  • \n
  • cycle_width - Toggle through preset window widths
  • \n
  • cycle_height - Toggle through preset window heights
  • \n
  • slurp_in - Move current window into column to the left
  • \n
  • barf_out - Remove current window from column and place to the right
  • \n
  • switch_space_1 - Switch to Mission Control space 1
  • \n
  • switch_space_2 - Switch to Mission Control space 2
  • \n
  • switch_space_3 - Switch to Mission Control space 3
  • \n
  • switch_space_4 - Switch to Mission Control space 4
  • \n
  • switch_space_5 - Switch to Mission Control space 5
  • \n
  • switch_space_6 - Switch to Mission Control space 6
  • \n
  • switch_space_7 - Switch to Mission Control space 7
  • \n
  • switch_space_8 - Switch to Mission Control space 8
  • \n
  • switch_space_9 - Switch to Mission Control space 9
  • \n
  • move_window_1 - Move current window to Mission Control space 1
  • \n
  • move_window_2 - Move current window to Mission Control space 2
  • \n
  • move_window_3 - Move current window to Mission Control space 3
  • \n
  • move_window_4 - Move current window to Mission Control space 4
  • \n
  • move_window_5 - Move current window to Mission Control space 5
  • \n
  • move_window_6 - Move current window to Mission Control space 6
  • \n
  • move_window_7 - Move current window to Mission Control space 7
  • \n
  • move_window_8 - Move current window to Mission Control space 8
  • \n
  • move_window_9 - Move current window to Mission Control space 9
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "275", + "name": "bindHotkeys", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9" + ], + "parameters_gfm": "
    \n
  • mapping - A table containing hotkey modifer/key details for the following items:
      \n
    • stop_events - Stop automatic tiling
    • \n
    • focus_left - Focus window to left of current window
    • \n
    • focus_right - Focus window to right of current window
    • \n
    • focus_up - Focus window to up of current window
    • \n
    • focus_down - Focus window to down of current window
    • \n
    • swap_left - Swap positions of window to the left and current window
    • \n
    • swap_right - Swap positions of window to the right and current window
    • \n
    • swap_up - Swap positions of window above and current window
    • \n
    • swap_down - Swap positions of window below and current window
    • \n
    • center_window - Move current window to center of screen
    • \n
    • full_width - Resize width of current window to width of screen
    • \n
    • cycle_width - Toggle through preset window widths
    • \n
    • cycle_height - Toggle through preset window heights
    • \n
    • slurp_in - Move current window into column to the left
    • \n
    • barf_out - Remove current window from column and place to the right
    • \n
    • switch_space_1 - Switch to Mission Control space 1
    • \n
    • switch_space_2 - Switch to Mission Control space 2
    • \n
    • switch_space_3 - Switch to Mission Control space 3
    • \n
    • switch_space_4 - Switch to Mission Control space 4
    • \n
    • switch_space_5 - Switch to Mission Control space 5
    • \n
    • switch_space_6 - Switch to Mission Control space 6
    • \n
    • switch_space_7 - Switch to Mission Control space 7
    • \n
    • switch_space_8 - Switch to Mission Control space 8
    • \n
    • switch_space_9 - Switch to Mission Control space 9
    • \n
    • move_window_1 - Move current window to Mission Control space 1
    • \n
    • move_window_2 - Move current window to Mission Control space 2
    • \n
    • move_window_3 - Move current window to Mission Control space 3
    • \n
    • move_window_4 - Move current window to Mission Control space 4
    • \n
    • move_window_5 - Move current window to Mission Control space 5
    • \n
    • move_window_6 - Move current window to Mission Control space 6
    • \n
    • move_window_7 - Move current window to Mission Control space 7
    • \n
    • move_window_8 - Move current window to Mission Control space 8
    • \n
    • move_window_9 - Move current window to Mission Control space 9
    • \n
    \n
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM.bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:centerWindow()", + "def_gfm": "PaperWM:centerWindow()", + "desc": "Moves current window to center of screen, without resizing.", + "desc_gfm": "

Moves current window to center of screen, without resizing.

\n", + "doc": "Moves current window to center of screen, without resizing.\n\nParameters:\n * None", + "doc_gfm": "

Moves current window to center of screen, without resizing.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "860", + "name": "centerWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:centerWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:cycleWindowSize(direction)", + "def_gfm": "PaperWM:cycleWindowSize(direction)", + "desc": "Resizes current window by cycling through width or height ratios.", + "desc_gfm": "

Resizes current window by cycling through width or height ratios.

\n", + "doc": "Resizes current window by cycling through width or height ratios.\n\nParameters:\n * direction - One of Direction { WIDTH, HEIGHT }", + "doc_gfm": "

Resizes current window by cycling through width or height ratios.

\n

Parameters:

\n
    \n
  • direction - One of Direction { WIDTH, HEIGHT }
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "907", + "name": "cycleWindowSize", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * direction - One of Direction { WIDTH, HEIGHT }" + ], + "parameters_gfm": "
    \n
  • direction - One of Direction { WIDTH, HEIGHT }
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:cycleWindowSize(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:focusWindow(direction, focused_index)", + "def_gfm": "PaperWM:focusWindow(direction, focused_index)", + "desc": "Change focus to a nearby window", + "desc_gfm": "

Change focus to a nearby window

\n", + "doc": "Change focus to a nearby window\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }\n * focused_index - The coordinates of the current window in the tiling layout\n\nReturns:\n * A boolean. True if a new window was focused. False if no nearby window\n was found in that direction.", + "doc_gfm": "

Change focus to a nearby window

\n

Parameters:

\n
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
  • focused_index - The coordinates of the current window in the tiling layout
  • \n
\n

Returns:

\n
    \n
  • A boolean. True if a new window was focused. False if no nearby window\nwas found in that direction.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "699", + "name": "focusWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + " * focused_index - The coordinates of the current window in the tiling layout" + ], + "parameters_gfm": "
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
  • focused_index - The coordinates of the current window in the tiling layout
  • \n
\n", + "returns": [ + " * A boolean. True if a new window was focused. False if no nearby window", + " was found in that direction." + ], + "returns_gfm": "
    \n
  • A boolean. True if a new window was focused. False if no nearby window\nwas found in that direction.
  • \n
\n", + "signature": "PaperWM:focusWindow(direction, focused_index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM::moveWindow(window, frame)", + "def_gfm": "PaperWM::moveWindow(window, frame)", + "desc": "Resizes a window without triggering a windowMoved event", + "desc_gfm": "

Resizes a window without triggering a windowMoved event

\n", + "doc": "Resizes a window without triggering a windowMoved event\n\nParameters:\n * window - An hs.window\n * frame - An hs.geometry.rect for the windows new frame size.", + "doc_gfm": "

Resizes a window without triggering a windowMoved event

\n

Parameters:

\n
    \n
  • window - An hs.window
  • \n
  • frame - An hs.geometry.rect for the windows new frame size.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1147", + "name": "moveWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * window - An hs.window", + " * frame - An hs.geometry.rect for the windows new frame size." + ], + "parameters_gfm": "
    \n
  • window - An hs.window
  • \n
  • frame - An hs.geometry.rect for the windows new frame size.
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM::moveWindow(window, frame)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:moveWindowToSpace(index)", + "def_gfm": "PaperWM:moveWindowToSpace(index)", + "desc": "Moves the current window to a new Mission Control space", + "desc_gfm": "

Moves the current window to a new Mission Control space

\n", + "doc": "Moves the current window to a new Mission Control space\n\nParameters:\n * index - The space number", + "doc_gfm": "

Moves the current window to a new Mission Control space

\n

Parameters:

\n
    \n
  • index - The space number
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1096", + "name": "moveWindowToSpace", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * index - The space number" + ], + "parameters_gfm": "
    \n
  • index - The space number
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:moveWindowToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:refreshWindows()", + "def_gfm": "PaperWM:refreshWindows()", + "desc": "Searches for all windows that match window filter.", + "desc_gfm": "

Searches for all windows that match window filter.

\n", + "doc": "Searches for all windows that match window filter.\n\nParameters:\n * None\n\nReturns:\n * A boolean, true if the layout needs to be re-tiled, false if no change.", + "doc_gfm": "

Searches for all windows that match window filter.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • A boolean, true if the layout needs to be re-tiled, false if no change.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "563", + "name": "refreshWindows", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * A boolean, true if the layout needs to be re-tiled, false if no change." + ], + "returns_gfm": "
    \n
  • A boolean, true if the layout needs to be re-tiled, false if no change.
  • \n
\n", + "signature": "PaperWM:refreshWindows()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "def_gfm": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "desc": "Remove window from tiling layout", + "desc_gfm": "

Remove window from tiling layout

\n", + "doc": "Remove window from tiling layout\n\nParameters:\n * remove_window - A hs.window to remove from tiling layout\n * skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.\n\nReturns:\n * The hs.spaces space for removed window.", + "doc_gfm": "

Remove window from tiling layout

\n

Parameters:

\n
    \n
  • remove_window - A hs.window to remove from tiling layout
  • \n
  • skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.
  • \n
\n

Returns:

\n
    \n
  • The hs.spaces space for removed window.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "652", + "name": "remove_window", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * remove_window - A hs.window to remove from tiling layout", + " * skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed." + ], + "parameters_gfm": "
    \n
  • remove_window - A hs.window to remove from tiling layout
  • \n
  • skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed.
  • \n
\n", + "returns": [ + " * The hs.spaces space for removed window." + ], + "returns_gfm": "
    \n
  • The hs.spaces space for removed window.
  • \n
\n", + "signature": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:setWindowFullWidth()", + "def_gfm": "PaperWM:setWindowFullWidth()", + "desc": "Resizes current window's width to width of screen, without adjusting height.", + "desc_gfm": "

Resizes current window's width to width of screen, without adjusting height.

\n", + "doc": "Resizes current window's width to width of screen, without adjusting height.\n\nParameters:\n * None", + "doc_gfm": "

Resizes current window's width to width of screen, without adjusting height.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "885", + "name": "setWindowFullWidth", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:setWindowFullWidth()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:slurpWindow()", + "def_gfm": "PaperWM:slurpWindow()", + "desc": "Moves current window into column of windows to the left", + "desc_gfm": "

Moves current window into column of windows to the left

\n", + "doc": "Moves current window into column of windows to the left\n\nParameters:\n * None", + "doc_gfm": "

Moves current window into column of windows to the left

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "961", + "name": "slurpWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:slurpWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:start()", + "def_gfm": "PaperWM:start()", + "desc": "Start automatic tiling of windows", + "desc_gfm": "

Start automatic tiling of windows

\n", + "doc": "Start automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "doc_gfm": "

Start automatic tiling of windows

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The PaperWM object
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "354", + "name": "start", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * The PaperWM object" + ], + "returns_gfm": "
    \n
  • The PaperWM object
  • \n
\n", + "signature": "PaperWM:start()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:stop()", + "def_gfm": "PaperWM:stop()", + "desc": "Stop automatic tiling of windows", + "desc_gfm": "

Stop automatic tiling of windows

\n", + "doc": "Stop automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "doc_gfm": "

Stop automatic tiling of windows

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The PaperWM object
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "391", + "name": "stop", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [ + " * The PaperWM object" + ], + "returns_gfm": "
    \n
  • The PaperWM object
  • \n
\n", + "signature": "PaperWM:stop()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:swapWindows(direction)", + "def_gfm": "PaperWM:swapWindows(direction)", + "desc": "Swaps window postions between current window and window in specified direction.", + "desc_gfm": "

Swaps window postions between current window and window in specified direction.

\n", + "doc": "Swaps window postions between current window and window in specified direction.\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + "doc_gfm": "

Swaps window postions between current window and window in specified direction.

\n

Parameters:

\n
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "749", + "name": "swapWindows", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }" + ], + "parameters_gfm": "
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:swapWindows(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:switchToSpace(index)", + "def_gfm": "PaperWM:switchToSpace(index)", + "desc": "Switch to a Mission Control space", + "desc_gfm": "

Switch to a Mission Control space

\n", + "doc": "Switch to a Mission Control space\n\nParameters:\n * index - The space number", + "doc_gfm": "

Switch to a Mission Control space

\n

Parameters:

\n
    \n
  • index - The space number
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1080", + "name": "switchToSpace", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * index - The space number" + ], + "parameters_gfm": "
    \n
  • index - The space number
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:switchToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "def_gfm": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "desc": "Tile a column of windows", + "desc_gfm": "

Tile a column of windows

\n", + "doc": "Tile a column of windows\n\nParameters:\n * windows - A list of hs.windows.\n * bounds - An hs.geometry.rect. The area for this column to fill.\n * h - The height for each window in column.\n * w - The width for each window in column.\n * id - A hs.window.id() for a specific window in column.\n * h4id - The height for a window matching id in column.\n\nNotes:\n * The h, w, id, and h4id parameters are optional. The height and width of\n all windows will be calculated and set to fill column bounds.\n * If bounds width is not specified, all windows in column will be resized\n to width of first window.\n\nReturns:\n * The width of the column", + "doc_gfm": "

Tile a column of windows

\n

Parameters:

\n
    \n
  • windows - A list of hs.windows.
  • \n
  • bounds - An hs.geometry.rect. The area for this column to fill.
  • \n
  • h - The height for each window in column.
  • \n
  • w - The width for each window in column.
  • \n
  • id - A hs.window.id() for a specific window in column.
  • \n
  • h4id - The height for a window matching id in column.
  • \n
\n

Notes:

\n
    \n
  • The h, w, id, and h4id parameters are optional. The height and width of\nall windows will be calculated and set to fill column bounds.
  • \n
  • If bounds width is not specified, all windows in column will be resized\nto width of first window.
  • \n
\n

Returns:

\n
    \n
  • The width of the column
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "408", + "name": "tileColumn", + "notes": [ + " * The h, w, id, and h4id parameters are optional. The height and width of", + " all windows will be calculated and set to fill column bounds.", + " * If bounds width is not specified, all windows in column will be resized", + " to width of first window." + ], + "notes_gfm": "
    \n
  • The h, w, id, and h4id parameters are optional. The height and width of\nall windows will be calculated and set to fill column bounds.
  • \n
  • If bounds width is not specified, all windows in column will be resized\nto width of first window.
  • \n
\n", + "parameters": [ + " * windows - A list of hs.windows.", + " * bounds - An hs.geometry.rect. The area for this column to fill.", + " * h - The height for each window in column.", + " * w - The width for each window in column.", + " * id - A hs.window.id() for a specific window in column.", + " * h4id - The height for a window matching id in column." + ], + "parameters_gfm": "
    \n
  • windows - A list of hs.windows.
  • \n
  • bounds - An hs.geometry.rect. The area for this column to fill.
  • \n
  • h - The height for each window in column.
  • \n
  • w - The width for each window in column.
  • \n
  • id - A hs.window.id() for a specific window in column.
  • \n
  • h4id - The height for a window matching id in column.
  • \n
\n", + "returns": [ + " * The width of the column" + ], + "returns_gfm": "
    \n
  • The width of the column
  • \n
\n", + "signature": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileSpace(space)", + "def_gfm": "PaperWM:tileSpace(space)", + "desc": "Tile all windows within a space", + "desc_gfm": "

Tile all windows within a space

\n", + "doc": "Tile all windows within a space\n\nParameters:\n * space - A hs.spaces space.", + "doc_gfm": "

Tile all windows within a space

\n

Parameters:

\n
    \n
  • space - A hs.spaces space.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "460", + "name": "tileSpace", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * space - A hs.spaces space." + ], + "parameters_gfm": "
    \n
  • space - A hs.spaces space.
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:tileSpace(space)", + "stripped_doc": "", + "type": "Method" + } + ], + "Variable": [ + { + "def": "PaperWM.default_hotkeys", + "def_gfm": "PaperWM.default_hotkeys", + "desc": "Default hotkeys for moving / resizing windows", + "desc_gfm": "

Default hotkeys for moving / resizing windows

\n", + "doc": "Default hotkeys for moving / resizing windows", + "doc_gfm": "

Default hotkeys for moving / resizing windows

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "111", + "name": "default_hotkeys", + "signature": "PaperWM.default_hotkeys", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.logger", + "def_gfm": "PaperWM.logger", + "desc": "Logger object. Can be accessed to set default log level.", + "desc_gfm": "

Logger object. Can be accessed to set default log level.

\n", + "doc": "Logger object. Can be accessed to set default log level.", + "doc_gfm": "

Logger object. Can be accessed to set default log level.

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "165", + "name": "logger", + "signature": "PaperWM.logger", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_filter", + "def_gfm": "PaperWM.window_filter", + "desc": "Windows captured by this filter are automatically tiled and managed", + "desc_gfm": "

Windows captured by this filter are automatically tiled and managed

\n", + "doc": "Windows captured by this filter are automatically tiled and managed", + "doc_gfm": "

Windows captured by this filter are automatically tiled and managed

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "150", + "name": "window_filter", + "signature": "PaperWM.window_filter", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_gap", + "def_gfm": "PaperWM.window_gap", + "desc": "Number of pixels between tiled windows", + "desc_gfm": "

Number of pixels between tiled windows

\n", + "doc": "Number of pixels between tiled windows", + "doc_gfm": "

Number of pixels between tiled windows

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "160", + "name": "window_gap", + "signature": "PaperWM.window_gap", + "stripped_doc": "", + "type": "Variable" + } + ], + "desc": "A scrolling window manager. Inspired by PaperWM Gnome extension.", + "desc_gfm": "

A scrolling window manager. Inspired by PaperWM Gnome extension.

\n", + "doc": "A scrolling window manager. Inspired by PaperWM Gnome extension.\n\n# Usage\n\n`PaperWM:start()` will begin automatically tiling new and existing windows.\n`PaperWM:stop()` will release control over windows.\n`PaperWM::bindHotkeys()` will move / resize windows using keyboard shortcuts.\n\nHere is an example Hammerspoon config:\n\n```\nPaperWM = hs.loadSpoon(\"PaperWM\")\nPaperWM:bindHotkeys({\n -- switch to a new focused window in tiled grid\n focus_left = {{\"ctrl\", \"alt\", \"cmd\"}, \"left\"},\n focus_right = {{\"ctrl\", \"alt\", \"cmd\"}, \"right\"},\n focus_up = {{\"ctrl\", \"alt\", \"cmd\"}, \"up\"},\n focus_down = {{\"ctrl\", \"alt\", \"cmd\"}, \"down\"},\n\n -- move windows around in tiled grid\n swap_left = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"left\"},\n swap_right = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"right\"},\n swap_up = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"up\"},\n swap_down = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"down\"},\n\n -- position and resize focused window\n center_window = {{\"ctrl\", \"alt\", \"cmd\"}, \"c\"},\n full_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"f\"},\n cycle_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"r\"},\n cycle_height = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"r\"},\n\n -- move focused window into / out of a column\n slurp_in = {{\"ctrl\", \"alt\", \"cmd\"}, \"i\"},\n barf_out = {{\"ctrl\", \"alt\", \"cmd\"}, \"o\"},\n\n -- switch to a new Mission Control space\n switch_space_1 = {{\"ctrl\", \"alt\", \"cmd\"}, \"1\"},\n switch_space_2 = {{\"ctrl\", \"alt\", \"cmd\"}, \"2\"},\n switch_space_3 = {{\"ctrl\", \"alt\", \"cmd\"}, \"3\"},\n switch_space_4 = {{\"ctrl\", \"alt\", \"cmd\"}, \"4\"},\n switch_space_5 = {{\"ctrl\", \"alt\", \"cmd\"}, \"5\"},\n switch_space_6 = {{\"ctrl\", \"alt\", \"cmd\"}, \"6\"},\n switch_space_7 = {{\"ctrl\", \"alt\", \"cmd\"}, \"7\"},\n switch_space_8 = {{\"ctrl\", \"alt\", \"cmd\"}, \"8\"},\n switch_space_9 = {{\"ctrl\", \"alt\", \"cmd\"}, \"9\"},\n\n -- move focused window to a new space and tile\n move_window_1 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"1\"},\n move_window_2 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"2\"},\n move_window_3 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"3\"},\n move_window_4 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"4\"},\n move_window_5 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"5\"},\n move_window_6 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"6\"},\n move_window_7 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"7\"},\n move_window_8 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"8\"},\n move_window_9 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"9\"}\n})\nPaperWM:start()\n```\n\nUse `PaperWM:bindHotkeys(PaperWM.default_hotkeys)` for defaults.\n\nSet `PaperWM.window_gap` to the number of pixels to space between windows and\nthe top and bottom screen edges.\n\nOverwrite `PaperWM.window_filter` to ignore specific applications. For example:\n\n```\nPaperWM.window_filter = PaperWM.window_filter:setAppFilter(\"Finder\", false)\nPaperWM:start() -- restart for new window filter to take effect\n```\n\n# Limitations\n\nUnder System Preferences -> Mission Control, unselect \"Automatically\nrearrange Spaces based on most recent use\" and select \"Displays have separate\nSpaces\".\n\nMacOS does not allow a window to be moved fully off-screen. Windows that would\nbe tiled off-screen are placed in a margin on the left and right edge of the\nscreen. They are still visible and clickable.\n\nIt's difficult to detect when a window is dragged from one space or screen to\nanother. Use the move_window_N commands to move windows between spaces and\nscreens.\n\nArrange screens vertically to prevent windows from bleeding into other screens.\n\n\nDownload: [https://github.com/mogenson/PaperWM.spoon](https://github.com/mogenson/PaperWM.spoon)", + "doc_gfm": "

A scrolling window manager. Inspired by PaperWM Gnome extension.

\n

Usage

\n

PaperWM:start() will begin automatically tiling new and existing windows.\nPaperWM:stop() will release control over windows.\nPaperWM::bindHotkeys() will move / resize windows using keyboard shortcuts.

\n

Here is an example Hammerspoon config:

\n\n
PaperWM = hs.loadSpoon("PaperWM")\nPaperWM:bindHotkeys({\n    -- switch to a new focused window in tiled grid\n    focus_left  = {{"ctrl", "alt", "cmd"}, "left"},\n    focus_right = {{"ctrl", "alt", "cmd"}, "right"},\n    focus_up    = {{"ctrl", "alt", "cmd"}, "up"},\n    focus_down  = {{"ctrl", "alt", "cmd"}, "down"},\n\n    -- move windows around in tiled grid\n    swap_left  = {{"ctrl", "alt", "cmd", "shift"}, "left"},\n    swap_right = {{"ctrl", "alt", "cmd", "shift"}, "right"},\n    swap_up    = {{"ctrl", "alt", "cmd", "shift"}, "up"},\n    swap_down  = {{"ctrl", "alt", "cmd", "shift"}, "down"},\n\n    -- position and resize focused window\n    center_window = {{"ctrl", "alt", "cmd"}, "c"},\n    full_width    = {{"ctrl", "alt", "cmd"}, "f"},\n    cycle_width   = {{"ctrl", "alt", "cmd"}, "r"},\n    cycle_height  = {{"ctrl", "alt", "cmd", "shift"}, "r"},\n\n    -- move focused window into / out of a column\n    slurp_in = {{"ctrl", "alt", "cmd"}, "i"},\n    barf_out = {{"ctrl", "alt", "cmd"}, "o"},\n\n    -- switch to a new Mission Control space\n    switch_space_1 = {{"ctrl", "alt", "cmd"}, "1"},\n    switch_space_2 = {{"ctrl", "alt", "cmd"}, "2"},\n    switch_space_3 = {{"ctrl", "alt", "cmd"}, "3"},\n    switch_space_4 = {{"ctrl", "alt", "cmd"}, "4"},\n    switch_space_5 = {{"ctrl", "alt", "cmd"}, "5"},\n    switch_space_6 = {{"ctrl", "alt", "cmd"}, "6"},\n    switch_space_7 = {{"ctrl", "alt", "cmd"}, "7"},\n    switch_space_8 = {{"ctrl", "alt", "cmd"}, "8"},\n    switch_space_9 = {{"ctrl", "alt", "cmd"}, "9"},\n\n    -- move focused window to a new space and tile\n    move_window_1 = {{"ctrl", "alt", "cmd", "shift"}, "1"},\n    move_window_2 = {{"ctrl", "alt", "cmd", "shift"}, "2"},\n    move_window_3 = {{"ctrl", "alt", "cmd", "shift"}, "3"},\n    move_window_4 = {{"ctrl", "alt", "cmd", "shift"}, "4"},\n    move_window_5 = {{"ctrl", "alt", "cmd", "shift"}, "5"},\n    move_window_6 = {{"ctrl", "alt", "cmd", "shift"}, "6"},\n    move_window_7 = {{"ctrl", "alt", "cmd", "shift"}, "7"},\n    move_window_8 = {{"ctrl", "alt", "cmd", "shift"}, "8"},\n    move_window_9 = {{"ctrl", "alt", "cmd", "shift"}, "9"}\n})\nPaperWM:start()\n
\n

Use PaperWM:bindHotkeys(PaperWM.default_hotkeys) for defaults.

\n

Set PaperWM.window_gap to the number of pixels to space between windows and\nthe top and bottom screen edges.

\n

Overwrite PaperWM.window_filter to ignore specific applications. For example:

\n\n
PaperWM.window_filter = PaperWM.window_filter:setAppFilter("Finder", false)\nPaperWM:start() -- restart for new window filter to take effect\n
\n

Limitations

\n

Under System Preferences -> Mission Control, unselect "Automatically\nrearrange Spaces based on most recent use" and select "Displays have separate\nSpaces".

\n

MacOS does not allow a window to be moved fully off-screen. Windows that would\nbe tiled off-screen are placed in a margin on the left and right edge of the\nscreen. They are still visible and clickable.

\n

It's difficult to detect when a window is dragged from one space or screen to\nanother. Use the move_window_N commands to move windows between spaces and\nscreens.

\n

Arrange screens vertically to prevent windows from bleeding into other screens.

\n

Download: https://github.com/mogenson/PaperWM.spoon

\n", + "items": [ + { + "def": "PaperWM:addWindow(add_window)", + "def_gfm": "PaperWM:addWindow(add_window)", + "desc": "Adds a window to layout and tiles.", + "desc_gfm": "

Adds a window to layout and tiles.

\n", + "doc": "Adds a window to layout and tiles.\n\nParameters:\n * add_window - An hs.window\n\nReturns:\n * The hs.spaces space for added window or nil if window not added.", + "doc_gfm": "

Adds a window to layout and tiles.

\n

Parameters:

\n
    \n
  • add_window - An hs.window
  • \n
\n

Returns:

\n
    \n
  • The hs.spaces space for added window or nil if window not added.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "594", + "name": "addWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * add_window - An hs.window" + ], + "parameters_gfm": "
    \n
  • add_window - An hs.window
  • \n
\n", + "returns": [ + " * The hs.spaces space for added window or nil if window not added." + ], + "returns_gfm": "
    \n
  • The hs.spaces space for added window or nil if window not added.
  • \n
\n", + "signature": "PaperWM:addWindow(add_window)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:barfWindow()", + "def_gfm": "PaperWM:barfWindow()", + "desc": "Removes current window from column and places it to the right", + "desc_gfm": "

Removes current window from column and places it to the right

\n", + "doc": "Removes current window from column and places it to the right\n\nParameters:\n * None", + "doc_gfm": "

Removes current window from column and places it to the right

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1026", + "name": "barfWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:barfWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.bindHotkeys(mapping)", + "def_gfm": "PaperWM.bindHotkeys(mapping)", + "desc": "Binds hotkeys for PaperWM", + "desc_gfm": "

Binds hotkeys for PaperWM

\n", + "doc": "Binds hotkeys for PaperWM\n\nParameters:\n * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9", + "doc_gfm": "

Binds hotkeys for PaperWM

\n

Parameters:

\n
    \n
  • mapping - A table containing hotkey modifer/key details for the following items:
  • \n
  • stop_events - Stop automatic tiling
  • \n
  • focus_left - Focus window to left of current window
  • \n
  • focus_right - Focus window to right of current window
  • \n
  • focus_up - Focus window to up of current window
  • \n
  • focus_down - Focus window to down of current window
  • \n
  • swap_left - Swap positions of window to the left and current window
  • \n
  • swap_right - Swap positions of window to the right and current window
  • \n
  • swap_up - Swap positions of window above and current window
  • \n
  • swap_down - Swap positions of window below and current window
  • \n
  • center_window - Move current window to center of screen
  • \n
  • full_width - Resize width of current window to width of screen
  • \n
  • cycle_width - Toggle through preset window widths
  • \n
  • cycle_height - Toggle through preset window heights
  • \n
  • slurp_in - Move current window into column to the left
  • \n
  • barf_out - Remove current window from column and place to the right
  • \n
  • switch_space_1 - Switch to Mission Control space 1
  • \n
  • switch_space_2 - Switch to Mission Control space 2
  • \n
  • switch_space_3 - Switch to Mission Control space 3
  • \n
  • switch_space_4 - Switch to Mission Control space 4
  • \n
  • switch_space_5 - Switch to Mission Control space 5
  • \n
  • switch_space_6 - Switch to Mission Control space 6
  • \n
  • switch_space_7 - Switch to Mission Control space 7
  • \n
  • switch_space_8 - Switch to Mission Control space 8
  • \n
  • switch_space_9 - Switch to Mission Control space 9
  • \n
  • move_window_1 - Move current window to Mission Control space 1
  • \n
  • move_window_2 - Move current window to Mission Control space 2
  • \n
  • move_window_3 - Move current window to Mission Control space 3
  • \n
  • move_window_4 - Move current window to Mission Control space 4
  • \n
  • move_window_5 - Move current window to Mission Control space 5
  • \n
  • move_window_6 - Move current window to Mission Control space 6
  • \n
  • move_window_7 - Move current window to Mission Control space 7
  • \n
  • move_window_8 - Move current window to Mission Control space 8
  • \n
  • move_window_9 - Move current window to Mission Control space 9
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "275", + "name": "bindHotkeys", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * mapping - A table containing hotkey modifer/key details for the following items:\n * stop_events - Stop automatic tiling\n * focus_left - Focus window to left of current window\n * focus_right - Focus window to right of current window\n * focus_up - Focus window to up of current window\n * focus_down - Focus window to down of current window\n * swap_left - Swap positions of window to the left and current window\n * swap_right - Swap positions of window to the right and current window\n * swap_up - Swap positions of window above and current window\n * swap_down - Swap positions of window below and current window\n * center_window - Move current window to center of screen\n * full_width - Resize width of current window to width of screen\n * cycle_width - Toggle through preset window widths\n * cycle_height - Toggle through preset window heights\n * slurp_in - Move current window into column to the left\n * barf_out - Remove current window from column and place to the right\n * switch_space_1 - Switch to Mission Control space 1\n * switch_space_2 - Switch to Mission Control space 2\n * switch_space_3 - Switch to Mission Control space 3\n * switch_space_4 - Switch to Mission Control space 4\n * switch_space_5 - Switch to Mission Control space 5\n * switch_space_6 - Switch to Mission Control space 6\n * switch_space_7 - Switch to Mission Control space 7\n * switch_space_8 - Switch to Mission Control space 8\n * switch_space_9 - Switch to Mission Control space 9\n * move_window_1 - Move current window to Mission Control space 1\n * move_window_2 - Move current window to Mission Control space 2\n * move_window_3 - Move current window to Mission Control space 3\n * move_window_4 - Move current window to Mission Control space 4\n * move_window_5 - Move current window to Mission Control space 5\n * move_window_6 - Move current window to Mission Control space 6\n * move_window_7 - Move current window to Mission Control space 7\n * move_window_8 - Move current window to Mission Control space 8\n * move_window_9 - Move current window to Mission Control space 9" + ], + "parameters_gfm": "
    \n
  • mapping - A table containing hotkey modifer/key details for the following items:
      \n
    • stop_events - Stop automatic tiling
    • \n
    • focus_left - Focus window to left of current window
    • \n
    • focus_right - Focus window to right of current window
    • \n
    • focus_up - Focus window to up of current window
    • \n
    • focus_down - Focus window to down of current window
    • \n
    • swap_left - Swap positions of window to the left and current window
    • \n
    • swap_right - Swap positions of window to the right and current window
    • \n
    • swap_up - Swap positions of window above and current window
    • \n
    • swap_down - Swap positions of window below and current window
    • \n
    • center_window - Move current window to center of screen
    • \n
    • full_width - Resize width of current window to width of screen
    • \n
    • cycle_width - Toggle through preset window widths
    • \n
    • cycle_height - Toggle through preset window heights
    • \n
    • slurp_in - Move current window into column to the left
    • \n
    • barf_out - Remove current window from column and place to the right
    • \n
    • switch_space_1 - Switch to Mission Control space 1
    • \n
    • switch_space_2 - Switch to Mission Control space 2
    • \n
    • switch_space_3 - Switch to Mission Control space 3
    • \n
    • switch_space_4 - Switch to Mission Control space 4
    • \n
    • switch_space_5 - Switch to Mission Control space 5
    • \n
    • switch_space_6 - Switch to Mission Control space 6
    • \n
    • switch_space_7 - Switch to Mission Control space 7
    • \n
    • switch_space_8 - Switch to Mission Control space 8
    • \n
    • switch_space_9 - Switch to Mission Control space 9
    • \n
    • move_window_1 - Move current window to Mission Control space 1
    • \n
    • move_window_2 - Move current window to Mission Control space 2
    • \n
    • move_window_3 - Move current window to Mission Control space 3
    • \n
    • move_window_4 - Move current window to Mission Control space 4
    • \n
    • move_window_5 - Move current window to Mission Control space 5
    • \n
    • move_window_6 - Move current window to Mission Control space 6
    • \n
    • move_window_7 - Move current window to Mission Control space 7
    • \n
    • move_window_8 - Move current window to Mission Control space 8
    • \n
    • move_window_9 - Move current window to Mission Control space 9
    • \n
    \n
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM.bindHotkeys(mapping)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:centerWindow()", + "def_gfm": "PaperWM:centerWindow()", + "desc": "Moves current window to center of screen, without resizing.", + "desc_gfm": "

Moves current window to center of screen, without resizing.

\n", + "doc": "Moves current window to center of screen, without resizing.\n\nParameters:\n * None", + "doc_gfm": "

Moves current window to center of screen, without resizing.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "860", + "name": "centerWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:centerWindow()", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:cycleWindowSize(direction)", + "def_gfm": "PaperWM:cycleWindowSize(direction)", + "desc": "Resizes current window by cycling through width or height ratios.", + "desc_gfm": "

Resizes current window by cycling through width or height ratios.

\n", + "doc": "Resizes current window by cycling through width or height ratios.\n\nParameters:\n * direction - One of Direction { WIDTH, HEIGHT }", + "doc_gfm": "

Resizes current window by cycling through width or height ratios.

\n

Parameters:

\n
    \n
  • direction - One of Direction { WIDTH, HEIGHT }
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "907", + "name": "cycleWindowSize", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * direction - One of Direction { WIDTH, HEIGHT }" + ], + "parameters_gfm": "
    \n
  • direction - One of Direction { WIDTH, HEIGHT }
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:cycleWindowSize(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM.default_hotkeys", + "def_gfm": "PaperWM.default_hotkeys", + "desc": "Default hotkeys for moving / resizing windows", + "desc_gfm": "

Default hotkeys for moving / resizing windows

\n", + "doc": "Default hotkeys for moving / resizing windows", + "doc_gfm": "

Default hotkeys for moving / resizing windows

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "111", + "name": "default_hotkeys", + "signature": "PaperWM.default_hotkeys", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM:focusWindow(direction, focused_index)", + "def_gfm": "PaperWM:focusWindow(direction, focused_index)", + "desc": "Change focus to a nearby window", + "desc_gfm": "

Change focus to a nearby window

\n", + "doc": "Change focus to a nearby window\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }\n * focused_index - The coordinates of the current window in the tiling layout\n\nReturns:\n * A boolean. True if a new window was focused. False if no nearby window\n was found in that direction.", + "doc_gfm": "

Change focus to a nearby window

\n

Parameters:

\n
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
  • focused_index - The coordinates of the current window in the tiling layout
  • \n
\n

Returns:

\n
    \n
  • A boolean. True if a new window was focused. False if no nearby window\nwas found in that direction.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "699", + "name": "focusWindow", + "notes": [], + "notes_gfm": "", "parameters": [ - " * `eventCallback` - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:\n * `eventType` - The type of event, e.g. `StudioModeStateChanged`\n * `eventIntent` - The event subscription value that caused this event to be sent, e.g. `OBS.eventSubscriptionValues.General`\n * `eventData` - A table containing the event data, e.g. `{ \"studioModeEnabled\": true }`", - " * `host` - The hostname or IP address of the machine running OBS", - " * `port` - The port number that obs-websocket is listening on", - " * `password` - An optional password string that obs-websocket is configured to use", - " * `eventSubscriptions` - An optional number containing the bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + " * focused_index - The coordinates of the current window in the tiling layout" ], - "parameters_gfm": "
    \n
  • eventCallback - A function to be called when an event is received from OBS. The function will be passed a table containing the event data. The keys of the table are:
      \n
    • eventType - The type of event, e.g. StudioModeStateChanged
    • \n
    • eventIntent - The event subscription value that caused this event to be sent, e.g. OBS.eventSubscriptionValues.General
    • \n
    • eventData - A table containing the event data, e.g. { "studioModeEnabled": true }
    • \n
    \n
  • \n
  • host - The hostname or IP address of the machine running OBS
  • \n
  • port - The port number that obs-websocket is listening on
  • \n
  • password - An optional password string that obs-websocket is configured to use
  • \n
  • eventSubscriptions - An optional number containing the bitmask of the events to subscribe to, see OBS.eventSubscriptionValues
  • \n
\n", + "parameters_gfm": "
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
  • focused_index - The coordinates of the current window in the tiling layout
  • \n
\n", "returns": [ - " * None" + " * A boolean. True if a new window was focused. False if no nearby window", + " was found in that direction." ], - "returns_gfm": "
    \n
  • None
  • \n
\n", - "signature": "OBS:init(eventCallback, host, port[, password, eventSubscriptions])", + "returns_gfm": "
    \n
  • A boolean. True if a new window was focused. False if no nearby window\nwas found in that direction.
  • \n
\n", + "signature": "PaperWM:focusWindow(direction, focused_index)", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:reconnectDelay", - "def_gfm": "OBS:reconnectDelay", - "desc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", - "desc_gfm": "

Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to 5

\n", - "doc": "Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to `5`", - "doc_gfm": "

Controls how long to wait, in seconds, before attempting to reconnect to OBS. Defaults to 5

\n", - "file": "Source/OBS.spoon/init.lua", - "lineno": "112", - "name": "reconnectDelay", - "signature": "OBS:reconnectDelay", + "def": "PaperWM.logger", + "def_gfm": "PaperWM.logger", + "desc": "Logger object. Can be accessed to set default log level.", + "desc_gfm": "

Logger object. Can be accessed to set default log level.

\n", + "doc": "Logger object. Can be accessed to set default log level.", + "doc_gfm": "

Logger object. Can be accessed to set default log level.

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "165", + "name": "logger", + "signature": "PaperWM.logger", "stripped_doc": "", "type": "Variable" }, { - "def": "OBS:removeEventSubsciption(event)", - "def_gfm": "OBS:removeEventSubsciption(event)", - "desc": "Removes an event subscription", - "desc_gfm": "

Removes an event subscription

\n", - "doc": "Removes an event subscription\n\nParameters:\n * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None\n\nNotes:\n * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`", - "doc_gfm": "

Removes an event subscription

\n

Parameters:

\n\n

Returns:

\n
    \n
  • None
  • \n
\n

Notes:

\n
    \n
  • If you wish to remove multiple event subscriptions you can use the & operator to combine them, e.g. spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)
  • \n
\n", + "def": "PaperWM::moveWindow(window, frame)", + "def_gfm": "PaperWM::moveWindow(window, frame)", + "desc": "Resizes a window without triggering a windowMoved event", + "desc_gfm": "

Resizes a window without triggering a windowMoved event

\n", + "doc": "Resizes a window without triggering a windowMoved event\n\nParameters:\n * window - An hs.window\n * frame - An hs.geometry.rect for the windows new frame size.", + "doc_gfm": "

Resizes a window without triggering a windowMoved event

\n

Parameters:

\n
    \n
  • window - An hs.window
  • \n
  • frame - An hs.geometry.rect for the windows new frame size.
  • \n
\n", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "326", - "name": "removeEventSubsciption", - "notes": [ - " * If you wish to remove multiple event subscriptions you can use the `&` operator to combine them, e.g. `spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)`" - ], - "notes_gfm": "
    \n
  • If you wish to remove multiple event subscriptions you can use the & operator to combine them, e.g. spoon.OBS:removeEventSubscription(spoon.OBS.eventSubscriptionValues.Config | spoon.OBS.eventSubscriptionValues.Scenes)
  • \n
\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1147", + "name": "moveWindow", + "notes": [], + "notes_gfm": "", "parameters": [ - " * `event` - The event to unsubscribe from, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" - ], - "parameters_gfm": "\n", - "returns": [ - " * None" + " * window - An hs.window", + " * frame - An hs.geometry.rect for the windows new frame size." ], - "returns_gfm": "
    \n
  • None
  • \n
\n", - "signature": "OBS:removeEventSubsciption(event)", + "parameters_gfm": "
    \n
  • window - An hs.window
  • \n
  • frame - An hs.geometry.rect for the windows new frame size.
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM::moveWindow(window, frame)", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:request(requestType[, requestData[, requestId]])", - "def_gfm": "OBS:request(requestType[, requestData[, requestId]])", - "desc": "Sends a request to OBS", - "desc_gfm": "

Sends a request to OBS

\n", - "doc": "Sends a request to OBS\n\nParameters:\n * `requestType` - A string containing the type of request to send\n * `requestData` - An optional table containing the data to send with the request, or nil\n * `requestId` - An optional string containing the ID of the request\n\nReturns:\n * The `requestId` that was sent\n\nNotes:\n * If `requestId` is not specified then a random UUID will be generated.\n * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.\n * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)", - "doc_gfm": "

Sends a request to OBS

\n

Parameters:

\n
    \n
  • requestType - A string containing the type of request to send
  • \n
  • requestData - An optional table containing the data to send with the request, or nil
  • \n
  • requestId - An optional string containing the ID of the request
  • \n
\n

Returns:

\n
    \n
  • The requestId that was sent
  • \n
\n

Notes:

\n
    \n
  • If requestId is not specified then a random UUID will be generated.
  • \n
  • The requestId will be passed to your event callback (provided to OBS:init()) when the response is received.
  • \n
  • Values for requestType can be found in the obs-websocket documentation
  • \n
\n", + "def": "PaperWM:moveWindowToSpace(index)", + "def_gfm": "PaperWM:moveWindowToSpace(index)", + "desc": "Moves the current window to a new Mission Control space", + "desc_gfm": "

Moves the current window to a new Mission Control space

\n", + "doc": "Moves the current window to a new Mission Control space\n\nParameters:\n * index - The space number", + "doc_gfm": "

Moves the current window to a new Mission Control space

\n

Parameters:

\n
    \n
  • index - The space number
  • \n
\n", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "343", - "name": "request", - "notes": [ - " * If `requestId` is not specified then a random UUID will be generated.", - " * The `requestId` will be passed to your event callback (provided to [OBS:init()](#init)) when the response is received.", - " * Values for `requestType` can be found in the [obs-websocket documentation](https://github.com/obsproject/obs-websocket/blob/master/docs/generated/protocol.md#requests)" + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1096", + "name": "moveWindowToSpace", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * index - The space number" ], - "notes_gfm": "
    \n
  • If requestId is not specified then a random UUID will be generated.
  • \n
  • The requestId will be passed to your event callback (provided to OBS:init()) when the response is received.
  • \n
  • Values for requestType can be found in the obs-websocket documentation
  • \n
\n", + "parameters_gfm": "
    \n
  • index - The space number
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:moveWindowToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:refreshWindows()", + "def_gfm": "PaperWM:refreshWindows()", + "desc": "Searches for all windows that match window filter.", + "desc_gfm": "

Searches for all windows that match window filter.

\n", + "doc": "Searches for all windows that match window filter.\n\nParameters:\n * None\n\nReturns:\n * A boolean, true if the layout needs to be re-tiled, false if no change.", + "doc_gfm": "

Searches for all windows that match window filter.

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • A boolean, true if the layout needs to be re-tiled, false if no change.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "563", + "name": "refreshWindows", + "notes": [], + "notes_gfm": "", "parameters": [ - " * `requestType` - A string containing the type of request to send", - " * `requestData` - An optional table containing the data to send with the request, or nil", - " * `requestId` - An optional string containing the ID of the request" + " * None" ], - "parameters_gfm": "
    \n
  • requestType - A string containing the type of request to send
  • \n
  • requestData - An optional table containing the data to send with the request, or nil
  • \n
  • requestId - An optional string containing the ID of the request
  • \n
\n", + "parameters_gfm": "
    \n
  • None
  • \n
\n", "returns": [ - " * The `requestId` that was sent" + " * A boolean, true if the layout needs to be re-tiled, false if no change." ], - "returns_gfm": "
    \n
  • The requestId that was sent
  • \n
\n", - "signature": "OBS:request(requestType[, requestData[, requestId]])", + "returns_gfm": "
    \n
  • A boolean, true if the layout needs to be re-tiled, false if no change.
  • \n
\n", + "signature": "PaperWM:refreshWindows()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:requestBatch(requests[, haltOnFailure])", - "def_gfm": "OBS:requestBatch(requests[, haltOnFailure])", - "desc": "Sends a batch of requests to OBS", - "desc_gfm": "

Sends a batch of requests to OBS

\n", - "doc": "Sends a batch of requests to OBS\n\nParameters:\n * `requests` - A table containing the requests to send\n * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false\n\nReturns:\n * The `requestId` that was sent for the batch\n\nNotes:\n * Each request should be a table with the keys:\n * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)\n * `requestData` - An optional table containing the data to send with the request, or `nil`\n * `requestId` - An optional string containing a unique ID for the request\n * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID\n\nExample:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", - "doc_gfm": "

Sends a batch of requests to OBS

\n

Parameters:

\n
    \n
  • requests - A table containing the requests to send
  • \n
  • haltOnFailure - An optional boolean indicating whether to halt the batch if a request fails, defaults to false
  • \n
\n

Returns:

\n
    \n
  • The requestId that was sent for the batch
  • \n
\n

Notes:

\n
    \n
  • Each request should be a table with the keys:
      \n
    • requestType - A string containing the type of request to send, see OBS:request()
    • \n
    • requestData - An optional table containing the data to send with the request, or nil
    • \n
    • requestId - An optional string containing a unique ID for the request
    • \n
    \n
  • \n
  • Unlike OBS:request() the requestId is an auto-generated UUID
  • \n
\n

Example:

\n
spoon.OBS:requestBatch({\n {["requestType"] = "StartVirtualCam"},\n {["requestType"] = "SetCurrentProgramScene", ["requestData"] = { ["sceneName"] = "FancyScene" }}\n})\n
\n", + "def": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "def_gfm": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "desc": "Remove window from tiling layout", + "desc_gfm": "

Remove window from tiling layout

\n", + "doc": "Remove window from tiling layout\n\nParameters:\n * remove_window - A hs.window to remove from tiling layout\n * skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.\n\nReturns:\n * The hs.spaces space for removed window.", + "doc_gfm": "

Remove window from tiling layout

\n

Parameters:

\n
    \n
  • remove_window - A hs.window to remove from tiling layout
  • \n
  • skip_new_window_focus - A boolean. True if a nearby window should not be\n focused after current window is removed.
  • \n
\n

Returns:

\n
    \n
  • The hs.spaces space for removed window.
  • \n
\n", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "377", - "name": "requestBatch", - "notes": [ - " * Each request should be a table with the keys:", - " * `requestType` - A string containing the type of request to send, see [OBS:request()](#request)", - " * `requestData` - An optional table containing the data to send with the request, or `nil`", - " * `requestId` - An optional string containing a unique ID for the request", - " * Unlike [OBS:request()](#request) the `requestId` is an auto-generated UUID", - "", - "Example:", - "```lua", - "spoon.OBS:requestBatch({", - " {[\"requestType\"] = \"StartVirtualCam\"},", - " {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}", - "})", - "```" - ], - "notes_gfm": "
    \n
  • Each request should be a table with the keys:
      \n
    • requestType - A string containing the type of request to send, see OBS:request()
    • \n
    • requestData - An optional table containing the data to send with the request, or nil
    • \n
    • requestId - An optional string containing a unique ID for the request
    • \n
    \n
  • \n
  • Unlike OBS:request() the requestId is an auto-generated UUID
  • \n
\n

Example:

\n
spoon.OBS:requestBatch({\n {["requestType"] = "StartVirtualCam"},\n {["requestType"] = "SetCurrentProgramScene", ["requestData"] = { ["sceneName"] = "FancyScene" }}\n})\n
\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "652", + "name": "remove_window", + "notes": [], + "notes_gfm": "", "parameters": [ - " * `requests` - A table containing the requests to send", - " * `haltOnFailure` - An optional boolean indicating whether to halt the batch if a request fails, defaults to false" + " * remove_window - A hs.window to remove from tiling layout", + " * skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed." ], - "parameters_gfm": "
    \n
  • requests - A table containing the requests to send
  • \n
  • haltOnFailure - An optional boolean indicating whether to halt the batch if a request fails, defaults to false
  • \n
\n", + "parameters_gfm": "
    \n
  • remove_window - A hs.window to remove from tiling layout
  • \n
  • skip_new_window_focus - A boolean. True if a nearby window should not be focused after current window is removed.
  • \n
\n", "returns": [ - " * The `requestId` that was sent for the batch" + " * The hs.spaces space for removed window." ], - "returns_gfm": "
    \n
  • The requestId that was sent for the batch
  • \n
\n", - "signature": "OBS:requestBatch(requests[, haltOnFailure])", - "stripped_doc": "Example:\n```lua\nspoon.OBS:requestBatch({\n {[\"requestType\"] = \"StartVirtualCam\"},\n {[\"requestType\"] = \"SetCurrentProgramScene\", [\"requestData\"] = { [\"sceneName\"] = \"FancyScene\" }}\n})\n```", + "returns_gfm": "
    \n
  • The hs.spaces space for removed window.
  • \n
\n", + "signature": "PaperWM:remove_window(remove_window, skip_new_window_focus)", + "stripped_doc": "", "type": "Method" }, { - "def": "OBS:setLogLevel(level)", - "def_gfm": "OBS:setLogLevel(level)", - "desc": "Sets the logging level for the OBS Spoon", - "desc_gfm": "

Sets the logging level for the OBS Spoon

\n", - "doc": "Sets the logging level for the OBS Spoon\n\nParameters:\n * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values\n\nReturns:\n * None", - "doc_gfm": "

Sets the logging level for the OBS Spoon

\n

Parameters:

\n\n

Returns:

\n
    \n
  • None
  • \n
\n", + "def": "PaperWM:setWindowFullWidth()", + "def_gfm": "PaperWM:setWindowFullWidth()", + "desc": "Resizes current window's width to width of screen, without adjusting height.", + "desc_gfm": "

Resizes current window's width to width of screen, without adjusting height.

\n", + "doc": "Resizes current window's width to width of screen, without adjusting height.\n\nParameters:\n * None", + "doc_gfm": "

Resizes current window's width to width of screen, without adjusting height.

\n

Parameters:

\n
    \n
  • None
  • \n
\n", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "419", - "name": "setLogLevel", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "885", + "name": "setWindowFullWidth", "notes": [], "notes_gfm": "", "parameters": [ - " * `level` - A string containing the logging level to use, see [hs.logger.setLogLevel](https://www.hammerspoon.org/docs/hs.logger.html#setLogLevel) for possible values" - ], - "parameters_gfm": "\n", - "returns": [ " * None" ], - "returns_gfm": "
    \n
  • None
  • \n
\n", - "signature": "OBS:setLogLevel(level)", + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:setWindowFullWidth()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:shouldReconnect", - "def_gfm": "OBS:shouldReconnect", - "desc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", - "desc_gfm": "

Controls whether the websocket connection should be re-established if it is lost. Defaults to true

\n", - "doc": "Controls whether the websocket connection should be re-established if it is lost. Defaults to `true`", - "doc_gfm": "

Controls whether the websocket connection should be re-established if it is lost. Defaults to true

\n", - "file": "Source/OBS.spoon/init.lua", - "lineno": "105", - "name": "shouldReconnect", - "signature": "OBS:shouldReconnect", + "def": "PaperWM:slurpWindow()", + "def_gfm": "PaperWM:slurpWindow()", + "desc": "Moves current window into column of windows to the left", + "desc_gfm": "

Moves current window into column of windows to the left

\n", + "doc": "Moves current window into column of windows to the left\n\nParameters:\n * None", + "doc_gfm": "

Moves current window into column of windows to the left

\n

Parameters:

\n
    \n
  • None
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "961", + "name": "slurpWindow", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * None" + ], + "parameters_gfm": "
    \n
  • None
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:slurpWindow()", "stripped_doc": "", - "type": "Variable" + "type": "Method" }, { - "def": "OBS:start()", - "def_gfm": "OBS:start()", - "desc": "Connects to OBS", - "desc_gfm": "

Connects to OBS

\n", - "doc": "Connects to OBS\n\nParameters:\n * None\n\nReturns:\n * None", - "doc_gfm": "

Connects to OBS

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", + "def": "PaperWM:start()", + "def_gfm": "PaperWM:start()", + "desc": "Start automatic tiling of windows", + "desc_gfm": "

Start automatic tiling of windows

\n", + "doc": "Start automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "doc_gfm": "

Start automatic tiling of windows

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The PaperWM object
  • \n
\n", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "161", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "354", "name": "start", "notes": [], "notes_gfm": "", @@ -12613,23 +14230,23 @@ ], "parameters_gfm": "
    \n
  • None
  • \n
\n", "returns": [ - " * None" + " * The PaperWM object" ], - "returns_gfm": "
    \n
  • None
  • \n
\n", - "signature": "OBS:start()", + "returns_gfm": "
    \n
  • The PaperWM object
  • \n
\n", + "signature": "PaperWM:start()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:stop()", - "def_gfm": "OBS:stop()", - "desc": "Disconnects from OBS", - "desc_gfm": "

Disconnects from OBS

\n", - "doc": "Disconnects from OBS\n\nParameters:\n * None\n\nReturns:\n * None", - "doc_gfm": "

Disconnects from OBS

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • None
  • \n
\n", + "def": "PaperWM:stop()", + "def_gfm": "PaperWM:stop()", + "desc": "Stop automatic tiling of windows", + "desc_gfm": "

Stop automatic tiling of windows

\n", + "doc": "Stop automatic tiling of windows\n\nParameters:\n * None\n\nReturns:\n * The PaperWM object", + "doc_gfm": "

Stop automatic tiling of windows

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The PaperWM object
  • \n
\n", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "274", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "391", "name": "stop", "notes": [], "notes_gfm": "", @@ -12638,41 +14255,148 @@ ], "parameters_gfm": "
    \n
  • None
  • \n
\n", "returns": [ - " * None" + " * The PaperWM object" ], - "returns_gfm": "
    \n
  • None
  • \n
\n", - "signature": "OBS:stop()", + "returns_gfm": "
    \n
  • The PaperWM object
  • \n
\n", + "signature": "PaperWM:stop()", "stripped_doc": "", "type": "Method" }, { - "def": "OBS:updateEventSubscriptions(eventSubscriptions)", - "def_gfm": "OBS:updateEventSubscriptions(eventSubscriptions)", - "desc": "Updates the event subscriptions", - "desc_gfm": "

Updates the event subscriptions

\n", - "doc": "Updates the event subscriptions\n\nParameters:\n * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)\n\nReturns:\n * None", - "doc_gfm": "

Updates the event subscriptions

\n

Parameters:

\n\n

Returns:

\n
    \n
  • None
  • \n
\n", + "def": "PaperWM:swapWindows(direction)", + "def_gfm": "PaperWM:swapWindows(direction)", + "desc": "Swaps window postions between current window and window in specified direction.", + "desc_gfm": "

Swaps window postions between current window and window in specified direction.

\n", + "doc": "Swaps window postions between current window and window in specified direction.\n\nParameters:\n * direction - One of Direction { LEFT, RIGHT, DOWN, UP }", + "doc_gfm": "

Swaps window postions between current window and window in specified direction.

\n

Parameters:

\n
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
\n", "examples": [], - "file": "Source/OBS.spoon/init.lua", - "lineno": "289", - "name": "updateEventSubscriptions", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "749", + "name": "swapWindows", "notes": [], "notes_gfm": "", "parameters": [ - " * `eventSubscriptions` - A bitmask of the events to subscribe to, see [OBS.eventSubscriptionValues](#eventSubscriptionValues)" + " * direction - One of Direction { LEFT, RIGHT, DOWN, UP }" ], - "parameters_gfm": "\n", + "parameters_gfm": "
    \n
  • direction - One of Direction { LEFT, RIGHT, DOWN, UP }
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:swapWindows(direction)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:switchToSpace(index)", + "def_gfm": "PaperWM:switchToSpace(index)", + "desc": "Switch to a Mission Control space", + "desc_gfm": "

Switch to a Mission Control space

\n", + "doc": "Switch to a Mission Control space\n\nParameters:\n * index - The space number", + "doc_gfm": "

Switch to a Mission Control space

\n

Parameters:

\n
    \n
  • index - The space number
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "1080", + "name": "switchToSpace", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * index - The space number" + ], + "parameters_gfm": "
    \n
  • index - The space number
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:switchToSpace(index)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "def_gfm": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "desc": "Tile a column of windows", + "desc_gfm": "

Tile a column of windows

\n", + "doc": "Tile a column of windows\n\nParameters:\n * windows - A list of hs.windows.\n * bounds - An hs.geometry.rect. The area for this column to fill.\n * h - The height for each window in column.\n * w - The width for each window in column.\n * id - A hs.window.id() for a specific window in column.\n * h4id - The height for a window matching id in column.\n\nNotes:\n * The h, w, id, and h4id parameters are optional. The height and width of\n all windows will be calculated and set to fill column bounds.\n * If bounds width is not specified, all windows in column will be resized\n to width of first window.\n\nReturns:\n * The width of the column", + "doc_gfm": "

Tile a column of windows

\n

Parameters:

\n
    \n
  • windows - A list of hs.windows.
  • \n
  • bounds - An hs.geometry.rect. The area for this column to fill.
  • \n
  • h - The height for each window in column.
  • \n
  • w - The width for each window in column.
  • \n
  • id - A hs.window.id() for a specific window in column.
  • \n
  • h4id - The height for a window matching id in column.
  • \n
\n

Notes:

\n
    \n
  • The h, w, id, and h4id parameters are optional. The height and width of\nall windows will be calculated and set to fill column bounds.
  • \n
  • If bounds width is not specified, all windows in column will be resized\nto width of first window.
  • \n
\n

Returns:

\n
    \n
  • The width of the column
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "408", + "name": "tileColumn", + "notes": [ + " * The h, w, id, and h4id parameters are optional. The height and width of", + " all windows will be calculated and set to fill column bounds.", + " * If bounds width is not specified, all windows in column will be resized", + " to width of first window." + ], + "notes_gfm": "
    \n
  • The h, w, id, and h4id parameters are optional. The height and width of\nall windows will be calculated and set to fill column bounds.
  • \n
  • If bounds width is not specified, all windows in column will be resized\nto width of first window.
  • \n
\n", + "parameters": [ + " * windows - A list of hs.windows.", + " * bounds - An hs.geometry.rect. The area for this column to fill.", + " * h - The height for each window in column.", + " * w - The width for each window in column.", + " * id - A hs.window.id() for a specific window in column.", + " * h4id - The height for a window matching id in column." + ], + "parameters_gfm": "
    \n
  • windows - A list of hs.windows.
  • \n
  • bounds - An hs.geometry.rect. The area for this column to fill.
  • \n
  • h - The height for each window in column.
  • \n
  • w - The width for each window in column.
  • \n
  • id - A hs.window.id() for a specific window in column.
  • \n
  • h4id - The height for a window matching id in column.
  • \n
\n", "returns": [ - " * None" + " * The width of the column" ], - "returns_gfm": "
    \n
  • None
  • \n
\n", - "signature": "OBS:updateEventSubscriptions(eventSubscriptions)", + "returns_gfm": "
    \n
  • The width of the column
  • \n
\n", + "signature": "PaperWM:tileColumn(windows, bounds, h, w, id, h4id)", + "stripped_doc": "", + "type": "Method" + }, + { + "def": "PaperWM:tileSpace(space)", + "def_gfm": "PaperWM:tileSpace(space)", + "desc": "Tile all windows within a space", + "desc_gfm": "

Tile all windows within a space

\n", + "doc": "Tile all windows within a space\n\nParameters:\n * space - A hs.spaces space.", + "doc_gfm": "

Tile all windows within a space

\n

Parameters:

\n
    \n
  • space - A hs.spaces space.
  • \n
\n", + "examples": [], + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "460", + "name": "tileSpace", + "notes": [], + "notes_gfm": "", + "parameters": [ + " * space - A hs.spaces space." + ], + "parameters_gfm": "
    \n
  • space - A hs.spaces space.
  • \n
\n", + "returns": [], + "returns_gfm": "", + "signature": "PaperWM:tileSpace(space)", "stripped_doc": "", "type": "Method" + }, + { + "def": "PaperWM.window_filter", + "def_gfm": "PaperWM.window_filter", + "desc": "Windows captured by this filter are automatically tiled and managed", + "desc_gfm": "

Windows captured by this filter are automatically tiled and managed

\n", + "doc": "Windows captured by this filter are automatically tiled and managed", + "doc_gfm": "

Windows captured by this filter are automatically tiled and managed

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "150", + "name": "window_filter", + "signature": "PaperWM.window_filter", + "stripped_doc": "", + "type": "Variable" + }, + { + "def": "PaperWM.window_gap", + "def_gfm": "PaperWM.window_gap", + "desc": "Number of pixels between tiled windows", + "desc_gfm": "

Number of pixels between tiled windows

\n", + "doc": "Number of pixels between tiled windows", + "doc_gfm": "

Number of pixels between tiled windows

\n", + "file": "Source/PaperWM.spoon/init.lua", + "lineno": "160", + "name": "window_gap", + "signature": "PaperWM.window_gap", + "stripped_doc": "", + "type": "Variable" } ], - "name": "OBS", - "stripped_doc": "\nInstall and configure the obs-websocket plugin first from [their project](https://github.com/obsproject/obs-websocket/releases)\n\nNote: This Spoon will only work with Hammerspoon 0.9.100 or later.\n\nNote: This Spoon will only work with obs-websocket 5.0.1 or later, which also requires OBS Studio v27 or later.\n\nDownload: [https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip](https://github.com/Hammerspoon/Spoons/raw/master/Spoons/OBS.spoon.zip)\n\nExample:\n```\n-- This example will start OBS, connect to it, and then start streaming once connected\nobs = hs.loadSpoon(\"OBS\")\nobsCallback = function(eventType, eventIntent, eventData)\n print(eventType)\n print(eventIntent)\n print(hs.inspect(eventData))\n\n if eventType == \"SpoonOBSConnected\" then\n obs:request(\"StartStream\")\n end\nend\nobs:init(obsCallback, \"localhost\", 4444, \"password\")\nobs:start()\n```", + "name": "PaperWM", + "stripped_doc": "\n# Usage\n\n`PaperWM:start()` will begin automatically tiling new and existing windows.\n`PaperWM:stop()` will release control over windows.\n`PaperWM::bindHotkeys()` will move / resize windows using keyboard shortcuts.\n\nHere is an example Hammerspoon config:\n\n```\nPaperWM = hs.loadSpoon(\"PaperWM\")\nPaperWM:bindHotkeys({\n -- switch to a new focused window in tiled grid\n focus_left = {{\"ctrl\", \"alt\", \"cmd\"}, \"left\"},\n focus_right = {{\"ctrl\", \"alt\", \"cmd\"}, \"right\"},\n focus_up = {{\"ctrl\", \"alt\", \"cmd\"}, \"up\"},\n focus_down = {{\"ctrl\", \"alt\", \"cmd\"}, \"down\"},\n\n -- move windows around in tiled grid\n swap_left = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"left\"},\n swap_right = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"right\"},\n swap_up = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"up\"},\n swap_down = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"down\"},\n\n -- position and resize focused window\n center_window = {{\"ctrl\", \"alt\", \"cmd\"}, \"c\"},\n full_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"f\"},\n cycle_width = {{\"ctrl\", \"alt\", \"cmd\"}, \"r\"},\n cycle_height = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"r\"},\n\n -- move focused window into / out of a column\n slurp_in = {{\"ctrl\", \"alt\", \"cmd\"}, \"i\"},\n barf_out = {{\"ctrl\", \"alt\", \"cmd\"}, \"o\"},\n\n -- switch to a new Mission Control space\n switch_space_1 = {{\"ctrl\", \"alt\", \"cmd\"}, \"1\"},\n switch_space_2 = {{\"ctrl\", \"alt\", \"cmd\"}, \"2\"},\n switch_space_3 = {{\"ctrl\", \"alt\", \"cmd\"}, \"3\"},\n switch_space_4 = {{\"ctrl\", \"alt\", \"cmd\"}, \"4\"},\n switch_space_5 = {{\"ctrl\", \"alt\", \"cmd\"}, \"5\"},\n switch_space_6 = {{\"ctrl\", \"alt\", \"cmd\"}, \"6\"},\n switch_space_7 = {{\"ctrl\", \"alt\", \"cmd\"}, \"7\"},\n switch_space_8 = {{\"ctrl\", \"alt\", \"cmd\"}, \"8\"},\n switch_space_9 = {{\"ctrl\", \"alt\", \"cmd\"}, \"9\"},\n\n -- move focused window to a new space and tile\n move_window_1 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"1\"},\n move_window_2 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"2\"},\n move_window_3 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"3\"},\n move_window_4 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"4\"},\n move_window_5 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"5\"},\n move_window_6 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"6\"},\n move_window_7 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"7\"},\n move_window_8 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"8\"},\n move_window_9 = {{\"ctrl\", \"alt\", \"cmd\", \"shift\"}, \"9\"}\n})\nPaperWM:start()\n```\n\nUse `PaperWM:bindHotkeys(PaperWM.default_hotkeys)` for defaults.\n\nSet `PaperWM.window_gap` to the number of pixels to space between windows and\nthe top and bottom screen edges.\n\nOverwrite `PaperWM.window_filter` to ignore specific applications. For example:\n\n```\nPaperWM.window_filter = PaperWM.window_filter:setAppFilter(\"Finder\", false)\nPaperWM:start() -- restart for new window filter to take effect\n```\n\n# Limitations\n\nUnder System Preferences -> Mission Control, unselect \"Automatically\nrearrange Spaces based on most recent use\" and select \"Displays have separate\nSpaces\".\n\nMacOS does not allow a window to be moved fully off-screen. Windows that would\nbe tiled off-screen are placed in a margin on the left and right edge of the\nscreen. They are still visible and clickable.\n\nIt's difficult to detect when a window is dragged from one space or screen to\nanother. Use the move_window_N commands to move windows between spaces and\nscreens.\n\nArrange screens vertically to prevent windows from bleeding into other screens.\n\n\nDownload: [https://github.com/mogenson/PaperWM.spoon](https://github.com/mogenson/PaperWM.spoon)", "submodules": [], "type": "Module" }, @@ -19866,7 +21590,7 @@ "doc_gfm": "

Starts the indicator

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The TimeMachineProgress object
  • \n
\n", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "203", + "lineno": "207", "name": "start", "notes": [], "notes_gfm": "", @@ -19891,7 +21615,7 @@ "doc_gfm": "

Stops the indicator

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The TimeMachineProgress object
  • \n
\n", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "221", + "lineno": "225", "name": "stop", "notes": [], "notes_gfm": "", @@ -20039,7 +21763,7 @@ "doc_gfm": "

Starts the indicator

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The TimeMachineProgress object
  • \n
\n", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "203", + "lineno": "207", "name": "start", "notes": [], "notes_gfm": "", @@ -20064,7 +21788,7 @@ "doc_gfm": "

Stops the indicator

\n

Parameters:

\n
    \n
  • None
  • \n
\n

Returns:

\n
    \n
  • The TimeMachineProgress object
  • \n
\n", "examples": [], "file": "Source/TimeMachineProgress.spoon/init.lua", - "lineno": "221", + "lineno": "225", "name": "stop", "notes": [], "notes_gfm": "",