Welcome to the lab.

Modifying Jekyll post data with inline tags

[Tweet : ADN : nvALT]

This post will only be of interest to Jekyll users, but if you want to start creating your own customizations to your Jekyll setup, this will be an easy start.

Jekyll posts include YAML frontmatter at the top of the post. After the default keys (title, date, layout, etc.), you can define any key you want and assign data to it. That data is then available in your template using Liquid output tags (via {{ page.[key] }}). For example, I use a “description” key that—if it’s set in the post—will generate custom <meta> tags in head.html for “description” (and its OpenGraph counterparts) with the key’s value.

Going further, you can also affect the custom page/post data with Liquid tags in the post content. A short custom plugin is all that’s needed to define a custom tag that will set metadata before the template renders.

When a Jekyll finds a {% tag %} it calls render on the plugin that registered that tag. It passes a context object to the plugin which contains the data for the post or page currently being processed (among a lot of other info). The data for the current page is contained within the first element of the context.environments array, and modifications to that data are passed by reference.

Thus, if you wanted to create a block tag called “describe” and use it to surround text which will be lifted into the page.description data for a post, you could use something as simple as:

module Jekyll

  class OGDescriptionTag < Liquid::Block
    def initialize(tag_name, markup, tokens)
      super
    end

    def render(context)
      output = super
      context.environments.first['page']['description'] = output
      output
    end
  end
end

Liquid::Template.register_tag('describe', Jekyll::OGDescriptionTag)

The initialize and render functions are standard and called automatically when the plugin loads and when it runs. The only line in the code above that matters is:

context.environments.first['page']['description'] = output

In the case of this block tag, it’s simply modifying (or adding) the value of description key in the page data hash for the current post. Then it returns the original contents of the tag unmodified. You could also make an inline tag that sets boolean values or processes the tag’s tokens to set anything you want.

With the above plugin saved in your plugins folder, you could use markup like this anywhere in a post to set the description value:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed 
do eiusmod {% describe %}stempor incididunt ut labore et dolore magna 
aliqua.{% enddescribe %} Ut enim ad minim veniam, quis nostrud 
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

This version does no processing or modification of the contents. You could, if desired, do things like HTML escape or truncate the content before setting the variable, but I usually handle that with custom Liquid filters.

What you do with it from there is up to your template, but simple plugins like this offer some interesting customization possibilities. Consider that instead of passing back the original contents, the plugin could modify it or add elements based on its context. As a wild example, you could create a block tag that added HTML wrappers that varied based on its contents, and then assigned a key to the page data to change a body class.

Hopefully that gives you some ideas for your own customizations!

MeisterTask for iOS and Apple Watch

[Tweet : ADN : nvALT]

MeisterTask, which I mentioned recently (also a previous sponsor), just launched the iOS version of their new productivity and project management tool.

The iOS app is a great complement to the web version, but it’s also functional enough to effectively replace it, depending on your workflow and needs. The ability to turn MindMeister mind maps (also on iOS) into agile projects has been especially appealing to me.

There’s Apple Watch support built in to the iOS version, too. Of course. I don’t have an Apple Watch yet, so I can’t tell you much other than that I’m a bit jealous of all of you who have taken the plunge. I do know that it allows you to create, assign, and complete tasks right from your wrist, and has support for predefined messages and voice input for efficient responses. Dick Tracy will be more productive than ever.

Check out the new MeisterTask iOS app free on the iTunes App Store, and sign up for an account at meistertask.com (or use your existing MindMeister account).

Sublime Text tips for Markdown table editing

[Tweet : ADN : nvALT]

I edited a bunch of MultiMarkdown tables in Sublime Text 3 yesterday, and by about halfway through I’d developed a pretty good system. I thought I’d document a couple of tricks for my own future reference, and for anyone else it might help.

Setup

First, you want MarkdownEditing if you’re working in Sublime. It’s the package I built long ago, now cared for by Ali Ayas and Felix Hao, and being actively updated by the community.

Next, you need the Table Editor package. If you edit tables in any of the humane text formats, this is a godsend. It allows you to tab between columns, wrapping to the next row at the end, auto format the entire table every time you finish an edit, and swap, add and delete columns and rows.

