December 2008

Weekly review: Week ending November 30, 2008

December 1, 2008 - Categories: weekly


  • Submitted my business results for the year (Personal Business Commitments)
  • Participated on a Gen Y and Government 2.0 panel at the City of Toronto’s Web 2.0 Summit. Lots of great conversations.
  • Attended Rahaf Harfoush’s talk on social media and the Obama campaign. Chatted with Jeff Muzzerrall, Gregory Lam and Fiona Cunningham over tea.
  • Finished my assigned tasks (except for wontfixes) for the Drupal-based microsite project we’re working on.
  • Got mysite and other modules working. Whee!
  • Gave release engineer detailed notes, implementation sketch, sample scripts for fancy Drupal deployment system. ;)
  • Set up rudimentary deployment script.


  • Contacted a bunch of people met at various events.
  • Adopted a new cat from Toronto Animal Services! He’s _adorable._
  • Started sewing a lightweight gray wool vest.
  • Hiked with W- and J- a bit more than 7 km near Caledon Hills.
  • Sent out invitations for storytelling soiree, hooray!
  • Submitted passport renewal application.
  • Submitted Philippine police clearance application.

Next week:

  • Work: Extend mysite to work with Organic Groups nodes, get site ready for testing.
  • Work: Get ready for Web 2.0 for Biz community call with yearly summary.
  • Pick up notarized police clearance application from Philippine embassy and send it home for processing.
  • Apply for Japan police clearance again.
  • Take pictures of cats.
  • Finish vest.
  • Start working on annual letter.
  • Host dinner party.

Notes from conversations: Ushnish Sengupta, consulting

December 2, 2008 - Categories: braindump, connecting, social

Ushnish Sengupta was interested in exploring social media consulting. He picked my brains over hot chocolate at the Bluestar Cafe. Here are some rough notes from that conversation:

  • The first tip I gave him was to blog. I think it’s a good idea for consultants to keep a blog because it’s an easy and nearly-free way to help establish credibility and build connections. The blog can contain success stories, articles, lessons learned, announcements of upcoming events, tips, tidbits, and other pieces of information that can help both potential and existing clients. Besides, it’s awfully hard to do social media consulting if you’re not immersed in the space and you don’t have a presence.
  • Business cards: I told him about putting pictures and interesting conversation hooks on business cards, showing him mine as an example.
  • Ushnish was interested in potentially getting a PhD looking at consulting services and similar areas. I recommended that he check out services science. A recent conference we both attended (CASCON) had a number of sessions about the topic, so I suggested reviewing the proceedings to find people and topics of potential interest. I also recommended that he get in touch with people like Kelly Lyons – she’s currently doing research in this field.
  • Twitter backchannel: He asked me how the City of Toronto’s Web 2.0 Summit went. I told him about the interesting conversations that happened in real life and on the Twitter backchannel, and suggested that the next time he’s at an event, he should find the tag that people are using and tune in to for some lively conversation.
  • Professional networking: He asked me which professional social networks I’m on. I told him that I’m active on LinkedIn and I use it to connect with people so that I can find out about changes in e-mail addresses and positions. He asked me if I was on Plaxo. I told him that I never got into Plaxo because it started off with a bad value-proposition for people who entered their data and that it had been fairly spammy. I haven’t looked into Plaxo Pulse in detail, but LinkedIn and my personal addressbook handles most of my needs.
  • Multiple networks: He asked me about being on multiple networks and how networks become popular and then fade away. The key things I shared with him were that ideas and skills tend to be transferrable between networks, and that an external profile such as a personal site or blog is important because it ties all the networks together. I also told him about something I picked up from Rahaf Harfoush’s talk on the Obama campaign: produce a piece of content and then distribute it through different channels.
  • Partnership: Ushnish asked me if I preferred to work with people I know well or if I preferred to work alone. I told him that I definitely prefer to work with other people because I learn much more in the process. I also told him that I actually enjoy working with people I don’t know that well yet, because it gives me an opportunity to develop a new relationship and spread the skills. If I’m asked to give a presentation, I often look for ways to enable other people to give the presentation, perhaps with a little coaching from me. I want other people to develop wonderful skills, too.
  • Teaching as I learn: The point on partnership segued into a discussion of how useful, fulfilling, and effective it is to try to teach everything I know how to do. I recapped some of the points from “If you can, teach; If you can’t teach, do“.
  • Event management: I told him that I’m interested in learning more about hosting external events in 2009. Alex Sirota does a lot of events for the New Path Network (which Ushnish belongs to), so I might see if I can use some of those events as models.
  • Address book: Ushnish was curious about how I manage my network. I told him about my wonderful addressbook setup (automatically tracks who I send mail to, automatically inserts notes into my mail), and the visualization improvements I’d like to make. I also told him of my plans to try porting some of these ideas to Drupal so that other people can experiment with them.
  • Social media and change management: I told him about the spectrum of social media consulting, and that organizational change plays a large part in it.
  • Rough notes: We ended the conversation with a homework assignment: he’s supposed to blog the lecture he was also going to that day, and perhaps the notes from the conversation as well. I reassured him that rough notes are fine, and that he’ll make things clearer and clearer as he writes about them again and again.

What did I learn?

  • I seem to have learned something about social media consulting after all. =) Hooray! I need to package that into some kind of internal blog post and presentation so that my coworkers can make the most of it.
  • I should find a way to package up these social networking tips into a blog post, a presentation, and maybe an event.
  • In an alternate future, I could probably keep myself very busy building and selling tools for making all of these things easier…

One of Canada’s Most Influential Women in Social Media?

December 2, 2008 - Categories: canada, life, passion, reflection, social, web2.0

I’ve been nominated as one of Canada’s Most Influential Women in Social Media in a poll run by Dave Forde, whom I know from the Toronto technology scene. It’s a little odd thinking about that, because I’m nowhere near the likes of Amber MacArthur (popular geek television / videocasting personality), Leesa Barnes (who made it onto a worldwide list of female social media luminaries), and Sandy Kemsley (prolific Enterprise 2.0 blogger well-known for her comprehensive live-blogged conference notes). Me? I’m a recent hire figuring things out and posting notes along the way. =)

I’ve stumbled across influence by being in the right place at the right time, maybe. My story is now woven into IBM’s story about social media, and we’re helping other large companies figure things out as well. I’ve given numerous presentations helping people figure out what Web 2.0 means for them and for their company, facilitated workshops for generating, developing and prioritizing initiatives, and done a fair bit of hand-holding to get people over their concerns. All of that is pretty cool, come to think of it, but what I’d like to do is make it possible for other people to do even cooler things.

Thinking about this poll on Canada’s most influential women in social media, I realized that I didn’t consider myself any way equal to all these role models I have here and around the world. =) I also realized that I had a pretty good idea of a future me that would feel perhaps at home in that list. So here’s what I think “influential” looks like for me:

  • I would organize regular events that brought together interesting people and helped people connect. These events would include workshops on social networking, storytelling and presentations, quarter-life crises, lifehacking and productivity, happiness, geek growth, personal finance, and other topics I’m interested in or passionate about.
  • I would also build a bit of infrastructure that would help transform the networking aspects of these events: sign-up pages with more details, aggregators to bring together people’s blog posts, business card prints and other in-person networking aids, active matchmaking both online and offline, and so on.
  • I would be one of those people that people mention their projects and ideas to in the off chance that I could recommend people to talk to, books to read, and sites to check out–because I would. =) In order to do this, I’d find ways to more effectively capture information to support a somewhat fuzzy associative memory. (It’s _so_ frustrating to know that you’ve seen something before that people will like, but not be able to find it again!)
  • I would help lots of people to figure out what their passion is, deepen their skills, and share the results with lots of people through presentations, new and existing businesses, and other good things. I’d do that by asking people, helping them connect and make things happen, and helping them find a forum or opportunity where they can talk to other people.
  • I would have a big archive of things I’ve thought about and shared with others so that I can pull useful resources out and give them to people.
  • I would build systems to make it possible for other people to do this kind of awesomeness as well. =)

So that’s what “influential” looks like to me. I’m not there yet, but I think I can get there. =) I can learn how to hold external events, and gradually get into the swing of it. I can keep blogging and summarizing interesting resources, gradually refining my collection of resources. I can keep tweaking my addressbook, and someday I’ll build systems to help other people try this out. =)

Stay tuned.

Drupal rockitude

December 4, 2008 - Categories: development, drupal, geek

I joined my current Drupal project two weeks ago after documenting and wrapping up my other Drupal-based project (which I’m happy to report is chugging along quite nicely without me). Since then I’d been quickly going through my task list. I’ve also been poaching other people’s tasks, such as the configurable group home pages and the deployment scripts. As I told my cat, I’m having fun rocking Drupal. ;)

Today, one of my project team members demonstrated the site to members of the other consulting team. He wasn’t sure if the reception would be neutral or even hostile. He walked through the various features we’d built in two weeks of work, a short period of time that included the numerous issues other people encountered and my ramp-up time as a new member of the team.

One consultant from the other team couldn’t help but say, “Wow.” And the rest of the team really liked it, too!

So I guess I can count that as my first “melting a tough client” story. =)

What worked well?

  • Even though I was new to the team, my team members gave me plenty of latitude in building tools and reorganizing things. There were a couple of changes that we needed to discuss, but usually, the practices I suggested made things a bit easier and the changes weren’t difficult to get used to.
  • I set up my local development environment (my uber-tricked-out Emacs) to make it easy for me to quickly shift between files in different branches of code, look up definitions of functions, and re-build the site.
  • As a lazy programmer, it’s in my best interest to automate as much as I can. I kept tweaking the build process until I could get it to work without manual intervention, and I plugged it into the web-based deployment script I’d written for my previous project.
  • I reused as much as I could, relying on a combination of grep, var_dump, printf, tags, and asking coworkers what’s responsible for what.
  • Also, starting work at 5:15 AM turns out to be pretty good for me. I get almost a full day of work into the morning, I can spend a little time in the afternoon attending to things that require less creative energy, and I can even take a short catnap in the afternoon sun (complete with purring cat!).

