All custom code is lua running in hammerspoon, I consider working with lua stimulating and a great distraction from my daily coding languages. EDIT: there's a tomato in there because clicking on it starts a pomodoro timer. Apr 06, 2018 Hammerspoon - A powerful, extensible OS X automation tool. A community-maintained fork of Mjolnir. Kpie - A scripting utility to juggle windows. Lumail - A console-based mail client, with extensive scripting capabilities.
- How To De-install Hammerspoon Mac Catalina
- Hammerspoon Mac
- Hammerspoon Tutorial
- Hammerspoon Github
- Hammerspoon
POST
Hammerspoon’s configuration files are written in Lua, so a basic knowledge of the language is very useful to be an effective user of Hammerspoon. In this 2-part article I will show you the basics of Lua so you can read and write Hammerspoon configuration. Along the way you will discover that Lua is a surprisingly powerful language.
Lua is a scripting language created in 1993, and focused from the beginning in being an embedded language for extending other applications. It is easy to learn and use while having pretty powerful features, and is frequently used in games, but also in many other applications including, of course, Hammerspoon.
The purpose of this section is to give you a quick overview of the Lua features and peculiarities you may find most useful for developing Hammerspoon policies. I assume you are a programmer who knows some other C-like language–if you already know C, Java, Ruby, Python, Perl, Javascript or some similar language, picking up Lua should be pretty easy. Instead of detailing every structure, I will focus on the aspects that are most different or that are most likely to trip you up as you learn it.
Flow control
Lua includes all the common flow-control structures you might expect. Some examples:
How To De-install Hammerspoon Mac Catalina
In this example, in addition to the if statement, you can see in the line that runs
hs.execute
that Lua functions can return multiple values (which is not the same as returning an array, which counts as a single value). Within the function, this is implemented simply by separating the values with commas in the return
statement, like this: return val1, val2
. You can also see in action the following operators:- for equality;
~=
for inequality (in this respect it differs from most C-like languages, which use!=
);..
for string concatenation;and
for the logical AND operation (by extension, you can deduct thator
andnot
are also available).
In this example we see the for statement in its so-called generic form:
This statement loops the variables over the values returned by the expressions, executing the block with each the consecutive value until it becomes
nil
.Strictly speaking,
expression
is executed once and its value must be an iterator function, which returns one new value from the sequence every time it is called, returning nil
at the end.The
for
statement also has a numeric form:This form loops the variable from the first to the last value, incrementing it by the given increment (defaults to 1) at each iteration.
Going back to our example, we can also learn the following:
- The
pairs()
function, which loops over a table. We will learn more about Lua tables below, but they can be used to represent both regular and associative arrays.pairs()
treats thefiles
variable as an associative array, and returns in each iteration a key/value pair of its contents. - The
_
variable, while not special per se, is used by convention in Lua for “throwaway values”. In this case we are not interested in the key in each iteration, just the value, so we assign the key to_
, never to be used again. - Our first glimpse into the Lua string library, and the two ways in which it can be used:
- In
file:sub(-4)
, the colon indicates the object-oriented notation (see “Lua dot-vs-colon method access” below). This invokes thestring.sub()
function, automatically passing thefile
variable as its first argument. This statement is equivalent tostring.sub(file, -4)
. - In
string.match(file, '/')
, we see the function notation used to callstring.match()
. Since thefile
variable is being passed as the first argument, you could rewrite this statement asfile:match('/[.]')
. In practice, I’ve found myself using both notations somewhat exchangeably - feel free to use whichever you find most comfortable.
Dot-vs-colon method access in Lua
You will notice that sometimes, functions contained within a module are called with a dot, and others with a colon. The latter is Lua’s object-method-call notation, and its effect is to pass the object on which the method is being called as an implicit first argument called
self
. This is simply a syntactic shortcut, i.e. the following two are equivalent:Note that in the second statement, we are calling the method using the dot notation, and explicitly passing the object as the first argument. Normally you would use colon notation, but when you need a function pointer, you need to use the dot notation.
Functions
Hammerspoon Mac
Functions are defined using the
function
keyword.In this example we can also see some examples of the Hammerspoon library in action, in particular two extremely powerful libraries:
hs.mouse
for interacting with the mouse pointer, and hs.eventtap
, which allows you to both intercept and generate arbitrary system events, including key pressed and mouse clicks. This function simulates a double click on the current pointer position:- We first get the current position of the mouse pointer using
hs.mouse.getAbsolutePosition
. - We create a new mouse event of type
leftMouseDown
in the obtained coordinates and with the given modifiers. - By convention, most Hammerspoon API methods return the same object on which they operate. This allows us to chain the calls as shown:
setProperty()
is called on thehs.eventtap
object returned bynewMouseEvent
to set its type to a double click, andpost()
is called on the result to issue the event. - Since we are generating system events directly, we also need to take care of generating a “mouse up” event at the end.
Function parameters are always optional, and those not passed will default to
nil
, so you need to do proper validation. In this example, the function can be called as leftDoubleClick()
, without any parameters, which means the modifiers
parameter might have a nil
value. Looking at the documentation for newMouseEvent()
, we see that the parameter is optional, so for this particular function our use is OK.You should try this function to see that it works. Adding it to you
~/.hammerspoon/init.lua
function will make Hammerspoon define it the next time you reload your configuration. You could then try calling it from the console, but the easiest is to bind a hotkey that will generate a double click. For example:Once you reload your config, you can generate a double click by moving the cursor where you want it and pressing Ctrl-⌘-Alt-p. While this is a contrived example, the ability to generate events like this is immensely powerful in automating your system.
By now you have seen that we are using Ctrl-⌘-Alt very frequently in our keybindings. To avoid having to type this every time, and since the modifiers are defined as an array, you can define them as variable. For example, I have the following at the top of my
init.lua
:Then I simply use
hyper
or shift_hyper
in my key binding declarations:Until next time!
In the next installment, we will dive into Lua’s types and data structures. In the meantime, feel free to explore and learn on your own. If you need more information, I can recommend the following resources, which I have found useful:
- The Lua 5.3 Reference Manual, available at the official Lua website.
- The Lua Wiki, a community-maintained wiki with many descriptions, tips, examples and tutorials.
Hammerspoon Tutorial
- Tags:
- Related:
Hammerspoon is a tool for powerful automation of OS X. At its core, it is just a bridge between the operating system and a Lua scripting engine. What gives Hammerspoon its power is a set of extensions that expose specific pieces of system functionality, to the user.
This is very hard to describe succinctly. You can write Lua code that interacts with OS X APIs for applications, windows, mouse pointers, filesystem objects, audio devices, batteries, screens, low-level keyboard/mouse events, clipboards, location services, wifi, and more.
Typically you would write a configuration file in Lua that connects events to actions. You might want to bind a keyboard shortcut to a series of window operations, or an Applescript. You might want to run a series of commands when your wifi interface connects to your home network. You might want to display an alert when your battery drops below a certain percentage. You might want to do something crazy like having iTunes automatically start playing when your Mac detects you are in Paris.
Hammerspoon Github
Hammerspoon
If you want to explore the options Hammerspoon offers, check out the Getting Started Guide and the full API documentation.