Home Link

Hello, my name is Brett Terpstra, and it’s nice to meet you. Elegant solutions to complex problems. Curious?

Logging with Day One, geek style

Logging with Day One, geek style Tagged:
Jan 16, 2012 (121 days ago)

I have long kept a journal–more precisely, a log–using VoodooPad with the Scratchpad scripts by Ian Beck. It’s been a great system, but after years of usage it’s started to become a bit cumbersome. VoodooPad can handle the load, but running the custom scripts is inconvenient on a document with thousands of pages. In the interest of trying new things (and fiddling away some time this evening), I decided to try switching the system over to Day One.

Day One is a gorgeous app for keeping a personal journal. I discovered it, if I recall correctly, via David Sparks. It has iOS companion apps and iCloud syncing. It also has excellent search capabilities, likes MultiMarkdown and can export my entries to plain text at any time. I like it because it’s good-looking and concise; just what I need, with no feature bloat. Plus, it’s specifically designed to do exactly what I want: keep a timestamped journal of what I’m working on, have accomplished or have just discovered in my digital travels.

Day One already has a quick entry palette in the menubar. It also has a command line interface (/usr/local/bin/dayone)1 which provides some geeky options (try dayone in Terminal) and the flexibility needed to replace my current logging system. You can create entries quickly with either method, but I wanted just a little bit more out of it. I built a quick script which allows a basic syntax for starring entries and defining dates (using natural language) inline in the entry itself. It can be used from the command line, from LaunchBar (or similar) and can be incorporated into just about any scriptable workflow.

The natural language portion of the script is built on the “Chronic” Ruby gem, so running this script as is requires that you have that installed. If you don’t have it available, just run gem install chronic to add the gem. If you run into errors doing that, try sudo gem install chronic and provide your system password. Here’s the script, complete with some explanation in the comments.

#!/usr/bin/ruby
 
# logtodayone.rb
# Brett Terpstra (http://brettterpstra.com)
# Use and modify freely, attribution appreciated
# 
# This script works with the Day One[1] command line utility
# It parses an input string for an exclamation point prefix to mark starred
# and/or a [date string] at the beginning to parse natural language dates
# 
# Requirements:
# Chronic ruby gem
#
# Example usage:
# logtodayone.rb "! This is a starred entry."
# logtodayone.rb "[yesterday 3pm] Something I did yesterday at 3:00PM"
# logtodayone.rb "! [-2 1:30am] A starred entry about something I did two days ago"
 
require 'rubygems'
require 'chronic' # (`gem install chronic`)
 
if ARGV.length > 0
  input = ARGV.join(" ").strip
else
  print "Log entry: "
  input = gets.strip
end
 
# If the input starts with an exclamation point, make it starred
starred = input =~ /^!/ ? "true" : "false"
# remove the bang from the input string
input = input.gsub(/^!\s*/,'')
 
# if there's a [date] specified, parse it
if input =~ /^\[(.*?)\]/
  datestring = $1
  # if the date starts with -X, assume it means X days ago
  if datestring =~ /^\-(\d+)/
    datestring.sub!(/\-(\d+)/,"\\1 days ago ")
  end
  # Replace a single 'y' within the date brackets with "Yesterday" for parsing
  datestring.sub!(/\by\b/,'yesterday')
  # Parse the resulting date string with Chronic
  d = Chronic.parse(datestring, {:context => :past, :ambiguous_time_range => 8})
  d = DateTime.now if d.nil?
else
  # if no [date] specified, make it right now
  d = DateTime.now
end
date = d.strftime("%m/%d/%Y %l:%M%p") # dayone formatted
input = input.gsub(/^\[.*?\]\s*/,'') # remove [date] from input
 