I’m looking forward to tidying this site up, and I’m sure I’ll have lots of fun getting the next site off the ground, too!

Drupal, Makefiles: save time, make awesome

December 4, 2008 - Categories: development, drupal, geek

One day I’ll post a generalized version of the Makefile that makes my Drupal life so much easier, but in the meantime, here’s the general structure I use:

  1. Lots of configuration settings:
    Database name for Drupal site
    Database user for Drupal site
    Database user password for Drupal site
    Root MySQL password, used to drop and recreate the database, and grant permissions
    Subversion branch for source code control
    Subversion user name
    Subversion password
    Particularly useful when working with sites that use Domain Access, but handy even with other sites because of BASE_PATH
    Location of source code, needed for Drush
    Drush command line, just in case I want to fiddle with it
    Database prefix, for make clearcache

    Base URL

    Regular expression to match against simpletests using my modified Drush_simpletest that lets me run all groups of tests matching a regular expression
  2. An include statement
    -include *.mk
    This is really useful. This lets you override the variables using a file like, dropped into your current directory and kept out of your source code control system. I use this to make my Makefile just Do The Right Thing when it’s in different directories or on different servers. Do not forget to tweak your included file (or make sure there is one) if you need different configuration settings.
  3. Lots of targets:
    Uses mysqldump to back up the database.
    Drops the database and restores it from the backup.
    Drops the database
    Calls the site’s install.php with the appropriate profile.
    Calls the site’s cron.php
    Starts a MySQL connection to the Drupal database. I don’t have to remember what the database name is or what the connection details are, hooray!
    Clears the {cache}, {cache_menu}, {cache_views}, {cache_content}, {cache_filter}, and {cache_page} tables
    Hits the panic button and reverts my tree. (because svn revert . -R is too long)

    Regenerate the TAGS file that lets me find function definitions really quickly
    Use Drush to run all of my simpletest functional tests for this project

Sometimes I’ll have an “rsync” target to deploy files to a server and a “doc” target to regenerate my low-level documentation using doxygen, too.

This Makefile is seriously cool and seriously time-saving because it means that no matter which project, branch, directory, or server I’m working on, I have a consistent set of commands for the most common things I need to do. The less time I spend thinking about fiddly administrative tasks, the more time I can enjoy in the coding zone.

This is also one of the reasons why Drupal development is _so_ much easier on Linux or other Unix-ish systems, or even Microsoft Windows with the Cygwin environment. If you see yourself doing a fair bit of Drupal work, it’s well worth investing the time in setting up a virtual machine or a second partition, learning a new operating system, and re-setting-up your development environment.

make awesome. =)

What’s in your Makefile, or what other tricks do you use to increase your developer happiness?

Let’s talk about passion

December 7, 2008 - Categories: connecting, passion

Of all the small-talk questions people usually ask, the one I avoid asking is “What do you do?” I’m not interested in people’s job titles, which rarely lead to conversations. You know how it goes: “What do you do?” “I’m an IT consultant.” “Oh.” If you’re particularly diligent, you might ask a number of questions like “What kind of consulting?” “Software.” It’s like pulling teeth, and it doesn’t tell me anything about what lights people up.

When people ask me, “What do you do?”, I often answer that with something along the lines of “My passion is helping people connect and collaborate,” followed by a brief description of what I do and maybe a recent story showing how I work.

I picked up that tip from Make Your Contacts Count, where the authors advised people to introduce themselves using the “best-test” structure: teach people what you’re best at, and show them a test of that.

But I usually like preempting the question of “What do you do?” with a question of my own: “What’s your passion?” That makes people stop and think. If I know someone already, I ask, “What have you been excited about lately?” It’s much better than “How are you?” because the other person actually thinks about the answer instead of just tossing off the customary “Good. How are you?”

Mireille Massue sent me this link to 25 Passion-Finding Questions to Invite Someone to Talk about What They Love. The list has lots of variants on the questions I like asking. Pick a couple of those questions and use them in your next conversation, and see how much more interesting things get!

The benefits of writing

December 7, 2008 - Categories: blogging

Jeff Muzzerall sent me this paper on the Benefits of Writing: Health and Productivity. The paper summarizes other research showing, among other things, that people who write about their long-term goals and their best possible selves become happier and more satisfied than people who write about trivial and short-term topics.

Might be a good reason to blog about what your ideal life would be like… =)

If everything went really, really well, what would life look like five years from now, when I’m 30?

Life: I have a wonderful relationship with W- and J- and other members of the family, full of experiences and laughter and deep moments. I’m close to my family and friends back in the Philippines, too, and we regularly chat over the phone, exchange stories and pictures, and visit. I can sew clothes I enjoy wearing, and I can take portraits that people like. I’ll have finally finished a book. =) I have plenty of friends that I’ve brought together so that they can meet my other friends, and they’ll also have formed good friendships among themselves. I’m always meeting people and connecting them with other people and ideas for making things happen.

Work: Whether I’m working at a large company or a small one, I’m helping people connect and collaborate. I divide my time between helping people connect, creating tools to support that, and teaching lots of people how to do what I do (or even better).

Weekly review: Week ending Dec 7

December 7, 2008 - Categories: weekly

Last week:

  • Work: Totally rocked with Drupal and Linux. =)
  • Work: Set up next two conference calls for Web 2.0 for Business community within IBM.
  • Picked up Philippine police clearance form.
  • Almost finished vest, but realized the front has some fit problems.
  • Mindmapped annual letter topics.
  • Hosted dinner party – yay! Lots of fun. Great conversations. Yummy chili and curry, too.

Next week:

  • Work: Testing, cleaning up development
  • Sketch annual letter, send to my mom.
  • Catch up on e-mail.
  • Attend a number of holiday events.
  • Finish pattern for basic dress.

Library shortcuts

December 7, 2008 - Categories: library

Matt Price e-mailed me about this wonderful piece of wizardry he added to YubNub (which is kinda like a command line for the Web). He set up the tpl command, which searches the Toronto Public Library. This prompted me to finally make YubNub the default handler for my Mozilla Firefox address bar, which you can also do by going to about:config and setting or creating the keyword.URL option to

This is good stuff, and one of the many reasons why blogging saves me time and lets me hear about all sorts of interesting things. =) Matt, thanks for sharing!

Crazy business idea: videoconferencing event/party spaces =)

December 7, 2008 - Categories: idea

Yes, videoconferencing should be the kind of thing anyone can get working at home, but technical glitches often come up.

I think there’s a market for at least one company that can set up an event space with a good screen, a computer, a reliable network connection, and a sound system. It beats having lots of people clustered around one laptop and spending most of the time struggling with technical issues. Market: business meetings during the day, globally dispersed families / friends at night and on weekends.

Anyone with that kind of business in Manila, please contact my mom. =)

Notes from today’s Drupal hacking

