Posts for Tag: osx

Hammerspoon - OSX automation in Lua for the win

For those who don't know, Hammerspoon is a fantastic automation tool for OS X.  It's basically a bridge between the operating system and the Lua scripting language. With its set of extensions (which you can write your own, by the way) you can automate pretty much anything.

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.

Here's the current script i'm using on my development laptop. It currently does the following:

  • Auto reloads whenever i change the configuration script;
  • Sets up a menu bar button so i can control whether my laptop goes to sleep or is continuously awake. If you know the app Caffeine, you know what i'm saying;
  • Monitors my Wifi connection and warns me when i lose connection or connect to a different SSID;
  • Monitors my battery and warns me when i get to 10 and 5%.
  • Work in progress: Monitor and from times to times to check if i have Internet connection.

The great thing about it is its simplicity. Even if you don't know Lua, you'll find it very easy to write simple watchers and callbacks.

Give it a try! :)


-- Auto Reloading when config changes
function reload_config(files)
  -- Kill bat watcher
  if batWatcher then
  -- Kill wifi watcher
  if wifiWatcher then
  -- Kill caffeine
  if caffeine then
  -- Reload config
end"HOME") .. "/.hammerspoon/", reload_config):start()"Config reloaded")

-- Keep display on or allow going to sleep
local caffeine =
function setCaffeineDisplay(state)
    if state then
function caffeineClicked()
if caffeine then

-- Network connection and disconnection
local wifiWatcher = nil
function ssidChangedCallback()
    newSSID = hs.wifi.currentNetwork()
    if newSSID then"Network connected: " .. newSSID)
    else"Network lost :(")
wifiWatcher =

-- Battery Low warnings
local batWatcher = nil
local lastBatVal = hs.battery.percentage()
function batPercentageChangedCallback()
  currentPercent = hs.battery.percentage()
  if currentPercent == 10 and lastBatVal > 10 then"Getting low on juice...")
  if currentPercent == 5 and lastBatVal > 5 then"Captain, she can't take any more!")
  lastBatVal = currentPercent
batWatcher =

--status, data, headers = hs.http.get("")

"Call piped shell commands from Objective-C"

If you happen to want to know how to run - say - the following command from inside an Objective-C application:

echo "something something" | multimarkdown

So that the fantastic [MultiMarkdown]( runs its magic and transforms **something something** into **\something something\**, then you need to do as below:

- (NSString*) convertMD:(NSString *)data {

// Task for echo NSTask *echoTask = [[NSTask alloc] init]; [echoTask setLaunchPath: @"/bin/echo"]; // Tell which command we are running [echoTask setArguments: [NSArray arrayWithObjects:data, nil]];

// Task for multimarkdown NSTask *mdTask = [[NSTask alloc] init]; // Make a new task [mdTask setLaunchPath: @"/usr/local/bin/multimarkdown"]; // Tell which command we are running [mdTask setArguments: [NSArray arrayWithObjects:@"--snippet", nil]];

// Pipes for input and output NSPipe *pipeBetween = [NSPipe pipe]; // Handles getting the result of echo and injecting into md NSPipe *outPipe = [NSPipe pipe]; // Handles getting the result of md

// Rig it together [echoTask setStandardOutput:pipeBetween]; [mdTask setStandardInput:pipeBetween]; [mdTask setStandardOutput:outPipe];

// Execute [echoTask launch]; [mdTask launch];

// And get the result data NSData *result = [[outPipe fileHandleForReading] readDataToEndOfFile];

return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; }

A couple of notes here:

- What this does is pipe the result of the echoTask (which will run **echo "\"**) as input (standard) to the mdTask, which will run **multimarkdown --snippet**; - The outPipe will simply take the output of the mdTask so we can return what multimarkdown created; - The commands need the full path in order for the tasks to run; - In case you are curious, i'm creating a markdown editor for OSX with realtime preview inline; - If you want to test this particular piece of code as-is, make sure you [install multimarkdown for OSX first](


'Error compiling pg Ruby gem on OSX'

If you get this error (or similar) while trying to run **bundle install** on one of your Ruby projects or trying to install the **pg** gem:

Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

/Users/void/.rvm/rubies/ruby-2.0.0-p0/bin/ruby extconf.rb --with-iconv-include=/usr/local/opt/libiconv/include --with-iconv-lib=/usr/local/opt/libiconv/lib checking for pg_config... no No pg_config... trying anyway. If building fails, please try again with --with-pg-config=/path/to/pg_config checking for libpq-fe.h... no Can't find the 'libpq-fe.h header *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options.

The solution is to install the gem like this:

sudo env ARCHFLAGS="-arch i386" gem install pg -- --with-pg-include=/Library/PostgreSQL/8.4/include/ --with-pg-lib=/Library/PostgreSQL/8.4/lib/

**Note:** Replace 8.4 with your installed PostgreSQL version in the above command.