Now, with those two packages, editing is almost as simple as just working in a spreadsheet.

Note: Keyboard combinations mentioned in this post are Mac-specific, but available on other platforms with the usual meta key substitutions.

Building tables

To start a table, just lay out the header row:

| Column 1 | Column 2 | Column 3

I’m working in MultiMarkdown, so the next row also needs to be a divider row, which Table Editor makes as simple as a pipe and a dash:

| Column 1 | Column 2 | Column 3
|-

Hitting TAB on the second line will generate:

| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
|          |          |          |

Converting lists

My specific task was to turn a series of bullet lists into columns of a table. I could have written out fancy regex scripts to automate this, but there were enough variances that it was worth figuring out faster ways to do it by hand.

I knew how many lists the table needed to hold, so setting up the header row was easy. I knew how long the longest of the lists would be, so I could add rows of empty cells ahead of time. With Table Editor’s ability to tab through cells, this is handy.

Table Editor has commands for adding rows, but I’ve disabled a few of them because the shortcuts interfere with my normal editing commands (Option-Right, for example). The Control-Shift-Down command to insert a new row above is still active, so once the table skeleton is set up, I can just add the rows with repeated keystrokes.

You can also use some of Sublime’s great editor commands, which also come in handy in the next part. To add a certain number of rows to the end of the table quickly, just select that number of lines, use Command-Shift-L to split the selection into lines, then type a “|” and hit tab. Table Editor will add the missing dividers for the number of columns in the header row.

If you use Vintage mode (the Vim emulation in Sublime) you can make this even faster by just typing the number of rows followed by “j” before doing the multiple selection split (I don’t think Vintage mode handles repeat on “o” and “i” commands).

Method 1

I have three bullet lists (with no nesting) that I want to insert into the table as columns. There are a couple of ways to do this with about the same amount of efficiency.

First, clear out the bullet markers (*,+,-). Either search and replace, or select the lists, split the lines (Command-Shift-L), move to home (Command-left), cursor to after the list marker, and delete to home (Command-Del). If your lists are interspersed with other elements, you can use multiple selections to do them all at once without affecting other parts. Just hold down command and make the block selections with the mouse, then perform the same steps.

First, you can skip the empty column creation and do this:

  1. Select the longest list, or the one for the first column if they’re all the same length
  2. Break the selection into lines
  3. Use Command-Left/Right to add pipes at the beginning and end of every line
  4. Select another list
  5. Break the selection into lines (important)
  6. Copy or cut the second list with the multiple selections
  7. Select the first list and break the selection again
  8. Move the cursor to where the new column is going
  9. Add a pipe as needed if inserting into the middle of the table
  10. Hit Command-V to paste
  11. Hit TAB to reformat the table with the new data

Pasting “broken” selections into multiple cursors is a very handy trick that proves useful in all kinds of situations.

Method 2

Another method is to use the “empty columns” trick above, and then use Ctrl-Shift-Up/Down to create multiple cursors in the necessary number of cells in a column before pasting a list from a broken selection.

This method is more useful when doing more piecemeal editing of cell blocks.

For visual learners

I get nothing out of watching other people do things in videos (I’m a 100% tactile learner), but I’ve found that some people make more sense of a visual presentation than they do from my attempts at textual explanation. Thus:

YouTube Video

Backstory: a tale of sleep deprivation woe

In case you’re curious, the reason I was working on this was because I’d had a sleepless night and decided to take a day off from my usual projects. I was dinking around and decided to fork Justin Blake’s tool for generating LICENSE files in open source projects.

I wanted to add the ability to get a quick summary of each license (licgen info mit). I used Marky to rip the overview page from choosealicense.com to Markdown and then split it up into summary files. Then I wanted to shorten the height of the output for a summary, so I made the “Required/Permitted/Forbidden” lists that Marky had generated into tables like this.

It was at that point that I realized that in my haze I had entirely forgotten that GitHub’s new licenses API does all of this already and went back to bed. My fork is finished and working, but what’s the point?

At least I honed my Markdown table editing process.

