Archive for the 'Programming' Category


Shooting for the 5%: reading more, writing more (code)

2008-01-04 / 14:10 / dave

An even more fascinating metric is this: 5% of programmers are 20x more productive than the other 95%. If this were a science, like it claims, we could figure out how to get everyone to the same level
– Bruce Eckel, The Mythical 5%

Good point, but how? Bruce’s advice, distilled, is something like:

  1. Create the best environment–tools, people, practices–you can
  2. Be analytical, reject fads
  3. Be diverse: don’t forget business, economics & people skills
  4. Be willing to change your mind

Despite getting a BS in both engineering and computer science, a big weakness of mine is #2. Not so much because I lack the skill to be analytical, but because I lack the patience. I have trouble turning my brain off of internet time. Why concentrate one thing when I can write code, while reading blog posts, while listening to podcasts (65% faster no less)? Another weakness is one that he doesn’t mention but which is mightily flogged in every other “how to be successful” piece: willingness to fail. I tend to be pretty inertial and fear of failure is one main reason.

Like most deadlines, I’m late with my new year’s resolutions. With an eye towards the 5%, here they are:

  1. Be analytical in my self-reflection: Track my life “bugs”, make some metrics pretty & shareable
  2. Practice patience by reading books instead of just crappy blog posts (mine included)
  3. Write more code even if it sucks: my fun a day is solving Project Euler problems. I’m only one behind!

You down with APP? Yeah you know me! (Oh wait, maybe not on Dreamhost)

2007-12-24 / 14:02 / dave

In a combined quest to edit this blog from Emacs and stay super-cool, I’ve been trying to get atompub working on Wordpress 2.3.1 hosted on Dreamhost.

Will it work? Will I master the Atompub standard? Am I typing this in the world’s best editor?

Spoiler: NO

Read on for the thrilling details…

All I need to do is get to the damn URL

I started with the Wordpress AtomPub page in the Codex which recommends testing with Tim Bray’s APE. Time to first error: 5 seconds.

A typo in the codex said the end point was http://[Blog URL]/wp-app.php service. Er, that’s probably not a space, huh? I do the right thing and fix it.

The right URL still gave either a 404 or the extremely helpful “No input file specified” (I forget which condition produced which). Googling for “No input file specified” brought up this helpful number. I had already checked that Dreamhost was running PHP as CGI, so the error means that something is not getting forwarded right.

Well it looks like Wordpress Atompub might not work with PHP4, so I switched Dreamhost to PHP5:

Dreamhost: how to change PHP version

Now I can surf to the URL and, thanks to the magic of the “cookies give you permission” hack inside wp-app.php and