December 8, 2008 - Categories: drupal
  • Avatar selection/upload during registration: Oddly enough, avatar_selection doesn’t handle this. You need the reg_with_pic module, too.
  • Shared and per-site file directories: We’re segregating uploaded files by microsite, but we want to share some files as well. Hacking the shared path into is a kludge, but it works. Like so:
    ---    (revision 1046)
    +++    (revision 1589)
    @@ -66,6 +66,11 @@
    else if (file_check_location($file_path . '/' . $dest, $file_path)) {
    return $file_path . '/' . $dest;
    +  // Not found, check by going up one more
    +  else if (file_check_location($file_path . '/' . $dest, $file_path . '/../')) {
    +    return $file_path  . '/' . $dest;
    +  }
    // File not found.
    return FALSE;
  • Group names with signed-up events: signup.module doesn’t make it easy to theme the list of events, so I created my own block based on the code in signup_list_user_signups. To determine the possible group a node came from, I check for the intersection between $node->og_groups and the array keys of $user->og_groups.
  • Fixed panes: I couldn’t figure out a way to set a block as fixed in Panels 2, but a workaround is to define a custom layout that includes the block in the right place. Here’s an example:
     * Implements hook_panels_layouts
    function mymodule_panels_layouts() {
      $items['my_panel'] = array(
        'title'  => t('My Panel Layout'),
        'icon'   => 'my_panel.png',
        'theme'  => 'my_panel',
        'css'    => 'my_panel.css',
        'panels' => array(
          'top' => t('Top'),
          'left' => t('Left'),
          'right' => t('Right'),
      return $items
     * This function uses heredoc notation to make it easier to convert
     * to a template.
    function theme_my_panel($id, $content) {
      if ($id) {
        $idstr = " id='$id'"
      // Pull in the Organic Groups - 0 block.
      $group_details = og_block('view', 0)
      $group_block = < <<EOT
      <div class="block block-og" id="block-og-0">               
        <h2 class="title">$group_details[subject]</h2>
        <div class="content">
      $output = < <<EOT
    <div class="panel-2col-stacked clear-block panel-display" $idstr>
      <div class="panel-col-top panel-panel">
        <div class="inside">$content[top]</div>
        <div class="center-wrapper">
        <div class="panel-col-first panel-panel">
        <div class="inside">
        <div class="panel-col-last panel-panel">
        <div class="inside">
      <div class="panel-col-bottom panel-panel">
        <div class="inside">$content[bottom]</div>
      return $output;

    To limit the choices to just that layout, put this in your installation profile:

      $allowed_layouts = new panels_allowed_layouts();
      $allowed_layouts->allow_new = TRUE;
      $allowed_layouts->module_name = 'panels_common';
      $allowed_layouts->allowed_layout_settings = array(
        'threecol_33_34_33_stacked' => 0,
        'twocol' => 0,
        'flexible' => 0,
        'threecol_25_50_25' => 0,
        'threecol_25_50_25_stacked' => 0,
        'onecol' => 0,
        'threecol_33_34_33' => 0,
        'twocol_stacked' => 0,
        'twocol_bricks' => 0,
        'my_panel' => 1
  • Organic Groups RSS feed: There’s an og_aggregator module, although it doesn’t quite fit in neatly with everything else.
  • Organic Groups tag cloud: I was surprised to find that this wasn’t built in. I ended up defining my own block using a SQL query like this:
            if (($node = og_get_group_context()) && node_access('view', $node)) {
              $result = db_query(
                'SELECT COUNT(*) AS count, d.tid,, d.vid FROM {term_data} d
                 INNER JOIN {term_node} n ON (d.tid=n.tid)
                 INNER JOIN {og_ancestry} og ON (og.nid=n.nid)
                 WHERE og.group_nid=%d AND d.vid=0 GROUP BY d.tid,, d.vid ORDER BY count DESC', $node->nid);
              $steps = 6;
              $tags = tagadelic_build_weighted_tags($result, $steps);
              $tags = tagadelic_sort_tags($tags);
              $output = theme('og_tagadelic_weighted', $node, $tags);
              $block['content'] = $output;

    og_tagadelic_weighted was a custom theme function that constructed a link to a faceted_search using the og: and taxonomy: filters. I had to hack faceted_search, too. First I needed to enable the og filter, and then I needed to make taxonomy_facets.module recognize free tags (vid=0). Patch for taxonomy_facets.module:

    --- taxonomy_facets.module	(revision 1046)
    +++ taxonomy_facets.module	(revision 1582)
    @@ -147,6 +147,7 @@
           // and create facets from it.
           if ($found_text = search_query_extract($arg, 'taxonomy')) {
             $vocabularies = taxonomy_get_vocabularies();
    +        $vocabularies[0] = 1;
             // Extract separate facets
             $paths = explode(',', $found_text);
             foreach ($paths as $path_index => $tids) {

It’s a good thing I can find my way around sparsely-documented code with few or no examples… <laugh>

DrupalCon 2009 abstract: Totally Rocking Your Development Environment

December 10, 2008 - Categories: drupal


Totally Rocking Your Development Environment

Are you a lazy developer? If you aren’t, you should be! Find out about editor tricks for Emacs, Vi, and Eclipse that can save you hours and hours of effort and frustration. Learn about browser tips that make it easy to test your sites with different users, track down elusive bugs, and test things out. Develop the virtue of laziness by automating as much as you can with makefiles, the Drupal Shell, regression tests, and other goodies. Share your best tips during this interactive session. Use your new-found free time to rock even more!

I would really like to make it to DrupalCon 2009. The deadline for session submissions is today, and I would hate to miss an opportunity to share what I’ve learned, meet all sorts of cool folks, and learn even more.


Why automation matters to me

December 11, 2008 - Categories: geek, kaizen

The release engineer working on our Drupal project is happy. He manages the deployment of four Drupal projects (each with three multisites), and the project I’m on takes the least time to deploy.

In the beginning, it took two hours to deploy one set of Drupal multisite because of many manual configuration steps. The team had gotten it down to fifteen minutes thanks to node imports and other time-savers, but it still required someone to click on buttons, type in text, and upload files from the source code tree.

Shortly after I joined the team, I started automating as much as I could. This helped me because I could quickly test my configuration from a clean install. I also wrote a web-based deployment script based on the script I’d written for my previous Drupal project. This script made it easy for any team member to deploy a selected revision to the site and reinstall all the microsites. Any time a manual step entered into the installation process, I ruthlessly automated it. Now deployments take a single click (or three, if you want to select a revision other than the latest one), and the build process has shrunk from fifteen minutes to five minutes, with no manual interaction required.

So the release engineer is happy, the team’s happy, I’m happy, and we can quickly deploy and test new code.

I like automating repetitive tasks. It’s not just about showing off a clever shell script or Makefile (although my scripts are clever) or about saving myself time (although I do). It’s about freeing people up to do better work.

One of my best friends was on an internship at a large computer company. A large part of her work involved copying and pasting data between spreadsheets, a task she detested. However, the cost of getting interns to do the work had been lower than the cost of automating the process, so she was assigned to copy and paste the information. If she were more comfortable with programming, she might have automated it herself, but she wasn’t familiar enough with Microsoft Excel to do so. So she did the mind-numbing work. When she left her role, no progress had been made on automating the work, and she knew that the next intern would probably also need to copy and paste information manually.

I remember hearing her frustration with the kind of work she was doing. I wished I could do something about it. I couldn’t, but at least I can automate whatever routine tasks I come across so that people can work more effectively.

Twitter, Whuffie, and Amazing Connections

December 12, 2008 - Categories: story, web2.0

Thanks to Don Marti’s post about a possible business model for Twitter, I came across Tara Hunt’s post about Twitter, whuffie (reputation), and the amazing power of connection. In her blog post, she tells the story of how disappointed she was when she was waiting for UPS delivery (which didn’t come during the delivery window specified), how another friend of hers helped connect with someone in UPS, and how the ending wasn’t just happy, it was spectacular. What I like about her post is that she describes the background story and the timeline, showing how one thing leads to another.

Check it out. See, Twitter can be awesome. =)

Drupal: Changing module behavior without changing the source code

December 12, 2008 - Categories: drupal

For the project I’m currently working on, I’m not allowed to make any changes to third-party source code. Yes, I’ve pointed them to the GPL and Drupal FAQs about being legally allowed to make modifications to a system that will be hosted but not publicly discributed, without being required to contribute those changes back to the community. As much as I would like to release all the modifications back to the community, I also care about proper interpretation of the GPL. I suspect our project restrictions are a combination of wanting to be able to upgrade modules easily and erring on the safe side when it comes to the legal requirements of open source.

Anyway. If you’re trying to avoid making changes to third-party source code when you’re customizing your Drupal system, here are several ways you can alter the module’s behavior:

  • Hooks: Drupal has an extensive hook system allowing you to alter forms (hook_form_alter), node behavior (hook_nodeapi), user behavior (hook_user), and do other cool things. Read about the hooks in your version of Drupal, and see if any of those hooks can help you wrap code around what you want to modify.
  • Theme functions: Well-written Drupal modules use theme functions to make the HTML output easily customizable. Check the function you want Create a custom theme and override the functions in your template.php. For example, if you’re using the PHPTemplate engine, you can override a theme_foo_bar(…) method by defining a phptemplate_foo_bar(…) function in your template.php.
  • String overrides: If you want to change a displayed string and it’s wrapped in t(‘…’) calls (as it should be), use String Overrides to set up an English-to-English translation for that string. If you use the internationalization and localization features of Drupal, you don’t need String Overrides – just set up custom English translation for your site.
  • Menu overrides: Use this if the module outputs HTML directly, or if you want to change more of the functionality. In your custom module, you can define a menu item with the same path as a menu item defined by a different module. Copy the menu item definition from the other module, then change the callback function and the arguments to point to customized copies of the functions. If you do this, check the {system} table to make sure that your module has a greater weight than the module it’s overriding. You may have to duplicate a number of functions in order to get to the menu item you need to change.
  • String replacement: If you’re desperate, you can use string replacement on the page before it’s sent to the browser. Use this only in emergencies, as it’s ugly and it wastes all the processing time spent coming up with the string you’re going to replace.
  • Module replacement: If you’re absolutely desperate, make a copy of the module and change all the names so that you remember this is a customized module instead of something that you can cleanly update.

Your Drupal modifications are also under the GPL, so pay attention to the licensing terms. =)

Drupal and return on sharing

December 12, 2008 - Categories: drupal, web2.0

Another IBMer sent me an instant message out of the blue and introduced himself as a fellow Drupal developer. I noticed from the chat window that he was based in Atlanta, where a number of my other Drupal team members are from. He thanked me for sharing so much on the wiki, the peer-to-peer learning knowledge path, and my blog, and he said that he subscribed to my blog. He was interested in setting up a chat with me so that he could get advice on improving his team’s development process, and perhaps also getting a Drupal community started at our company. He also told me that he had voted for my abstract submission for DrupalCon09 (Totally Rocking Your Development Environment), and that he hoped to go to DrupalCon. I’m looking forward to chatting with him next week, and setting up more regular knowledge-sharing sessions around Drupal – we all have plenty of tips to share.

Random connections like that show the power of investing a few minutes to share what you know. It usually takes me fifteen minutes to write up a quick Drupal-related post about something I’ve tried or something I’ve learned, and the time helps me reflect on what I’ve done and make sure I understood what I was doing. As I keep investing these fifteen-minute chunks here and there, I accumulate an archive of useful resources. When people stumble across this archive – by searching, by coming across my digital footprints, by checking out a link – the archive gives them a lot of value without any additional effort from me. This is similar to the way investments earn residual income. You put in the work once, and you keep reaping the benefits.

Share what you know. You’ll learn a lot in the process, and you’ll meet a lot of people.

The economics of entertaining at home

December 13, 2008 - Categories: party

Last Saturday, we hosted a dinner party at our house. There were eight people, including me and W-. For starters, we served broccoli and cauliflower crudites with blue cheese dip and home-made hummus. For the main course, we served vegetarian chili and chicken curry, accompanied by naan bread and basmati rice. People brought dessert: halva, chocolates, sesame snacks, buns, and all sorts of assorted goodies. The party went from 7:00 to 11:30 or so, and we had tons of fun chatting about storytelling, university advice, and whatever else came to mind. After the party, we had a week of leftovers to feast on. I estimate that we ate just a third of the food prepared.

Ingredients bought for the party: $52.81 total
Home ingredients used: Approximately $10 (one pack of chickpeas, half a pack of black beans, half a pack of red beans, three packs of curry paste, assorted spices)
Estimated cost of party: ~$63 / 3 (as we only ate a third of the food available) = ~$21 total, or ~$3 each

plus the cost of whatever desserts people shared, of which we probably ate a fifth. Maybe a total of $4 each, for the whole meal + desserts?

I don’t think you can find a restaurant in Toronto where people can eat such a spread for $4, or stay for so long and chat with such ease without the waiters trying to drop hints about freeing up tables. ;) Nor could you find a restaurant with such friendly cats, I think – Luke was _such_ a charmer, immediately identifying the cat fans and climbing onto their laps for a good purr.

I traded time for these savings, of course, but not as much time as one might expect. Pre-cooking the beans using a pressure cooker took up most of my Friday evening, which was a good time to relax and unwind. Chopping everything up for all the meals took an hour, and cooking both the chili and the curry took another hour and a half – during which I was learning more about cooking, thinking about what was going on in the week, and planning what I wanted to do next. (And listening to bouncy Japanese pop songs…) Time well spent.

And the conversation and company? Priceless.

If we had more chairs, or found some way to squeeze more people into the house (in an elegant way that doesn’t mean some people are privileged enough to sit at the table while everyone else just stands around ;) ),I can easily scale up. It seems that the time and money I spent on the get-together could scale up to 24 people, and even more if we decided to make it a well-organized pot-luck get-together.

What would this house look like with 24 people in it? Where would people sit? How would we deal with the coats and shoes? Someday I’ll figure that out. =)

Tonight I’m attending a dinner get-together for recent hires in my department. The pre-set menu is $30 per person. Now that I look at that sum, I’m thinking, “I could host a quite a dinner party for that amount!” ;)

Cintiq 12WX, OpenSuse 11.0, and much pain and suffering

December 14, 2008 - Categories: linux

Let that be a lesson to me: Always blog solutions to problems. The cost of doing so is not just time wasted solving things again, but also the frustration of knowing I’d solved the problem before and if I had just taken a few extra minutes to share what I knew… GRR.

When I upgraded to OpenSuse 11 on the desktop at home, I forgot to back up my X11 configuration files: the Nvidia-Twinview-Cintiq12WX configuration I’d laboriously pieced together from fragments on the Internet and lots of troubleshooting.


Anyway, here it is, so I don’t lose it again: my xorg.conf:

Section "ServerLayout"
    Identifier     "Layout[all]"
    Screen         0 "Screen0" 0 0
    InputDevice    "Keyboard[0]" "CoreKeyboard"
    InputDevice    "Mouse[1]" "CorePointer"
    InputDevice    "stylus"   "SendCoreEvents"
    InputDevice    "eraser"  "SendCoreEvents"
    InputDevice    "pad"
    Option         "Clone" "off"
    Option         "Xinerama" "off"

Section "Files"
    InputDevices   "/dev/gpmdata"
    InputDevices   "/dev/input/mice"
    InputDevices   "/dev/input/wacom"
    FontPath       "/usr/share/fonts/misc:unscaled"
    FontPath       "/usr/share/fonts/local"
    FontPath       "/usr/share/fonts/75dpi:unscaled"
    FontPath       "/usr/share/fonts/100dpi:unscaled"
    FontPath       "/usr/share/fonts/Type1"
    FontPath       "/usr/share/fonts/URW"
    FontPath       "/usr/share/fonts/Speedo"
    FontPath       "/usr/share/fonts/PEX"
    FontPath       "/usr/share/fonts/cyrillic"
    FontPath       "/usr/share/fonts/latin2/misc:unscaled"
    FontPath       "/usr/share/fonts/latin2/75dpi:unscaled"
    FontPath       "/usr/share/fonts/latin2/100dpi:unscaled"
    FontPath       "/usr/share/fonts/latin2/Type1"
    FontPath       "/usr/share/fonts/latin7/75dpi:unscaled"
    FontPath       "/usr/share/fonts/baekmuk:unscaled"
    FontPath       "/usr/share/fonts/japanese:unscaled"
    FontPath       "/usr/share/fonts/kwintv"
    FontPath       "/usr/share/fonts/truetype"
    FontPath       "/usr/share/fonts/uni:unscaled"
    FontPath       "/usr/share/fonts/CID"
    FontPath       "/usr/share/fonts/ucs/misc:unscaled"
    FontPath       "/usr/share/fonts/ucs/75dpi:unscaled"
    FontPath       "/usr/share/fonts/ucs/100dpi:unscaled"
    FontPath       "/usr/share/fonts/hellas/misc:unscaled"
    FontPath       "/usr/share/fonts/hellas/75dpi:unscaled"
    FontPath       "/usr/share/fonts/hellas/100dpi:unscaled"
    FontPath       "/usr/share/fonts/hellas/Type1"
    FontPath       "/usr/share/fonts/misc/sgi:unscaled"
    FontPath       "/usr/share/fonts/xtest"
    FontPath       "/opt/kde3/share/fonts"

Section "Module"
    Load           "glx"
    Load           "type1"
    Load           "extmod"
    Load           "dbe"
    Load           "freetype"
    Load           "vbe"
    Load           "ddc"
    Load           "i2c"
    Load           "bitmap"

Section "ServerFlags"
    Option         "AllowMouseOpenFail" "on"
    Option         "Xinerama" "0"
    Option "AutoAddDevices"  "False"

Section "InputDevice"
    Identifier     "Keyboard[0]"
    Driver         "kbd"
    Option         "Protocol" "Standard"
    Option         "XkbLayout" "us"
    Option         "XkbModel" "microsoftpro"
    Option         "XkbOptions" "ctrl:nocaps"
    Option         "XkbRules" "xfree86"

Section "InputDevice"
    Identifier     "Mouse[1]"
    Driver         "mouse"
    Option         "Buttons" "9"
    Option         "Device" "/dev/input/mice"
    Option         "Name" "Razer Diamondback Optical Mouse"
    Option         "Protocol" "explorerps/2"
    Option         "Vendor" "Sysp"
    Option         "ZAxisMapping" "4 5"

Section "InputDevice"
    Driver         "wacom"
    Identifier     "cursor"
    Option         "Mode" "Absolute"
    Option         "Device" "/dev/input/wacom"
    Option         "Type" "cursor"
    Option         "USB" "on"                  # USB ONLY
    Option         "ScreenNo" "0"
    Option         "TwinView" "horizontal"
    Option         "TVResolution"  "1280x800,1600x1200"
Section "InputDevice"
    Driver         "wacom"
    Identifier     "stylus"
    Option         "Mode" "Absolute"
    Option         "Device" "/dev/input/wacom"
    Option         "Type" "stylus"
    Option         "USB" "on"                  # USB ONLY
    Option         "ScreenNo" "0"
    Option         "TwinView" "horizontal"
    Option         "TVResolution"  "1280x800,1600x1200"
Section "InputDevice"
    Driver         "wacom"
    Identifier     "eraser"
    Option         "Device" "/dev/input/wacom"
    Option         "Type" "eraser"
    Option         "USB" "on"                  # USB ONLY
    Option         "ScreenNo" "0"
    Option         "TwinView" "horizontal"
    Option         "TVResolution"  "1280x800,1600x1200"
Section "InputDevice"
    Driver         "wacom"
    Identifier     "pad"
    Option         "Device" "/dev/input/wacom"
    Option         "Type" "pad"
    Option         "USB" "on"                  # USB ONLY
    Option         "ScreenNo" "0"
    Option         "TwinView" "horizontal"

Section "Monitor"
    Identifier     "Monitor1"
    VendorName     "DELL"
    ModelName      "D1626HT"
    DisplaySize     388    291
    HorizSync       30.0 - 96.0
    VertRefresh     50.0 - 160.0
    Option         "dpms"

Section "Device"
    Identifier     "VideoCard"
    Driver         "nvidia"
    VendorName     "NVidia"
    BoardName      "GeForce 6800 GT"
    Option "TwinView" "true"
    Option "MetaModes" "1600x1200,1280x800"
    Option "SecondMonitorHorizSync"   "31-107"
    Option "SecondMonitorVertRefresh" "50-75"
    Option "TwinViewOrientation" "LeftOf"

Section "Screen"
    Identifier     "Screen0"
    Device         "VideoCard"
    Monitor        "Monitor1"
    DefaultDepth    24
    SubSection     "Display"
        Depth       24
    Option "SecondMonitorHorizSync"   "31-107"
    Option "SecondMonitorVertRefresh" "50-75"
    Option "TwinViewOrientation" "LeftOf"
    Option "MetaModes" "1600x1200,1280x800"
    Option "TwinView" "on"

Getting back to the xorg.conf above was a bit of a pain. First I needed to get the nvidia drivers working again, which was a matter of adding the repository and downloading the RPMs. Then I needed to get the dual-monitor setup. I was running into all sorts of problems with it, and I must’ve tried configuring TwinView from scratch at least five times. Then I noticed I had an xorg.conf.twinview in my home directory, so I copied that and used it as a basis. Progress! The screen on the Cintiq started working as a proper screen again.

I had been having problems with the wacomcpl in OpenSuse 11 (Error: unknown device “stylus” or it is currently a core device), so I recompiled the drivers from the Linux Wacom Project. While trying to recompile the driver, I discovered that the kernel-source installed on my system… didn’t have the source files. Pfft.

After much poking around, I threw up my hands and downloaded the kernel source code that matched my system, copied the appropriate config file from /boot as the kernel source code directory’s .config, and started “make oldconfig; make”.

After make had set up the directory tree, I switched back to the linuxwacom drivers and ran “./configure –with-kernel= –enable-wacom –enable-hid –enable-evdev –enable-usbmouse –enable-modver –enable-xsetwacom > log”. Fortunately, make and make install proceeded without incident. (After all the false starts I’ve had today, I was glad at least something worked.)

Then it was a matter of more TwinView poking around to get the tablet confined to just one screen instead of being mapped to two. With a lot of fiddling, I finally got it to work.

Now it’s Sunday evening and I’m grumpy from an entire afternoon spent dealing with hardware issues, so I’m in no mood to write our annual updates. I’ll probably feel much better after the Chicken Maryland we’ve planned for dinner, though. =) And after some cat cuddling. Cats are nice and warm.

All that griping aside, I’d still rather use Linux than Microsoft Windows for stuff like this. =)

Weekly report: Week ending Dec 14

December 16, 2008 - Categories: weekly

Last week’s activities:

  • Work: Site moved into user acceptance testing, hooray! Lots of stuff to work on.
  • Reviewed pictures. Got tablet to work again. Will do annual letter this week.
  • Caught up on e-mail, a bit.
  • Attended holiday events.
  • Did first fitting of basic sloper dress pattern.
  • Balanced books.

This week:

  • Drupal: Clean up development for site.
  • Attend #hohoto and other holiday events.
  • Lay out pictures and some text for annual letter.
  • Get more sleep (maybe cut back on events)…
  • Get a massage! =D

The Return on Mistakes

December 16, 2008 - Categories: geek

I still remember the round-eyed awe on a first-year computer science student’s face when I walked past the monitor set into his desk, scanned his screen (upside down), pointed out the error, and nudged him in the direction of the solution. He had been trying to solve the problem by making small, random changes to his program, and he was amazed at how quickly I identified what was going on. Many of the students in the class were new to programming, and still had a long way to go before they could become comfortable with it. And there I was, figuring things out just by looking at them.

It would have been easy for the new students to feel as if they could never do what I do, so I made sure to save some time during that class session for a secret I wanted to share with them. That secret was:

If I can figure out a programming problem quickly, it’s because I’ve made so many mistakes before.

The more you program, the more intimate you become with error messages. This quote is attributed to Maurice Wilkes:

As soon as we started programming, we found out to our surprise that it wasn’t as easy to get programs right as we had thought. Debugging had to be discovered. I can remember the exact instant when I realized that a large part of my life from then on was going to be spent in finding mistakes in my own programs.

M. Wilkes

I like reading, trying things out, and making things up, so I’ve run into all sorts of errors. I also enjoy helping other people, so I’ve run into all sorts of other people’s errors, too. I haven’t encountered every single error yet (my printer has never been on fire). But I’ve hung out in IRC channels where people help other people troubleshoot in real-time, I’ve read countless mailing list posts in the process of troubleshooting something I’m working on, and I don’t mind rolling up my sleeves and getting my hands into the source code. In the process, I’ve learned some of the techniques for finding out where problems might lurk.

So that’s it. That’s the magic, really. Learn. Make mistakes. Figure things out. Help other people figure things out. Then, when weird problems come up, you can say, “Hmm. Hang on. Let me poke around… hmm… ah, there it is, the doohickey was kerfluzzled and a quick xyzzy fixed it.” Or something like that.


See, all those hours hanging out on mailing lists, #linuxhelp, and #emacs in university are paying off…

#hohoto conversations

December 17, 2008 - Categories: braindump, toronto
  • I put “Sacha Chua, @sachac,” on my nametag because putting “Sacha Chua, @sachac,” felt a bit repetitive. It made a number of people smile, although some people asked me if I was no longer working with IBM. I told them I’d gotten an alternate domain name for my blog because it’s a bit easier to spell.
  • Kristan Uccello pointed me to the red glowsticks near the stage. I stuck one in my hair. That and my white blazer made me slightly easier to spot in the club, although it was still quite, quite packed.
  • Ian Irving told me about some Twitter data analysis and visualization he’d like to do. I promised to send him some information about Many Eyes, Wordle, and other visualizations.
  • I introduced Elena Yusunov to Patrick Dinnen, who regularly spends some time at the Center for Social Innovation. Elena is interested in social media for nonprofits, and would like to check CSI out. I should get Elena and Jane Zhang together for coffee next week. Also, I should check out those capoeira lessons.
  • I told James Walker about the Drupal hacking I’m having a lot of fun with at IBM. =) I also told him about after he mentioned that he occasionally drops by the Center for Social Innovation to hang out and print stuff.
  • Saleem Khan mentioned
  • Eva Amsen mentioned that she’d heard about me from Jen Dodd and Michael Nielsen, and that she was one of the organizers of SciBarCamp. I think she’d have a great conversation with Elena Yusunov about organizing events and about social media for nonprofits. She also explained the meaning of her Twitter ID, easternblot – it’s a biochemist secret handshake thing.
  • Sunir Shah asked me if I’d been to Toastmasters lately. I haven’t, but I might try exploring some of the downtown clubs with him after he’s done with house-hunting.
  • James Woods said he’d been to Mauritius, and he found it interesting to hear unexpected people fluently speak French. Gabriel Mansour mentioned that Sameer Vasta had been to Mauritius recently.
  • Gabriel Mansour told me about, which looks interesting. I promised to e-mail the details to Greg Frank, who is interested in cooking but doesn’t bake much.
  • David Crow’s 15-month-old daughter is getting quite good at sign language, and tends to string signs together like sentences.
  • Adam Schwabe turned out to be the guy doing my usability test this week. We talked about the challenge of finding out what other people are doing when it comes to Web 2.0 at IBM. I promised to send him info about our upcoming Web 2.0 for Business community call, and to connect him with a few people. (I actually talked shop at a party; meep!)
  • Brent Ashley’s on his third ultra-mobile PC. He handed down the rest to his two daughters. Reminds me of the way my dad goes through Swiss knives…
  • Kieran Huggins should definitely look into getting one or two external flashes. They’re portable and they really make a difference in pictures. For photography awesomeness, buy glass (lenses) and light (flashes). And practice, of course, which he obligingly let me do.
  • Mike Miner runs into all sorts of interesting stories as a producer. He wants to go to Africa or South America.
  • Pete Forde’s planning a dinner party. I’m looking forward to it!
  • Bryan Watson can dance swing! That was lots of fun. I may have accidentally stepped on someone’s foot while finding this out, though.
  • I promised to e-mail David Crow and Jay Goldman about volunteering to help out with events so that I can learn how to organize external events.
  • I caught up with or met a whole bunch of other interesting people. =) (Hooray! I’ve been in Canada long enough to have old friends!)

… I feel like a gossip columnist with all these names in my blog post. Odd!

Also, I need to port my BBDB-auto-hyperlink-to-people’s-blogs-or-websites code over to Org mode. Ah, Emacs…

Leavin’ well enough alone

December 17, 2008 - Categories: geek

So I’ve gotten my Linux partition mostly back into working order. I had run out of hard disk space on my main partition. I tried to move files to the other partition. I must’ve done something terribly wrong, because things started failing. My mail server. My graphical user environment. And – oh no! – my VPN connection back to the IBM network. So I booted into Microsoft Windows to take care of some of the things they wanted for the project and to stick around on instant messaging just in case people started panicking, but let me tell you – it’s no fun developing without my tools.

Someday I’m going to learn to leave well enough alone. Or make my partitions large enough in the first place. Or look into properly resizing partitions.

Actually, nix that leaving well enough alone bit, because if I left well enough alone all the time, I’d never get anywhere. So maybe it’s just about being able to dig myself out of problems. I know how to deal with this: I can still work on Windows, and I’ll fix my system tomorrow morning when I get into the office.

Hosting a teleconference call

December 18, 2008 - Categories: event

Last Wednesday, I hosted a teleconference call for the first time. It was the December community call for IBM’s Web 2.0 for Business Community, and I wanted to bring people together and talk about the interesting things people had done over the last year.

Before the event, I set up an event post on Beehive (one of our internal social networking platforms), figured out how to send out a Lotus Notes message with a button to add the event to people’s calendars (thank you, Bernie Michalik!), and borrowed a teleconference line from Ian McNairn. I also reviewed the comments and updates people had shared on the event post, copying it into a list so that I could summarize things briefly.

I was so nervous before the call started. What if I couldn’t figure out how to start the teleconference call? What if I couldn’t get into the Sametime Unyte session that we were using to provide an e-meeting backchannel? What if I’d made a dreadful mistake on the teleconference invitation? Fortunately, I kept enough of my wits about me to upload the material I’d prepared and start recording the session.

When I got everything set up and I saw people joining, I felt so relieved. A number of people joined the call early. We waited for five minutes for more people to call in, but I didn’t want to leave that time as dead air, so I kept repeating the call details and adding some notes about Web 2.0 resources I’d heard about. I had a slide with all the call-in information and the (very short) agenda, and I invited people to start introducing themselves in the backchannel.

We started the agenda at 11:05 AM EST. I welcomed everyone again (sixth time, perhaps?). I summarized the updates that people posted. People jumped in with more details, questions, and other topics for discussion.

What worked well?

  • I liked having the call-in information posted on the first slide, to help people orient themselves and reconnect in case they were lost.
  • I remembered to repeat the questions from the e-meeting on the phone, because some people weren’t connected to the chat room.
  • I liked the way that the event post allowed us to start the conversation and get lots of material for the call.
  • I really enjoyed connecting the dots during the call, recommending that people check out various resources or talk to other people. I also appreciated how lots of people shared their thoughts, too. It reminded me a little of talk shows with call-in questions. =)