OS X shell tricks: speaking in tongues

[Tweet : ADN : nvALT]

Darwin says...

I have an always-on Mac mini that sits in the corner of my office. It toils away running staging servers for media, web development, and home automation. It also runs a lot of scheduled scripts.

I’m happy to have most of those scripts just run silently. Important notifications and errors get sent to my laptop and mobile devices via the Pushbullet API. Some fall in between those levels of severity, though. I have scheduling systems, such as the one that lets me schedule a generate and deploy of my Jekyll blog based on future dates found in posts1. I like to have these quietly announce themselves (with a little bit of status notification), just so I know they’re running if I’m in the office.

I love the say command in OS X for this purpose. For scripting purposes, it’s as simple as say "what you're doing" in a shell or AppleScript. You can customize the script to say something appropriate, and even pass variables to it to make it dynamic. I discovered the -v flag for say a couple of years ago, and it doubles its usefulness in this application.

You can use -v NAME to change the voice of the speech synthesizer to any of the available system voices. This lets me give a different voice to each context, and use a different timbre for different status reports.

You can see all the available voices using say -v ?. Then, in your shell command, just use say -v Zarvox "[text to speak]" to switch. There’s also a useful -r flag, which changes the rate of speech (by words-per-minute). I find that -r 250 provides more fluid speech than the default for short sentences.

Side note: I’ve mentioned it before, but say is pretty smart about things like roman numerals. A few quirks, but try say "Mac OS X" or say "Superbowl XXVII".

There are a bunch of new voices in the recent versions of OS X, mostly an assortment of localized voices geared toward languages other than English. Here’s the full list with localities, and asterisks to indicate recent additions.

While exploring the new voices, I made a quick shell script to test them all at once. You can run it alone for default settings, or pass it a test string and/or a rate setting, e.g. play_all_voices.sh "this is my test string" 250. And here’s the audio output, in case you don’t want to bother:

All OS X voices “How are you?”
  1. By the way, Apple recently (10.10.3) broke the at command I’ve always used for this. I’ll post soon about a solution using Automator, osascript, iCloud, and Calendars.

Web Excursions for April 20, 2015

[Tweet : ADN : nvALT]

A special edition of “Web Excursions” with two more links than usual. That’s the kind of service you can expect from us here at BrettTerpstra.com.

Lightpack — ambient backlight for your displays
Lightpack creates ambient colors around your monitor or TV based on the color averages being displayed. I’ve seen some hacks of the IKEA light strips to do this, but they were beyond my USB programming capabilities. I’m very tempted to go for this ready-to-use-but-still-open-source version…
icefox/git-hooks
Dammit, this is something I’ve been trying to build, but better.

git-hooks lets hooks be installed inside git repositories, users home directory, and globally. When a hook is called by git, git-hooks will check each of these locations for the hooks to run.

DIY: Frozen Treats for Dogs
Our dog Emma loves these, so my wife published the recipe.
By the way, Emma has her own Facebook page and does not care how you feel about dogs having Facebook pages.
Jon Stewart: why I quit The Daily Show
Over the years, Jon Stewart become my most respected news source. I have no shame in admitting that. The Daily Show has been more “fair and balanced” than any other source. It’s sad to see this era of it ending, but you have to admire Stewart for knowing when to fold. The linked article is long, but fun and insightful for Jon Stewart fans.
LaunchDR
I was researching ways to handle scheduled publishing on Jekyll now that Apple’s broken my atrun system, and stumbled on this tool from my old friend Elliott Cable1 for programmatically creating launchd plist files in Ruby.
Apple Watch Vector UI Kit for Keynote and PowerPoint
I’ve personally moved away from Keynote as a prototyping tool, but Keynotopia keeps making me reconsider that.
Sketch Tricks
I’m really getting into Sketch, primarily because of the community surrounding it. This site compiles great tips and tutorials for the vector design app.
  1. whom I met through his incessant and useful bug reports and feature requests for MoodBlast, way back when. He’s what forced me to start learning about proper UI design and intuitive interfaces.

VOX for iOS

[Tweet : ADN : nvALT]

