August 2008

Weekly review – week ending Aug 1-ish

August 2, 2008 - Categories: weekly

This week was about mornings. I successfully switched over to an early-morning schedule, waking up at around 6 in order to write. I found that writing was much easier and more enjoyable in the morning, with lots of energy and a fresh mind, and I also appreciated the incidental benefits of being able to have a leisurely breakfast and a non-stressed start to my day. (W-‘s gratitude for early-morning coffee was a nice bonus!)

This early-morning schedule meant that I found myself getting sleepy at 9, though, and I was often in bed by 10. W- expressed some concern that we might end up leading separate lives, so we’ll figure out how to balance that. We could either figure out how to make the most of a late schedule, shift to an early schedule, or make sure we have enough quality time together. If you’re in a wonderful relationship with someone with a different circadian rhythm, how do you make the most of it?

(I’d definitely like to keep my early-morning writing, though. I liked the feeling of that more than I like afternoon or evening writing…)

Result: Lots of Emacs blog posts this week, as I set up my Emacs development environment for PHP!

In other news, the Drupal project I’ve been working on is now live on the production server. Hooray! The project manager asked us last week to estimate how much time it would take to move the system from the quality assurance server to the production server. I plucked a number out of the air based on how long it took to move to the QA server: one hour? My teammate adjusted my estimate to account for finicky things: three hours? The project manager laughed and told us that we had a week to do it. I took care of it yesterday, and it took me almost exactly an hour (including DNS changes). I’ll check later if any bugs have come up.

I was also happy with some of the infrastructure I built and the tests I added at work. Kaizen! Experience++!

Other parts of my life:

  • I’ve achieved the savings target for my gadget fund, which means I _could_ go out and get a Lenovo Thinkpad X61 tablet PC if I _really_ wanted to. I don’t have a compelling need for it, though. I’d like to use it to draw and mindmap, but there are plenty of things to keep me busy in the meantime, so I won’t touch the gadget fund until I know that it’ll give me a lot of extra value.
  • I’m saving up some of my play money so that I can experiment with delegating chores and swapping money for time. I don’t have a good sense yet of whether that’s an efficient long-term tradeoff, but it’s worth exploring. Personal assistant agencies in Toronto tend to charge about $25 / hour.
  • Yoga classes have been cancelled for August, so it’s just going to be krav maga. I’ll continue to do yoga at home.

I’m planning to install Ubuntu today. I need to borrow W-‘s CD drive, as mine seems to be somewhat broken. I’d like to get everything set up over the long weekend.

My goals for next week are:

  • Work out a better schedule with W- so that we have time to keep developing in-jokes and enjoying each other’s company
  • Keep the production server running; begin development on phase 2?
  • Cook beef stroganoff for the first time
  • Get ready for our trip to the Philippines – yay!

Switching to Ubuntu

August 3, 2008 - Categories: linux

Switching my laptop to Ubuntu took much less time and effort than I thought it would take. I couldn’t resize my existing partitions, so I formatted my data partition and made my swap partition smaller. This gave me about 6.5GB of space for the base Ubuntu system. My /home directory was already on a separate partition, and the other partitions had my installations of Microsoft Windows and Redhat Enterprise Linux.

Reusing my /home partition made it really easy to get up and running. I’ve also symlinked a few shared directories such as /usr/src and /usr/local. End result: a system that’s pretty much like my RHEL system, but much more current.


Year in review: Life as a 24-year-old

August 3, 2008 - Categories: life, yearly

I’m turning 25 in a little over a week. Birthdays are a terrific opportunity to look backward and look forward–what I’ve done, how I’ve grown, and what I want to do or be next. I’ll be celebrating my birthday in the Philippines, among family and my oldest friends. But I’d also like to celebrate my birthday with you, as through my blog, you’ve shared my journey too.

The blog makes it easy to review the year. So, how am I different from the person I was in August 2007?

There were three major changes in my life, all related to each other.

The first is my relationship with W-, which began in March 2008 and is now such a core part of my life. I can’t say enough good things about it without sounding like a Hallmark card.

The second major change is the transition from the academe to the industry: I finished my master’s degree and joined IBM Canada as a technology evangelist and application developer.

The third major change followed naturally from the first two: instead of going home to the Philippines, I’ll be in Canada for a while. Because of W-, I chose not to return to the Philippines after the completion of my studies, and because of my work, I had the means to support myself here. This change was the most challenging, but I’m sure it will work out somehow.

Along the way, I learned how to sketch, cook, defend myself, do yoga, drive in winter, make it across the monkey bars, go on the static and flying trapezes, grow a herb garden, script virtual worlds, manage my retirement investments, survive the conference circuit, dictate to the computer, inspire my colleagues, share thoughts about my generation, develop with Drupal, and connect with amazing people.

I’ve grown as a person. I’ve learned a lot about love. I’ve learned a lot about fighting for what I feel and building bridges after the storms. I’ve learned about the wonder and delight one can feel in ordinary things. I’ve learned about the kind of person I can be.

I’ve grown as a writer, speaker, and developer. I’ve learned about how writing fits into my life. I’ve learned about my personal style of presenting (interactive, enthusiastic, practical). I’ve learned about configuration management, testing, and all sorts of tweaks to make my development environment a better fit for me. I’ve shared what I’ve learned along the way.

What will the next year be like?

I’m looking forward to deepening my relationship with W- and seeing what another year of shared experiences will bring us. I’d like to get better at connecting with friends and family. I hope to get an even clearer idea of how I can contribute professionally, and to do so. I’d like to explore other ways to work and live more fully.

Here are some of my measurable goals for the next year. By August 2009, I’d like to be able to look back and say that I’ve:

  • completed a book on Emacs (whether published by No Starch Press or self-published)
  • increased my reach and responsibilities at and outside work
  • completed my paperwork for the permanent residency application (Canadian experience class?)
  • continued to donate 10% of my income
  • continued to save at least 50% of my income
  • developed another income source aside from salary, interest, and index growth
  • learned how to cook at least 20 new recipes

Join me as I figure more things out! =)

Emacs: Caps lock as M-x

August 4, 2008 - Categories: emacs

Inspired by Lennart Borgman’s recent post on help.gnu.emacs about binding Caps Lock to M-x on Microsoft Windows, I set my system up with the Linux equivalent.

To make Caps Lock a shortcut for M-x, add the following lines to your ~/.emacs:

