Books as code
My toolset for Cassandra: The Definitive Guide, 3rd Ed
Last night I completed the first draft of the final chapter of the 3rd edition of Cassandra: The Definitive Guide for O’Reilly (early access chapters available at the link). That might explain where all my writing energy has been invested lately :).
Now that I get a short pause while my reviewers take aim at the text, I thought it was about time to get back to blogging. I received a question about the image in that tweet above which inspired me to write this post:
What tool do you use for writing the book?
Great question! Here we go…
The old toolset
When I started work on the 2nd edition a couple of years back, I did most of my editing in O’Reilly’s Atlas tool, which uses Git for source control and provides a very nice WYSIWYG / HTML interface. The only thing I didn’t like about it actually was having to switch back and forth between the text editor and raw HTML views (it was occasionally necessary to dive down into HTML to fix cross references and paragraph breaks).
But enough about the 2nd edition, that’s ancient history.
A new toolset for writing books as code
When it came time to start work on the 3rd edition, I decided to go for a “books as code” type of experience. I had a small number of preferences I was hoping to satisfy:
- ability to use my preferred IDE (IntelliJ)
- using a markdown-like format for editing
- side-by-side view of source code and rendered versions
- ability to edit my own image files according to O’Reilly style guide
Thankfully, I was able to achieve these goals. O’Reilly was kind enough to convert the 2nd edition source code from HTML to Asciidoc, which was similar enough to Markdown for me to be comfortable pretty quickly.
So the components of my toolset were:
- IntelliJ IDEA Ultimate Edition — my preferred IDE, used both for book text and code for the Reservation Service example used throughout the book
- Asciidoctor plugin — provides syntax highlighting, side-by-side rendered view, and PDF/HTML generation
- Git — using familiar version control was a big comfort factor
- LucidChart — provides great UX for editing drawings and made it easy to conform with standard O’Reilly conventions and fonts
This picture gives a good view of my typical editing environment (dark mode FTW!):
Even though it took me a while to learn the Asciidoc syntax, I was usually able to find an example of the format I needed elsewhere in the text and copy it. I really only had to resort to the documentation when it came time to update a couple of math formulas in LaTEX.
There were a couple of benefits of this approach that I discovered along the way:
Because Asciidoc supports comments, I was able to leverage IntelliJ’s TODO feature to keep track of action items for myself as well as reviewer comments I needed to address:
Then I could use the TODO window to iterate through my various work items and burn them down one at a time:
Previewing Rendered Content
It brings a great comfort factor to be able to read the rendered content side by side with the original source.
Being able to review the rendered content immediately kept me from needing to continually print out paper copies to review and mark up, which was my practice when working on the 2nd edition. Using less paper is a big plus!
The Asciidoctor plugin does support HTML and PDF generation, which is a super nice feature. There are a couple small dialect differences between the plugin and O’Reilly’s Atlas, but nothing too distracting.
I mainly used the PDF generation as a quick way to determine how long a given chapter was, as I was trying to keep each chapter to 30 pages or less. Even though the layout used for O’Reilly print editions is quite different than the Asciidoctor generated PDFs (compare the images above and below), they typically result in about the same number of pages.
Another great discovery I made while working on the book was how easy it was to refactor content when working in IntelliJ. This took two main forms: moving content and renumbering images.
In working on the 3rd edition, I was really trying to improve on the flow of the book by telling a consistent story from start to finish. To accomplish this I sometimes needed to reorder content within a chapter, or move content between chapters. Sometimes I even moved content to a “parking lot”. This was useful when I wanted to get some content out of the way but wasn’t ready to make a final decision on whether to keep or delete. The “structure” view was also super helpful for making sure I had my outline levels correct.
The second form of refactoring was image renumbering. In working on the 2nd edition it was a real pain whenever I decided I wanted to introduce a new image into the flow of a chapter, because O’Reilly uses a convention of storing images in numbered order by chapter.
For the 3rd edition this was so much easier. I just used IntelliJ’s name refactoring to rename image files, which would also update references in the text:
One other thing I would love to have automated was the process of updating images. I’ve been managing all my own artwork using LucidChart.
I love LucidChart as a drawing tool but I wasn’t able to coerce the filenames it uses on generated image files, so I had to do a lot of manual
mv commands to move images from my
Downloads folder into my Git repo.
Do I really need revision history?
One interesting thing I found that didn’t match my original expectation. I thought I would make use of revision history to compare previous versions. In actual practice, I found that beyond using a simple
git diff to compare my current changes with the last saved version, I never actually needed to compare versions. However, I will say that it felt great to do a
git commit with comment each time I finished writing a new section. For some reason or force of habit I always seem to jump out to command line for my commits:
So there it is, my toolset for writing a book as code. Hope you find it interesting and/or helpful, and I can’t wait to have a completed book to share with you. I’m pushing hard on edits so we can have have paper copies in hand in time for DataStax Accelerate in May, we will see what happens…