An Overview of Ubersicht and Some Fun Widgets.

Oct 6, 2020 · 5 min read

One of my favorite programs for macOS is Ubersicht, which renders custom widgets to the desktop. The widgets available for download can be out-of-this world; some developers have published widgets to track the International Space Station or check the weather on Mars.

I have written more modest widgets, because I think Ubersicht serves best when its output is informative and unobtrusive. Widgets are built with a combination of JavaScript and shell scripting. Essentially, you build a component in React, and Ubersicht positions the JSX to the desktop. The commands can be written in any language, but I practiced shell scripts for these six widgets.

1. The Structure of the JSX component

All widgets share the same JavaScript backbone, so we’ll walk through that first.

Every Ubersicht widget exports four things: command (string), refreshFrequency (number), className (object), and render (function). All operate as one would expect.

The command string can be any valid shell command string. Whether command has any relation to the output of the widget is your decision. You could assign command to an empty string and execute pure JavaScript (like myFunc below).

You could also write a script in a different language, like Ruby or Python, and pass the output (so long as it can be printed to stdout) to the render function.

The value refreshFrequency is, naturally, the rate at which the widgets refresh their outputs. It is measured in milliseconds. Date updates every four seconds, but Forecast updates every hour.

className is an object that holds CSS information for the position and presentation of the widget. (If the output is spread across multiple css selectors, you can ‘import css from ubersicht’ to create more CSS objects. The documentation has more information.) JSX expects these keys to be camelCased, and not kebab-cased like ordinary CSS.

Finally, the function render can be as elaborate as you wish, but its return value should be a <div>. (Ubersicht will present this <div> according to the CSS rules in className).

2. Date
Date is the simplest widget. The date command, which is included in every shell, displays date and the time. With a +, we indicate that we want a user-defined format string. Date interprets letters preceded by a % sign. The many symbols are difficult to memorize, so I consulted a guide.

3. Tray
The Tray widget informs me if two background applications (Flux and KeepingYouAwake) are active. The Tray widget calls a shell script ( instead of executing a command string (like Date). The sequence of commands in, adhere to a pattern that I will repeat. I’ll execute a command that outputs more data than I need. I’ll parse this data and transform it into something more presentable. call pgrep, a built-in shell utility that searches the table of processes and finds a match based on a regular expression pattern. It’s much like using grep, which stands for “globally search for a regular expression and print matching lines” — grep is probably one of the tools I use most often on the command line.

The syntax of shell scripts can feel user-unfriendly or downright hostile. In a test for a conditional, you have to mind the number of square brackets ([ exp ] v. [[ exp ]]). Take care that the inner expression is a space away from the closing brackets!

4. Network and Battery/Volume
The Network widget is more straightforward than Tray. The output of a macOS command (one that took some Googling to find) called airport is ‘piped’ to grep, which extracts the line of data we want. A pipe (|) ‘feeds’ the output of one shell command into the input of a second shell command. Pipes were a big deal when invented in the ’80s. (Brian Kernighan was excited to explain pipes in this ATT video on Unix).

The Battery/Volume, similarly, requires a macOS system command, and this one is called ‘ioreg.’ I can match the lines I want from ioreg with grep, but to further transform the lines, I’ll use sed (stream-editor) to remove extraneous information. Sed can match a regular expression pattern and replace it with a different pattern, and I chose to replace with an empty string.

The third great command line utility is AWK, which is actually its own interpreted language, and it’s a bit, uh, awkward to learn. We’ll use it here to do some arithmetic to display the percentage of charge left in my computer’s battery.

5. Temperature and Forecast
For my Temperature widget, I found that the local college’s meteorological uploads its data to the web every ten minutes. At first I tried analyzing the HTML with JavaScript, but none of the divs of the webpage had friendly CSS selectors. Instead, I found that the measurement I wanted was always on line 86 of the HTML. So, I can pipe the output of wget (which is like fetch() in JavaScript or RestClient for Ruby) to sed and select the 86th line of the output.

I converted the Fahrenheit to Celsius with AWK.

Fun conversion patterns to keep in mind:

004 C approx. 40.0 F
016 C approx. 61.0 F
028 C approx. 82.0 F
40.1 C approx. 104 F

As John Paul Jones once said at the Battle of Flamborough Head, probably, “I have not yet begun to pipe!” required many, many pipes to wrangle the data. Finally, I had to tell AWK to use a comma as a field separator, not a space. This is much like telling Python or JavaScript to split a string on a comma or another delimiter.

Shell scripts are fun, with the right attitude. With this practice, I think I’m ready to start automating more of my workflow.

The Startup

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store