Writing Code is Hard or “I wrote a Ruby gem!”

So, I wrote a Ruby gem. It’s a little inventory app called “stocker” and I built it to fullfill a need I had to keep track of things I regularly use and buy like food items, toiletries and the like. I had two big issues with distributing the gem. First, I apparently didn’t add the dependencies to the gemfile. I didn’t notice because I had them installed on my machines. Secondly, I am using the pathname class instead of IO or File. pathname is a super useful class for manipulating files and whatnot, but while the Pathname#write method worked fine in 2.2, it threw an exception when someone tried running it under 2.0 (the version installed under OS X Mavericks). When I switched Pathname#write to Pathname#open('w') { |t| t << contents } the error went away. I’m not sure if it’s a 2.0 bug or if that method was added in Ruby 2.1, but seeing as I enjoy using Pathname#write, I’m a little worried.

But, changing the method seems to work. I don’t have any documentation written up for the web, but running stocker -h gets you a list of commands to use with the app.


Update (2014-02-20 10:30AM): Apparently, Pathname#write just doesn’t exist in Ruby 2.0. This is unfortunate.

Pretty Print Tables with Thor

When you’re outputting to a terminal in a Thor app, you’ve got two useful formatting methods. One is print_in_columns and the other is print_table. print_table is probably the more useful of the two. print_in_columns is slightly easier to use, because it takes a string instead of an array of arrays like table does, but if you’re going to be outputting more than a single line, table is what you should be using. The tricky thing is that you need to pass an array of arrays to print_table. If you want to further improve the look of your application, Thor comes with a set_color method that you can use to pretty up your text. It’s used like this: set_color(string, :color), where string is the string to be colorized and :color is the a symbol named either blue, red, yellow, cyan, green, magenta, black, or white. There are also :on_red and the like that you can pass into set_color as well for background colors. The catch with using colors in your table is that all elements in your table need to be colored or else the formatting will get thrown off. set_color and print_table make pretty printing very easy in Thor, just remember to color everything, which is why you might find yourself needing :white or :black.

Use MailMate Rules to Easily Create OmniFocus Tasks From Flags

Quickly Turn Flagged Emails into OmniFocus Inbox Items

If you’re a MailMate user and an OmniFocus user, I’ve got a hot tip for you. You can easily flag emails on your iPhone or iPad and have MailMate stick them in your OmniFocus your inbox. Here’s how:

  1. Modify MailMate’s “Add to OmniFocus” script to skip the quick entry tree.

    on run argv
        set theFilename to item 1 of argv
        set theName to do shell script "head -n1 " & theFilename
        set theNote to do shell script "tail -n+2 " & theFilename
    
        tell application "OmniFocus"
            tell default document
                --tell quick entry
                    set theTask to make new inbox task with properties {name:theName, note:theNote}
                    select {theTask}
                    set note of theTask to theNote
                    open
                    --tell application "System Events" to keystroke tab
                --end tell
            end tell
        end tell
    end run

  2. Set up a “Follow-Up” smart mailbox that watches for flagged emails.

  3. Set up rules on your “Follow-Up” mailbox to run your OmniFocus script and then remove the “Flagged” IMAP tag.

  4. Flag email on your iOS devices.

This approach means your flags will never stick around, but if you’re sticking to your “one inbox”, which is OmniFocus, it doesn’t really matter.

On Literate CoffeeScript

One of the coolest CoffeeScript things I’ve run into is Literate CoffeeScript.

name = "Literate CoffeeScript"
console.log "This is an example of #{name}."

It’s almost like I’m writing a Markdown file. I believe other languages have literate versions (Haskell, for one), but this is the first time a language I’ve been using had one. I binged and purged on JavaScript last weekend and it’s what I’ve got on the brain this week. I finished up the second half of Codecademy’s JavaScript tutorial, I did Code School’s two JavaScript “Road-Trip” courses, Code School’s “Try jQuery” course and lastly Code School’s “A Sip of CoffeeScript”. Literate CoffeeScript is just a text file where only indented lines get treated as code. When you run a “.litcoffee” file through the CoffeeScript compiler, it ignores unindented lines and spits out the code from the indented lines. I suppose if you’re into writing code that reads like a story, this could be pretty useful.

Revisiting SmartPerspective

CheckMark

I’ve finally done it! (I think…)

I wrote up a little script called SmartPerspective for OmniFocus that smartly opens up different perspectives depending on whether certain conditions have been met. If tasks in my “Daily” project (all the junk that needs to be done every day), it opens the “Daily” perspective. If that’s clear, it looks for flagged tasks in every context and if any exist, it opens “Flagged”. After that, if any available tasks are left, it opens “Next Actions”. Lastly, if none of these conditions have been met, it opens up the “Someday” perspective and then you can look at stuff that isn’t blocked (by a start date) but isn’t in an active project.

