The fact that Thorsten manually synchronizes the snippets in the text and external source files seems like crazy talk to me. But the fact that he's cranked out two really good books on languages while I'm still slowly lumbering through my one [1] is proof that his system works for him.<p>Personally, I'm too error-prone to pull that off. I change the code snippets frequently after chapters are done (often in response to bug reports from readers) and having to manually update the snippets in the text would drive me bonkers.<p>Also, I want to rigorously, automatically validate that the code in the book is correct and contains everything you need.<p>To do that, I wrote a Python script [2] that weaves the code and the Markdown together. In the Markdown files, you use a marker like (here in the chapter "Strings"):<p><pre><code> ^code memory-include-object (2 before, 2 after)
</code></pre>
This means "insert the code snippet labeled "memory-include-object" here. Include 2 lines of contextual code (which is shown grayed out) before, and 2 after. In the code, the marker looks like:<p><pre><code> //> Strings memory-include-object
#include "object.h"
//< Strings memory-include-object
</code></pre>
The "//>" begins the snippet and the "//<" ends it.<p>The build script reads the "^code" markers and finds the snippet of code in the sources that correspond to it, as well as any desired surrounding lines. But it can also do a lot of other useful things with the snippet markers:<p>* If some lines of code are marked as being part of a chapter, but that chapter doesn't have a "^code" marker to include them, it reports an error. This way I can't accidentally drop code on the floor.<p>* It can generate a separate copy of the entire codebase that only includes the snippets that are in a given chapter (and the preceding ones). In other words it can output "what does all the code look like by the time the reader reaches the end of chapter ___" for every chapter.<p>I output the code for each chapter and then compile that and run all of the tests. This way, I can ensure that by the end of each chapter, the program supports what it's supposed to support by then. I've found countless bugs doing this -- places where I inadvertently put code in a later chapter that is actually needed earlier.<p>However, this build script is <i>not</i> a generic "build a book" system. It's a bespoke program that only supports this one specific book. That helps keep the complexity down and makes it much easier to put little hacks in when I run into weird edge cases my specific book has. I think that's a reasonable trade-off to keep me producing a high-quality book without too much yak shaving.<p>One of the days, I'll write a full blog post going through this in more detail.<p>Of course, none of this is a criticism of Thorsten's system. The simple most important skill in writing a book is figuring how to get those pages done. It doesn't matter if that means waking up at three in the morning and writing on parchment with a red pencil. Whatever works for you, works.<p>[1]: <a href="http://www.craftinginterpreters.com/" rel="nofollow">http://www.craftinginterpreters.com/</a><p>[2]: <a href="https://github.com/munificent/craftinginterpreters/tree/master/util" rel="nofollow">https://github.com/munificent/craftinginterpreters/tree/mast...</a>