%x{echo "#{input}"|/usr/local/bin/dayone -d="#{date}" -s=#{starred} new}

Some usage tips

You can star an entry by beginning it with an exclamation point. I’m not sure how I’ll use stars yet, but I figured the option was there, so I’d add a syntax for it.

I often end up logging things after the fact but before I forget what I was doing, so it’s important for me to be able to enter an approximate date and time for the sake of organization. Date strings are entered in square brackets at the beginning (or after an exclamation point) of the entry. The natural language accepts basic strings such as “yesterday 3pm” or “noon” and converts them to Day One-compatible dates. It also accepts “-X” operators to specify a number of days ago (I’m assuming I won’t be logging entries in the future). “y” by itself will be converted to “yesterday.” A typical entry for me would look like “[y 11:45pm] working on silly scripts for logging to Day One.” An entry with no exclamation point and no date brackets is just read as a normal entry at the current time.

I’m using generic @tags–a habit carried over from my VoodooPad scratchpad–to make my entries easily searchable by topic or project. Beyond that, I’m just relying on Day One’s built-in chronological organization and full-text search.

The script is all fine and good, but it’s not much use if it’s not convenient to access. Here are a few of the ways I’m making it universally accessible in my workflow.

Bash alias

First things first, lets make it really easy to log entries from the command line. A simple alias in your ~/.bash_profile shortens things up:

alias log="~/scripts/logtodayone.rb"

Now you can make an entry with log "the thing I was just doing".

LaunchBar Action

Given that few of us are always on the command line, it would be nice to access the script easily from other utility apps. I personally use LaunchBar, but you can create similar scripts for Alfred, Quicksilver, etc. If you use LaunchBar, you can just save the three-line script below as Log to Day One.scpt in ~/Library/Application Support/LaunchBar/Actions:

on handle_string(message)
  do shell script "/Users/ttscoff/scripts/logtodayone.rb \"" & message & "\""
end handle_string

Now, just pop up LaunchBar and type ldo or similar to select the action, then type space to get a text field where you can type your log entry. The script syntax applies in full, so start with an exclamation point to star the entry, and use natural language date syntax between square brackets to specify a date, if needed.

Git commit wrapper

I do something similar to this with an nvALT note, so I thought I’d try it with Day One for a while. It’s a basic bash function to copy a note from a git commit into my daily log. It just wraps git -am (commit all, message), so more complex commit commands won’t work. It covers 90% of the commits I’d actually want in my journal, though.

function cdo(){
  msg=$*
  path=$(pwd)
  ~/scripts/logtodayone.rb "@${path##*/} $msg"
  git commit -am "$msg"
}

Update: I made the git wrapper significantly smarter, thanks to a little assist from @nnutter. It basically parses up your git tree for the actual repo name instead of using the directory name you’re currently in.

# experimental wrapper for git to log commits to Day One
# lots of credit to http://nnutter.com/2012/01/git-todo/
function cdo(){
  msg=$*
  GIT_DIR=$(git rev-parse --git-dir)
  if ! (( $? )); then
      GIT_DIR=$(echo "$GIT_DIR" | awk -F/ '{nlast = NF -1;print $nlast}')
      if [ -z "$GIT_DIR" ]; then
                path=$(pwd)
                GIT_DIR=${path##*/}
      fi
            ~/scripts/logtodayone.rb "@$GIT_DIR $msg"
  fi

  git commit -am "$msg"
}

So that’s my fiddling for the evening. Back to doing something more useful (like preparing for my Macworld | iWorld talk with Merlin Mann and David Sparks).


  1. I forgot this originally, but you need to symlink the dayone CLI from the app bundle to your /usr/local/bin directory. As mentioned in the comments, more information can be found in the faq.### The script 

37 Responses to “Logging with Day One, geek style”

  1. ron says:

    Love the script. I was using the CLI via Alfred, but this makes it super easy as an extension.

    I can’t get the Starred entry to function though. Script returns an error that ’”!\” event not found’. I think the regex is fine. Too tired (and engrossed in Alcatraz) to figure it out.

    • Brett says:

      Sounds like the string isn’t being quoted properly. Are you triggering from the command line or via the AppleScript? If you’re on the command line, be sure to put quotes around the argument so that the bang isn’t interpreted as a bash command:

       logtodayone.rb "! This is a starred entry"
      
      • ron says:

        Brett, thanks for pointing me in the right direction. I add “escape spaces” checked in the Alfred extension options. That solved it.

        • Thomas says:

          Ron:

          How did you get it to work with Alfred? Did you just copy Brett’s script into a Script Extension? I have Silent and Action options set, and “Required Parameter” but the script does nothing.

          • Thomas, I was having the same issue so I tested it in the AppleScript editor. It turns out my version of Ruby is in a different location than Brett’s. I changed the shebang in his script to #!/usr/local/bin/ruby and it now works fine.

            Type ‘which ruby’ in your Terminal to see what you should add there.

          • BooneJS says:

            Tom: You should also be able to do “#!/usr/bin/env ruby”. I use env for perl & ruby in Lion.

  2. Neil says:

    For people who may be confused like I was, the command line program is in the app bundle. Full details are at the bottom of the FAQ: http://​dayoneapp​.com/​f​aq/.

    You can try

    ln –s /Applications/Day\ One.app/Contents/MacOS/dayone /usr/local/bin/dayone

    to put it on the path.

  3. BooneJS says:

    Excellent idea, Brett. I’ll end up buying LaunchBar yet; the reasons to own it keep piling up. Until I got Day One, I’d been using OhLife (after seeing it linked on http://​minimalmac​.com) for a while. Your post offered a tip that the dayone command-line tool was going to make it easy to import my OhLife history. I’ve posted the write-up on my tumblr if anyone’s interested in taking a look. Thanks again!

  4. Ronald says:

    I’m wondering how you search for your @tags in Day One. I’ve also always used those to tag my files, but in Day One searching for them somehow doesn’t seem to work properly…

  5. Mark says:

    Thanks Brett. Got it working from LaunchBar which is great. One minor annoyance (since I’m not a unix/ruby geek) is that the time being grabbed in the ruby script when no time is specified is off by 5 hours.

    • Brett says:

      That’s odd. It comes out right for me, but it could be a time zone offset or defaulting to UTC. You might have to use .local to get it right… I’ll play with some code later and see if I can figure that one out.

      • Mark says:

        So, here’s what I’ve tracked down. I put together the following simple ruby script:

        !/usr/bin/ruby

        d = Time.now

        date = d.strftime(“%m/%d/%Y %l:%M%p”)

        puts d puts date

        %x{echo “just some text” | /usr/local/bin/dayone –d=”#{date}” new}

        and run it from terminal. It works fine with “just some text” showing up in Day One with the local time affixed. Thus, I don’t think the issue is in the logtodayone.rb script.

        But, if I enter a message using LaunchBar and the “Log to Day One.scpt” calling logtodayone.rb, the time for the entry shows up with the UTC offset applied.

  6. keizo says:

    I couldn’t work with LounchBar. Maybe I missed a place logtodayone.rb file. Could you tell me where logtodayone.rb file put in? I put it in Scripts folder which I created.

  7. […] Brett Terpstra posted a fantastic little script to leverage Day One’s built-in CLI (command line interface, more information available here) to […]

  8. Dave says:

    Hi Brett,

    I did the same thing with Launchbar last year. I posted the Applescript to handle this on the Objective Development Forums. It depends on the DayOne command line app being copied out to somewhere in your path (or hardcoding in the script) but doesn’t rely on ruby or any externals. Also, it doesn’t bother with funky tagging.

    • Vlahn says:

      I followed this post here from the Macstories article about using this script to post from Alfred — however I can’t for the life of me get it to work. CLI symlink is in place, Chronic is installed, Ruby is installed in the correct place, the script is executable.. no luck.

      • james says:

        same here no luck…

        • james says:

          It’s a problem with my dayone, if I type dayone into terminal I get a permissions error. Even though permissions were even placed at 777 — if someone knows what’s wrong please let me/us know.

          • james says:

            Fixed my problem by archiving the ‘dayone’ CL file then moving that file into the /usr/local/bin/ — no symlink. works now. Two copies of the file on my system but at least it works.

    • Robert says:

      The MacStories tip works just fine, but it is too complex. Just let Alfred directly run the ruby script as a terminal extension with the plain vanilla command

      /Users//scripts/logtodayone.rb {query}

  9. […] of the cool kids are using Day One in some really interesting ways. There’s Brett, who is using it to leave himself a bread-crumb trail of things he works on. Now there’s this great example from Stephen Hargrove on Spirit of Nine […]

  10. Andrew Broman says:

    I’m having trouble getting the LaunchBar Action working with rvm installed. There’s apparently a problem calling rvm’s default ruby from AppleScript. Instead, it calls the system ruby, which doesn’t have the Chronic gem.

    As a workaround, I replaced “do shell script” with ‘tell application “Terminal” to do script’ — This unfortunately calls up Terminal.

    Does anyone know a better solution?

    • Dave says:

      There’s an all-applescript version I posted up there (linked on ObjectiveDevelopment’s forums) which doesn’t require any extra software installing. It depends on how important being able to specify dates and flag entries is to you.

    • Brett says:

      You can install Chronic on all Ruby installs with rvm all gem install chronic, or try using /usr/bin/env ruby in the hashbang and see if it finds the correct version of Ruby in your environment.

      • Andrew Broman says:

        Thanks, Brett. Unfortunately, even with the “/usr/bin/env ruby” hashbang, it still doesn’t find the rvm ruby, instead using the Ruby.framework version. I think this has something to do with how rvm sets up the environment.

        rvm’s way of changing the environment also makes it difficult to install gems for that system ruby installation.

        I’ve seen this problem discussed around the web, but I haven’t seen a solution anywhere.

  11. […] while ago I read on Brett Terpstra Logging with Day One Geek Style (Brett’s blog is great – loads of poweruser tips and scripts all the […]

  12. […] Terpstra has posted a number of very cool things that can be done with the OS X and iOS application DayOne. They were so compelling that I gave in […]

  13. […] Logging with Day One, geek style – Brett Terpstra […]

  14. Makzan says:

    Thanks for the code. In my version, I prefer to use the branch name.

    https://​gist​.github​.com/​1​9​6​3​105

    And here is how my dayone log message looks like: SnakeAndBall @dev_swipe_ctrl : Added control determine to show/hide snake up/right/down/left buttons; Also load alternative level only when control is swipe.

  15. […] Tagebuch zu führen. Genauso wenig protokolliere ich Projekte im Journal-Format oder dokumentiere Job-Logbücher mit […]

  16. For the heck of it, I ported the script to Tcl. This has the advantage of not requiring any external dependencies, and avoiding some of the RVM problems when using with LaunchBar, etc.:

    https://​gist​.github​.com/​2​4​7​5​369

Leave a Reply

Comments may use standard Markdown formatting


Notify me of followup comments via e-mail. You can also subscribe without commenting.

Entries (RSS) and Comments (RSS), or Subscribe by Email