The first version of the script stupidly closed all windows and then created a new document window. This was awkward and slower than just resetting the perspective name property for the document window. Now, if a front document window is visible, it resets the perspective name property. If one isn’t visible, then a new document window is created. This is faster and smarter. Also, this approach finally seems to make using Keyboard Maestro’s application trigger “when OmniFocus activates” open the right perspective every time.

Check out the SmartPerspective Gist.

The Today Card/Journal File

I saw Patrick Rhone’s post about his Today Card and it reminded me that I may have never talked about my journal and accompanying AppleScript to file it in OmniFocus at the end of the day.

I keep a basic plain text journal in Dropbox and I open it up quickly using Keyboard Maestro.

Screen Shot 2013 08 16 at 10 42 41 AM

wkg="$HOME/Dropbox/Documents/Markdown"
journal="$wkg/Journal.md"
touch $journal;open -a "BBEdit" $journal

At the end of the day (I run a Launch Agent every day at 8pm to file my journal) I run this AppleScript to import my journal into OmniFocus.

set the_file to "Users:your_username:Dropbox:Documents:Markdown:Journal.md" as alias

open for access the_file
try
   set the_text to read the_file as «class utf8»
on error
   return "Journal empty."
end try
close access the_file

tell application "OmniFocus"
   tell front document
    make new inbox task with properties {name:"Journal for " & ¬
    date string of (current date), note:the_text, flagged:true}
   end tell
end tell

set eof of the_file to 0

Set the_file to wherever you keep your journal file, and then if the file has text in it, it will create the task in OmniFocus. If there’s no text in the file, it will error out and do nothing. Run this with launchd every day and you have an automatic way to dump your daily journal into your inbox.[1]


  1. I use as «class utf8» in order to properly read and write Japanese characters.  ↩

SmartPerspective for OmniFocus

Screen Shot 2013 08 15 at 3 47 56 PM

I have an order to the tasks I work on. If something’s flagged in OmniFocus, it should be done first. If there aren’t any flagged tasks, then I move on to regular next actions. If there aren’t any next actions, (which is rare) then I move on to “someday” tasks. This AppleScript checks if tasks fit those conditions, and shows you the proper perspective.

Check out SmartPerspective here.

If you want to take it a step further, run SmartPerspective with Keyboard Maestro and have it run anytime OmniFocus activates. If there’s no front window, nothing will happen. If there isn’t a front window, then the proper perspective will open up.

Update: 2013-09-14

I’ve finally done it! (I think…)

I wrote up a little script called SmartPerspective for OmniFocus that smartly opens up different perspectives depending on whether certain conditions have been met. If tasks in my “Daily” project (all the junk that needs to be done every day), it opens the “Daily” perspective. If that’s clear, it looks for flagged tasks in every context and if any exist, it opens “Flagged”. After that, if any available tasks are left, it opens “Next Actions”. Lastly, if none of these conditions have been met, it opens up the “Someday” perspective and then you can look at stuff that isn’t blocked (by a start date) but isn’t in an active project.

The first version of the script stupidly closed all windows and then created a new document window. This was awkward and slower than just resetting the perspective name property for the document window. Now, if a front document window is visible, it resets the perspective name property. If one isn’t visible, then a new document window is created. This is faster and smarter. Also, this approach finally seems to make using Keyboard Maestro’s application trigger “when OmniFocus activates” open the right perspective every time.

Import Moves for iOS Logs to Day One

I’ve been using Moves for iOS to track my movement and I wanted to add the saved images the app can produce to Day One for OS X for journaling purposes.[1] So, if you create a Hazel rule to check if you have one of these images, you can then process them with this AppleScript. This script assumes you created the log the following day (or the moves) and then it uses that created day –1 to create a Day One entry for the day the moves actually happened.

set theFile to choose file

tell application "System Events"
    set old_date to creation date of (info for theFile)
    set new_date to old_date - days * 1
    set processed_date to ((month of new_date as number) & "/" & day of new_date & "/" & year of new_date as text) & " 11:59PM"
end tell


set photo_path to quoted form of POSIX path of theFile

set the_script to "echo \"Moves\"" & "| /usr/local/bin/dayone -d=\"" & processed_date & "\" -p=" & photo_path & " new"

do shell script the_script

When you’re running this as an embedded script in Hazel, just remove the line where you set theFile. Also, you’ll have to manually export the file from Moves. There’s no way to automate that unfortunately.


  1. You will need the Day One CLI.  ↩