Creatively Technical

Thoughts on photography, electrical engineering, and management

6 notes

Moving from OhLife to Day One

For the past 18 months I’ve been using a service called OhLife. I’ve got it set to email me at 8:00 PM every day, and I have the option to respond to the email from any device with an email client. Lately I’ve been hearing some great things about Day One, and a post by Brett Terpstra struck a chord as I’ve been thinking about moving my work journal from my Levenger Circa Notebook into the searchable digital domain.

Brett’s post exposed me to the dayone command-line tool, and after looking at the exported text from OhLife I figured I could glue the two together with a little bit of perl.

Link: ohlife2dayone.pl @ github.com

Usage

  1. Save this file someplace (~/Downloads, perhaps?)
  2. Open a Terminal in OS X (/Applications/Utilities/Terminal.app)
  3. chmod +x ~/Downloads/ohlife2dayone.pl
  4. cat ~/Downloads/ohlife_YYYYMMDD.txt | ~/Downloads/ohlife2dayone.pl

If you have any questions or problems, please catch me on Twitter!

0 notes

Removing Flash from your Mac

This post from November ‘10 on Daring Fireball lead me to uninstall Flash from my 4 year old Macbook Pro to preserve battery life while browsing the web.

So, whenever I hit a page with Flash content I wish to view, I open that page in Chrome. As soon as I’m done watching it, I quit Chrome, which ensures Flash Player isn’t left running in the background.

Using Chrome’s built-in Flash was a great workaround, but there were 2 behaviors of Safari’s “Open Page With” mechanism I wanted to tweak using AppleScript. First, it opened a new Tab all the time, even if it has to launch Chrome. Of course, when you launch Chrome you’re presented with a blank tab or your homepage, depending on settings. Since I wasn’t running Chrome before, I’m launching it for the sole purpose of viewing this URL and I don’t care about my Chrome homepage. Secondly, since Flash sites usually have a noticeable load time on my laptop, I don’t want Chrome to pop to the front. I let it pop under Safari, letting me continue to browse while Chrome and the Flash website loads.

Finally, I launch this script using Red Sweater’s excellent FastScripts.

tell application "Safari"
    set safariURL to URL of document 1
end tell

if appIsRunning("Google Chrome") then
    tell application "Google Chrome"
        set myTab to make new tab at end of tabs of window 1
        set URL of myTab to safariURL
    end tell
else
tell application "Google Chrome"
    set URL of active tab of window 1 to safariURL
    end tell
end if

on appIsRunning(appName)
    tell application "System Events" to (name of processes) contains appName
end appIsRunning

Enjoy!

4 notes

Banking Automation, OS-X Style

This year, I resolve to …

My big New Year’s resolution placed on January 1, 2009 was to manage my finances better. I’m one of those people who prefers order everywhere, but doesn’t necessarily require it. This resolution was ripe for surviving a few months before dropping. Turns out, I was right.

I surveyed the banking applications for OS X, sampling the demos, before purchasing iBank 3 from IGG Software. I was getting CSV files from my bank for my Checking & Savings, and a QIF file from my VISA card to fill my iBank register. I had already set up the CSV import settings from my demo period, so I was ready to go when I purchased my license.

It worked just fine for a few months, when I just got sick of the manual labor required to download & import files for 3 accounts, categorizing imports, and balancing the checking account. So, I dropped it.

Mint trial

A week ago, after about the 400th lunch discussion with my co-workers about Mint.com, I broke down and gave it a try. Everything was going really well until I tried to add my credit union and ran into a major roadblock: Passfaces. My credit union implemented a popular form of two factor authentication: Passfaces and passwords. Passfaces require to select, in order, the 3 faces that you have memorized, with an apparent advantage of being very difficult to penetrate by hackers. While Mint.com can read in my VISA information via OFX, I’m still relying on CSV to get data out of my CU. Mint.com of course claimed to support my CU, but after tinkering long enough to lock myself out I was unable to continue. I opened a ticket with Quicken and a post on the Mint forums, and came to realize that I was going to be unable to win the day. Mint doesn’t support manual uploads, and I wasn’t going to be able to connect Mint and my CU.

Back to iBank

Because I was back in the banking mood, I fired up iBank, upgraded to version 3.5.6, and started over. What’s new?

  • iBank and my VISA account can automatically communicate via OFX
  • My stock brokerage and retirement plan can communicate via OFX also
  • A real, non-webapp exists: iBank Mobile!
  • My CU doesn’t support OFX, and therefore relies on CSV