(if (eq window-system 'x)
    (shell-command "xmodmap -e 'clear Lock' -e 'keycode 66 = F13'"))
(global-set-key [f13] 'execute-extended-command) Replacing dingbats

August 4, 2008 - Categories: geek

I _really_ should have blogged this when I first wrote it. That would’ve saved me time writing it again!

Sub ReplaceDingbats(optional doc)
	oDocument = IIf(IsMissing(doc), ThisComponent, doc)
	oSearchDesc = oDocument.createSearchDescriptor	
	for i = 1 to 9 
		oSearchDesc.searchString = "(;; )?\(" + i + "\)"
		oSearchDesc.searchRegularExpression = true
		mFound = oDocument.findFirst(oSearchDesc)
		do while not isNull(mFound)
			mFound.string = chr(&HF08B + i)
			mFound.CharFontName = "Wingdings"
			mFound = oDocument.findNext(mFound.End, oSearchDesc)
	next i
End Sub

It’s a macro for – replaces the widgets I use in formatting the book chapter…

Emacs and Gnus: zomg, new chapter out the door!

August 4, 2008 - Categories: emacs, wickedcoolemacs

So I _finally_ pulled everything together and got my Gnus chapter out the door. Hooray, hooray, hooray!

Disclaimers: It’s rough, it probably makes a few assumptions about whatever version of Emacs I’m running, it’s probably missing your favorite tips (and I’d love to add them!), and it probably has typos. Meep. But it’s out there!

Hooray, hooray, hooray!

Next step: write about web-browsing in Emacs…

Finding something worth talking about

August 4, 2008 - Categories: presentation, speaking

"I don’t know what I’d talk about," people often tell me when I encourage them to think of topics for conferences and events. "I don’t know what to write about," they say when I encourage them to blog. "I’m not an expert. I don’t know anything."

I get that imposter feeling as much as anyone else. I wonder what I know and why people are interested. I worry that the next presentation, the next article is when I’ll be unmasked as just another newbie. Sometimes I think that my enthusiasm is the main reason why people listen, because they already know everything I’m saying. I hate wasting time by not adding anything new.

You might recognize these things as reasons that stop you from standing up and speaking. Before you can think of improving your presentation skills or even becoming comfortable in front of the crowd, you need to find your _why_–your reason to speak, something worth talking about.

I struggle with this every time I see a call for participation or come across a conference I want to attend. These questions are helpful:

  • Who will be at the event, and who do I want to get into my session? This gives me an idea of the audience.
  • What do they care about that I also care about? If I can’t find something that I’m passionate about and the audience is probably interested in, then it’s not worth presenting. I’d like to avoid presenting on things I don’t particularly care about, and no one’s going to listen if I’m passionate about something and I can’t show people what’s in it for them. If I can find something we all care about, though, then it’s easy to go forward.
  • How can I help them? What can I do to save them time or help them work more effectively? If I spent a lot of time learning about something, I can save lots of people time by summarizing what I’ve learned, pointing out good ways to do things, and helping people avoid the pitfalls.
  • What do I want to learn more about? Teaching helps me learn something new or deepen my knowledge of something I’ve learned. Every presentation should stretch me at least a little, even if it covers similar ground as a previous presentation. Each presentation is a good excuse to learn. I’ll often submit stretch presentations where I know maybe half of the material, and this helps me learn even more in the process of preparing the presentation.

The next time an opportunity to share comes up–a call for participation, an educational community meeting–ask yourself:

  • Who will be at the event?
  • What do they care about that you also care about?
  • How can you help them?
  • What do you want to learn more about?

Chances are that you’ll find something you want to share. Good luck and have fun!

Drupal shell: quickly evaluating PHP statements in a Drupal context

August 5, 2008 - Categories: drupal

I often find myself needing to variable_set something temporarily, just to try things out. The drush module provides a command-line interface that solves this problem with a little more hacking. To minimize the effect on my source tree, I’ve unpacked it into the sites directory for my local installation and enabled it in my test database. After I enabled the main drush module and the related modules, I tweaked drush_tools to include an insecure-but-useful eval command. Here it is:

--- sites/    2008-08-05 17:18:48.000000000 -0400
+++ sites/    2008-08-05 17:18:55.000000000 -0400
@@ -46,6 +46,10 @@
     'callback' => 'drush_tools_sync',
     'description' => 'Rsync the Drupal tree to/from another server using ssh'
+  $items['eval'] = array(
+    'callback' => 'drush_tools_eval',
+    'description' => 'Evaluate a command',
+  );
   return $items;
@@ -156,3 +160,6 @@
+function drush_tools_eval($command) {
+  eval($command);

I also added an alias to my ~/.bashrc along the lines of:

alias drush='php ~/drupal/sites/ -r ~/drupal -l'

where ~/drupal is my multisite Drupal directory root.

After I loaded the alias with “source ~/.bashrc”, I can now execute PHP statements in my Drupal context with commands like:

drush eval "variable_set('hello', 'world');"

Good stuff!

Drupal, Emacs, and templates: Module update functions

August 6, 2008 - Categories: drupal, emacs

Drupal’s coding conventions make it easier to hook into system behavior, but they also result in a lot of repetitive typing. For example, you can run code when upgrading a module by putting the code in a function named modulename_update_N() in your module’s install file. I found myself scrolling up and copy-pasting stuff too many times, so I decided to automate it instead.

I’ve been using yasnippet for my Emacs templates. All I needed to do to automate that little update bit was to write some code that figured out what the next update number should be. Here’s the snippet file I’ve just added (~/elisp/snippets/php-mode/drupal-mode/_update):

function `(sacha/drupal-module-name)`_update_`(sacha/drupal-module-update-number)`() {
  $ret = array();
  $ret[] = array(
    'success' => true,
    'query' => '$1',
  return $ret;

The relevant functions from my ~/.emacs:

(defun sacha/drupal-module-update-number ()
  "Return the number of the next module update function.
This is one more than the highest number used so far.
This function should be called in a module's .install file."
      (goto-char (point-min))
      (let ((module-name (sacha/drupal-module-name))
	    (max 0))
	(while (re-search-forward
		(concat "function[ \t\n]+" module-name "_update_\\([0-9]+\\)") nil t)
	  (setq max (max (string-to-number (match-string 1)) max)))
	(number-to-string (1+ max))))))

(defun sacha/drupal-module-name ()
  "Return the Drupal module name for .module and .install files."
  (file-name-sans-extension (file-name-nondirectory (buffer-file-name))))

I can’t think of how I’d do that in Eclipse. =) Don’t get me wrong–I still like Eclipse–but I heart being able to hack my editor on the fly.

Lifehacking: Switching to a rolling laptop bag

August 6, 2008 - Categories: life

I’ve been paying attention to the preventive advice I picked up during my last session with a registered massage therapist, and I thought I’d post an update on how things are going with this life-hacking.

  • I switched to flat shoes. When the massage therapist mentioned that high-heeled shoes could be the reason why some of my muscles were tense, I said I’d switch to flat shoes. This was apparently not the way most women react. They’re more likely to say, “Sure, when they make flat shoes that aren’t ugly.” Well, I found two pairs of shoes that look presentable enough for the office. =)

    It turns out that you really do need to walk a mile in your own shoes before they’re broken-in enough to be comfortable. Both of my new pairs of flat shoes are now comfy enough for extended walks. The fancy insoles I picked up to add arch support threw me off balance and induced enough pain to make me hobble, so I got rid of the insoles. Now I just use plain liners to keep the shoes relatively clean.

  • I switched to crossing my legs at the ankles, not at the knees. Sometime after grade school, I picked up the habit of crossing my legs at the knees. I suppose it was because practically everyone else I saw did it. Probably not good for my back muscles and circulation in the long run. Stopping this behavior took a little conscious thought for a couple of days, and then it felt natural not to do it any more. Now I just cross at the ankles if I want to, all proper-like.
  • I switched to a rolling laptop case instead of a backpack. Yes, it’s a bit of a challenge getting a bulky rolling laptop case through the wickets or up and down stairs, but my shoulders think it’s a good trade-off.

There’s only one thing I’m having a hard time doing: leaning back. The massage therapist said that some of my back and neck muscles are tenser than they need to be because I lean forward instead of using the chair back. I’m not used to the idea of leaning back against the chair. It feels casual, and it sometimes means that I’m not in quite the right position to type.


Making things tangible: agile bug-tracking with LEGO!

August 6, 2008 - Categories: geek

What a creative way to make things concrete… <laugh>

Do what works for you; It’s not about being Gen Y, it’s about being new

August 6, 2008 - Categories: geek, learning, life

Luis Suarez has just realized that being a Web 2.0 evangelist doesn’t mean getting into every new Web 2.0 tool, and he linked to Chris Brogan’s post on doing what works for you.

This reminds me of a point I’ve been wanting to think about for a while. =)

