The Toolchain for My iOS Book

There’s no way I’d have written my iOS Book for O’Reilly if they hadn’t allowed me to use cool tools. Here’s how it works.

AsciiDoc and the Joy of Text

I write using plain text, marked up only very slightly, thanks to the magic of AsciiDoc. AsciiDoc is sort of like Markdown: the idea is that you write essentially in plain text, indicating formatting by extremely mild punctuation marks such as surrounding a word with underlines to indicate italics (like _this_) or starting a line (a short paragraph) with equal signs to indicate that it’s a heading.

The value of tools like AsciiDoc and Markdown (and Markdown’s new Ruby cousin kramdown, which I’m using to write this page) is that text is just text. I can write, copy and paste, and generally edit in a very fast and agile fashion, concentrating on content rather than form. I know it may sound heretical but I have come to detest WYSIWYG editing: type some text, select a word, choose Style > Italic, rinse, repeat — it drives me nuts. Plus text is utterly simple and portable.

(This theme of separating form from content so you can concentrate on content and let the computer supply the form in a separate step is something I’ve been harping on since the old days when I wrote about Frontier; and of course it is a major aspect of my Web site generation tool RubyFrontier.)

So, AsciiDoc and Markdown are really two things: a text format that you learn to work in, and a tool that will then transform your formatted text into their ultimate format.

In the case of Markdown (and kramdown), that ultimate format would typically be HTML, for display in a Web browser.

In the case of AsciiDoc, that format is not actually a legible format at all; it’s DocBook, an XML specification describing a (possibly very large and complex) structured document such as a book. The idea is that since DocBook is XML, a further tool can then transform the XML into some other format, such as HTML, PDF, ePUB, or whatever. AsciiDoc all by itself will perform the secondary transformation to HTML. I’ll talk more about all that in a moment.

TextMate

Since I’m just working with text, marked up with various punctuation delimiters, I use my favorite editor for working on structured text with delimiters, TextMate. TextMate has a number of helpful cool features:

  • It can work on a collection of multiple files (including global search, with optional regular expressions).

  • You type an opening delimiter, it automatically types the closing delimiter.

  • It can run customizable keyboard shortcuts. So, for example, select a word and press command-I, and it surrounds that word with underlines.

  • It can run scripts. So, for example, I can press a keyboard shortcut that runs a script that runs AsciiDoc against the text file I’m working on, displaying the resulting HTML in a browser.

TextMate works through “bundles” that encapsulate its behavior for the particular language you’re writing in. So, I use the AsciiDoc bundle by Christian Zuckschwerdt, except that I’ve modified it so heavily he probably wouldn’t recognize it any more.

My book is structured as a single file, book.asc, consisting of a series of include commands, one for each chapter. It starts like this:

:revnumber: 1.1
:author: Matt Neuburg
:revdate: Feb 24, 2011
:data-uri:
:rq: ’

= Programming iOS 4

include::ch00preface.asc[]

= Language

include::ch01justEnoughC.asc[]

include::ch02objects.asc[]

include::ch03IntroducingObjC.asc[]

I work on each chapter individually, as an individual file (such as ch03IntroducingObjC.asc, which you can see listed above). Here’s an excerpt from that chapter, to show you what working in AsciiDoc looks like:

In real life, you're likely to pass an instance off as a parameter to some other object, or to receive it as a parameter from some other object:

----
Stack* myStack = // ... create a Stack instance and assign it to myStack
// ... more code might go here ...
[myObject doSomethingWithThis: myStack];
----

Passing a parameter to a method is just like assignment, so now some other object, +myObject+, has a pointer to the very same instance we're already pointing to as +myStack+. So we must be careful and thoughtful. The object +myObject+ might mutate +myStack+ right under our very noses. Even more, the object +myObject+ might _keep_ its reference to the stack instance and mutate it _later_ — possibly much later, in a way that could surprise us. This is possible because instances can have instance variables that point to other objects, and those pointers can persist as long as the instances themselves do. This kind of shared referent situation can be intentional, but it is also something to watch out for and be conscious of (xref:FIGtwoptrsoneinstance[]).

[[FIGtwoptrsoneinstance]]
.Two instances end up with pointers to the same third instance
image::figs/twoPointersToOneInstance.png[]

The Little Toolchain and the Big Toolchain

So here I am, nimbly working away in TextMate using just plain text, in AsciiDoc format. But so far I have not actually described using AsciiDoc, the tool, to interpret and transform my text. I use AsciiDoc in two ways.

One way is to proofread my work, and to check that my AsciiDoc text formatting is legal. So, from time to time, I press the TextMate keyboard shortcut that runs AsciiDoc and shows me my chapter as HTML in my browser. That’s because, although I find it easiest to write and edit as text directly in TextMate, I don’t proofread very well in that form; I proofread better viewing the material formatted, in the browser. That way, I’m reading it similarly to how it would appear in a printed book, with actual formatting instead of text markup. Also, this lets me check that my formatting is coming out right, that my image links and cross-reference links are working, and so forth.