So close, but I hate manual steps. To make matters worse, my CU’s CSV lists 11 fields per transaction, and iBank prefers to import 4: Date, Payee, Memo, and Amount. For checks, the Payee is “Check” and the Reference Number is the check number. For EFTs, interesting information was put in fields other than the Reference Number. I needed to conditionally map the CSV fields to iBank’s import fields. iBank lets you setup rules for re-writing Payee (i.e. turn “Gymboree #45624” into “Gymboree”), but I wanted the ability to mix and match fields using regular expressions.

On the plus side, the $5 iBank Mobile app for iPhone lets me better track my Cash Account. I’ve always wondered where my cash goes, and now I can; all while keeping up to date on my monthly budget and other financial status. As an aside: while the App Store is seemingly dominated by $0.99 applications, do not be afraid to pay for something you will use every day. The market will tell you that $5 is expensive, but I’ve already paid $60 for iBank 3 and both will provide value

…and a dash of perl

My entire professional life has seen me operate in front of a Linux terminal, so I’m quite familiar with using perl to manipulate text. Since CSV is nothing more magical than a plain text file, I used a few lines of perl to conditionally translate each line into what I was after. For example, if field 8 is “Check”, I would join fields 8 and 6 to get make a descriptive Payee field of “Check 1234” (Check + Check Number). EFTs and Internet transfers spread their interesting information in different fields altogether. The perl script would take the name of the file to read in as the first command line argument, and it would write out a new CSV file with “.iBank.out.csv” appended to the input file name. I can now open Terminal (Applications > Utilities > Terminal) and execute the perl script, launch iBank, and import the generated file. The process is a lot better, but it still has too many manual steps.

When Apple released OS X 10.4 (“Tiger”), a minimally hyped feature called Automator was introduced. The masses decried the complexity of AppleScript, so Apple provided a GUI to make scripts in a drag-n-drop way. Any app that exports Automator actions can be linked together to create a workflow or service. AppleScript just doesn’t have the abilities that scripting languages like perl, python, and Ruby have, but it’s still the main way to get the most complex interactions with apps.

Automator

In a perfect world, I could create a script that would do the following:

  • Download the CSV files from my credit union
  • Manipulate the CSV files to format the Payee string as I saw fit
  • Tell iBank to import the new CSV files into specific bank accounts (checking, savings)

The first step was to create an Automator Service that receives text files in Finder. This means that every time I right-click (or ⌘-leftclick) in Finder on a text file my “Service” is seen at the bottom. I dragged in “Run Shell Script” from Library > Utilities, and pasted in the following script:

foreach my $arg (@ARGV) {
    unless( -e $arg ) {
        print "File $arg does not exist\n";
        help;
    }

    my $header=1;
    open IFILE, "<$arg" or die $!;
    open OFILE, ">$arg.iBank.out.csv" or die $!;

    print "$arg.iBank.out.csv";

    # Loop through each line of IFILE and re-code the CSV
    while(<IFILE>) {

        # The first line of the input CSV is a header - Skip to the next line
        if($header) {
            $header = 0;
            next;
        }

        #Split CSV into an array of fields indexed [0..N]
        my @line = split(',', $_);

        my $payee = "";
        # iBank expects the following by default:
        # Payee, Date, Memo, Amount
        # Always leave 'memo' blank, since iBank user will input that.

        # Set $payee to whatever desired, depending on other fields
        # Checks
        $payee = "$line7 $line5" if($line7 =~/^"Check"$/);

        # EFTs, Internet Transfers, etc.
        $payee = ...... if(......);

        # Print "Payee, Date, Memo, Amount" to match iBank's default
        print OFILE "$payee,$line1,,$line2\n";
    }

    close IFILE;
    close OFILE;
}

I print the name of the output file, as Automator seems to use STDOUT (standard out) to communicate between Actions. Next, I append a “Run AppleScript” action also found in Library > Utilities. I knew iBank had AppleScript support, and spent the next few hours learning enough AppleScript and iBank interaction to cobble together a script to import the file written out by the last step into iBank.

on run {input, parameters}
    set theImportFileName to input
    set cuList to {"Checking", "Savings"}
    set theAccountName to item 1 of (choose from list cuList with prompt "Choose the account")

    tell application "iBank"
        activate
        open "Users:username:Documents:iBankData.ibank"
        tell last document
            set theAccount to account theAccountName
            set the import file of theAccount to theImportFileName
            set the import file of theAccount to input
            import theAccount
        end tell
    end tell
    return theAccountName

end run

The filename printed out by perl is now the ‘input’ variable in the AppleScript. However, I don’t know which account this file should be importing. I create a list (Checking, Savings) to prompt myself on import. These 2 items exactly match the names of accounts in my iBank document. Finally, I tell iBank to switch to the chosen account name, set the name of the import file, and finally import the file.

It works, and I’m happy. My lone non-automated step is downloading CSV files from my bank, but given the two factor authentication, it’s a step I can deal with.

Closing Thoughts

I’m no stranger to debugging perl scripts, either through print statements or the perl debugger. However, debugging AppleScripts within Automator actions is another story. I was unable to find any ability to step through statements, and any error messages received wouldn’t point to a line number. I was forced to use

 log "value of " & variable

or

log "setting theAccountName..."

to send messages to the Console (Applications > Utilities > Console) to see what lines had been successfully executed so I could better isolate the source of the error. I’m reasonably decent at perl, but I still have to debug the code I write. I know less than nothing about AppleScript, so the lack of debugging capability damages considerably hinders my productivity.