Skip to content

Luarocks and Hammerspoon

Alpha Chen edited this page Sep 23, 2020 · 2 revisions

Using Luarocks with Hammerspoon isn't that difficult, but can pose some challenges, especially when the Lua version included with Hammerspoon changes faster than the default (or even available) version of Lua in Homebrew or MacPorts does.

The most commmon challenges I've observed fall into two categories, each of which will be addressed in the following sections:

The solutions provided are by no means the only ones, but they have worked for me and I hope will work for you as well.

Addressing Paths

LuaRocks can install rocks into various directories, by default your home directory and a globally available location, but possibly more depending upon how it has been configured on your machine (called trees in LuaRocks parlance). The simplest approach I've found to making sure Hammerspoon knows what the paths are for all of the defined trees is to ask luarocks itself:

Add the following somewhere near the top of your Hammerspoon configuration file (usually ~/.hammerspoon/init.lua), before any lines where you try to load any installed rocks with require:

local lVer = _VERSION:match("Lua (.+)$")
-- specify luarocks path yourself if this doesn't find it in the normal places
local luarocks = hs.execute("which luarocks"):gsub("\n", "")
if #luarocks > 0 then
    package.path = package.path .. ";" .. hs.execute(
            luarocks .. " --lua-version " .. lVer .. " path --lr-path"
        ):gsub("\n", "")
    package.cpath = package.cpath .. ";" .. hs.execute(
            luarocks .. " --lua-version " .. lVer .. " path --lr-cpath"
        ):gsub("\n", "")
end

If you're version of luarocks is installed in a common location (e.g. Homebrew uses /usr/local/bin by default) then this code should find it and query for the necessary package.path and package.cpath additions. If this doesn't work for you, you can specify the exact path to luarocks by changing line 3 above to something like: local luarocks = "/usr/local/bin/luarocks".

In the past I've hardcoded the paths in myself, but have moved to this solution because it tracks the version of Lua that Hammerspoon is using and will include additional trees that you may have defined for LuaRocks as well.

Addressing Lua Version Differences

Because I use Homebrew for other things, what follows is based upon a standard installation of Homebrew for lua (version 5.3 as of this writing) and luarocks. If you've installed Homebrew in a non-standard location or are using MacPorts, the paths may differ, but it will hopefully be clear enough to you what changes, if any, you may need to make to the steps outlined here.

If your ports solution already provides Lua 5.4 and it is installed but not used by default, then you can skip to Preparing LuaRocks.

For the rest of us, we have to build the current version of lua ourselves. If you're using Homebrew or MacPorts, and LuaRocks already, you probably have a compiler already installed, but if you don't, you'll need to install one. The easiest way is to install Xcode from the App Store application and then run it at least once so that it can install all of the necessary parts where they need to go. (You can quit it once the About screen appears).

Once that's done, you'll need to download the latest lua source code. Make sure you download the latest version that matches the major version number of Lua that Hammerspoon is running (in the Hammerspoon console, type _VERSION and hit enter). Usually, this will be the latest version available.

For the purposes of this demonstration, I'm going to install everything in my home directory, but adjust as you like to match your preferred arrangement. You also need to decide where you want to install the new version of Lua we're about to compile. I'm going to use ~/customlua in this example, but you can use something else as long as it doesn't interfere with your regular ports solution (e.g. if you use Homebrew's default, don't use /usr/local as this will collide with the version of lua already installed).

Now, open a Terminal window and type:

$ tar -xvf ~/Downloads/lua-5.4.0.tar.gz # adjust for whatever version you downloaded
$ cd lua-5.4.0 # again, adjust version if necessary

You will need to edit Makefile and src/luaconf.h in the directory you are now in... I use vi myself, but any text editor will do.

In Makefile, change the line that reads INSTALL_TOP= /usr/local to INSTALL_TOP= ~/customlua (or whatever path you chose above). As of this writing, this is on line 13, but it should be close even if a subsequent update moves it.

In src/luaconf.h, change the line that reads #define LUA_ROOT "/usr/local/" to #define LUA_ROOT "~/customlua/" (or whatever path you chose above). As of this writing, this is on line 230, but it should be close even if a subsequent update moves it.

Now, back to the Terminal:

$ make macosx
$ make install

This will install the latest version of Lua in ~/customlua. You can test it out by entering ~/customlua/bin/lua in the Terminal command line to verify that it's working.

Preparing LuaRocks

To see if a specific Lua 5.4 config file is required for your luarocks installation (it probably will be, unless you skipped ahead because your package manager already supplies Lua 5.4), type the following in the Terminal:

$ luarocks --lua-version 5.4

... output cut for brevity ...

Configuration:
   Lua version: 5.4

   Configuration files:
      System  : /usr/local/etc/luarocks/config-5.4.lua (not found)
      User    : /Users/<username>/.luarocks/config-5.4.lua (not found)

If either System or User show (ok) then you can skip to Rebuilding Rocks. Otherwise we forge ahead:

In the Terminal application, enter the following:

$ cd
$ mkdir .luarocks # skip if this already exists; if unsure try anyways and ignore any error returned
$ cd .luarocks

In this directory, create a file name config-5.4.lua and enter the following (again, I personally use vi but any text editor will work):

lua_version = "5.4"
lua_interpreter = "lua"
rocks_trees = {
    {
        name = "user",
        root = "/Users/<username>/.luarocks"
    },
}
variables = {
    LUA_DIR = "/Users/<username>/customlua"
}

Unfortunately we have to use full paths here, so instead of ~ put in the path to your home directory (usually /Users/<username>) as appropriate.

The reason we do not define a system tree is so that all rocks will go into ~/.luarocks and still be available when (in my case) Hombrew supports Lua 5.4 and a system config file for version 5.4 appears at /usr/local/etc/luarocks/config-5.4.lua. (Note that when this occurs, you can safely delete ~/customlua. Until then, however, our custom build has to stick around in case we need to build more rocks for use with Hammerspoon in the meantime.)

Save the file and run luarocks --lua-version 5.4 again in the terminal. You should now see (ok) after the User line.

Rebuilding Rocks

Now you need to reinstall the rocks you have previously used... To see a list of the ones you have installed for Lua 5.3, you can enter luarocks list.

For each rock you wish to reinstall for Lua 5.4, issue the following in the Terminal:

$ luarocks --lua-version 5.4 install <rockname>

Rinse and repeat for each rock you need to install and then do a full restart of Hammerspoon (after making the necessary changes to paths or using the example given in Addressing Paths). You can do this by entering hs.relaunch() in the Hammerspoon console, or simply quitting it and relaunching it in your usual manner.


Final Remarks

That should take care of the most common issues I've encountered with LuaRocks and Hammerspoon. If you believe we've missed something, need to address another issue, or need to explain something better, do not hesitate to open an issue at https://github.com/Hammerspoon/hammerspoon/issues.

We are looking into the possibility of including the necessary files for the version of Lua used within Hammerspoon as part of the application itself, and if this should come to pass, this documentation will be updated as appropriate -- this would remove the need for you to install your own custom version of lua when the ports managers lag behind Hammerspoon.