I can also run AsciiDoc on the main book file, book.asc. This outputs the entire book as a single gigantic HTML file and shows it to me in my browser. That isn’t something I do very often, but it’s useful for making sure that, for example, cross-references between chapters are working correctly.

What I’ve been describing so far, however, is what I call the “little toolchain”. It’s very fast and very convenient, but the HTML that AsciiDoc generates in this way should probably be thought of as a kind of preview. For full, serious customizability and maximum flexibility, I use the “big toolchain”. In this version of the toolchain, AsciiDoc doesn’t transform my text to HTML; it transforms my text to DocBook XML and stops. Then another tool is called into play to transform the DocBook XML to some final format.

The big toolchain is conveniently accessed through a tool supplied with AsciiDoc, called a2x. As you can see from its man page, you can hand a2x various parameters so that the second half of the process will transform DocBook XML to PDF, ePUB, or any of a number of other formats.

At the moment, what I use the big toolchain for is to generate “chunked” HTML. This means that the entire book is processed, but each chapter is broken out into a separate HTML file, with Next and Prev links from chapter to chapter, and cross-references that work between files. The second half of the process uses xsltproc and the famous DocBook XSL transforms. These XSL transforms are big and complicated, but they do their job correctly right out of the box, plus they provide numerous parameters whose values I can set to influence the outcome, plus I can append my own XSL to customize the outcome still further (as discussed in this online book).

By supplying XSL parameters and customizing the XSL appropriately, plus supplying my own CSS, I can generate a very acceptable “chunked” display of my book, suitable for showing to the public, as I do here. Plus, running the big toolchain against my book lets me test my AsciiDoc formatting even more rigorously; and it helps me prevent errors which would occur when the O’Reilly folks use their version of the big toolchain on my files.

Subversion and the O’Reilly Toolchain

Now comes the really cool part. (Okay, the whole thing is the really cool part. But this is the part that is a game-changer for me.) O’Reilly maintains a Subversion repository for me. From time to time, I commit my AsciiDoc files and the accompanying image files to the Subversion repository. That way, my files are safely versioned at every step. But, even more important, if my commit message includes a certain Secret Phrase, the O’Reilly Subversion commit hook script fires up and runs AsciiDoc at their end against my book files, using their own version of the big toolchain.

The way they’ve got this commit hook script set up, AsciiDoc doesn’t generate HTML; it generates a PDF file. And that PDF uses the same fonts and layout as an actual O’Reilly book! What’s more, the commit hook script automatically commits the PDF file into the Subversion repository. So now, at my end, when I update (downloading the latest version of the repository to my own machine), I wind up with a copy of this PDF, simulating what my book will look like in print! That’s very helpful, because it shows me how many pages my book is, whether any of my code lines are too long, and so forth; it’s also much the best way to proofread seriously. Typically, I load the PDF onto my iPad and walk around the house, reading the book out loud and watching for mistakes and clumsy structure. I straighten things out in my AsciiDoc original, and go through the whole cycle again.

But wait, there’s more! The O’Reilly people have another way to run AsciiDoc at their end. So, every once in a while I ask them to run it in this second way, and presto, the latest version of my book is “pushed out” to all my readers who have purchased the book in Early Release form. No matter whether they’re reading as an ePUB, as a PDF, or online at Safari Books Online, they magically acquire a new copy of my book, up-to-date with all my most recent changes (added chapters, revised chapters, and so on).

And that’s something I really like. What I dreaded about writing this book was that I’d have to go into a closet and write for months and months, with no one knowing anything about it, and meanwhile the technology I was writing about would be changing rapidly. I’d be out of circulation, no one could benefit from my work, and there might never come a good moment to “publish.” This way, my O’Reilly book is alive and agile: readers can benefit from it, and make comments and suggestions, before it’s even finished, and if the technology changes, I simply revise and my readers acquire those revisions automatically. That’s given me a happy relationship with my readers.

Why This is Cool

So, to sum up, here’s why I really like using these tools:

  • I’m working in plain text, lightly formatted; so my writing and editing and revising are easy and nimble.

  • I’m using TextMate, a text editor that makes my use of lightly formatted text easy.

  • I can preview my work as HTML, which makes me a better proofreader.

  • I can “chunk” my book into nice-looking HTML chapter files for public consumption, so the rest of the world can watch me work.

  • Thanks to the O’Reilly commit hook, I automatically get a PDF version of my work. This is fun and encouraging as the book grows, and makes me an even better proofreader.

  • We’re using Subversion, so my editor and I have an easy time communicating changes back and forth to each other.

  • Without any trees being killed, readers can purchase an electronic Early Release edition of my book, and they are kept up-to-date as I continue to write and revise.


Back to Matt Neuburg’s Home Page

This page prepared August 15, 2012 by Matt Neuburg, phd = matt at tidbits dot com, using RubyFrontier. RubyFrontier is a port, written in the Ruby language, of the Web-site-creation features of UserLand Frontier. Works just like Frontier, but written in Ruby!
Download RubyFrontier from GitHub.