Unofficial Hammerspoon extension for Visual Studio Code.
- IntelliSense for Hammerspoon API (requires Lua Language Server).
- Evaluate Hammerspoon code from vscode without reloading the configuration. (thanks to @velios).
- Execute vscode commands from Hammerspoon via socket connection.
- Reload Hammerspoon configuration command. (Requires
hs.ipc
. See Requirements) - Hammerspoon console output to Visual Studio Code output window. (Requires
hs.ipc
. See Requirements) - Spoon utilities:
- Create Spoon template.
- Generate Spoon documentation. (Requires
hs.ipc
. See Requirements)
- Lua Language Server extension (it is included with the extension pack by default).
- hs.ipc module installed.
Some commands depend on the
hs.ipc
module. To install it, executehs.ipc.cliInstall()
in your Hammerspoon environment and call it at the beginning of yourinit.lua
withrequire('hs.ipc')
(more on module documentation). If you are on an Apple silicon Mac, you might need to follow those instructions to properly install the module.
The extension now uses the Lua Language Server to provide IntelliSense. In order to provide the Hammerspoon API, the extension uses the EmmyLua.spoon stubs from the official Hammerspoon Spoons repository. The extensions offers a quick utility command to download and generate the stubs. The command Hammerspoon: Add Stubs
will:
- Download the EmmyLua stubs.
- Place them in the Hammerspoon spoons directory (default:
~/.hammerspoon/Spoons
). - Import them in the
init.lua
file. - Add them to the
Lua.workspace.library
user setting. - Reload the Hammerspoon configuration.
Once the stubs are added, you might need to reload VSCode for the changes to take effect.
-
Some stubs might fail to load especially when constructors are involved. In that case, you can always add the type annotation manually:
---@type hs.application local app = hs.application("Safari")
-
The
EmmyLua.spoon
will try to compile the stubs also for your custom spoons. This can cause an error if there is something wrong with your spoondocs.json
. -
The extension still supports the old way of providing the API, but it is highly recommended to use the new method. The old method can be enabled/disabled via the
hammerspoon.enableLegacyProviders
setting.
You can evaluate Hammerspoon code from vscode without reloading the configuration. To do so, you need to have the hs.ipc
module installed. See Requirements for more information.
To evaluate code, you can use one of the following commands:
Hammerspoon: Evaluate Line
: Evaluate the current line.Hammerspoon: Evaluate File
: Evaluate the entire file.Hammerspoon: Evaluate Selection
: Evaluate the selected code.
The commands are also available in the editor right-click context menu.
You can execute vscode commands from Hammerspoon by sending data via the socket
module.
socket = hs.socket.new()
socket:connect('localhost', 54321)
socket:send('workbench.action.toggleZenMode')
-- calling socket:disconnect() immediately, will fail to register the message
hs.timer.doAfter(1, function() socket:disconnect() end)
You can also write arguments inside curly brackets and delimit them by a comma: {arg1, arg2}
socket:send('workbench.action.tasks.runTask {My Task}')
For the extension to accept incoming data, you need to start the server
via the command: Hammerspoon: Toggle server connection
or via the button in lower the
status bar and specify the port in the extension settings (default: 54321
).
All commands are available by opening the Command Palette Command+Shift+P
and
typing in one of the following Command Name:
Command Name | Command ID | Description |
---|---|---|
Hammerspoon: Add Stubs |
hammerspoon.addStubs |
Add EmmyLua stubs to the Hammerspoon Spoons directory |
Hammerspoon: Evaluate Line |
hammerspoon.evaluateCurrentLineText |
Evaluate the current line |
Hammerspoon: Evaluate File |
hammerspoon.evaluateCurrentFileText |
Evaluate the entire file |
Hammerspoon: Evaluate Selection |
hammerspoon.evaluateSelectedText |
Evaluate the selected code |
Hammerspoon: Add Stubs |
hammerspoon.addStubs |
Add EmmyLua stubs |
Hammerspoon: Reload Hammerspoon configuration |
hammerspoon.reloadConfiguration |
Reload Hammerspoon configuration |
Hammerspoon: Show Hammerspoon Console |
hammerspoon.showConsole |
Show Hammerspoon console |
Hammerspoon: Toggle server connection |
hammerspoon.createSpoon |
Toggle connection that allows incoming data to be executed as vscode commands |
Hammerspoon: Create Spoon |
hammerspoon.createSpoon |
Quick Spoon startup template |
Hammerspoon: Generate Spoon Documentation |
hammerspoon.generateSpoonDoc |
Generate docs.json for current spoon |
-
Hammerspoon: Reload Hammerspoon configuration
command can be executed via a button in the Editor Toolbar. -
The Spoon template will get created in the
Hammerspoon: Spoons: Path
configuration value which defaults to.hammerspoon/Spoons
. -
When generating documentation for the Spoon, the editor's current active file must be a
init.lua
. -
By default, the extension does not provide any shortcut. But you can assign each command to one. (see Key Bindings for Visual Studio Code for more information).
{ "key": "cmd+shift+e", "command": "hammerspoon.evaluateCurrentLineText", "when": "editorTextFocus && resourceLangId == lua" }
-
Enable Legacy Providers
-hammerspoon.enableLegacyProviders
Enable the legacy providers. Defaults to
true
.Note: The legacy providers are incomplete and might not work as expected. It is highly recommended to use the stubs instead.
-
Console: Focus Output Window
-hammerspoon.console.focusOutputWindow
Focus the output window when a message is received from Hammerspoon. Defaults to
true
.Tip: I always have
hs.console.clearConsole()
at the top of theinit.lua
since it gets pretty messy understanding where starts what. -
Console: Filter Output
-hammerspoon.console.filterOutput
An array of regex patterns. Useful to filter out the Hammerspoon console output inside VScode.
Example:
{ "hammerspoon.console.filterOutput": [ "➡.+", "ERROR:.+" ] }
Tip: I use the extension Python EasyPrint (which also works on Lua) to quickly print debug statements. The print statement always starts with a Unicode char
➡
, which I can use in the regex filter. -
Network: Port
-hammerspoon.network.port
:number
A port to use for incoming connection when sending message from Hammerspoon. Defaults to
54321
. -
Spoons: Extra Documentation
-hammerspoon.spoon.extraDocumentation
To generate the extra documentation (HTML/Markdown), you need to have access to the Hammerspoon source code repository with its python dependency.
From Hammerspoon official documentation:
- Clone https://github.com/Hamerspoon/hammerspoon
- Install the required Python dependencies (e.g.
pip install --user -r requirements.txt
in the Hammerspoon repo)
With that done, the setting takes two options:
repository-path
: The Hammerspoon source code repository path.interpreter-path
: The Python interpreter path of the Hammerspoon source code repository.
Example:
"hammerspoon.spoons.extraDocumentation": { "repository-path": "/Users/virgil/Developer/SourceCode/hammerspoon", "interpreter-path": "/Users/virgil/Developer/SourceCode/hammerspoon/.venv/bin/python" }
-
Spoons: Path
-hammerspoon.spoons.path
The path where to create the Spoons. Defaults to
~/.hammerspoon/Spoons
. If a custom path is specified, remember to add it to yourinit.lua
.From Hammerspoon official documentation:
Note that
hs.loadSpoon()
uses package.path to find Spoons. Hence you can have it look for Spoons in other paths by adding those paths to package.path as follows:-- Look for Spoons in ~/.hammerspoon/MySpoons as well package.path = package.path .. ";" .. hs.configdir .. "/MySpoons/?.spoon/init.lua"
luaparse for generating the symbol table. EmmyLua for the stubs.