Maintaining (Omni)Focus

After using OmniFocus for several years I have finally settled on a workflow that I’m comfortable with.

It is largely influenced by this article from Learn OmniFocus which emphasizes the following:

“Use due dates to honour your commitments. Just make sure that you’re only using due dates for things that are due.”

From the release of OmniFocus 2 I started using the “Forecast” perspective to “queue up” what I needed to work on for a given day. If I wanted or needed to complete a task for a given day, I’d assign it a respective due date and it shows up in the forecast view for that day. The thing that I didn’t like about this is sometimes the tasks I was viewing there were not due. If they didn’t get done—they just get moved to the next day. This didn’t feel like I was using due dates correctly and honoring the commitments I made to myself. Not to mention that all the due dates were not created equally. For instance: “complete final checklist before tomorrows release” that is on a given day is not equal to “respond to Tommy’s casual email about what he’s been up to.” One is due today, and the other would just be nice to get done.

I have now settled on a workflow suggested like this from Learn OmniFocus:

“If, however, there’s no commitment around having something complete by a specific date, leave the due date blank. If a particular task is important and is something you’d like to get done today, flag the task to make it stand out from your other available tasks. If it’s something that you’d like to get to on Friday, flag it and then defer it to Friday. Once Friday comes along it will become available and the flag will remind you that it’s especially important.”

So I have now moved to leveraging OmniFocus’ “Flagged” perspective as it queue of “what I need to do today.” If I want to work on something next week, or tomorrow, or even this afternoon. Then I flag it and set the appropriate defer time. The task shows up in the flagged perspective after the defer time.

Early Impressions of the Audio Technica AD900x Open-back Headphones

alt

In short: I am now an open-back headphone convert.

After purchasing the Audio Technica ATH-AD900X’s I had a sensation much like the first time I purchased mid-range headphones. It like was hearing music I’ve been listening to for years for the first time. The details and “depth” of the music I could make out was so much greater. After testing the AD900X’s with a variety genres over the last few days including indie rock, post-rock, electronica, and hip-hop here are my initial thoughts:

  • Everything you read online about open-back headphones is true. You can totally here your surroundings. The result feels somewhat like listening to desktop monitors—yet different…
  • The sound is amazing for the price and definitely has a pretty flat frequency response.Though some higher frequencies attenuate more than I’d like. If you like a lot of bass emphasized in your hip-hop or electronica music then look elsewhere.
  • The “clamp” style head band the is a little awkward 1. Not uncomfortable. But definitely takes some getting use to.
  • Based on my experience thus far companies don’t make a mid-range headphone with a decent cable. The AD900X is no exception. The cable had a lot of bad memory the 1st few days and would coil up all over my desk. But it has started to mellow out now.
  • Did I mention the cable is long? 9.8’ in fact (3m). Though this is not unusual for audiophile-ish headphones—it is a little disorienting at 1st. But after a few days I have grown to like it. I am now running my headphone cable under my desk. (Yeah it is that long).
  • I have worn them a few hours on end without long breaks and can report they are comfortable. The weight isn’t surprising for the size and the ear cups have a soft, somewhat breathable material.

If you are in the market for some open-back headphones I highly recommend the ATH-AD900x’s.

  1. Audio Technica calls this 3D Wing Support Housing. Really, AT?

Cutting Page Load Time in Half

I cut the average page load of this site in half. From just over 1 second on down to around 500 milliseconds by my manual testing in Chrome.

After I removed Google Analytics from the site it reminded me about the number of additional resources I was loading over http within each page. I started to then think about just how much a relative performance impact they can have. This then begs the question: did I them?. No. So I decided removed them.

These assets included:

  • Prismjs
    • I like prism for what it does but I don’t need fancy syntax highlighting.
  • An icon font loaded from a CDN
    • I moved to inline SVG’s instead.
  • A Google web font
    • I decided to move to using the system font for where I was using this.
  • Custom CSS
    • I made this inline. Generally you would only want to inline critical CSS. But since the styling for this site is so minimal, I opted to inline everything. The increase to the page size is negligible.

Now this site (on a page that does not contain images or other inline assets) loads entirely from only one request from the server.

The second thing I did to improve performance was compress the resulting pages that are compiled by Jekyll. This was fairly straight forward as I just used a plugin. I haven’t had any issues with this other than needing and manually insert   in a few places where I wanted space in the page.The resulting pages are only slightly smaller. But these small performance wins aggregate into making the page load faster.

The performance on this site wasn’t terrible to begin with. But walking through this was a great reminder that sometimes small things on a site can hugely impact performance. And who doesn’t like a faster website?

I Removed Google Analytics from My Blog

I’ve wrestled a lot in the past about whether I should or should write a blog. But I’ve kept it up for long periods even when I did not write on it because I know that when I do write, it is good for me. Whether it is processing something more personal in a way I can share with others. Or explaining how to do something related to web development. My depth of knowledge on the subject is always increased. So, why don’t I do it more?

One of the big driving reasons behind my discouragement to write more here is not feeling like I have an “audience.” I haven’t checked my Google Analytics stats a lot. But I have checked them often enough to know that the impact isn’t that large. I am okay with that. But I am not okay laboring over whether this site is or isn’t “successful.” So I have decided to remove the tracking altogether. Because ultimately—I blog for me.