When people look at the way new generations or new hires immerse themselves in learning, they often think that they themselves could never do that, could never find the time to try out and learn all these different things.

If you’ve ever told yourself that or heard someone say that, I’d like to help you remember what it was like to be on the other side of the fence, and I’d like to remind my future self what it’s like to be here.

Yes, being new means I have no bad habits to unlearn. That’s part of it. But it’s also true that I don’t have as many good habits as you do, or even “good enough” habits that can get me through. That’s one of the things that drives me to go out there and experiment. Because I don’t have a “good” way of dealing with so many things, I need to try lots of different ways and see which ways work for me.

In other areas, where I’ve found things that work for me, I stick with them and get deeper and deeper into them. Someday, my mind might have been so shaped by the tools I’ve used that I won’t see any need or potential beyond them, and it might be someone else’s turn to explore even further.

I think that the trick, then, is to keep “breaking” things, keep stepping out of my comfort zone, so that I always feel the urge to learn something. For example, even though I’ve used Emacs for years, I’m always pushing it to do something new, and I’m always tinkering with other editors and other systems to see if I can steal any good ideas.

Helping other people also stops me from becoming complacent, becoming too comfortable with my current toolkit. When I’m helping people brainstorm, answering their questions, customizing systems to fit their needs, I learn more about them, the system, and myself. I learn in the process of teaching.

I’m not going to adopt every single thing that comes along, especially when I’ve already got something that works out quite well. (Look at how old my text editor is!) That’s okay. That kind of exploration will naturally fit other people. What I can do, though, is:

  • expand the breadth and depth of my tools so that I’m not just replacing interchangeable parts, but exploring new territory
  • keep exploring the depths and the interconnections between different tools
  • help people with as many tools as I can, especially if that takes me outside my toolkit
  • borrow ideas from other tools

That’s how I plan to mix being both new and experienced. =)

How do you keep yourself new?

Deploying to servers

August 8, 2008 - Categories: development, kaizen

I’m heading to the Philippines tomorrow, and to make life easer for the two other Windows-based PHP developers on my team, I updated the web-based deployment script I mentioned in
Development kaizen: deployment and testing. I added the ability to push a specified revision to the production server. It took me less time than I thought it would (I love it when things Just Work!), so I decided to spend time documenting it just in case I ever need to do it again (almost certainly) or just in case it breaks while I’m away (hope not).

Behind the scenes, there are a number of moving parts:

  • Key-based authentication. Because I need to copy files and run commands on the production and QA servers non-interactively, I needed to set up key-based authentication using SSH. I’m somewhat nervous about using a passphrase-less key, but I couldn’t see a way to work around this.
  • Rsync. I use rsync over ssh to transfer files to the remote system. It’s good at efficiently transferring changed files. I couldn’t use –delete to get rid of old files, though, as our source tree does not include the complete system.
  • A shell script with the suid bit. The shell script is responsible for exporting the requested revision to a temporary directory, rsyncing it over to the selected host, and running a few commands on the server in order to reset file permissions and clear the cache. The suid bit is there so that it takes my identity and uses the key that I set up. I resorted to suid because I couldn’t figure out how to make sure that Apache had its own key. I tried associating it with the user that Apache ran as, but I kept running into “no tty”-type errors. The suid workaround solved the problem quickly.
  • A PHP script that displays a form and the last 20 revisions. The form includes a drop-down box of the revisions displayed, a button for deploying to QA, and a button for deploying to the server. When submitted, the script does some error-checking, then uses system to call the relevant shell script. The script determines the list of revisions by using shell_exec to store the output of svn log … -limit 20 in a string, then using preg_match_all to match all instances of /r([0-9]+)/. Seems to work.

Drupal 5: Migrating a production database to a QA server

August 8, 2008 - Categories: development, drupal

Building on the configuration management strategy I described last time, I wrote some scripts to make it easier for other developers to migrate the production database to the QA server or to get a copy of the production database for their local system. I needed to consider the following factors:

  • Domain name changes: Because we use Domain Access to serve multiple subdomains using a single Drupal installation and shared sign-on, we needed to make sure that all instances of the domain root are replaced and the correct domain_root is set. For example, the site URLs might be:
    Production QA Local
  • Privacy concerns: The QA database and local copies of the database should not contain sensitive user information. All users aside from the administrator should be removed from the system, and all content on site should be limited to editorial content.
  • Efficiency: We don’t need data like access logs or watchdog logs in QA or for local testing. This saves quite a lot of time and space during the data migration process.

Here’s how I did it:

  1. I identified tables I needed to copy over and tables that I could just leave empty. I did this by going through the output of “SHOW TABLES” in a MySQL console.
  2. In my Makefile, I declared a DB_DATA variable that contained a list of tables I wanted to copy.
  3. I wrote a backup_partial target in my Makefile that issued a series of commands:
    mysqldump -u ${DB_USER} --password=${DB_PASSWORD} ${DB} --no-data > partial.dump  # export the schema
    mysqldump -u ${DB_USER} --password=${DB_PASSWORD} ${DB} --opt --complete-insert ${DB_DATA} >> partial.dump # Dump some of the data
    mysqldump -u ${DB_USER} --password=${DB_PASSWORD} ${DB} --opt --complete-insert --where='uid< =1' users users_roles >> partial.dump # Dump the admin and anonymous users
    echo "UPDATE node SET uid=1;" >> partial.dump # Set all the node authors to admin
    echo "REPLACE INTO search_index_queue (nid, module, timestamp)  select nid, type, unix_timestamp(now()) FROM node;" >> partial.dump # Prepare for reindexing
  4. I wrote a shell script on an internal server that accepted an argument (the domain to translate to) and performed the following steps:
    1. ssh into the production server and run make with my backup_partial target, compressing the resulting partial.dump
    2. scp the partial.dump.gz from the production server onto the internal server
    3. unpack partial.dump.gz
    4. figure out what $DOMAIN is supposed to be based on the arguments
    5. run perl -pi -e "s/$DOMAIN/" partial.dump
    6. load partial.dump into my database
    7. run cron.php if it can
  5. I added two buttons to my web-based deploy script: one button to migrate the production database to the QA server, one button to make a copy of the production database for the domain “”. Both buttons call
  6. I created multisite settings.php in my Drupal directory (ex: sites/ and sites/ The production settings go in default/settings.php, and the multisite settings.php override it like this:
    $conf = array(
      'domain_root' => '',
    $cookie_domain = '.' . $conf['domain_root'];

    $conf allows you to override Drupal variables returned by variable_get.

So now, I can click on a button to migrate a sanitized copy of the production database to the QA server or to my local system. Sweet!

Happy birthday to me!

August 12, 2008 - Categories: family, life

Last night, I figured out how I wanted to celebrate my birthday.

I’ve never really been one for gifts, and my family’s much the same way. One year, my mom said that for her birthday, she’d like to receive sturdy plants for her garden. Another time, she requested books. One year, I asked people for letters. On another birthday, I asked people for their two-year plans. (Seriously. I gave seatwork.)

This year, I wanted to celebrate my birthday by sharing stories. I realized that a large part of being homesick is missing the sense of being known, and I wanted to share both my Philippine stories with W- and my Canadian stories with my family.

I celebrated my 25th birthday with my parents, my middle sister Kathy, and my partner W-. In the morning, my dad took W- and me around the electronic shops at Raon, the combination of Catholicism and superstition around Quiapo, and the photography shops at R. Hidalgo. I’m looking forward to trying out the SB-800 flash my dad gave me as a birthday gift. =)

After our trip, my mom took us around Ateneo, UP, and Pisay. W- and I had watched "Philippine Science" at the Toronto International Film Festival, so it was nice for him to see where I’d gone to school. We told a lot of stories along the way.

In the evening, my dad and my sister gave the commencement speech at the graduation of the photography students at Benilde. It was a quick, informal affair accompanied by a photo exhibit, which inspired me to think about shooting more.

After the commencement reception, we went out to dinner at Chateau 1771 in Greenbelt. We told tons of stories over dinner, and W- got a better idea of the crazy adventures that my family finds ourselves in. =D It was just the way I wanted to spend my birthday. (Or, well, it would’ve been if I’d remembered to bring a way to record the stories…)

Tomorrow, my godparents are having a tea party at the house in Alabang. It’ll be fun seeing them again. =) The day after that is Diane’s wedding – hooray! I just finished sending a few of my high school pictures to Mario, who’s putting together a slideshow. Can’t wait to attend!

