Vortex Race 3 TKL LED Programming for Mac

I decided to switch to my Vortex Race 3 TKL for a more programming-centric job from the Vortex Tab 90M that felt a little better for email and spreadsheets. The Race 3 has Cherry MX Silent Reds vs. the Vortex Tab 90M’s Cherry MX Silent Blacks.

A couple of things that were a little bit difficult to follow were:

  1. How to set up the Race 3 for Mac (it had been used on a Windows PC most recently and never really used on a Mac). This Reddit thread gives some suggestions on how to optimize that.
  2. How to program the LEDs (for just basic effects):

The LED programming was fairly simple once I understood it (see here for a copy of the manual). The cool LED effects when you type are accessible by pressing the Pn key + one of the ‘1’ through ‘5’ keys. ‘4’ and ‘5’ have multiple effects:

Pn + ‘4’ cycles different “display single color LED mode”s which means that the interactive LED effects appear in context with your

  • [no effect?]
  • Interactive mode – keys light up as you type.
  • Flash vortex mode – keys pulse around the keyboard originating from your keystrokes
  • Aurora mode – keys pulse in color around the keyboard originating from your keystrokes

Pn + ‘5’ cycles different “Display full color LED mode”s which means “display on all the keys regardless of context”:

  • [no effect]
  • Full key light mode – just 100% on
  • Breath mode – keyboard pulses
  • Vortex mode – RGBs cycle in different phases with each other.
  • Rain drop mode – random drops of “color” appear on the keys

Pn + X – brightness down for the above effects

Pn + V – brightness up for the above effects

Pn + [< key] and Pn + [> key] are LED speed up and down.

Reviews of M1 Macs for Development

So far, the key interest for me have been the potential drastic improvement in battery life. I’m almost willing to sacrifice a bit of short term productivity to get there. I don’t know that the experiences sound any worse that trying to get my favorite development environments productive on Windows or a non-Debian flavor of Linux:

JetBrains and Xcode-centric perspective (11/23/2020):

Rubyist perspective (11/25/2020):


macOS 11 Big Sur compatibility on Apple Silicon · Issue #7857 · Homebrew/brew · GitHub (closed as of 12/26/2020):


TypeScript/JavaScript/Rust (12/3/2020):


Rails’ DHH’s own experience (12/28/2020):

DriftingRuby tweet:

Lua Script to Start, Unhide, and/or Auto-Arrange

I’m starting to try using HammerSpoon, which is driven by Lua, for automatically arranging my applications depending on application scenarios.

I have 3 screens, including a MacBook Pro at Retina native resolution and a Seiki 4K display. I grabbed the names of the monitors from Display Menu‘s menu bar menu.

I initially made the mistake of looking for “Outlook”, “OneNote”, and “Chrome”, but all three applications require their respective company’s names to be included in the application name.

