Here we go again with the automated work logging. I decided I wanted to keep a record of my public Github gists in my log as well, with descriptions and links. I use gists a lot these days and they’re a good indicator of some of the things I’ve been working on outside of my git repositories (which are logged separately).

Gist is a service provided by Github for easily storing and optionally sharing code snippets. All you need is a free Github account, and then there are plenty of tools for integrating it. Create snippets from the command line, create and manage them in Sublime Text 2, work with them in TextMate and more. You can even use them for posting longer notes by writing in Markdown, creating the gist and taking the id over to to have it turned into a fine looking web page.

The script only grabs public gists. It looks at the last 10 and if the most recent is from the last 24 hours, it adds it to the list, moving to the next one until the created stamp is beyond 24 hours.

If recent gists are found, it adds an entry to my GitLogger nvALT note and makes an journal entry in Day One12. Both options can be toggled in the config at the top.

As with GitLogger, this is set up in launchd to run once a day. See the “Scheduling” section of the GitLogger post for details on setting up a launch agent for the script (tip: just use Lingon). Set the user variable at the top to your Github user, turn Day One logging on or off with true or false in the dayone variable, and edit the path in textlog to point to a text file (or false to turn off text logging).

On my own system I’ll likely integrate this into GitLogger and get one unified log entry. I’m keeping them separate as I test the results for a few more days and so that it’s easier to separate them if you just want to log one type. A couple of configuration or command line options would simplify that, though, so if I decide to go that route I’ll post a hybrid script.

#!/usr/bin/env ruby

require 'open-uri'
require 'time'
require 'erb'
require 'rubygems'
require 'json'

user = 'ttscoff'
dayone = true # log to day one? (true or false)
textlog = "~/Dropbox/nvALT2.2/" # set to false to disable

def e_sh(str)
	str.to_s.gsub(/(?=[^a-zA-Z0-9_.\/\-\x7F-\xFF\n])/, '\\').gsub(/\n/, "'\n'").sub(/^$/, "''")

res = open(URI.parse("{user}/gists")).read
json = JSON.parse(res)

now =
yesterday = now - (60 * 60 * 24)

output = ""

json.each {|gist|
	date = Time.parse(gist['created_at'])
	if date > yesterday
		output += "* Created [Gist ##{gist['id']}](#{gist["html_url"]})\n"
		output += "    * #{gist["description"]}\n"

exit if output.strip == ""

if dayone
	uuid = %x{uuidgen}.gsub(/-/,'').strip
	datestamp =
	starred = false

	dayonedir = %x{ls ~/Library/Mobile\\ Documents/|grep dayoneapp}.strip
	dayonepath = "~/Library/Mobile\ Documents/#{dayonedir}/Documents/Journal_dayone/entries/"
	entry = "## Gists for #{now.strftime("%D")}:\n\n#{output}"
	template = <<-XMLTEMPLATE
	<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
	<plist version="1.0">
		<key>Creation Date</key>
		<date><%= datestamp %></date>
		<key>Entry Text</key>
		<string><%= entry %></string>
		<<%= starred %>/>
		<string><%= uuid %></string>

	fh =".doentry"),'w+')
	fh.puts template.result(binding)
	# puts "ENTRY ADDED"
	# puts "------------------------"
	# puts "Time:    " + datestamp
	# puts "UUID:    " + uuid
	# puts "Starred: " + starred.to_s
	# puts "Entry:   " + entrytext
if textlog
	entry = "---\n\n### #{now.strftime('%D')} [gist]:\n\n" + output + "\n\n"
	open(File.expand_path(textlog), 'a') { |f|
		f.puts entry

Technical note: the text entry formatting matches GitLogger’s and makes for easy parsing of entries into an array if you need to. A regex to split at /\n---\n/ and then one to parse the ### (\d{2}\/\d{2}\/\d{4})/ lines into a date object will give you a date-sortable hash to work with. In the gist entries, after the date I added gist to keep it distinct so I can identify them with a modified version of the above regex and separate Gist entries into another array if I need to.

  1. Like most of my Day One scripts recently, this doesn’t depend on the dayone binary that comes with Day One. It builds the XML entry on its own, so you don’t have to worry about it breaking due to Day One being forced to remove the CLI for the App Store. 

  2. Amended note: Day One’s cli will still be available for download on their website, which is really just as easy as symlinking it… plus it will have expanded features like photo import. They have us well covered.