How can I make this even better?

  • I can start the session with lots of useful tips on the first slide, to reward people who come in early.
  • I can show people’s pictures so that they get a sense of who else is in the community.
  • I can ask people to type the interesting bits into the chat, creating instant minutes.

Good stuff!

Emacs, Org, and BBDB: Hyperlinking names to blogs

December 18, 2008 - Categories: bbdb, emacs, org

Back when I used Planner for Emacs, I coded some shortcuts to make it easier to write about the people I met and the conversations I had. I used the hippie-expand module to complete names from my Big Brother Database addressbook, and I wrote a function that converted those names into links to people’s blogs or websites whenever I published my blog posts as HTML.

I switched to WordPress for my blog because I got tired of trying to figure out a way to enable comments without getting mired in spam-fighting. That meant I could explore other Emacs personal information managers like Org, which I turned into my main task manager. I often used the WordPress interface to write blog posts. I sometimes used Windows Live Writer to write posts about books (there’s a good book review plugin that makes this easy). I also sometimes used Emacs and Org to draft blog posts using Org’s friendlier markup, exporting snippets to HTML that I then pasted into my blog posts.

Reading the posts on Planet Emacsen reminded me that my customized configuration was pretty darn sweet. That and the conversation notes I’ve been blogging lately encouraged me to dust off my configuration files and get them to work under Org. So here’s the code:

 (defun sacha/org-bbdb-get (path)
   "Return BBDB record for PATH."
   (car (bbdb-search (bbdb-records) path path path)))
 (defun sacha/org-bbdb-export (path desc format)
   "Create the export version of a BBDB link specified by PATH or DESC.
 If exporting to HTML, it will be linked to the person's blog,
 www, or web address. If exporting to LaTeX FORMAT the link will be
 italicised. In all other cases, it is left unchanged."
      ((eq format 'html)
       (let* ((record
             (sacha/org-bbdb-get path))
       (setq url (and record
                      (or (bbdb-record-getprop record 'blog)
                          (bbdb-record-getprop record 'www)
                          (bbdb-record-getprop record 'web))))
       (if url
           (format "<a href=\"%s\">%s</a>"
                   url (or desc path))
         (format "<em>%s</em>"
                 (or desc path)))))
      ((eq format 'latex) (format "\\textit{%s}" (or desc path)))
      (t (or desc path))))
 (defadvice org-bbdb-export (around sacha activate)
   "Override org-bbdb-export."
   (setq ad-return-value (sacha/org-bbdb-export path desc format)))
 ;;;_+ Hippie expansion for BBDB; map M-/ to hippie-expand for most fun
 (add-to-list 'hippie-expand-try-functions-list 'sacha/try-expand-bbdb-annotation)
 (defun sacha/try-expand-bbdb-annotation (old)
   "Expand from BBDB. If OLD is non-nil, cycle through other possibilities."
   (unless old
     ;; First time, so search through BBDB records for the name
     (he-init-string (he-dabbrev-beg) (point))
     (when (> (length he-search-string) 0)
       (setq he-expand-list nil)
        (lambda (item)
        (let ((name (bbdb-record-name item)))
          (when name
            (setq he-expand-list
                  (cons (org-make-link-string
                       (org-make-link "bbdb:" name)
        (bbdb-search (bbdb-records)
                     nil nil))))
   (while (and he-expand-list
               (or (not (car he-expand-list))
                   (he-string-member (car he-expand-list) he-tried-table t)))
     (setq he-expand-list (cdr he-expand-list)))
   (if (null he-expand-list)
         (if old (he-reset-string))
       (he-substitute-string (car he-expand-list) t)
       (setq he-expand-list (cdr he-expand-list))

If you’ve got Org and BBDB, drop this into your ~/.emacs and fiddle with it. =)

Emacs: Working with multiple source trees

December 19, 2008 - Categories: emacs

As a developer, I often find myself working with multiple trees of source code. Sometimes, I’m comparing the trunk and the branches. Sometimes, I’m copying ideas from one place to another. Sometimes, I’m working on one project and an urgent defect comes in for a different project. With good development environments such as Eclipse, I’d still need to click on the project or directory in order to change my context, and then use a keyboard shortcut to find the resource in that tree.

With an awesome development environment like my customized Emacs, however, I can easily juggle multiple source trees. Here’s the macro I wrote to make setting this up much easier:

(defmacro sacha/file-cache-setup-tree (prefix shortcut directories)
  "Set up the file-cache tree for PREFIX using the keyboard SHORTCUT.
DIRECTORIES should be a list of directory names."
  `(let ((file-cache-alist nil)
	 (directories ,directories))
     (while directories
       (file-cache-add-directory-using-find (car directories))
       (setq directories (cdr directories)))
     (setq ,(intern (concat "sacha/file-cache-" prefix "-alist")) file-cache-alist)
     (defun ,(intern (concat "sacha/file-cache-ido-find-" prefix)) ()
       (let ((file-cache-alist ,(intern (concat "sacha/file-cache-" prefix "-alist"))))
	 (call-interactively 'file-cache-ido-find-file)))
     (global-set-key (kbd ,shortcut)
		     (quote ,(intern (concat "sacha/file-cache-ido-find-" prefix))))))

With that, I can use the following to map C-c p to finding files in my personal directories:

 "C-c p"

I’ve also set up keyboard shortcuts for the other trees I’m working on.

You’ll need file-cache, ido, and probably something like this:

(require 'filecache)
(require 'ido)
(defun file-cache-ido-find-file (file)
  "Using ido, interactively open file from file cache'.
First select a file, matched using ido-switch-buffer against the contents
in `file-cache-alist'. If the file exist in more than one
directory, select directory. Lastly the file is opened."
  (interactive (list (file-cache-ido-read "File: "
                                           (lambda (x)
                                             (car x))
  (let* ((record (assoc file file-cache-alist)))
      (if (= (length record) 2)
          (car (cdr record))
         (format "Find %s in dir: " file) (cdr record)))))))

(defun file-cache-ido-read (prompt choices)
  (let ((ido-make-buffer-list-hook
	 (lambda ()
	   (setq ido-temp-list choices))))
    (ido-read-buffer prompt)))
(add-to-list 'file-cache-filter-regexps "docs/html")
(add-to-list 'file-cache-filter-regexps "\\.svn-base$")
(add-to-list 'file-cache-filter-regexps "\\.dump$")

Summarizing my WordPress posts using XSLT; 2008 as a PDF

December 20, 2008 - Categories: blogging, geek, wordpress

It’s the time of the year for annual updates. I was thinking of reviewing all the blog posts I’d written this year. My weekly and monthly posts are incomplete, though, and I want to make sure I cover everything. I also know a few people who are slowly working their way through my archives. So I thought I’d export all of my posts from 2008 into something that people can read with fewer clicks.

If you want to skip past all the geek details, you can get the files here: 2008 blog (4.6 MB, 307 pages(!)), 2008 mostly nongeek entries (3.8 MB, 195 pages).

After some tinkering around with wptex and other modules that are supposed to make this easier, I gave up and decided to do it myself. I toyed with the idea of writing a short Ruby program that either parsed the XML or read the database, but I eventually ended up taking it as an excuse to learn XSLT, a language for transforming XML. WordPress can export posts and comments as XML. After I scrubbed my WordPress of spam and raised my PHP execution times, I downloaded the XML file and started figuring out how to get it into the form I wanted: a document organized by month, with a table of contents listing all the posts.

Here’s the main stylesheet I used:

 <xsl:stylesheet version="1.0"
   <xsl:output method="html"/>
   <xsl:template match="/">
       <h0>January 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Jan 2008') and wp:status='publish']"/>
       <h0>February 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Feb 2008') and wp:status='publish']"/>
       <h0>March 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Mar 2008') and wp:status='publish']"/>
       <h0>April 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Apr 2008') and wp:status='publish']"/>
       <h0>May 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'May 2008') and wp:status='publish']"/>
       <h0>June 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Jun 2008') and wp:status='publish']"/>
       <h0>July 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Jul 2008') and wp:status='publish']"/>
       <h0>August 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Aug 2008') and wp:status='publish']"/>
       <h0>September 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Sep 2008') and wp:status='publish']"/>
       <h0>October 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Oct 2008') and wp:status='publish']"/>
       <h0>November 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Nov 2008') and wp:status='publish']"/>
       <h0>December 2008</h0>
       <xsl:apply-templates select="/rss/channel/item[contains(pubDate, 'Dec 2008') and wp:status='publish']"/>
   <xsl:template match="//item">
       <xsl:attribute name="href">
         <xsl:value-of select="link"/>
       <xsl:value-of select="title"/></a></h1>
     <div class="link"><xsl:value-of select="link"/></div>
     <div class="date"><xsl:value-of select="pubDate"/></div>
     <div class="content">
       <xsl:value-of select="content:encoded" disable-output-escaping="yes" />

For the non-geek version, I replaced the template with:

   <xsl:template match="//item">
     <xsl:if test="not(category[@nicename='emacs']) and not(category[@nicename='drupal']) and not(category[@nicename='geek'])">
       <xsl:attribute name="href">
         <xsl:value-of select="link"/>
       <xsl:value-of select="title"/></a></h1>
     <div class="link"><xsl:value-of select="link"/></div>
     <div class="date"><xsl:value-of select="pubDate"/></div>
     <div class="content">
       <xsl:value-of select="content:encoded" disable-output-escaping="yes" />

I didn’t want to figure out how to demote all the headings in my blog posts (I have a few), so I used <h0> as my root element. I used xsltproc to transform the XML file I got from WordPress. Then I adjusted all the headings with the following bit of Emacs Lisp:

 (defun sacha/demote-all-headings ()
   (while (re-search-forward "</?h\\([1-7]\\)>" nil t)
    (replace-match (number-to-string (1+ (string-to-number (match-string 1)))) nil t nil 1)))

It’s all held together with bubblegum and string, really.

2008 blog (4.6 MB, 307 pages(!)), 2008 mostly nongeek entries (3.8 MB, 195 pages)

I haven’t looked at these files much yet – I just scrolled through them quickly. No, don’t worry, I’m not going to send my 2008 update as 307 pages in the mail. ;) But it’s there so that we can flip through it or you borrow the code, and someday I’ll even figure out how to format the output neatly and everything.

Next step: I need to read all of that and highlight a couple of things that made my year.

(307 pages! Wow.)

Weekly review: week ending Dec 21

December 22, 2008 - Categories: weekly

Last week:

  • Dealt with lots of little bugs for the Drupal-based project we’re working on. Solved an IE7 problem blind.
  • Automated the build process for the Drupal-based project I’m working on next week. Ah, lazy programmers.
  • Caught up with lots of people at #hohoto; still owe them e-mail.
  • Had coffee with Jeff Muzzerall and Sameer Vasta, who got along splendidly. Hooray!
  • Put together 2008 letter with W-. Getting pictures printed turned out to be more of an adventure than expected.
  • Picked up better cat food at Global Pet Foods store. Also picked up a can of turducken for their Christmas dinner. (Turducken! In a can! Sheesh.)
  • Had great fun chatting with my mom through her new computer.
  • Exercised a bit.
  • Watched classic movies. Picked up a bit of a drawl.

Next week:

  • Mail annual letter. – Mostly done.
  • Get in the groove of the education-related Drupal-based project. Generalize my web-based install and deployment script for the second project, and make the build guy very happy.
  • Celebrate the holidays. Maybe plan a treasure hunt for J-‘s present.
  • Make the Drupal-based conference site while work is at a lull.
  • Review all of my blog posts.
  • Contact Ian Eure about book.
  • Start editing Emacswiki pages.
  • Learn even more about Drupal.

My Enterprise 2.0 blogroll

December 24, 2008 - Categories: enterprise2.0, social, web2.0

A few weeks ago, Jeff Widman asked me what I do to learn more about Enterprise 2.0. I told him that there aren’t that many bloggers looking at how companies can use Web 2.0 internally, and that much of what I learn comes from my day-to-day interactions within IBM and the consulting I do for our clients. There are a number of blogs I read, though. Here’s the list from my Google Reader:

To read them on a neatly aggregated page, check out my Enterprise 2.0 page on Google Reader.

I just stumbled across that feature by checking out the Manage Subscriptions page, clicking on Folders and Tabs, and changing the sharing. Interesting…

Sketches: 2008 highlights

December 24, 2008 - Categories: sketches, yearly

A quick sketch of the highlights of my year:

Letter and photos to follow! =)

2008: Annus Mirabilis

December 25, 2008 - Categories: sketches, yearly

What an incredible year!

Di's wedding We took two trips to Manila: the first to introduce W- and J- to my family, and the second to attend the wedding of one of my best friends from high school. It was well worth all those nights of rice and beans–which were delicious, so that was no sacrifice. I can’t tell you how wonderful it is that W- can joke about local details like Cash and Carry or my barkada‘s hijinks. Manang Norma taught him how to make laing and pinakbet, and my dad taught both of us about high-speed photography. My godparents interrogated W- over tea, which (in the classic Filipino tradition) lasted until late evening. Now that he knows more about the home where I grew up, I feel more at home here in Canada.

Mali NekoDuring our trip, W- and J- met Mali, the elephant my dad takes care of at the zoo, and we all enjoyed feeding her bananas. I also introduced them to my cat, Neko. She gave W- the seal of approval by deigning to sit on his lap, which she doesn’t do for just anybody.

planeThe trips were full of experiences. We went to Pagsanjan Falls, Tagaytay, and a few other interesting places in the Philippines. My dad flew us around the ricefields and rivers of Angeles in an ultralight plane. We were serenaded by the UP Singing Ambassadors over dinner, too!

J- We’ve been practicing photography, and have started buying glass (lenses) and light (flashes). We’ve been getting plenty of practices at events like W-‘s grandfather’s 98th birthday, at which we all had a turn at being photographers – and being voice-activated light stands. We had our very first fashion shoot, too, taking pictures of J- in her back-to-school clothes.

This was the year of baked awesomes. I told W- a story about egg tarts and how some boys used to bring them for my family while courting, and he promptly figured out how to make egg tarts that beat anything you’d find at Lord Stow’s Bakery. He sometimes surprises me with freshly-baked cinnamon rolls or corn-bread muffins. Not to be outdone, I occasionally make cakes or piles of cookies. We’ve perfected our own <insert favourite topping> oatmeal cookie recipe, and have put it to good use during play-dates, tea parties, and dinner parties.

Fortunately, we’ve been reasonably active. During the earlier part of the year, W- and I took krav maga and yoga lessons. J- has just received her yellow belt in aikido, and is taking swimming lessons, too. Now that the weather’s cooler and the mosquitoes have disappeared, we’ve started hiking the Bruce Trail. The GPS unit W- picked up prevents us from getting too lost, and that’s nice to know when it’s cold and snowy.

I’m slowly getting the hang of winter. The hats I picked up at a Tilley sale are good at keeping my ears warm and my spirits up. The hiking staff helps me navigate slush and ice. And there are little things to look forward to – winter walks with W-, tobogganing down the hill… Well, I’m here, so I might as well find something to get me through!

Luke and Leia On a wintry day, there’s only one thing more wonderful than having a warm, purring cat: having two! The story begins with Magic, a stray cat who followed us home one fall evening, and became our guest for two weeks while we searched for her original owners. Shortly after we returned Magic to her grateful family, we adopted Leia from Toronto Animal Services. After Leia recovered from her sniffles and was spayed, she became such a wonderful cat that we just had to adopt another one. Thus Luke entered our lives. There’s never a dull moment with those two around, especially when they hear the fridge, microwave, crinkling plastic, or any sound associated with feeding time.

It’s been a terrific year at IBM, too. I’ve gotten really deeply into Drupal hacking, and I’m having a lot of fun. I’ve also facilitated a number of workshops and delivered talks on Web 2.0, social networking, and Generation Y. My team keynoted a couple of conferences – that was fun, too. I developed my own presentation style (ooh, stick figures) that made my self-introduction one of the winners of’s Worldwide Best Presentation Contest. I’m totally rocking my work. ;) You know, I might be getting the hang of application development and consulting… this is cool!

I’ve been learning a lot outside work. After four chapters of my Emacs book, I got distracted with all the cool Drupal stuff I did at IBM, so Emacs hacking got put on hold. I’ve recently resumed tweaking my configuration and sharing my notes, and I’m looking forward to more Emacs customization. I’m working on my visual communication skills, challenging myself to express abstract ideas through photographs (stock images or my own) and doodles. I’m getting better at connecting the dots between people and other people, ideas, or resources for making things happen, and that’s tons of fun too.

What’s next for me in 2009? More Drupal and Emacs hacking – there’s so much I can do now, and I can’t wait to learn more. I’d like to think about and share more things we’ve learned from social computing at IBM, too. I also want to learn how to organize events, and I’m volunteering to help with some of my favorite events in Toronto. I want to learn more about regularly connecting with people, and I hope to have monthly dinner parties and other get-togethers. I’m looking forward to learning more about illustrating and writing, and you’ll see stuff like that in my blog. I still have a lot of paperwork to do for my permanent residency application, but I hope to get that sorted out next year. I’m looking forward to 2009 – it’ll be awesome, too!

Happy holidays! Tell me about your year in a blog post or a comment – I’d love to know your 2008 highlights and 2009 plans!

2008 summary

True Change: How Outsiders on the Inside Get Things Done in Organizations

December 28, 2008 - Categories: book

True Change: How Outsiders on the Inside Get Things Done in Organizations

Janice A. Klein, 1st ed, ISBN 0-7879-7473-0

… changes in organizational strategies usually create micro challenges at the working level. These become opportunities for outsider-insiders throughout the organization to identify gaps between current work practices and changes needed to address the new strategic objectives. … Here is an opportunity for outsider-insiders within each functional group to identify gaps and introduce new ways of working collaboratively to achieve the company’s strategic objectives. (p53)

This made me think about how higher management changes the strategy, and how evangelists adapt to those changes and help their teams adapt to those changes. It also points to the role of top-down change management coupled with bottom-up.

Once the stage is set, outsider-insiders at the grassroots level can more effectively leverage opportunities to pull in change at a tactical (micro) level. They are the ones dealing with daily challenges that provide the opportunity for hem to help others see where cultural assumptions are getting in the way of overcoming those challenges. But few working-level outsider-insiders have the influence or resources that executive outsider-insiders, such as Lou Gerstner, are privileged to possess. Instead, they must find daily, local levers to help educate their peers and managers. Like their senior-level outsider-insiders, they must become teachers helping others to see the value in questioning assumptions. (p63)

Tech evangelists often need to influence without having direct authority. They use their understanding of people’s situations to help people see the value in new tools or ways of doing things.

People who are developing outsiders-insiders need to be continually reminded of the macro challenges facing their organizations. There are many possible outsider perspectives that insiders will be exposed to during their development journey. They need someone… to help steer them to develop perspectives that will be useful internally. Often this role is played by outsider-insiders who have already experienced the journey. Not only do they tend to be more sensitive to the trials and tribulations associated with learning to wear two hats, they already value outsider perspectives. (p111)

It’s easy for tech evangelists to focus on the new technologies or tools, chasing the next new thing. Mentorship by other people who can balance the inside and outside perspectives helps tech evangelists keep perspective.

The need to remain connected is especially keen for insiders who are fully immersed on the outside. The linkages must give distant employees sufficient autonomy to experience and absorb their new cultural environments while making them feel that someone back home still remembers them. If the bonds are too tight, there is a risk that one will not break out of the mental models that block absorption of new ideas or be willing to explore alternative worldviews. Linkages also serve as a conduit for letting home sponsors or peers have a window into what insiders are learning on the outside. Without periodic communications, insiders run a risk of being viewed as just someone who was away “on vacation” and not providing value to the organization. (p111)

This part reminded me of how many consultants are on long-term projects with other companies, and they can feel isolated. We had a lecture about the challenges of manpower outsourcing during my technical internship in Japan, and now that I think of it, I can see the same symptoms in our environment here in Canada.

… Since newcomers want to be accepted by others in their new organization, many attempt to conform to existing norms and avoid questioning existing ways of doing things. At the other extreme are those recruits who believe in the pushcart notion of change and take the opportunity of being an outsider to throw out trial balloons filled with new ideas. Without care, they generate so many waves that it inhibits their ability to be accepted and destroys any chance for building credibility for their outsider concepts. When the latter occurs, potential outsider-insiders begin questioning whether they made a wise employment choice. Many of those who decide to stay find the path of least resistance to be conformity to existing norms and expectations: they become insiders. Organizations must therefore find way to protect and nurture outsider perspectives while helping outsiders to develop the second half of the equation: becoming a valued and respected insider. (p123)

The book goes on to make the point that experienced hires may be the best for introducing change, because they can probably avoid most newbie mistakes and their experience can jump-start their credibility. Hmm.

Here the focus is twofold: (1), quickly plunging new recruits into the culture without stifling their outsider perspectives and (2) jumpstarting the credibility-building process to help new recruits become insiders without negating the value of the outsider perspectives. (p125)

This part made me think of social media. It can (1) introduce new recruits to the culture within an organization, and (2) make it easier for them to establish their credibility by sharing knowledge.

Given the sheer numbers of problems lying around organizations, outsider-insiders need more than luck to ensure that they can put their ideas and skills to work on the most critical gaps. Many outsider-insiders, especially those who reside in the lower echelons of large hierarchies, need assistance in finding their way through their organizations’ mazes. Likewise, managers who face key challenges at both the macro and micro levels need assistance in locating outsider-insiders who have appropriate competencies to help address the challenges. Both need matchmakers: scouts or friends throughout their organizations who can identify and connect outsider-insiders to key problem areas. Developing a critical mass of outsider-insiders is only the first step toward building an army of employees to create the “pong” required to address macro challenges. The final step is getting these outsider-insiders to the right place at the right time so that they can apply their two-hat perspectives to finding the right opportunities to pull in new ideas and ways of doing things. (p147)

Necessity of matchmakers. Must learn how to do this even more effectively…

Interactions with developing outsider-insiders can also present an opportunity for personal reflection. Effective mentoring serves as a dual support system for both mentors and mentees. Developing outsider-insiders act as windows for their mentors, enabling them to see gaps in generational assumptions — another form of cultural blinders. (p181)

Benefits to mentors – opportunities for reflection, questioning their own assumptions.

What I like about this book is that it looks at ways to cultivate an environment of questioning and innovation by preparing insiders to think with outsider perspectives and preparing outsiders to work with inside understanding. It’s not about pushing one particular change through; it’s about helping people learn how to build bridges across the chasm.

Weekly review: Week ending Dec 28, 2008

December 29, 2008 - Categories: weekly

You can tell a lot about people by the way they spend their vacations. Some people escape to tropical islands for a week of pampering. Others seek thrills in wild adventures. W- and I baked a ton of cookies and egg tarts, tidied up the house, and caught up on plenty of sleep.

Last week:

  • Virtually attended Adphoto Christmas party.
  • Finished custom-fit sewing pattern, after many struggles. Transferred onto pattern cloth.
  • Read plenty of books
  • Treated cats to turducken (cat food in a can, oh my!).
  • Had dinner with W-‘s family.
  • Prototype Drupal-based conference commando site for internal use.
  • Sent annual updates out by e-mail and blog post.
  • Reviewed and printed photos.

Plans for next week:

  • Continue bugging the project managers for more work.
  • Mindmap upcoming events.
  • Create conference type for Drupal-based site.

Web 2.0 Inside and Outside the Enterprise: York University MBA

December 29, 2008 - Categories: event, presentation, talk

I’ll be giving a presentation on how enterprises use Web 2.0 inside and outside the organization to Dorit Nevo‘s MBA class at York University on February 10, from 8:30 PM to 10:00 PM.

Current status: Mindmapped
Next action: Prepare detailed outline

Learning more about Drupal 6

December 29, 2008 - Categories: drupal

It’s another slow work day, so I invested some time in learning about Drupal 6. Now that I’m familiar with Drupal’s structure, I’m tempted to move my blog to it. The wordpress_import module successfully imported my existing blog posts and comments. In order to make it work, I needed to delete all the spam comments and increase my PHP execution limits to 4 minutes and 256 MB RAM.

I remember how I migrated all of my posts from Emacs Planner into WordPress by generating and slurping in the RSS feed. I’m using a similar process now using WordPress’ XML Export format. I don’t even need to break it into smaller RSS feeds for memory usage.

I’m currently prototyping things through Drupal’s web-based interface. It’s easier to explore, but it also makes me slightly nervous because my changes haven’t been checked into my git repository. I use a custom module instead of making types through CCK, though, as I find it easier to hack PHP than figure that out. ;)

So what is it like now?

Screenshot of Drupal site

The key piece I’m working on is a way to keep track of recent and upcoming presentations, conferences, and other events. I’d like to eventually tie that into a content management system that will make it easy for me to plan future talks, too. I wonder if I can use this to learn about Twitter and Facebook integration as well… =)

We’re still on Drupal 5 at work, but it’s fun experimenting with Drupal 6 and wrapping my mind around the differences. I’m looking forward to learning more about tasks in installation profiles, theming, and other good things.

Always learning!

More Drupal awesomeness: hosting with aegir

December 29, 2008 - Categories: drupal

Adrian Rossouw e-mailed me about aegir, a multi-site hosting system he had helped develop. I finally got around to trying it out on my local system, and I’m impressed. It easily handles the creation of virtual hosts and settings.php, and it can provision sites with different installation profiles. I could see people using this for the kind of Drupal hosting that many companies now do. Kudos to Bryght for giving this to the open source community!

It wasn’t difficult to get up and running. Follow the installation wizard, and you’re pretty much all set. I wonder if I can get our project to this level of awesomeness.

aegir: managing a large number of Drupal sites

Two screens without rebooting, with xrandr

December 30, 2008 - Categories: geek

Dual screens can improve your productivity by up to 50%. It’s one of the reasons why I like working at home – I can hook the desktop’s monitor up to my laptop for even more coding goodness. I could hook the Cintiq up if I ran X across a network connection, but three screens would just spoil me rotten. ;)

I used to switch my xorg.conf manually depending on whether I wanted a dual-screen or single-screen setup, but that required closing all my applications and restarting X. I wondered if there was a better way to do it. I came across Ubuntu Forums: Switch view modes (twinview) without leaving/reconfiguring X?, which led me to HOWTO: YES! There IS an easy way of trying out Xorg.conf without reloading X. The main post wasn’t helpful, but the segment “HOWTO: Make use of RandR 1.2 – or the ability to stick with one X configuration and dynamically add or remove screens and change display setups dynamically” was. I checked if xrandr was on my system, and it was. I removed the unnecessary lines from my xorg.conf and added the lines about SubSection “Display”… and it worked. Hooray!

For future reference, here’s the command I used to set up my dual-screen display:

xrandr --output LVDS --right-of VGA-0   

This rocks.

Not personal enough

December 30, 2008 - Categories: life, reflection

It took me a while to write to the bottom of that one, to break through the confusion and anger and get to some kind of understanding. I’m probably not going to post all of that, because now that I’m looking at it through the slightly-numbed lens of a good cry and a cat-cuddle, it’s a bit much for something triggered by a few words from two people.

It’d be good for me to share the summary, though.

For many people, a slightly-personalized version of my yearly update was a good reminder in a convenient format and a prompt to perhaps reflect on their own year and plan the next. Most people replied back with their own updates and plans, and I’m in the middle of many enjoyable conversations that branched off from there.

For some people, though, it wasn’t personalized enough. After lots of scribbling, writing, and a surprising anger at unrealistic expectations, I realized that my feelings about this can probably be traced to these things:

  • Sharing parts of your life with distant people is HARD. Great letter-writers like Jane Austen or Isaac Asimov might be able to handle it, but I’ve still got a lot to learn. I’m tired of feeling guilty about this, particularly as I think these expectations are unrealistic.
  • I really don’t like the “this glass is half empty” attitude towards relating with people. It makes me uncomfortable and even somewhat angry. I know people don’t mean it that way, but it hurts enough for me to feel tempted to avoid it.
  • The generic part of the e-mail is like the generic part of small talk – it’s just there to start a conversation. It would be awkward to start a conversation with a friend you haven’t talked to in ages with a deeply personal secret, and it feels awkward to start an e-mail conversation with people I don’t share many experiences with using the same kind of tone and banter I’d have with people I interact with every day. I’d be happy to reply to people or chat on the phone/computer with them, but I’m not going to start e-mail like that.
  • I feel comfortable sharing a great many things on my blog. I feel comfortable sharing more everyday or tentative things in person, with people who share those experiences. The set of things I don’t feel comfortable blogging but I feel comfortable sharing with distant people is very small, because I’d rather talk about things in person with people who are sharing those experiences. If I needed to think through something, I am more likely to talk over it with my partner or bring it up over lunch or dinner with friends than I am likely to talk about it with my parents over video-chat or e-mail distant friends. I could probably sit down and write an e-mail about something, explaining all the background context, but it’s much easier for me to just talk to someone who knows all of that already, and getting people to that point is hard because it builds on all these everyday things.
  • I find it really difficult to start conversations. Reading other people’s Facebook feeds, tweets, blog posts, or similar lifestreams is great, because I can just think of my e-mail as responding to them. Posting things on my blog for some unknown audience is easy, because I’m just putting things out there in case. Starting from scratch is hard. So I’m too shy to start a conversation, but not too shy to post things just in case other people want to start them. Someday I may learn how to do this, but it’ll probably take me several decades to become truly comfortable with it.

The glass is at least half-full, and if we focus on that part, it’ll be much better than focusing on the empty part.

UPDATE: I figured out some more while cooking dinner! I realized that one way to get around my shyness is to keep track of which people prefer fully-personalized e-mail, and ask _them_ to write first so I can reply. ;)

Websites that write websites

December 31, 2008 - Categories: drupal

“So nat’ralists observe, a flea
Hath smaller fleas that on him prey,
And these have smaller fleas that bite ’em,
And so proceed ad infinitum.”

– Jonathan Swift

One of the things we were daydreaming of having for our Drupal-based project was a meta-configuration system we could use to set up a custom microsite platform, which would then host hundreds of sites. The client was interested in being able to launch thousands of such platforms (hosting hundreds of microsites each). We’ve built four so far, forking the source tree and making all of our customizations in files included in the installation profile or in a few custom modules.

As the cats woke me up bright and early today and I had no defects on my list, I decided to see if I could build that a-la-carte configuration system we had been thinking of: a system that would allow us to choose a set of features and then generate the skeleton of a new project which developers and themers could then flesh out.

I started by refactoring the installation profile I used for a recent site, pulling out all the site-specific information and placing it in a separate file. For ease of use, I put the variables in a, which I included in my settings.php together with some clever code to load common variables and domain-specific variables. I refactored the rest of the code into When the dust settled, my settings.php was down to two lines: one line to pull in the project-specific includes, and one line to pull in the common set-up code. This was one of the files I was going to write to the disk, so I wanted to minimize the risk of errors by making the file as clean as possible.

Once I sorted out the code, it was time to dynamically generate the After studying aegir‘s provisioning system, I created a simple installation profile that loaded the aegir system and a custom module. I created a form that asked for all the relevant information. Then I wrote the code to generate sites/all/projects/<project>.inc, create the domain directories, and create the appropriate settings.php for each domain.

After I got my New Project Wizard to work, I wrote some code to list the project include files available, and then I tested loading and dumping them to the screen. When I successfully loaded the settings, I revised my project wizard to allow the selection of a previously-created project as a template. After that, I created an edit form that read in the generated project include file and saved the changes back to the file.

It’s a pretty nifty system. I like being able to set all the details I usually forget, like Google Maps API keys and database URLs. I’m looking forward to pushing it even further by being able to select groups of features, if the project managers are interested in it. With a bit more polishing, it could probably wow the client.

Apologies for the lack of code; IBM’s still a little iffy about this kind of stuff. =) Hope you can figure things out with these hints!