hs.streamdeck.init(function(connected, sd)
device = hs.streamdeck.getDevice(1)
device.setButtonColor("1", hs.drawing.color.x11.teal)
applications = { "Messages", "iTunes", "Skype for Business", "iTerm2", "Microsoft Outlook", "HipChat", "Microsoft OneNote", "MacVim", "RubyMine", "Firefox" }
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "pageup", function()
for _k, app_name in pairs(applications) do
app = hs.application.find(app_name)
if app then
local lgUltra="LG Ultra HD"
local windowLayout = {
upper right quadrant
{"Slack", nil, lgUltra, hs.geometry.rect(0,0,0.5,0.5), nil, nil},
upper left quadrant
{"Notes", nil, lgUltra, hs.geometry.rect(0.5,0,0.5,0.5), nil, nil},
lower right quadrant
{"Skype for Business", nil, lgUltra, hs.geometry.rect(0.5,0.5,0.5,0.5), nil, nil},
lower left quadrant
{"iTerm2", nil, lgUltra, hs.geometry.rect(0,0.5,0.5,0.5), nil, nil}
local laptopScreen="Color LCD"
local windowLayout = {
{"Microsoft Outlook", nil, laptopScreen, hs.geometry.rect(0.5,0,0.5,0.5), nil, nil},
{"HipChat", nil, laptopScreen, hs.geometry.rect(0.5,0.5,0.5,0.5), nil, nil},
{"Microsoft OneNote", nil, laptopScreen, hs.geometry.rect(0,0.5,0.5,0.5), nil, nil},
{"Notes", nil, laptopScreen, hs.geometry.rect(0,0,0.5,0.5), nil, nil}
local seiki4KScreen="SE39UY04"
local windowLayout = {
{"MacVim", nil, seiki4KScreen, hs.geometry.rect(0,0,0.5,0.5), nil, nil},
{"Emacs", nil, seiki4KScreen, hs.geometry.rect(0.5,0,0.5,0.5), nil, nil},
{"RubyMine-EAP", nil, seiki4KScreen, hs.geometry.rect(0,0.5,0.5,0.5), nil, nil},
{"iTerm2", nil, seiki4KScreen, hs.geometry.rect(0.5,0.5,0.5,0.5), nil, nil}
Convert a lua table into a lua syntactically correct string
function table_to_string(tbl)
local result = "{"
for k, v in pairs(tbl) do
Check the key type (ignore any numerical keys – assume its an array)
if type(k) == "string" then
result = result.."[\""..k.."\"]".."="
Check the value type
if type(v) == "table" then
result = result..table_to_string(v)
elseif type(v) == "boolean" then
result = result..tostring(v)
result = result.."\""..v.."\""
result = result..","
Remove leading commas from the result
if result ~= "" then
result = result:sub(1, result:len()1)
return result.."}"
hs.hotkey.bind({}, "f13", function()
locationTable = hs.location.get()
hs.eventtap.keyStrokes(locationTable["latitude"] .. "," .. locationTable["longitude"])
function move_to_third(r,c)
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local extents = screen:frame()
f.x = extents.x + (extents.w / 3) * c
f.y = extents.y + (extents.h / 3) * r
f.w = extents.w / 3
f.h = extents.h / 3
function move_to_two_third_horz(c)
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local extents = screen:frame()
f.x = extents.x + (extents.w / 3) * c
f.y = extents.y
f.w = extents.w / 3 * 2
f.h = extents.h
function move_to_two_third_vert(r)
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local extents = screen:frame()
f.x = extents.x
f.y = extents.y + (extents.h / 3) * r
f.w = extents.w
f.h = extents.h / 3 * 2
function move_to_four_ninths(r,c)
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local extents = screen:frame()
f.x = extents.x + (extents.w / 3) * c
f.y = extents.y + (extents.h / 3) * r
f.w = extents.w / 3 * 2
f.h = extents.h / 3 * 2
function move_to_fourth(r,c)
local win = hs.window.focusedWindow()
local f = win:frame()
local screen = win:screen()
local extents = screen:frame()
f.x = extents.x + (extents.w / 4) * c
f.y = extents.y + (extents.h / 4) * r
f.w = extents.w / 4
f.h = extents.h / 4
for i=0,15 do
hs.hotkey.bind({"cmd", "alt", "ctrl"}, string.format("%x", i), function()
for i=1,9 do
hs.hotkey.bind({"cmd", "alt", "ctrl"}, "pad"..tostring(i), function()
for i=1,9 do
hs.hotkey.bind({"cmd", "alt", "ctrl", "shift"}, "pad"..tostring(i), function()
if i == 1 then move_to_four_ninths(1,0)
elseif i == 3 then move_to_four_ninths(1,1)
elseif i == 7 then move_to_four_ninths(0,0)
elseif i == 9 then move_to_four_ninths(0,1)
elseif i == 2 then move_to_two_third_vert(1)
elseif i == 4 then move_to_two_third_horz(0)
elseif i == 6 then move_to_two_third_horz(1)
elseif i == 8 then move_to_two_third_vert(0)
TODO Plan:
Create application watcher
currentApp = ""
function applicationWatcher(appName, eventType, appObject)
if(eventType == hs.application.watcher.activated) then
if (appName == "HipChat") then
currentApp = "HipChat"
if (appName == "Google Chrome") then
currentApp = "Chrome"
function alertCurrent()
hs.timer.doEvery(5, alertCurrent)

view raw
hosted with ❤ by GitHub

Excel for Mac Breaks Up Spreadsheets Into Pages

Excel for Mac seems to use “Page Layout” view by default. This can be switched to the more sane Normal view by selecting View -> Normal from the menu.

You can change the default view in Excel -> Preferences -> View -> Preferred view for new sheets.

Still trying to figure out if there is a way to force all document openings to this setting as well.

Trying to Dig a Little More In-Depth With Maven

I’ve been reading Maven: The Definitive Guide (affiliate link) as a Kindle eBook and finally got to the point of trying the first example project. The book had mentioned that maven might be installed on Mac OS X already (due to usage with some versions of XCode). Magically, it’s there:

So far, I like the book’s approach to Maven.  It evangelizes maven as a tool, but puts the purpose of Maven in context, and explains, “Why Maven?” as well as explaining that “Maven or Ant?” is the wrong question.

If you’re looking to download the files to complete the example Maven projects, they’ve moved from the URLs in the Kindle version of the book because Maven: The Definitive Guide has been split into two books, Maven by Example and Maven: The Complete Reference.

All the project examples can still be downloaded from a single zip file from the Maven by Example book. However, the chapter numbers are not the same in the Maven by Example book, and the folders in the examples are named by a chap-{title} convention.

Within the zip file:

  • Chapter 4’s project (Simple Weather Application) (originally at http://www.sonatype.com/book/mvn-examples-1.0.zip or http://www.sonatype.com/book/mvn-examples-1.0.tar.gz) is now available in the zip file under:
    • ch-custom/simple-weather
  • Chapter 5’s project (Simple Web Application)
    • ch-simple-web/simple-webapp



MacBook Pro setup list.

Some things that I’ve set up on my MBP:

  • Terminal Settings
    • ~/.profile
      • Changed prompt
      • Default is ‘h:W u$ ‘ [ Computer-Name: current-directory username$ ]
      • Changed to ‘[w] ‘
      • man bash, find “PROMPTING” for escape codes
  • Editors
    • TextEdit – for simple text files, quick code tweaks
    • XCode [default code editor] – for longer code edit sessions and code viewing
    • macvim – for text file batch editing, power code substitution
  • Programming
  • XCode
  • git for Mac
  • Twitter
  • TweetDeck for Social Media Monitoring
  • Nambu for compact Twitter monitoring with lists
  • Tweetie for Twitter as a stream only
  • Mail
  • Mac Mail 4.2 connected to Exchange server is more useful than Outlook on Windows with Desktop Search or Xobni