25 years. So far, so good. Next up – even better!

Why browse the Web in Emacs?

August 12, 2008 - Categories: emacs, wickedcoolemacs
2014-11-27: Hi, Hacker News! Remember, this post is from 2008 and predates Emacs 24.4. I hear EWW (Emacs Web Wowser?) is pretty cool and have been meaning to try it out. Anyway, on with the show!

“Are you browsing Slashdot in Emacs?”, W- asked me after he glanced at my screen.

With Emacs’ reputation for including everything _and_ the kitchen sink, you probably won’t be surprised to hear that there’s more than one way to surf the Internet using your text editor. With today’s Javascript- and image-heavy websites, it can be hard to believe that anyone would use a text-based browser with limited support for many of the things we take for granted. Still, a Web browser in your text editor can be surprisingly useful. Here are some of the reasons why you might like it:

  • Browsing is faster and less distracting. Forget flashing ads, garish colors, and large images. When you surf the Web in Emacs, you can focus on reading, and you can use all the typical Emacs shortcuts for navigating around. You can view images when you want to. If you need to see something that Emacs doesn’t support, you can easily open the current page in an external Web browser.
  • You can integrate it into your work. With a little bit of Emacs Lisp, you can quickly look up information on the Web based on what you’re currently working on. For example, PHP mode comes with a shortcut that lets you look up the current function’s documentation in the PHP manual. You can look up bug report details, dictionary definitions, and Wikipedia pages with minimal typing, too. If you use Emacspeak, you can set up the web browser to speech-synthesize more than what’s displayed on screen. The more you use Emacs, the more benefits you get from the integration.
  • You can customize everything. You can customize your Emacs experience quickly and easily, and if you spend a lot of time on the Net, you’ll appreciate having your own shortcuts and functions. For example, I’ve completely remapped my keyboard shortcuts to support tabbed browsing on a Dvorak keyboard, and I’ve defined a few functions to make frequently-used commands much easier. You can even use functions to process Web pages and either summarize the information you’re interested in or make pages more navigable. It’s all just Emacs Lisp.
  • You’re safe from browser exploits. No Javascript pop-ups, no image bugs, no browser-based malware that can take over your comuter or steal data. Just content.
  • You need less memory. Why open up a memory-intensive graphical Web-based browser when you’ve got Emacs open anyway?

There’s more than one way to browse the Web in Emacs, of course. Browse-url is a package that makes it easy to open URLs in your preferred browser or browsers. For example, you can use it to browse the Web in Mozilla Firefox, and (of course) you can use it to browse the Web within Emacs itself. For browsing within Emacs, you can use w3m.el, an interface to the external W3M browser, or w3, a Web browser written entirely in Emacs Lisp. Of the two, I prefer w3m.el, which is much faster and more featureful than w3. Both can display graphics, tables, and frames, and w3 supports stylesheets.

More about Emacs and browsing the Web soon! Planned projects for this chapter of Wicked Cool Emacs:

*** Project XXX: Browse the Web
*** Project XXX: Open the current webpage in an external browser
*** Project XXX: Different browsers for different pages
*** Project XXX: Toggle between Web and work
*** Project XXX: Quick search
*** Project XXX: Customize your keymap
*** Project XXX: Download files
*** Project XXX: Add access keys
*** Project XXX: Use social bookmarking
*** Project XXX: Typeahead
*** Project XXX: Preview HTML
*** Project XXX: Read Web pages as news
2014-11-27: You can find more comments on Hacker News.

Sweet! Facebook in Emacs!

August 12, 2008 - Categories: emacs

So here’s how to access Facebook from w3m, one of the web browsers in

1. Enable cookies by setting w3m-use-cookies to t.
2. Go to .
3. Choose the HTTP login.
4. Log in with your username and password.

Hooray for mobile interfaces that don’t require Javascript! =D

So far, it seems to work. I can update my status! Sweet!

Next step: Figure out how to set up shimbun for Facebook mail so that I can read my Facebook mail like a newsgroup…

Weekly review: Week ending Aug 17, 2008

August 18, 2008 - Categories: weekly

What a hectic and fun week!

It was the first week of my vacation in the Philippines, and every day was just packed with things to do with friends and family.

On August 11 (Monday), we arrived in Manila. The Philippine Airlines flight we arrived on was full of boisterous Filipinos who joked with the flight attendants, sang way off-key, and cheered as the plane touched the tarmac, but I didn’t mind losing sleep on that red-eye flight. I was home! And I was awake enough to try the dress I was going to wear for Diane’s wedding and make other arrangements…

On August 12, I celebrated my birthday with W- and my parents. My dad took W- and me to Raon (the electronics district) and R. Hidalgo (the street of photography shops), and he gave me a flash for my birthday. I look forward to using it to light stuff! In the afternoon, my mom took W- and me to Ateneo de Manila University and Philippine Science High School, so that W- could get an idea of what my campus years were like. We also passed by the University of Philippines, where my mom told W- stories about her campus years. In the evening, I snuck into the Benilde commencement ceremony and exhibit for the graduates of their photography diploma course, and I listened to my dad and my sister give the short commencement speech. Cool!

On August 13, my dad gave W- and me a few shooting lessons. We discovered that the flash I have can freeze water drops in action, and we also practiced lighting small objects. I took a picture of the Scrabble game that W- and I had played on the flight home. It was definitely worth recording. =) After our shooting lessons, my mom took us to Alabang, where we had a tea party with several of my godparents. We listened to hilarious stories about avoiding traffic tickets, taking pictures in restricted areas, and other hijinks that my parents and godparents had done.

Practically all of August 14 was taken up by Diane’s wedding. She was the first of my best friends to get married, so we were all excited about that. I couldn’t help going "squee!" every few minutes. I loved the video montage that Mario had put together: childhood pictures, high school pictures, all the way up to their engagement pictures. The wedding photographers delighted us by showing a video montage of Di’s wedding pictures during the reception itself – that was fast work!

