Topic “Howto”

Emacs Org-mode: Custom agenda that filters by date AND tag

I started using Org-mode for Emacs a few weeks ago, in an attempt to get a better grip on the endless stream of TODOs, events, notes, and projects that come into my life, both personally and professionally.

So far, it’s been amazing, because it provides a single point to manage data that tends to get split up across multiple applications (Calendars, ToDo list managers, et cetera) and once you get in the habit of logging every new thing that comes across your radar, it’s all right there. Agenda views let you slice and dice all of that data to keep it from becoming overwhelming. Most often I find myself just using a basic 1-day agenda view that shows me all items with the current date, plus any overdue items and any upcoming deadlines. It’s a nice “at a glance” look at my life for the day, and what’s on the horizon for the next couple of weeks.

Sometimes, though, you want to get really specific. There are plenty of interactive commands in Agenda mode to facilitate this purpose, but as I contemplated the day’s chores (Dutifully entered into my org file with the tag :chores:) I decided I wanted to set up a custom agenda command that would do the following:

  • Show items with today’s date
  • Hide all previously scheduled items, and upcoming deadlines
  • Filter by the tag “chores”

I’m still an org-mode newbie and my grasp of EMacs LISP is almost non-existent, so this wound up taking me the better part of a Sunday morning to figure out - but I finally did, and wanted to share my solution with anyone else who may be trying to solve the same problem.

Figuring out how to filter by today only and hide previously scheduled and upcoming deadline items was easy; there are numerous examples floating around. What had me stumped was how to then further filter that list by a tag. I never found a working example of this specific problem, but I was able to sleuth my way to the org-agenda-filter-preset command, which turned out to be the special sauce I needed. org-agenda-filter-preset is mentioned in a footnote on the Org Manual Agenda Commands page, but I totally overlooked it.

You define custom agenda views in your .emacs file - here’s what I set up for my quick list of items dated today (minus previous scheduled, and upcoming deadlines) and tagged “chores”:

(setq org-agenda-custom-commands
      `(("c" agenda "Chores"
     ((org-agenda-ndays 1)
      (org-scheduled-past-days 0)
      (org-deadline-warning-days 0)
      (org-agenda-filter-preset '("+chores"))
      )
     )))

Subversion: Determine the highest revision number in the working copy

This seems to do the trick when run in a terminal from the top level of the working copy:

svn info -R  | grep Revision | sed "s/Revision: //g" | sort -n | tail -1

Updated
Or, you could just use the svnversion command.

Recapture the Cassette Experience (Sort of) with iTunes and AppleScript

I've been using iTunes for over six years now, and I rely pretty heavily on ratings and playcounts to create any number of Smart Playlists, most of which revolve around finding music in a particular genre that is highly rated OR frequently played AND has not been played in a while.

The result is not unlike the mix tapes of favorite music that I used to make for myself, back when I had few enough albums that picking a mere 90 minutes' worth of faves was not a laughable notion.

But having one giant, never-ending Smart Playlist is depressing in some ways; I could start my "unrecent favorites" playlist and never reach the end, thanks to the "Live Updating" feature. The major thing missing from having a massive digital music library is that sense of deliberateness that used to accompany listing to music on physical media. In particular, cassettes and vinyl LP's, which required the listener to get up, flip sides, and resume playing.

For a while now I've been paying homage in the nerdliest possible way to the act of flipping over a humble 45-minute per side mix tape. I started with a smart playlist titled "Unrecent alt/rock Faves", limited it to 45 minutes, and then unchecked the 'Live Updating Box'; after all of the songs play, I edit the playlist, re-check 'Live Updating', click 'OK', then re-edit the playlist and un-check 'Live Updating' again. Kind of a pain, but it does break the music up into nice listenable chunks.

Just now I decided to bite the bullet and hack together an AppleScript that consolidated this silliness into one step, and managed to pull it off. You need two playlists: The aforementioned "Unrecent Alt/Rock Faves" smart playlist (limited to 45 minutes, with the 'Live Updating' option checked) and a new regular playlist called "Unrecent Faves Cassette". As far as I can tell, there's no way to alter the 'Live Updating' attribute of a Smart Playlist via AppleScript, so this method just copies from a Smart Playlist to a static one.

Here's the script:

tell application "iTunes"
	set theSmartPL to playlist "Unrecent Alt/Rock Faves"
	set theDumbPL to playlist "Unrecent Faves Cassette"
	
	delete every track of theDumbPL
	
	set selectedTracks to every track of theSmartPL
	
	repeat with aTrack in selectedTracks
		duplicate aTrack to theDumbPL
	end repeat
	
	reveal theDumbPL
	play theDumbPL
	
end tell

When saved in ~/Library/iTunes/Scripts it shows up in the iTunes Scripts Menu, and when run it wipes out the current contents of 'Unrecent Faves Cassette' playlist, replacing it with the newly updated contents of the 'Unrecent Alt/Rock Faves' playlist. It then selects and plays the Cassette playlist. I can even run the script from Quicksilver! The only thing that would make it better is have the script play a .wav file of a cassette being flipped over before re-starting, but I can't seem find a free one online.

You can download the .scpt file as an attachment, but if you want to name your playlists something else you'll need to open it in Script Editor.app and tweak it yourself.

Handy Script for Installing an instance of PHP4 in CGI Mode

I’m working with some old code that needs to run PHP4… on my desktop machine I was able to throw it into MAMP and just check the PHP4 option, but our dev environment on Dreamhost is PHP5-only… that is to say, you don’t get to choose PHP4 or PHP5 when setting up a new host.

However, the DreamHost wiki has a pretty slick shell script that will download & compile PHP4 as a CGI executable… and with a little tweaking to some of the install paths there’s no reason this shouldn’t work for pretty much any environment:

http://wiki.dreamhost.com/Installing_PHP4

Fixing FireFox 3's Infuriating Location Field Click Behavior

While setting up a shiny new system after my recent hard drive failure, I decided to upgrade to FireFox 3.

Why in the world is the default behavior when single-clicking in the URL field to select the entire thing? A single-click in every graphical browser I’ve used since 1995 places the cursor so you can select or add whatever text you need; just click and start typing. I’ve spent the last two weeks clicking-and-typing out of habit, only to blow away the entire URL. It’s maddening! Instead you have to click once to select everything, then click again, then click a third time before it just puts the cursor where you wanted it in the first place.

Thankfully, while searching for a fix I found this FireFox tips & tricks page which clued me in to the existence of the “browser.urlbar” preference group. I decided to go exploring, and went to the URL about:config.

Putting ‘browser.urlbar’ into the filter field at the top of the huge preference list, I found two key settings:

  • browser.urlbar.clickSelectsAll, which I set to false.
  • browser.urlbar.doubleClickSelectsAll, which I set to true.

Problem solved.

Finally, a Concise Drupal 5.x Form example

When digging around for Drupal Forms API examples make sure you know which version of Drupal the examples you find are for; the differences between 4.x and 5.x are just subtle enough so as to be terribly confusing.

Finally, I found this discussion thread. For a clear, functional example see the second comment down by pwolanin, “Wrong code above, and 2nd point: form_id”. The code works, and the explanation of how the form_id is named is tremendously helpful:

http://drupal.org/node/119117

Syndicate content
Syndicate content

Twitter

Older

Contact

Andy Chase
(978) 297-6402
andychase [at] gmail.com
GPG/PGP Public Key