VOX developer Coppertino released VOX for iOS yesterday, and it continues their tradition of amazing and beautiful software. I love VOX for Mac (previous review), and this new iPhone companion is a perfect complement.

With full support for Soundcloud and iTunes, as well as custom VOX playlists, it’s a great central music player. VOX’s ability to play every file format you can imagine means you can use higher quality audio than with other players (or even iTunes). The idea of a “playlist” in VOX has evolved into “Collections,” which allow you to build your playlist from multiple sources. You can pull together your favorite Soundcloud tracks, your own FLAC files, and your iTunes music in one list.

There’s also LOOP, an entirely new way to store your music in the cloud. It’s directly integrated into the VOX players, so music you upload from VOX on your Mac is immediately available on your iPhone, ready to hit the road. The Mac App Store version of VOX hasn’t received this update yet, but the version you can download from Coppertino is ready to go.

I love the gesture support in VOX iOS, and I’ve always wondered why the default iTunes player in iOS doesn’t have it figured out. It’s all simple and intuitive: swipe up and down to open menus, left and right to change tracks, tap to play/pause.

Coppertino has always impressed me with their ability to make beautiful, unconventional interfaces that behave exactly the way you’d expect. Stunning looks with intuitive behavior. Check out VOX iOS on the App Store, and find more info about VOX for Mac at the Coppertino website.

Movie quote lipsum for TextExpander

[Tweet : ADN : nvALT]

I’ve been feeling horrible about my lack of posting recently, so this morning I decided to make something to share. It’s an addition to my Lorem Ipsum set of TextExpander tools. I know, again with the Lipsum.

This one takes a title of a movie (or a comma-separated list of titles) and grabs quotes from the movie(s) by scraping IMDB. It compiles them into paragraphs of 5 or fewer quotes and outputs plain filler text using your lines from your favorite flicks.

If more than one movie is listed, the results will be shuffled together, randomizing the paragraph order, with each paragraph containing quotes from one movie.

Paragraphs have periods appended if needed to complete punctuation. Quotes recognized as lyrics (split with “/” on IMDB) will be output as a Markdown block quote with hard line breaks.

Installation

Head to the te-snippets page and set a prefix. The prefix will be what you type before the shortcut, and is used to distinguish the snippet’s trigger from existing abbreviations. It can be left blank.

You can then copy the URL and use TextExpander’s “Add Group from URL” command, or download the group and add it manually.

I’ve made this one part of its own group for various and sundry reasons. Unlike most of the “Random Lipsum” snippets, it has no dependencies and no setup required, so the separation is more about form than function.

Options

In the fill-in fields you can set the movie title(s) to grab, enable the profanity filters (they default to disabled), and set a maximum number of paragraphs and/or maximum character count.

Profanity filters

Because this filler text might not be just for you, there are two levels of automatic profanity filtering. The regular filter will find a select group of the “worst” words, and leave their first and last characters in place, obscuring the rest with random punctuation characters.

The “strict” filter mode will use an expanded dictionary of bad words, and then completely obscure the full word.

Length parameters

Limit the total length of the output using either paragraph or character counts. Character count has the final say, if it’s any number other than blank or zero it will truncate the entire output to that number of characters. Any output at the end that doesn’t have trailing punctuation will be trimmed back to the end of the previous sentence.

Paragraphs can be of drastically different lengths depending on the length of each quote. The snippet will combine four quotes in a paragraph no matter how long each passage may be. Paragraph limiting simply truncates the total number of 4-sentence blocks.

Shuffling can be disabled in the fill-ins, but I don’t know why you’d ever need to do that.

You can set all of the options using fill-ins when you run it. If you want to create default options, just edit the snippet’s fill-in tags and set what you like. Then you can just hit return when it comes up and use the defaults.

You can also create a file called .loremimdb in your home directory, containing a list of movie titles, one title per line. If the fill-in title field is left blank, this file will be consulted. It will currently grab quotes from every movie listed in the file before shuffling and pulling out the desired number of paragraphs, so keep it short (less than five titles).

So, next time you need some filler text, why not source Hollywood? Go get the Movie Lipsum snippet.