<?xml version="1.0" encoding="utf-8" ?>
<service xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
  <workspace>
    <atom:title>WordPress Workspace</atom:title>
    <collection href="http://ndanger.org/blog/wp-app.php/posts">
      <atom:title>WordPress Posts</atom:title>
      <accept>application/atom+xml;type=entry</accept>
      <categories href="http://ndanger.org/blog/wp-app.php/categories" />
    </collection>
    <collection href="http://ndanger.org/blog/wp-app.php/attachments">
      <atom:title>WordPress Media</atom:title>
      <accept>image/*</accept>
      <accept>audio/*</accept>
      <accept>video/*</accept>
    </collection>
  </workspace>
</service>

Hooray!

Mere steps away

Predictably, APE gives me an authorization error

APE credentials required screen shot

That’s covered in the codex. Unfortunately, neither the “HTTP Authentication with PHP” suggestion the codex links to or Joseph Scott’s get hack works.

Time to turn on logging in wp-app.php, and tail -f wp-app.log.

Maybe the rewrite rule isn’t getting applied? A test–by forwarding to my about page–works, so the rule is getting applied. Maybe the environment hacking isn’t working, so I redirect to a test script:

<?
$agent       = $_SERVER['HTTP_USER_AGENT'];
$ip          = $_SERVER['REMOTE_ADDR'];
$port        = $_SERVER['REMOTE_PORT'];
$d           = date ('dS \of F Y h:1:s A');
$ha          = $_SERVER['HTTP_AUTHORIZATION'];

echo "Your IP : $ip<br>";
echo "You are using : $agent<br>";
echo "You are connected through port : $port<br>";
echo "Today is : $d<br>";
echo "HTTP_AUTHORIZATION : $ha<br>";
echo "<br>_SERVER:<br>";
foreach ($_SERVER as $key => $value) {
  echo "$key: $value<br>";
}
echo "<br>_ENV:<br>";
foreach ($_ENV as $key => $value) {
  echo "$key: $value<br>";
}
echo "<br>_GET:<br>";
foreach ($_GET as $key => $value) {
  echo "$key: $value<br>";
}
?>

Both hacks seem to work in theory, except that the header I need–HTTP_AUTHORIZATION–seems to be absent, even if I use curl to manually set the headers using the example in the RFC.

More googling turns up the blocking of BasicAuth in WinXP SP2. Enable that. Nothing.

By now it’s 4 am and I’m still starting at a 404, so I post to the Dreamhost support forums.

And you got an answer, right?

Nah. That was all 3 days ago, so now I submitted a help ticket to the support staff. Have’t heard anything back yet, but that’s probably because I marked it as “Hey, it’d be nice, but it’s not holding me up”.

Anyone got any suggestions? I was going to set up a test directory and see if Apache’s .htaccess authentication–in BasicAuth mode–works.

In the meantime I’ll try out XML-RPC… it looks like there’s even an Emacs package.


UPDATE:

Heard back from dreamhost:

Hello,

Unfortunately, I’m not sure what would cause this, however, we can’t
really provide support for custom scripting, or custom mod_rewrite rules.
Sorry about that.

If you need anything else, please let us know.

Thanks!
Brian


A brief higher order function example in python

2007-12-24 / 13:19 / dave

The cast

dataset
An object for handling table-like data
dataset2
Version 2
dsutils
Utility functions for dataset
dsutils2
utility functions for dataset2

Act I

# dsutils2.py
from dataset2 import Dataset2
import dsutils as dsutils1
row2col2 = lambda ds2, *a, **ka: \
     Dataset2.from_dataset1(dsutils1.row2col(ds2.as_dataset1(), *a, **ka))
col2row2 = lambda ds2, *a, **ka: \
     Dataset2.from_dataset1(dsutils1.col2row(ds2.as_dataset1(), *a, **ka))

Act II

# dsutils2.py
# same
wrap_ds1f = lambda f: lambda ds2, *a, **ka: \
    Dataset2.from_dataset1(f(ds2.as_dataset1(), *a, **ka))
row2col2 = wrap_ds1f(dsutils1.row2col)
col2row2 = wrap_ds1f(dsutils1.col2row)
# in interpreter
>>> import(dsutils2)
>>> help(dsutils2)
Help on module dsutils2:
...
    col2row2 lambda ds2, *a, **ka
    ...
    row2col2 lambda ds2, *a, **ka
    ...
    wrap_ds1f lambda f
...
# That's not very helpful

Act III

def wrap_ds1func(ds1_func):
    """Create a wrapper for a function that accepts a dataset1 as it's first
    argument.  This creates a wrapper that converts a dataset2 into a
    dataset1, runs the function and converts the result  back to a dataset2.
    """
    def ds2_func(ds2, *args, **kargs):
        return Dataset.from_dataset1(
            ds1_func(ds2.to_dataset1(), *args, **kargs))
    ds2_func.__name__ = "%s2" % ds1_func.__name__
    ds2_func.__doc__ = "dataset2 version of %s, orig docs below.\n%s" \
                       % (ds1_func.__name__, ds1_func.__doc__)
    return ds2_func

row2col2 = wrap_ds1func(dsutils1.row2col)
col2row2 = wrap_ds1func(dsutils1.col2row)
# in interpreter
# same
Help on module dsutils2:
...
    col2row2 = col2row2(ds, *args, **kargs)
        dataset2 version of col2row, orig docs below.
        Convert a row with several columns into several rows with...
    row2col2 = row2col2(ds, *args, **kargs)
        dataset2 version of row2col, orig docs below.
        Convert several rows with related values into a single row with...
    wrap_ds1func(ds1_func)
        Create a wrapper for a function that accepts a dataset1 as it's first...
...
# better!

Epilogue

Longer, but reusable. And with readable help. Is it worth it? We’ll see. Either way higher order functions sure are nice.


By the year 2100, humans will not pass the ServoTron8000 test

2007-12-21 / 13:55 / dave

It is also important to note that once a computer does achieve a human level of intelligence, it will necessarily soar past it.
– Ray Kurzweil

Ray Kurzweil and Mitch Kapor debate the distant future of the Turing Test. Kurzweil–who I agree with more than Kapor–bases his argument on exponentials. Once self-aware machines exist they will improve rapidly for two reasons: 1) short iterations and 2) directed evolution.

If we assume that a computer that is self aware will take 1 micro-second (10^-6) to reprogram itself, one human generation (say 20 years) is more than 6 x 10^14 machine generations. Put another way, humans have been around for 2 million (2 x 10^6) years, or 10,000 generations. Machines would go through 10,000 generations in less than a second.

And for humans that was 10,000 generations of trial and error! Machines can direct their evolution. It’s true we can direct our technology, but imagine being able to, say, reprogram yourself to be 10 times smarter (or 10 times more beautiful which is what we’d probably all choose instead).

Combine the two and as soon as we develop machine intelligence bam! singularity. The very definition of the singularity is that we can’t predict beyond it.

To hell with that.

The lifeforms of the future–a more apt term than artificial intelligence–will be as different from us as we are to mice. Or perhaps as different from us as we are to current AI’s.

Maybe in 2078 some pundits will be sitting around arguing if humans can pass the ServoTron8000 Test. “No, ” one will argue “although the humans have a demonstrable grasp of intuition, they have never shown anything like full fledged holo-logical thought processes.”

I, for one, welcome our self-reprogramming digital overlords.


But say you did want to automatically enable all ssh keys on login…

2007-12-19 / 15:33 / dave

I launch my ssh enabled shell on demand, but if you are comfortable leaving it open (or using ssh-add -x to manually lock your ssh keys) add this to your startup file (.bash_profile or whatever):

eval `ssh-agent -s`; ssh-add

You’ll need to enter your password when you start the shell, but afterwards you’ve got all the password-less ssh goodness you can stand.


Debt and ugly code

2007-12-19 / 14:54 / dave

Jeff Atwood says that nobody cares what your code looks like, which–despite Jeff’s absolutely hilarious Joel Spolsky diss–is something Joel also talked about.

Ok, your customers don’t care what your code looks like… but they probably do care what it does. So saying “code beauty doesn’t matter” is the same as saying “ugly code works just as well as beautiful code”. You could argue that if the tests pass it’s all the same. But most customers also care about how well your code will function in the future. Does anyone really think that ugly code is as easy to change?

The agilists would say that ugly code is Technical Debt (well actually they would say that smelly code is technical debt but that’s irrelevant). Like real debt, technical debt accrues interest. Bug fixes muck up its guts and new features build on its interface, and, if your code is hideous, it’s a fair bet the interfaces aren’t much prettier.

But if we torture the metaphor some more (though I don’t consider this #2), debt can be a valid growth plan, just ask 90% of startups. Debt (technically selling your future worth for venture capital) is betting that you can run fast enough to reach profitability.

For code it’s hard to imagine you can build a critical mass of ugly code that will suddenly become beautiful, in fact that probably violates the second law of thermodynamics. In companies where speed & features are tied to lifespan (via convincing people to give you money), however, a fortune might let you amass a big enough army that you can reach that asymptote. Some people seem to be using the strategy, though it’s questionable how well that’s been working.

What of open source? For a commercial company where open source is largely a “look, you can see our code, so no lock-in!” feature, like Jeff’s example of his friend at a “large open source database company”, technical debt functions almost the same as in a closed-source company. I’d argue that it’s a bit worse; some people still eat fast food after having worked in the kitchen, but most swear it off and tell their friends that it’s full of tubes of grade E meat and cockroaches. It’s especially bad if your customers are programmers.

And if you want people to contribute to your open source project…

Despite what some people who inherited my code might think, I’ve always been a fan of beautiful code but I’ve come to understand the economics of “screw it”. But I think that the two can be rectified.

A small example to conclude. When I was in school I interned working on a speech recognized written in C (it was for an embedded device). Every new feature or bug-fix I worked on had an accompanying local code-cleanup. Ultimately I did a massive clean-up on the audio front-end, touching something like 75% of the file, and remember that this was a C file (i.e. it was big). The code review spanned two day but afterwards the code was smaller and, to everyone’s agreement, cleaner. I don’t have any metrics about it reducing bugs by 20% or anything, but I’m fairly confident it was worth the cost: about 1 full-time developer day and about 1 part-time intern week.


Emacs & version control

2007-12-18 / 23:08 / dave

Emacs does version control! If you’re tunneling your version control through SSH, you should probably set up those ssh keys


Ron Paul’s army & Reddit just jumped the shark (oh wait, maybe not)

2007-12-18 / 22:46 / dave

Since Reddit has become the official site of Ron Paul stories, I wasn’t surprised to see this video of Ron Paul denying evolution. Nor was I surprised by Dr. Paul’s answer as I’ve heard him give the Republican “It’s the volcanoes and cow farts!” answer to global warming (citation needed). I was surprised (well, only a little) by the initial responses on the Reddit comment thread. I don’t feel like reading through the comments to find some examples, but a lot of them were making excuses for Paul, saying that he didn’t mean it.

It was maddening… maddening enough that I was going to write a sternly worded blog post about it!

But then I went back later and read the new comments and whew what an improvement. In fact, they had gotten so insightful it restored some of wavering faith in Reddit.

Reddit’s “hot” page has recently been a train wreck. It’s all pictures and stories about Dr. Paul. Ok, occasionally I up-mod both, but I really don’t feel like I need to see 8 stories about the same one day fundraiser record. But normally reddit’s comments are sane enough that I figure there must be smart people using it. So I switched from watching the hot feed to watching the new items. Come on reddit, don’t let me down!


Scaling up / scaling down (or should I write that CSS templating thing or just learn Lisp)

2007-12-18 / 22:32 / dave

Part of the ongoing Django vs. Rails debate revolves around the templating language (link needed). The Django templates are intentionally limited. The developers claim this is a feature: it forces your templates to delegate the logic to your domain layer, simplifying your template language and making them easier for your poor beleagured designers to learn.

“Sure,” I says to myself “but not having to learn ANY new language would be better.” Since designers already design their content for CSS styling, why not search the HTML for ID’s and perform substitutions in code? The input would be plain HTML, so the designers–and tools for that matter–could understand it.

Great!

Er, well, assuming you actually have designers to worry about.

Scaling down

I was reading through A Common Lisp web startup test-case, two years after the Reddit switch and saw this:

The entire codebase of stix.to is written in Common Lisp. That is to say, html output is written in s-expressions and all our Javascript is written in Parenscript (if we choose to ignore a few quick hacks).

This seems to be the standard Lisp “write everything in sexps and compile it!” approach. Or as Paul Graham responded to a question about spacer .gifs: “…we’re smart enough to realize that html is object code”

So if you’ve got a small team, why worry about the designer at all? Let the coders use the language they know best… you know the one they use for programming. If the tools are good, the teams can be small; if it’s a 100 year language maybe your team can then shrink to the smallest possible size: one.

So you’re learning lisp?

Not yet. Scaling down to a small tight team sounds good, but really it’s just me dicking around with my web page. I already know HTML and Python; the most Lisp I’ve written is in my ~/.xemacs directory. Still, the more I hear about higher-higher-level languages (Haskell and Lisp, specifically) the more I start to think that I might be working in blub. More correctly, a collection of several blubs.

Anyway, I still think using HTML itself as a templating language makes a lot of sense. I’ll probably eventually get around to trying to write my dinky CSS templating engine beacause it’s a good kata and I think the idea is pretty cool. So if you are working with an army of designers… well, watch this space!


CS vs. Bio: our brains are not the same (an anecdote)

2007-12-18 / 17:26 / dave

Today I tried helping my office mate resolve some data discrepancies. We made graphs, checked the current database, talked to people who were here when the original data was produced, etc. No luck. What next? Maybe pull all the graphs and look for a pattern? Or look for old data migration logs to check for data corruption?

Our bio-statistician over-heard us. His suggestion? “Throw them out and see if the results change.”

Biologists & computer scientists… the brains are not the same.

(Insert your own comparison of Haskell and Erlang here.)


XEmacs + TRAMP = remote editing (= awesome)

2007-12-11 / 04:43 / dave

XEmacs 21 comes pre-installed with TRAMP (Transparent Remote (file) Access, Multiple Protocol). As soon as you learn the naming convention, you can edit remote files just as easily as local files (well, as long as you don’t mind the 5 second start-up time). It’s as simple as

Find file: /[dgingrich@bam.dreamhost.com].bashrc

In the background, TRAMP opens a remote connection and either copies the remote file to a local temp directory (with something like scp) or mime encodes the remote file and streams it.

Despite the “careful! beta!” warnings in the documentation, the authors evidently took time making things “just work”. The handling of encoding for streaming is especially cool: it tries to use mimencode, falls back to uuencode and finally tries sending the remote host a snippet of perl code. A neat example of a dynamic programming mind-set: the real world is messy, so test and fall-back. The ultimate fall-back is the 7 bajillion configuration options, including ones for windows and old versions of ssh.

For me it just worked. The totality of my configuration was a single line in my .xemacs/custom.el:

(setq tramp-default-method "sshx")

The only hang-up I had was trying to use the emacs syntax (/dgingrich@bam.dreamhost.com:.bashrc) which is unfortunately used by the EFS package. So instead of getting a secure SSH connect, it tried to set-up an FTP connection. I aborted before putting in my precious precious password, but it was confusing that it “worked” but not with the protocol I expected. It turns out that this was a limitation of XEmacs setup. Ah well, no harm no foul.

Cherry on top? It works just fine with ssh-agent. So as long as I start XEmacs from a bash-ssh it’s a password-less experience.


OpenID

2007-12-04 / 23:49 / dave

Thanks Simon Willison! http://ndanger.org/ is now my OpenID URL!

More info on OpenID


Who needs xterm when you’ve got Cygwin and batch files?

2007-12-02 / 20:23 / dave

It’s cool that Cygwin includes an XWindows server, but, since I’m not running graphical programs remotely, I’ve never really seen the need to use it. But I really miss one thing: xterm.

I can get 80% of the way by using Launchy to start new cygwin shells. Unfortunately, the next 10% is important: environment. Xterm remembers where you are:

xterm example

The new window starts in the src directory, right where we were working before. While avoiding a cd is nice, it’s really an advantage when combined with bash-ssh. A new cygwin shell starts in non-ssh mode, requiring a fresh login.

We can get this next 10% with cyg, a 2 line batch file:

@echo off
start bash

All it does is call start on the bash executable (which is already in my path).

cyg example

So you can go switch to ssh mode, change your directory, and run cyg (1) and have those changes reflect in your new window (2). (I type cyg & out of habit–& runs a process in the background in *nix–but just cyg works fine). This matches my ADD work-flow: I can be in the middle of editing locally when I realize I need to clean up some temp files on the server. I launch a cyg, ssh to the server, do my deed and return without losing my place.

Using a batch file is also what produces the visual differences (3). At first I was annoyed, but it turns out pretty handy: I can easily tell my “main” window from my “omg I have to pop my stack right now” windows. Telling the windows apart is also important because there’s another limitation of cyg and bash-ssh. If the main window is closed, it takes ssh-agent with it, the cyg window needs an ssh password on each connect (though this is arguably better than xterm, which takes down all windows it launched. Oops.) (Also check out my awesome freehand text. Not bad considering I did it using a nipple.)

cyg after main window close ssh error example

Scratch my back

The last 10% I’d like is the ability to launch apps in a new window. Something like

$ cyg "man rsync"

And have that launch a new window and automatically run man rsync. I played around with % variables but couldn’t get anything working. I haven’t yet written a Python script to do it, and I’d like to keep it that way.


Hands cramped from typing your ssh password?

2007-12-02 / 18:01 / dave

I was thinking about the tools I use for messing around with this blog (more on that later) and realized that setting up ssh-agent might be the biggest efficiency boost ever (besides installing cygwin, learning emacs key bindings, tweaking the hell out of Firefox, installing launchy…)

Basically, follow the “Getting Started” section of HOWTO: set up ssh keys (Paul Keck’s article from 2001!).

You’ve now got keys made and deployed to your remote servers. But typing ssh-agent sh -c 'ssh-add < /dev/null && bash' each time sucks. I’m sure you could alter your shell startup to automatically start ssh-agent, but that would allow any shell open access to your remote machines. Not good, especially since my job sometime involves delicate information.

Instead, I added these lines to my .bashrc file:

# Shortcuts to start a bash shell w/ ssh-agent initialized
#alias bash-ssh="ssh-agent sh -c 'ssh-add < /dev/null && bash -li'"
# NOTE: to get --init-file to work couldn't use -li
alias bash-ssh="ssh-agent sh -c 'ssh-add < /dev/null && bash --init-file $HOME/.bashrc_ssh'"
# Shortcuts to lock & unlock ssh-agent (good if always on)
alias ssh-lock='ssh-add -x'
alias ssh-unlock='ssh-add -X'

Note that I commented out the original ssh-agent call and replaced it with a slightly different one. The new one drops the -li switches and instead calls a special initialization file, .bashrc_ssh

# .bashrc_ssh: special bash shell when running in SSH mode
# invoked w/ "bash-ssh" (defined as alias in ~/.bashrc

# source the system wide bashrc if it exists
if [ -e /etc/profile ] ; then
  source /etc/profile
fi

# source the system wide bashrc if it exists
if [ -e /etc/bash.bashrc ] ; then
  source /etc/bash.bashrc
fi

# source the regular bash
if [ -e "${HOME}/.bashrc" ] ; then
  source "${HOME}/.bashrc"
fi

# Modify prompt to reflect ssh mode
PS1=$PS1'[ssh] '

Now our prompt is modified to remind us that we’re running in convenient-but-insecure mode.
bash-ssh example

More information on ssh-agent via SecurityFocus


Firefox add-on of the day: draganddropupload

2007-12-01 / 22:57 / dave

draganddropupload.

1) drag…
draganddropupload 1, drag

2) dropandupload
draganddropupload 2, dropandupload

3) There is no step three.

Did you notice it handled multiple files? Awesome.


For the love of atom

2007-11-29 / 11:34 / dave

Previously on The Adventures of Trying to Default to Atom 1.0 Feeds… I installed the Wordpress Atom 1.0 plugin. Unfortunately it produces broken comments feeds for Wordpress 2.3.1: if there are no comments, the entire feed is broken (no id); if there are comments the feed is just empty.

After some stumbling around in a morass of Wordpress PHP, I was about to edit .htaccess when Google came through with Mark Pilgrim’s 2 line plugin hack. Brilliant.


I’ve got a whole new look

2007-11-28 / 18:29 / dave

Part 2 of the site redesign is done! In Part 1 I styled the blog and blah blah blah.

It turns out that styling is an open problem. I’ve spend the last 2 days making small fidgety changes until I’ve ended up with the black-and-white horizontally ruled wonder you’re looking at. Basically the low-rent version of Khoi Vinh’s excellent site. Though to be fair, he is the design director of NYTimes.com while I’m a programmer who makes interfaces that look something like:

dbdoc_screencap.png

Command line baby! If you can peek around my careful redacting, you can see that I leave the Cheetah warning in place. And although you can’t see it the command line parameters are currently case-sensitive. Yes, I am an interface genius. (Though the program itself is pretty neat: it reflects the database and generates documentation on our internal wiki. It uses diff and patch to try to merge human changes, so it can accommodate human edits to the page while the schema changes. Sexy.)

Blueprint

I did the basic structure using Blueprint CSS and then tweaked the hell out of the styles. Blueprint’s grid was extremely helpful, mostly because I don’t know anything about CSS layout. The typography module also produces a reasonably attractive page, though a bit on the “small in the way only designers can love” side. The typography is designed to produce a grid. While I understand the grid theoretically–mostly from reading web articles–I didn’t actually understand it in practice. I think it’s about defining some common elements (p, h?, .small, et.) with grid friendly spacing and then using these for all basic layout (images, pull-quotes and others can float outside the grid). So it would have been easiest if in my Wordpress templates I set the date to some pre-defined blueprint class that was already grid friendly. Instead I got all semantic and set it to a date class and then bumped it around with CSS until it looked good. Oh yeah, and until it had managed to destroy my grid spacing. I guess I could have styled my date class to preserve the grid, but…

One of the main complaints I’ve read about blueprint is that it encourages the mixing of semantic and style markup. A weak example is the the date line I just mentioned. I’d like to be able to set the class to date (well, I guess it should have been wp-date or something less ambiguous) and then been able to use blueprints typography to size it to the grid. Likewise my html & php pages all feature lots of class="column span-6" sorts of markup. Using Wordpress makes this easier, since I have less places to make changes, but it was still annoying. I’d really like to be able to use blueprint as a true framework: something you plug-in on the back end. This would be easy if you had something like inheritance:

.wp-date {
  @@inherit .small .right-align;
  color: #ccc;
}

So the wp-date class would inherit all the styles of the small and right-align classes and then override color. Basically CSS macros. switchcss might be the Python solution, but I haven’t tried it.

Logos

I also hand-made the delicious logo in the upper right. Just a few pencil lines, a few text-tools and an overlay in GIMP… not too bad. I’m still going to play around. In particular, I might darken the right and bottom edge to add some depth.

Miniature versions of the logo might also make nice article starts & stops.

404, 500

Get lost in style. You can check them out if you don’t feel like actually getting lost (or triggering an internal server error):

ToDos

When reviewing part 1 before writing this, I realized I hadn’t done the 404 pages yet. That’s what Todo lists are for, I guess. That’s why installing trac has made the top of this one:

  • Install Trac and add bugs for the site
  • Compress CSS
  • Play around with darkening right and bottom edge of logo
  • Use logo for start/stop icons on articles
  • Better–more flexible–styling of single page articles (pull-outs for images & blockquotes)
  • Drop shadow for images
  • Smart fonts (sifr)

That should keep me busy.

Tell me what you think

Oh yeah, I also finished my Wordpress templates. The big announcement is that (drumroll)… comments are enabled! So let me know what you think before the spam starts rolling in.


WTFOTD: NaN% loaded

2007-11-25 / 22:18 / dave

beatport_loading_nan.pngBeatport has the exclusive MP3 release of Radio Slave’s Bell Clap Dance.

The site has lots of problems. It’s flash based so you can’t open up lots of Firefox links. You can’t deep link or bookmark pages. Doing certain searches will reload the page and stop playing the audio samples. The interface is too cluttered.

And it’s slow. There’s lots of loading, and it’s only NaN % done? At this rate it’s going to take INF!


Site design, part 1: limping along

2007-11-24 / 17:47 / dave

Got some of the site redesign done, enough to put it on the server.

Changes

  • Well it looks different
  • Redirect the home page to the blog
  • Redid the links & about
  • Added google search box
  • Added sidebar
  • Used Blueprint CSS

ToDo

  • Compress CSS (right now serving 4 files or something ridiculous, maybe more but I’m not sure if @import happens on the server or client)
  • Style blog comments pages & turn on comments
  • Make 404 page
  • Redo favicon so font & color matches new site design

Takeaways: playing around with CSS is no fun, no fun at all.


Blog updates: futzing around

2007-11-19 / 15:49 / dave

Productive procrastination is my bread ‘n’ butter, so instead of redoing my Wordpress themes, I made a few other changes.

ID’ing the body

Following a tip from What Beautiful HTML Code Looks Like, I added an id to each body. My static HTML and Wordpress templates are generated with Cheetah, it was as simple as adding id="$page" to my header.tmpl.

But my site is simple enough I don’t have any page specific styling, so we’ll see if this change lasts.

Favicon

All the cool kids have favicons… Since mine is just text, I built a 128×128 version in The Gimp. Getting the colors to match my header was cake since Gimp supports HTML color codes, but it turned out the “d” was too light so I darkened it a bit.

I tried to be all fancy and use GIMP’s layers to export a multi-part .ico, but this didn’t seem to work in IE7. I also tried a single 16×16 .ico at 4b color depth and this seemed to cause problems. Eventually I used HTMLKit’s favicon generator on the 128×128 version. This produced a 16×16x8b image. I’m not sure if the multi-part ICO or the color depth was the problem, but the generated version looked better than my re-sized GIMP image, so I just went with that.

favicon

Ain’t it pretty?

If you want to read about favicons excessively, check out the wikipedia or the W3C’s guide to favicons.

Adding the x in xhtml

I figured I should check my changes against the Validator. My static pages validated (with a few glitches), but the blog didn’t. Mainly, it was because Wordpress was serving xhtml while the rest of the site was HTML Transitional. Jacking from Sam Ruby–his markup is my go-to for learning how to do slick web-standard stuff techie stuff, such as inline svg–quickly gave me xhtml markup:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

The immediate effect was:

xHTML changes XEmacs HTML-Mode indentation

Yup, it made XEmacs’s HTML mode think it needed an extra level of identation for the body element. SGML-Mode and XML-Mode didn’t solve the problem, in fact all XML-mode do was give me a bunch of extra output. Not bothersome enough to really debug, but in googling I found html-helper-mode which I plan on checking out.

UTF-8

Back to the validator: there were a few problems, the most serious was adding a content-type to the <head>:

  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <!-- ... -->
  </head>

UTF-8 because that seems to be the character-set of choice. Also I was inspired by Tim Bray’s article. And now I can play around and throw strange symbols into my html. Borrowing Tim’s examples:

HTML: &#x0026; &#x416; &#x4E2D; &#x10346;
Output: & Ж 𐍆 (click through if they don’t render)

And if that’s not , I don’t know what is. (Except I don’t know what that character actually means, someone let me know if it means “incredibly shitty” or something.)

Anyway:

Valid XHTML 1.1

Ting!

Alternate: Atom

Sam also had an alternate link to his Atom feed. I checked my feed and it was:

<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

Horrors! RSS2! The default Wordpress Atom feed didn’t validate, so I installed Benjamin Smedberg’s Wordpress Atom 1.0 plugin. It took all of 30 seconds, most of that rsyncing to my host server.

The Atom doesn’t validate for the same reason the blog doesn’t: I haven’t been careful about what I’m putting in my posts.

Finally, I added the feed as an alternate link:

  <head>
    <link rel="alternate" type="application/atom+xml"
      title="ndanger.org: posts"
      href="http://ndanger.org/blog/feed/"/>
  </head>

If you prefer RSS2, you can still get it at http://ndanger.org/blog/wp-rss2.php

Ready to start on those templates

To act like I was making some progress, I stole Andy Rutledge’s “reset everything” CSS (well, re-stole. I already used it for the Pirate Bike Triathlon) and added it as an additional CSS file. This broke all the styling, so I commented it out of the HTML.

Next project? Actually make those templates, probably using blueprint to handle the grid. Expect another meandering post soon!