We spent most of August 15 working at home. I was aghast to find out that a bug in my code had resulted in the deletion of users on our production system ( =( !), and that the project manager and the IT architect had to recreate many accounts by hand. That further emphasized the importance of test-first development and well-written tests. Ouch. I’ve paid the tuition for that mistake, now I just have to collect the paycheck; I can’t undo that mistake, but I can learn from it and become a better developer. To avoid that mistake in the future, I will write more tests using the Simpletest framework, and I’ll ask someone else to review the tests with me.

I perked up a bit more in the afternoon, when my mom took W- and me to a yoga class taught by one of her friends. It was more challenging than the yoga classes we normally attend, and it was a good break. The yoga teacher was so impressed that both W- and I do yoga, and waxed lyrical about how beautiful it was to see couples practice yoga together.

On August 16, I hosted a get-together for my friends. We spent the entire afternoon laughing at the best of the Internet memes: a pastiche of websites and Youtube videos that we or the others had missed. In the evening, we watched Shaun of the Dead and Hot Fuzz, which both left us practically crying from laughter (and maybe a little grossed out). It was so nice to laugh with my friends again!

We spent most of August 17 at a photography summit, where we learned about taking pictures of people. I’m looking forward to applying those lessons. I’d like to learn how to take good pictures of my friends! My mom also showed W- the rows and rows of stalls selling pearls at Greenhills. It was all quite overwhelming, and I was glad to get back to the photography summit.

So that was what last week was like. I hope next week will be a little calmer. <b>I plan to work during most of the week</b>. I’m going to be on a team call this evening, so I napped this afternoon to make sure I can stay up later. A quieter schedule should mean more early-morning writing time, too, and I’m looking forward to <b>posting more notes on browsing the Web from Emacs</b>.

Lastly, I’m thrilled at how BarCampManila’s turning out. I pinged a couple of people about having a geek get-together on Thursday, August 21, and gave them the responsibility for making it happen. And they did! So, if you’re near Metro Manila and you want to hang out, check out:

<a href="">BarCamp Manila</a> – August 21, 2008, 7:00 PM @ G2VC Innovation Center<br />
<a href="">SIGN UP ON BARCAMP.ORG!</a>

Emacs and w3m: Quick searches

August 18, 2008 - Categories: emacs

A number of browsers allow you to define quick searches so that you can type keywords into your address bar in order to search predetermined sites. With a little bit of code, you can do this in Emacs, too. In this project, you’ll learn how to set up your own keywords to work with w3m and browse-url, so you can use your keywords for browsing both inside and outside Emacs.

First, set up keywords by adding the following lines to your ~/.emacs. We’ll use an associative list of regular expressions and substitutions, like this:

(setq wicked/quick-search-alist
      '(("^g?:? +\\(.*\\)" . ;; Google Web 
        ("^g!:? +\\(.*\\)" . ;; Google Lucky
	("^dict:? +\\(.*\\)" . ;; Dictionary

This will turn "g keyword1 keyword2" into a Google search for keyword1 and keyword2.

Next, define advice for the functions that open URLs. Before-type advice allows you to modify arguments before the function is run, and we’ll use that to change the URLs. To modify the URL behavior of w3m, add the following to your ~/.emacs:

(require 'cl-seq)
(defadvice w3m-goto-url (before wicked activate)
  "Use the quick searches defined in `wicked/quick-search-alist'."
  (let* ((my-url (replace-regexp-in-string 
		  "^ *\\| *$" "" 
		  (replace-regexp-in-string "[ \t\n]+" " " (ad-get-arg 0))))
	 (match (assoc-if
		 (lambda (a) (string-match a my-url))
    (if match
	(ad-set-arg 0 (replace-regexp-in-string
		       (car match) (cdr match) my-url)))))

This sets up your quick searches for use within w3m. To set up quick searches for use with browse-url and external browsers, add the following to your ~/.emacs:

(defadvice browse-url (before wicked activate)
  "Use the quick searches defined in `wicked/quick-search-alist'."
  (let* ((my-url (replace-regexp-in-string 
		  "^ *\\| *$" "" 
		  (replace-regexp-in-string "[ \t\n]+" " " (ad-get-arg 0))))
	 (match (assoc-if
		 (lambda (a) (string-match a my-url))
    (if match
	(ad-set-arg 0 (replace-regexp-in-string
		       (car match) (cdr match) my-url)))))

To try out your searches, use M-x browse-url RET g emacs RET to do a Google search for all things Emacs, and use M-x w3m-goto-url (usually bound to g) inside w3m to use the quick searches.

You can define more quick searches like this:

(add-to-list 'wicked/quick-search-alist
          '("^ew:? *?\\(.*\\)" . ;; Emacs Wiki Search

Running groups of Drupal tests from the command line

August 19, 2008 - Categories: drupal

I’ve written about using drush to evaluate PHP statements in the Drupal context using the command line before, and it turns out that Drush is also quite useful for running Simpletest scripts. Drush comes with a module that allows you to display all the available tests with “drush test list”, run all the tests with “drush test run”, or run specified tests with “drush test run test1,test2”.

‘Course, I wanted to run groups of tests and tests matching regular expressions, so I defined two new commands:

drush test run re regular-expression
Run all tests matching a regular expression that uses ereg(..) to match.
Ex: drush test run re Example.*
drush test run group group1,group2…
Run all tests matching the given groups
Ex: drush test run group Example

Here’s the patch to make it happen:

Index: drush_simpletest.module
--- drush_simpletest.module	(revision 884)
+++ drush_simpletest.module	(working copy)
@@ -12,9 +12,13 @@
 function drush_simpletest_help($section) {
   switch ($section) {
       case 'drush:test run':
-        return t("Usage drush [options] test run.\n\nRun the specified specified unit tests. If  is omitted, all tests are run.  should be a list of classes separated by a comma. For example: PageCreationTest,PageViewTest.");
+        return t("Usage drush [options] test run .\n\nRun the specified unit tests. If  is omitted, all tests are run.  should be a list of classes separated by a comma. For example: PageCreationTest,PageViewTest.");
       case 'drush:test list':
         return t("Usage drush [options] test list.\n\nList the available tests. Use drush test run command to run them. ");
+      case 'drush:test group':
+        return t("Usage drush [options] test group .\n\nRun all unit tests in the specified groups. For example: drush test group Group1,Group2");
+      case 'drush:test re':
+        return t("Usage drush [options] test re .\n\nRun all unit tests matching this regular expression. For example: drush test re Page.*");
@@ -30,10 +34,18 @@
     'callback' => 'drush_test_list',
     'description' => 'List the available Simpletest test classes.',
+  $items['test re'] = array(
+    'callback' => 'drush_test_re',
+    'description' => 'Run one or more Simpletest tests based on regular expressions.',
+  );
+  $items['test group'] = array(
+    'callback' => 'drush_test_group',
+    'description' => 'Run one or more Simpletest test groups.',
+  );
   return $items;
-function drush_test_list() {
+function drush_test_get_list() {
   // TODO: Refactor simpletest.module so we don't copy code from DrupalUnitTests
   $files = array();
@@ -60,6 +72,11 @@
       $rows[] = array($class, $info['name'], truncate_utf8($info['desc'], 30, TRUE, TRUE));
+  return $rows;
+function drush_test_list() {
+  $rows = drush_test_get_list();
   return drush_print_table($rows, 0, TRUE);
@@ -75,3 +92,31 @@
   return $result;
+function drush_test_re($expression) {
+  if (!$expression) {
+    die('You must specify a regular expression.');
+  }
+  $rows = drush_test_get_list();
+  $tests = array();
+  foreach ($rows as $row) {
+    if (ereg($expression, $row[0])) {
+      $tests[] = $row[0];
+    }
+  }
+  simpletest_run_tests($tests, 'text');
+  return $result;
+function drush_test_group($groups) {
+  $rows = drush_test_get_list();
+  $tests = array();
+  $groups = explode(',', $groups);
+  foreach ($rows as $row) {
+    if (in_array($row[1], $groups)) {
+      $tests[] = $row[0];
+    }
+  }
+  simpletest_run_tests($tests, 'text');
+  return $result;

That makes running tests so much easier and more fun!

Emacs and w3m: Fake your user agent

August 19, 2008 - Categories: emacs, wickedcoolemacs

In an ideal world, you would never need to make your browser pretend to be a different browser. In reality, a number of websites check for specific browsers such as Mozilla or Internet Explorer, or even specific versions of those browsers. Other websites check for popular search engine crawlers such as the Googlebot in order to display content optimized for that search engine. You may want to change your user agent to work around such limitations, or you might want to change your user agent string just for fun.

The following code allows you to set your user agent (wicked/w3m-set-user-agent), reload the current page using a specified user agent (wicked/w3m-reload-this-page-with-user-agent), and define regular expression matches for URLs to control user agent strings (wicked/w3m-fake-user-agent-sites). To use this, add the following to your ~/.emacs:

 (defvar wicked/w3m-fake-user-agents ;; (1)
   `(("w3m" . ,(concat "Emacs-w3m/" emacs-w3m-version " " w3m-version))
     ("ie6" . "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)")
     ("ff3" . "Mozilla/5.0 (X11; U; Linux i686; en-US; rv: Gecko/2008070206 Firefox/3.0.1")
     ("ff2" . "Mozilla/5.0 (X11; U; Linux i686; en-US; rv: Gecko/20080208 Firefox/")
     ("ie7" . "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727)")
     ("ie5.5" . "Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)")
     ("iphone" . "Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_0 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5A347 Safari/525.20")
     ("safari" . "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; en-us) AppleWebKit/525.13 (KHTML, like Gecko) Version/3.1 Safari/525.13")
     ("google" . "Mozilla/5.0 (compatible; Googlebot/2.1; +"))
   "*Associative list of user agent names and strings.")

 (defvar wicked/w3m-fake-user-agent-sites ;; (2)
   '(("^https?://www\\.useragentstring\\.com" . "ff2"))
   "*Associative list of regular expressions matching URLs and the agent keyword or value.
 The first matching entry will be used.")

 (defun wicked/w3m-set-user-agent (agent)
   "Set the user agent to AGENT based on `wicked/w3m-fake-user-agents'.
 If AGENT is not defined in `wicked/w3m-fake-user-agents', it is used as the user agent.
 If AGENT is empty, the default w3m user agent will be used."
     (completing-read "User-agent [w3m]: "
                    (mapcar 'car wicked/w3m-fake-user-agents)
                    nil nil nil nil "w3m"))) ;; (3)
   (if agent
        (setq w3m-user-agent
               (and (string= agent "") (assoc "w3m" wicked/w3m-fake-user-agents)) ;; (4)
               (cdr (assoc agent wicked/w3m-fake-user-agents)) ;; (5)
               agent)) ;; (6)
        (setq w3m-add-user-agent t))
     (setq w3m-add-user-agent nil)))

 (defun wicked/w3m-reload-this-page-with-user-agent (agent)
   "Browse this page using AGENT based on `wicked/w3m-fake-user-agents'.
 If AGENT is not defined in `wicked/w3m-fake-user-agents', it is used as the user agent.
 If AGENT is empty, the default w3m user agent will be used."
   (interactive (list (completing-read "User-agent [w3m]: "
                    (mapcar 'car wicked/w3m-fake-user-agents)
                    nil nil nil nil "w3m")))
   (let ((w3m-user-agent w3m-user-agent)
       (w3m-add-user-agent w3m-add-user-agent))
     (wicked/w3m-set-user-agent agent) ;; (7)

 (defadvice w3m-header-arguments (around wicked activate) ;; (8)
   "Check `wicked/w3m-fake-user-agent-sites' for fake user agent definitions."
   (let ((w3m-user-agent w3m-user-agent)
         (w3m-add-user-agent w3m-add-user-agent)
         (sites wicked/w3m-fake-user-agent-sites))
     (while sites
       (if (string-match (caar sites) (ad-get-arg 1))
           (wicked/w3m-set-user-agent (cdar sites))
           (setq sites nil))
       (setq sites (cdr sites))))

wicked/w3m-fake-user-agents sets up a number of common user agents(1) using examples from If you frequently use other user agents, add them to this associative list. wicked/w3m-fake-user-agent-sites sets up some rules for URLs so that you can work around specific websites(2). The first matching rule will be used.

wicked/w3m-set-user-agent can be called from a w3m browser session to set the user agent for all new pages visited. By default, it uses the w3m user agent(3). It will also use the w3m user agent if the agent is blank(4). If the user agent is one of the frequently-used agents defined in wicked/w3m-fake-user-agents, then the corresponding user agent string will be used(5). If not, the string will be used as-is(6). If the agent is nil, the user agent string will be disabled.(7)

You can check a single page using a different user agent by using M-x wicked/w3m-reload-this-page-with-user-agent. It temporarily sets the user agent and then reloads the current page.(7)

The last segment of code modifies the behavior of w3m-header-arguments(8), matching wicked/w3m-fake-user-agents against the URL. This temporarily sets the user agent for matching sites.

Many hats: Technical writer

August 21, 2008 - Categories: geek

I just spent the last three days updating the administrator’s guide and related documentation for the Transition2 project, making pretty screenshots and typing in clear, step-by-step instructions. Last time I checked, I had 80 pages or so. I don’t know if anyone’s going to read it, but at least it’s there. =)

I actually had fun writing it. I do miss hacking on Drupal code, though.

So here’s my current hierarchy of things I enjoy doing for work, going from most enjoyable to least enjoyable:

  • Connecting with people, brainstorming, giving presentations about things I’m passionate about, learning, writing about what I’m learning – love love love!
  • Helping people learn about tools they’re going to love
  • Developing on open source platforms with terrific user communities (hello, Drupal, Emacs!)
  • Writing documentation (not so much)
  • Dealing with paperwork and fiddly things I can’t automate
  • Making front-ends
  • Dealing with cross-browser issues and other things that force me to use Microsoft Windows (not a happy kitty!)

The Leisure of Work

August 21, 2008 - Categories: life

Many people hate working during vacations. Others hate going on vacations with people who stay just as connected to the office in the country as they are in the cubicle. One of the things that I’m learning on this trip, though, is that work can actually make the trip more relaxing.

This isn’t a forget-your-worries kind of vacation, but more about keeping my ties. I grew up in the Philippines, and most of my family and my friends live in Metro Manila. The short trips I take are the only time I get to catch up with them face-to-face.  I remember one trip when I felt so distraught at the prospect of leaving that it was hard to enjoy the days before my flight back to Toronto. When departure looms, every moment gets thrown into hyperfocus, and there’s such a temptation to pack every instant with activity. When I return to my quiet(er) Toronto life, the the sudden vacuum in my schedule gets filled with the pain of being between worlds.

So when I decided that I’d find a way to make it to the wedding of one of my best friends, I felt guilt over not being able to spend the whole time relaxing. My team members were counting on me to contribute to the project. I didn’t feel comfortable taking an entire two weeks off, and it didn’t make sense to fly halfway around the world for a trip of only a week. My compromise was to spend the first week on a proper vacation and the second week working remotely.

It turned out remarkably well. This week of work is what made everything feel more like home. It seems that the greatest leisure is the feeling of normalcy, of being part of the everyday routine, of following the rhythm of meals and work and some unwinding at the end of the day. Last week was hectic: lots of fun, hardly any time to breathe, hardly any time to reflect, hardly any time to slow down. This week, I feel more like I’m at home.

This trip to the Philippines feels much more relaxed than the others, as if we’re not trying to cram too much in too little time. Yes, we’re flying back to Toronto two days from now. Yes, two weeks is still too short a trip. Yes, I’ve run out of evenings for planning get-togethers. But it doesn’t feel as jarring as the last time I traveled. I don’t feel as misplaced, and I don’t feel that I’m unraveling from the strain of being “on” all the time. I have space to be normal. I have time to breathe.

I’ve checked off some bugs, written some documentation, responded to some mail, and thought about some improvements. There’s a sleepy cat on my lap. All is well with the world.

I’m flying back to Toronto in a couple of days. In the past two weeks, I learned that I can work anywhere, there are things I love about both worlds I live in, and that I can be fully present–here and now–even though I’m becoming a person of two worlds.


August 21, 2008 - Categories: geek

BarCampManila drew over 80 people. There were 16 presentations ranging from 5 to 7 minutes each. What an amazing turnout!

Jerome Gotangco is my new hero. He organized everything (including getting a banner printed with the BarCampManila logo) less than two weeks after I e-mailed him saying that it would be fantastic to have a geek get-together on the 21st and could he please Make It Happen… Wow!

Highlights for me:

  • Mario Carreon’s “Maritess and her first computer” sketch. Dual-core aquarium indeed!
  • Calen Legaspi and his 7… no… 6… no… 2 lessons from starting a software company! (Nobody expects the Calen Exposition!)
  • JM Ibanez and git-svn – gotta check that out

What would make this even better?

  • More of a networking session after the talks – maybe limit it to 5 or 10 talks
  • Longer slots for demos (no Powerpoint allowed for those!)
  • Better sound system (they’re already working on this)
  • Table for laptops
  • Presenter remote

Catch the replay! I’m looking forward to hearing about the next one. I’m probably going to be in Canada, but that’s what streaming is for… =)

Just ordered a tablet

August 26, 2008 - Categories: geek

I’ve just ordered the Cintiq 12WX, a 12.1″ pressure-sensitive tablet that also includes a screen so that you can see what you’re working on. I think it’s brilliant. It will probably be even more useful than the Lenovo X61 Tablet PC–the other gadget I was considering getting with the gadget fund I’d saved up.

I hope it will arrive in time for the four-day weekend we’ve got coming up. I’d love to use it to sketch my presentations, and W- will certainly enjoy using it to retouch photos.

I like this feeling. I knew I’d be in the market for some kind of drawing thing, so I started saving a few months ago. After I gave my Nintendo DS to my mom, I needed another drawing tool, and it was nice to know what I wanted AND know that I could freely get it.

More sketches to come!

Weekly review: August 16 to August 23

August 26, 2008 - Categories: weekly

My second and last week in the Philippines was more relaxed, but it was just as enjoyable as the first week. I spent most of the time working, and I learned a lot about documentation. I helped kickstart the first BarCampManila. I also got to spend more time with my parents, have high tea with my godparents, and watch Blades of Glory with friends. Leaving the Philippines was difficult – it always is – and I found myself near tears as I walked through the airport with W-. But it was a very good trip, and I was happy to have gone.

Work: I put on my technical writer hat and rewrote most of the documentation for the administrator, bringing it up to date and adding plenty of screenshots. I still haven’t quite figured out if I should document the system as it currently is (which means revising it often) or as it will be (which means inconsistent documentation for work in progress). My project manager suggested this compromise: I’ll document the system assuming some critical bugs are fixed on the production server, but leave other enhancements out of the manual.

I’m learning how to use doxygen to extract source code comments, too. I’d prefer to keep low-level design documentation close to the source code so that I can keep it up to date, and I definitely don’t want to reboot to Windows and start both Lotus Notes and Microsoft Word every time I need to make a change. Doxygen looks like a good tool for documenting not only the functions but also the design of the system, and I’m looking forward to learning how to make it dance. Even with what I learned after half a day of study, I was already much more comfortable with it than with the idea of keeping our developer documentation in Word. I’ve gotten permission from my project manager to use it for our low-level documentation, and I’ve promised him an archive of HTML documents by Wednesday.

That wasn’t the only thing I did during the second week of my vacation, of course. I had a lot of fun at BarCampManila, a hastily-organized unconference that went really well. I gave a short speech on why geeks should blog, and I hope I convinced a few people to make it a habit. I’ve also posted other notes about the event. Check them out!

My parents spent a lot of time with us that week. My dad took us flying in an ultralight, and W- got this totally amazing shot of the blue sky and the volcano reflecting off the ricefields. We also snuck into a photo summit lecture on portrait photography, and we picked up lots of tips. We passed by the zoo to say hi to Maali, and we took some fun pictures with the zoo animals. Once we sort our vacation pictures, I’ll post the pics on my blog.

My goals for next week (well, this week, now) are:

  • get back into the swing of work by finishing the admin guide and the developer documentation
  • contact everyone I promised to get back to after the trip
  • write three more posts about Emacs
  • use my gadget budget for awesome (maybe get that Cintiq tablet; UPDATE: ordered!)

Emacs and W3M: Toggling between work and the Web

August 27, 2008 - Categories: emacs, wickedcoolemacs

Here’s a handy shortcut that toggles between the W3M web browser and other buffers you’re working on. I use it to quickly switch between code and documentation (or your favorite timewasting site, as it also makes a handy boss key).

Define the function by adding the following code to your ~/.emacs:

(defun wicked/toggle-w3m ()
  "Switch to a w3m buffer or return to the previous buffer."
  (if (derived-mode-p 'w3m-mode)
      ;; Currently in a w3m buffer
      ;; Bury buffers until you reach a non-w3m one
      (while (derived-mode-p 'w3m-mode)
    ;; Not in w3m
    ;; Find the first w3m buffer
    (let ((list (buffer-list)))
      (while list
	(if (with-current-buffer (car list)
	      (derived-mode-p 'w3m-mode))
	      (switch-to-buffer (car list))
	      (setq list nil))
	  (setq list (cdr list))))
      (unless (derived-mode-p 'w3m-mode)
	(call-interactively 'w3m)))))

Then bind it to a shortcut key sequence (F7 F7 in this example) by adding the following code to your ~/.emacs:

(global-set-key (kbd " ") 'wicked/toggle-w3m)

You can then use F7 F7 to switch back and forth between your web browser and whatever else you’re working on.

Mouse woes on Ubuntu Hardy

August 27, 2008 - Categories: geek

It’s really quite odd. I’ve tried two USB mice (one wireless, one wired) on my Kubuntu system. They work well… once. The next time I try to use them, I’m lucky if I manage to get a minute of use out of them. Something is very wrong. =(

Anyway, that’s enough time spent on mouse issues–one hour today, one hour yesterday! Pfft. I’ll try it again later.

Work that I love: reflecting on the whats and hows

August 27, 2008 - Categories: career, life, work

At the team-building event the other day, I got to meet a number of other people who had been with IBM for a number of years. Several people told me stories about projects planned using at least 80-hour weeks, of high turnover and stressful environments, but also the increased responsibilities and career opportunities for people who stay with those projects. Other people talked about priorities and intentionally limiting the number of hours they worked in order to make time for other things, their happiness with their decisions, and the support they received from the company. It made me think about what work I love to do and how I want to live.

I’m getting a better idea of the work I enjoy doing. Here’s a rough sketch:

  • I love sharing what I’m passionate about, helping people learn more and become more effective, and encouraging people to grow. In my current role, I get to do plenty of presenting, conducting workshops, coaching, and writing. People appreciate not only the information I share but also the enthusiasm with which I share it and the thoughtfulness with which I help people learn.
  • I love learning about all sorts of things. I’m currently working on visual literacy, and I’m looking forward to using the Cintiq tablet to experiment with graphics even more. I also love learning about social networking, communication skills, and other topics that I can share with people around me.
  • I love connecting people with other people, ideas, or tools. It gives me a thrill whenever I can introduce people to just the right person who can help them do what they want, to a book or article that fits their interests, or to a tool they’ll love.
  • I love exercising my creativity and helping people brainstorm. As part of my work, I often get to help people brainstorm Web 2.0 business ideas, and I really enjoy bringing in things I’ve learned from all the different aspects of my life.
  • I enjoy working on lightweight projects based on open source technologies with vibrant user communities. I get to do this with my Drupal-based project and with my Emacs book. I love being able to read source code and learn from other people’s contributions. I love sharing tips on my blog and learning more from others. I love giving back to the community, too!
  • I can write technical documentation better than most developers can. And I don’t mind doing it, too, as long as it doesn’t require me to keep changing applications or operating systems.
  • I don’t like working on front-end interfaces, such as designing graphics, writing CSS, or trying to make a page look exactly like the design. I can do it, but I’d rather do a simple design.
  • I really don’t like working on cross-browser or cross-platform issues.
  • I really don’t like dealing with inconsistent, fiddly, or frustrating things such as bugs in one’s operating system (really, my mouse should Just Work) or convoluted administrative paperwork. Some people enjoy solving problems like that. I don’t.

I’d like to explore sales at some point, too. I want to find out if it might be a good fit for me, too, and I like the idea of helping people find the right solution for them.

So that’s a general idea of my strengths. I love helping people be more effective, whether it’s by sharing ideas or tips, connecting them with others, or building or tweaking tools for them. I enjoy software development and technical writing too, but mainly as a way of supporting my ability to help people be more effective. Those are the “whats,” at least right now. What about the hows?

I don’t see myself working on projects with unrealistic time expectations. I don’t see myself sacrificing life for work or for career advancement. If I did, I’d be going up the ladder, yes, but it might be the wrong ladder for me.

The things I love doing and the things that make me special all require me to be happy and passionate about my work. I believe that I can be successful at them while living according to my values. I’m looking forward to seeing the kind of life I can build. =)

Have you thought about your whats and hows?


August 28, 2008 - Categories: sketches

It’s 2:51 in the morning. I’ve just spent the last… umm… six hours getting the Cintiq mostly sorted out, and I have barely enough time to get enough sleep to be barely functional tomorrow.

But it’s worth it.

Okay, it doesn’t seem obvious from the quality of my drawing, but it’s certainly fun…

Mindmapping on infinite paper

August 28, 2008 - Categories: geek

I am officially in love.

I can’t believe how much fun it is to mindmap with the Cintiq 12WX tablet and the free Inkscape vector-drawing program. The Cintiq’s integrated display means I can just draw on my mindmap, like the way people do on Tablet PCs. I can zoom in and out by sliding a finger along the touch strip. I can move around by pressing a button on the stylus and then moving in the direction I want. I can quickly switch to pencil mode, switch to selection mode, or delete items with a button press. And Inkscape gives me an infinite canvas to work with…

About the only thing that could make this even better would be for me to use a real mindmapping program that can hide and show outline notes–and index my handwriting, too. Oh, and it would need to run on Linux.

In the meantime, I’m going to have some fun. =D

Celebrating the little things you learn

August 29, 2008 - Categories: learning, life

Photo (c) 2007 Sean Dreilinger, Creative Commons Attribution Noncommercial Copyleft

I love learning. I love being able to do something I’d never done before or to do something even better than before.

This week, I learned how to write a good set of low-level documentation using the doxygen tool, influence project decisions, test a website for accessibility, set up a digitizing tablet under Linux, sketch and edit my sketches, mindmap using a tablet, lay out a photobook, and answer some of J’s old homework in French. I’m looking forward to learning even more over this long weekend!

Every time I learn or improve a skill, I like celebrating. I often write about what I learn on my blog, as it’s a great way to not only share what I’m learning but also that sense of accomplishment in learning something new. Sometimes I take a moment to pat my own head, which alwas makes W- smile when he sees this. “Celebrating the little things?” he says. You bet!

Why shouldn’t we celebrate these little victories? A baby’s first smile, first word, and first step are all monumental milestones people celebrate. Growing up, we celebrate the first time we tie our shoes by ourselves, the first degree, the first paycheck. What if we never grew out of celebrating these milestones? What if we celebrated more?

Celebrating the little things keeps learning fun. What have you learned lately?

On Changing the World

August 29, 2008 - Categories: life, passion

Like Daniel at Young and Frugal, I am going to change the world.

I’m changing it already, and as I grow, I’ll do better and better. I won’t always succeed, but I’ll always learn. I’ll get better and better at finding better and better fits between what I’m passionate about, what I’m good at, and what the world needs.

It’s not because I can be anything I want to be, but because I’m becoming more of who I am. Let’s face it: I’m unlikely to become an Olympic swimming champion or the CEO of a wildly successful social networking platform. But there’s so much I can do right now, and there’s so much I want to grow into in the future.

There are amazing people around me who encourage me to keep following my passion, keep exploring new areas. They know you can’t train people to do what I do, and that I create a lot of value you can’t put into a job description. If people around me weren’t this supportive, I’d just look for a different environment. I would keep following my passions, because I can’t imagine living any other way.

I have what-am-I-doing moments. I have do-I-really-have-to-do-this moments. I have just-get-me-through-this-day moments. But I also have I-totally-rock moments and I-helped-someone-else-totally-rock moments, and I’m going to have more of those.

When people tell me I’m special, I tell them that I’m just like they are, and I ask them what it would take for them to live like I do. What would it take for people to live with passion and joy?

I’m Sacha Chua, and this is not just about Generation Y. =)

Editors for blogging

August 29, 2008 - Categories: blogging

Penelope Trunk’s editor helps her improve her blogging and her tweeting:

In case you didn’t know, I have an editor for my blog. This comes from being a columnist for so long. My editors were incredible—one was from Vanity Fair, one went on to the Harvard Business Review, and they definitely made me a better writer. So I have an editor for my blog, and if you think that’s over the top, consider this: he also edits my Twitters. I mean, you can’t write about sex and investors in the same 140-character phrase and still get funding unless you have an editor to save you from yourself.

What I’ve been doing while I’ve not been posting » Brazen Careerist by Penelope Trunk

Of course, she’s a professional writer and she probably has a gazillion readers. =) But maybe small(er) fry like me might gain a lot from asking an editor what he or she would do to make this blog even awesomer… =) Someday!

Weekly review: Week ending Aug 31, 2008

August 31, 2008 - Categories: sketches, weekly

Weekly review

Lots of learning this week!

The Cintiq tablet I ordered from Vistek arrived the very next day. After learning way too much about in the process of setting it up, I’ve gotten it to work as a tablet and as a second screen. Hooray! Someday I’ll get GIMP and Inkscape to recognize pressure and the eraser tip, but for now, it’s good enough.

I used the Cintiq to quickly process and layout the pictures we took during the vacation. The last time I made a photobook, I used Shutterfly’s predetermined layouts. This time, I used the open source Scribus desktop publishing program to make everything from scratch. Now I just need to find a nice printer and binder who’ll take a PDF…

New dish of the week: pad thai, from a mix. It was okay.

We borrowed some magazines from the library and I flipped through them to get an idea of things I might play with this fall. My wardrobe’s already been tending towards warm earth colors, so maybe I’ll try playing with metallics.

At work: propagated a few good ideas, including persistent chat rooms; worked on accessibility.

Love: W- is totally awesome. =) This week’s reason: he hung up the memory scroll my friends and family had made for me before I left for Canada. =) Aww!

Next week:

  • More sketching and photography
  • Prepare presentation
  • Cook salmon and couscous
  • Sort out new sewing machine =)