Rake it Up (How I Manage My Jekyll Site)

A few years ago I ported this site to Jekyll. It honestly hasn’t changed much since then, but I have been through various interactions of deployment methods. For a little over a year I have used Rake to manage creating new posts and deploying the site. It use to be way more complicated with tasks defined to create drafts and move them to a published state. But I have found it much more productive to keep it as simple as possible and leave my drafted posts elsewhere.

In theory I could use any build tool for this because Rake is just doing executing the Jekyll commands from as any tool would from the command line. As appose to using Jekyll’s API. But at the time it seemed like a good fit. Here is the current status:

_config.yml


#
# == Configuration relevant to deployment
post:
  template: _post.txt
  extension: md
editor: 'mvim -v'
git:
  branch: master
transfer:
  command: rsync
  settings: -avp --delete
  source: _site/
  destination: "username@url.site/www/dir"

Rakefile


#
# == Dependencies
#

require 'rake'
require 'yaml'
require 'fileutils'
require 'rbconfig'

#
# == Configuration
#

# Set "rake watch" as default task
task :default => :watch

#Tag date YYYY-MM-DD HH:MM:SS +/-TTTT
TAG_DATE = Time.now.strftime("%Y-%m-%d-%H-%M")
# Load the configuration file
CONFIG = YAML.load_file("_config.yml")
# Get and parse the date
DATE = Time.now.strftime("%Y-%m-%d")
# Current time
CURRENT_TIME= Time.now.strftime("%Y-%m-%d %H:%M:%S")

#
# == Helper functions
#

# Add title case method to String.
class String
  def titlecase
    downcase.split.map {|w| capitalization_exceptions.include?(w) ? w : w.capitalize}.join(" ").upfirst
  end

  def upfirst
    self[0,1].capitalize + self[1,length-1]
  end

  private
    def capitalization_exceptions
      [
        'of','a','the','and','an','or','nor','but','if','then','else','when','up','at','from','by','on',
        'off','for','in','out','over','to'
      ]
    end
end

# Execute a system command
def execute(command)
  system "#{command}"
end

# Chech the title
def check_title(title)
  if title.nil? or title.empty?
    raise "Please add a title to your file."
  end
end

# Transform the filename and date to a slug
def transform_to_slug(title, extension)
  characters = /("|'|!|\?|:|\s\z)/
  whitespace = /\s/
  "#{title.gsub(characters,"").gsub(whitespace,"-").downcase}.#{extension}"
end


# Save the file with the title in the YAML front matter
def write_file(content, title, directory, filename)
  title = title.titlecase
  content = content.gsub("title:", "title: \"#{title}\"")
  parsed_content = content.gsub("date:", "date: \"#{CURRENT_TIME}\"")
  File.write("#{directory}/#{filename}", parsed_content)
  puts "#{filename} was created in '#{directory}'."
end

# Create the file with the slug and open the default editor
def create_file(directory, filename, content, title, editor)
  if File.exists?("#{directory}/#{filename}")
    raise "The file already exists."
  else
    write_file(content, title, directory, filename)
    if editor && !editor.nil?
      sleep 1
      execute("#{editor} #{directory}/#{filename}")
    end
  end
end

# Allow passing argv to tasks without throwing
# undefined task errors.
def escape_argv(argv)
  # This defines an empty task at runtime for
  # each argv item.
  argv.each { |a| task a.to_sym do ; end }
end

#
# == Tasks
#

# rake post "My Post Title"
desc "Create a post in _posts"
task :post do
  escape_argv(ARGV)
  title = ARGV[1]
  if title.nil? or title.empty?
    raise "Please add a title to your file."
  end
  template = CONFIG["post"]["template"]
  extension = CONFIG["post"]["extension"]
  editor = CONFIG["editor"]
  filename = transform_to_slug("#{DATE}-#{title}", extension)
  content = File.read(template)
  create_file('_posts', filename, content, title, editor)
end

# rake build
desc "Build the site"
task :build do
  execute("bundle exec jekyll build")
end

# rake watch
desc "Serve the site locally and watch for changes"
task :watch do
  execute("bundle exec jekyll serve")
end


# rake deploy "Commit message"
desc "Deploy the site to a remote git repo"
task :deploy do
  escape_argv(ARGV)
  message = ARGV[1]
  branch = CONFIG["git"]["branch"]
  command = CONFIG["transfer"]["command"]
  source = CONFIG["transfer"]["source"]
  destination = CONFIG["transfer"]["destination"]
  settings = CONFIG["transfer"]["settings"]
  if message.nil? or message.empty?
    message = CURRENT_TIME
  end
  if branch.nil? or branch.empty?
    raise "Please add a branch."
  else
    execute("bundle exec jekyll build")
    execute("git add .")
    execute("git tag #{TAG_DATE}")
    execute("git commit -m \"#{CURRENT_TIME}\"")
    execute("git push --follow-tags origin #{branch} && git push --tags")
  end
  if command.nil? or command.empty?
    raise "Please choose a file transfer command."
  else
    Rake::Task[:build].invoke
    execute("rsync #{settings} #{source} #{destination}")
    puts "Your site was transfered."
  end
end

Update: I added a method for automatically adjusting the title case of a new post.