Repository: tweag/topiary
Pull request #890: Topiary Book: Tidy-up Guides
Author: login: Xophmeister
Created: 2025-03-03T10:56:47Z | Merged: 2025-03-04T15:01:13Z

Tidy-up "Guides" section and link to @yannham's tutorial.

Resolves #874

* [x] Depends on #885

Linked issue #874: Link to the tutorial blog post in the README
I feel there should be a link to [@yannham 's tutorial blog post](https://www.tweag.io/blog/2025-01-30-topiary-tutorial-part-1/) somewhere in the readme. I haven't thought about where, so not making a PR sorry 🙂 .

Diff:
diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md
index 36f4e37f9..447f75ddd 100644
--- a/docs/book/src/SUMMARY.md
+++ b/docs/book/src/SUMMARY.md
@@ -38,6 +38,7 @@ TODO: Documentation for the web-based playground; see issue #875
 
 - [Adding a new language](guides/adding-a-new-language.md)
 - [Suggested query development workflow](guides/suggested-workflow.md)
+- [Writing a formatter has never been so easy: a Topiary tutorial](guides/yann-tutorial.md)
 
 # Reference
 
diff --git a/docs/book/src/guides/adding-a-new-language.md b/docs/book/src/guides/adding-a-new-language.md
index bee9acf7e..fd35265bd 100644
--- a/docs/book/src/guides/adding-a-new-language.md
+++ b/docs/book/src/guides/adding-a-new-language.md
@@ -1,17 +1,29 @@
 # Adding a new language
 
-This section illustrates how to add a supported language to Topiary, provided it already has a tree-sitter grammar.
+This chapter illustrates how to add a supported language to Topiary,
+provided it already has a Tree-sitter grammar.
 
-We will use C as the running example in this section.
+We will use C as the running example. The following steps are enough to
+bootstrap the formatting of a new language.
 
-### Minimal steps
+<div class="warning">
 
-The two following steps are enough to jumpstart the formatting of a new language:
+This guide discusses the steps needed to allow Topiary to recognise a
+new language and drive the test suite. It does not discuss the details
+of creating formatting queries for the language.
 
-#### Register the grammar in `topiary-config/languages.ncl`:
+The _bare minimum_ -- say, for example, if you only have access to a
+pre-compiled Topiary binary -- is covered in the first two steps:
+Registering the grammar in the configuration and creating the query
+file. It is not strictly necessary to update the test suite or bake in
+your query file to be able to iterate on formatting query writing.
+
+</div>
+
+## Register the grammar in `topiary-config/languages.ncl`:
 
 ```nickel
-    c = {
+    clang = {
       extensions = ["c", "h"],
       grammar.source.git = {
         git = "https://github.com/tree-sitter/tree-sitter-c.git",
@@ -20,36 +32,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
 
-### Add the new language to the test suite
+## Add the new language to the test suite
 
-#### Create input/expected files
-```bash
-echo 'void main ();' > topiary-cli/tests/samples/input/c.c
-echo 'voidmain();' > topiary-cli/tests/samples/expected/c.c
+### Create input/expected files
+
+Topiary's I/O tester will format input files and check them against an
+expected output. For the time being, let's stick with the mangled
+output, so we can get the tests to run and pass.
+
+```sh
+echo 'void main ();' > topiary-cli/tests/samples/input/clang.c
+echo 'voidmain();' > topiary-cli/tests/samples/expected/clang.c
 ```
 
-#### Add the Cargo feature flags
+### Add Cargo feature flags
+
+Each language is gated behind a feature flag. We'll use the `clang`
+feature flag for C -- to match the language name in the configuration --
+which needs to be added in the appropriate places.
+
+#### In `topiary-cli/Cargo.toml`
 
-##### In `topiary-cli/Cargo.toml`
 ```toml
 experimental = [
   "clang",
@@ -58,7 +83,8 @@ experimental = [
 clang = ["topiary-config/clang", "topiary-queries/clang"]
 ```
 
-##### In `topiary-config/Cargo.toml`
+#### In `topiary-config/Cargo.toml`
+
 ```toml
 clang = []
 
@@ -67,58 +93,113 @@ all = [
 ]
 ```
 
-##### In `topiary-queries/Cargo.toml`
+#### In `topiary-queries/Cargo.toml`
+
 ```toml
 clang = []
 ```
 
-#### Add tests in `topiary-cli/tests/sample-tester.rs`
+### Add tests in `topiary-cli/tests/sample-tester.rs`
+
+To register the I/O and coverage tests for the new language, we need to
+add it to the test suite.
+
+#### In `fn get_file_extension`
 
-<!-- FIXME Change this to use new macros -->
+You will need to add a mapping from the language (feature name) to the
+file extension under test:
 
 ```rust
-fn input_output_tester() {
+fn get_file_extension(language: &str) -> &str {
+    match language {
 
-[...]
+        [...]
 
-    #[cfg(feature = "clang")]
-    io_test("c.c");
+        "clang" => "c",
 
-[...]
+        [...]
 
-fn coverage_tester() {
+    }
+}
+```
 
-[...]
+#### In `mod test_fmt`
+
+Then you'll need to add the language to the `lang_test!` macro calls in
+the `test_fmt` module, respectively:
+
+```rust
+    lang_test!(
+
+        [...]
+
+        "clang",
+
+        [...]
+
+        fmt_input
+    );
+```
+
+#### In `mod test_coverage`
+
+Likewise in the `test_coverage` module:
+
+```rust
+    lang_test!(
 
-    #[cfg(feature = "clang")]
-    coverage_test("c.c");
+        [...]
+
+        "clang",
+
+        [...]
+
+        coverage_input
+    );
 ```
 
-#### Testing
-You should be able to successfully run the new tests with
-```bash
+### Testing
+
+You should be able to successfully run the new tests with:
+
+```sh
 cargo test --no-default-features -F clang -p topiary-cli --test sample-tester
 ```
 
-### Include the query file in Topiary at compile time
+## Include the query file in Topiary at compile time
+
+### In `topiary-queries/src/lib.rs`
 
-#### In `topiary-queries/src/lib.rs`
 ```rust
 /// Returns the Topiary-compatible query file for C.
 #[cfg(feature = "clang")]
-pub fn c() -> &'static str {
-    include_str!("../queries/c.scm")
+pub fn clang() -> &'static str {
+    include_str!("../queries/clang.scm")
 }
 ```
 
-#### In `topiary-cli/src/io.rs`
+### In `topiary-cli/src/io.rs`
+
 ```rust
 fn to_query<T>(name: T) -> CLIResult<QuerySource>
 
 [...]
 
         #[cfg(feature = "clang")]
-        "c" => Ok(topiary_queries::c().into()),
+        "clang" => Ok(topiary_queries::clang().into()),
 ```
 
-This will allow your query file to by considered as the default fallback query, when no other file can be found at runtime for your language.
+This will allow your query file to by considered as the default fallback
+query, when no other file can be found at runtime for your language.
+
+## Iterate
+
+Once the above steps have been completed, Topiary will be able to use
+the C Tree-sitter grammar and the formatting queries in `clang.scm` to
+format C code.
+
+You can now iterate on the formatting queries and the respective input
+and expected sample files to build your formatter, using the I/O and
+coverage tests to guide the process. Please also see the [following
+chapter](suggested-workflow.md) on query development for more
+information.
diff --git a/docs/book/src/guides/suggested-workflow.md b/docs/book/src/guides/suggested-workflow.md
index a6c52624c..5a1ebe166 100644
--- a/docs/book/src/guides/suggested-workflow.md
+++ b/docs/book/src/guides/suggested-workflow.md
@@ -3,13 +3,34 @@
 In order to work productively on query files, the following is one
 suggested way to work:
 
-1. If you're working on a new language, follow the steps in [the previous chapter](adding-a-new-language.md).
+1. If you're working on a new language, first follow the steps in [the
+   previous chapter](adding-a-new-language.md).
 
-2. Add a snippet of code you want to format to `topiary-cli/tests/samples/input/mylanguage.mlg`.
+2. Say you are working on formatting `mylanguage` code, then from the
+   previous step (or otherwise), there should be two files that drive
+   the test suite:
 
-3. Add the properly formatted version of the code to `topiary-cli/tests/samples/expected/mylanguage.mlg`.
+   - `topiary-cli/tests/samples/input/mylanguage.code`
+   - `topiary-cli/tests/samples/expected/mylanguage.code`
 
-4. Run:
+   These respectively define the input, which will be formatted by
+   Topiary when under test, and the expected output, which will be
+   compared against the formatted input. (Note that the `.code`
+   extension here is arbitrary, for illustrative purposes, but an
+   appropriate extension is required.)
+
+   Add a snippet of code to each of these files that exhibit the
+   formatting you wish to implement as Tree-sitter queries. These
+   snippets can be identical, but it would be a better test if the input
+   version was intentionally misformatted.
+
+   <div class="warning">
+   If code already exists in these files, please ensure that the new
+   snippet is both syntactically valid, in the context of the other
+   code, and inserted at the same relative position in both files.
+   </div>
+
+3. Run:
 
    ```sh
    cargo test \
@@ -27,21 +48,15 @@ suggested way to work:
 
 > **Note**\
 > As an alternative to using the debugging output, the [`visualise`
-> subcommand](../cli/usage/visualise.md) line option exists to output
-> the Tree-sitter syntax tree in a variety of formats.
+> subcommand](../cli/usage/visualise.md) exists to output the
+> Tree-sitter syntax tree in a variety of formats.
 
-5. The test run will output all the differences between the actual
+4. The test run will output all the differences between the actual
    output and the expected output, e.g. missing spaces between tokens.
    Pick a difference you would like to fix, and find the line number and
    column in the input file.
 
-<!-- FIXME: Is this still true? I seem to remember this being changed to 1-based output -->
-> **Note**\
-> Keep in mind that the CST output uses 0-based line and column numbers,
-> so if your editor reports line 40, column 37, you probably want line
-> 39, column 36.
-
-6. In the CST debug or visualisation output, find the nodes in this
+5. In the CST debug or visualisation output, find the nodes in this
    region, such as the following:
 
    ```
@@ -52,7 +67,7 @@ suggested way to work:
    [DEBUG atom_collection] CST node:       {Node type_constructor (39, 36) - (39, 42)} - Named: true
    ```
 
-7. This may indicate that you would like spaces after all
+6. This may indicate that you would like spaces after all
    `type_constructor_path` nodes:
 
    ```scheme
@@ -79,5 +94,9 @@ suggested way to work:
    )
    ```
 
-8. Run `cargo test` again, to see if the output is better now, and then
-   return to step 5.
+> **Note**\
+> Using the [`#query_name!`](../reference/capture-names/general.md#query_name)
+> predicate will help identify which query does what.
+
+7. Run `cargo test` again, to see if the output has improved, then
+   return to step 4.
diff --git a/docs/book/src/guides/yann-tutorial.md b/docs/book/src/guides/yann-tutorial.md
new file mode 100644
index 000000000..e27e1a629
--- /dev/null
+++ b/docs/book/src/guides/yann-tutorial.md
@@ -0,0 +1,15 @@
+# Writing a formatter has never been so easy: a Topiary tutorial
+
+[Yann Hamdaoui](https://github.com/yannham) has written a step-by-step
+guide on how to write a new formatter for your own language, starting
+from zero.
+
+## [Part 1]
+
+[Part 1] introduces Topiary and motivates its use to create a formatter
+for a toy language, Yolo. Yann first guides you through the creation of
+a Tree-sitter grammar for Yolo, then plugs it into Topiary to write its
+formatting queries.
+
+<!-- Links -->
+[part 1]: https://www.tweag.io/blog/2025-01-30-topiary-tutorial-part-1


Reviews:
user: login: nbacquey
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-03T17:45:21Z
user: login: Xophmeister
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T10:08:53Z
user: login: Xophmeister
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T10:22:45Z
user: login: Xophmeister
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T10:50:52Z
user: login: Xophmeister
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T10:51:05Z
user: login: nbacquey
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T12:52:25Z
user: login: nbacquey
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T12:57:47Z
user: login: Xophmeister
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T13:20:09Z
user: login: Xophmeister
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T13:30:17Z
user: login: nbacquey
body: Otherwise lgtm
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-04T14:05:10Z
user: login: Xophmeister
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-04T14:54:07Z

Review comments:
diff_hunk: @@ -20,36 +18,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
path: docs/book/src/guides/adding-a-new-language.md
user: login: nbacquey
body: There should be a paragraph here stating that the steps above are the _bare minimum_ to format a language with Topiary, and that the following steps are only necessary to add the language as "formally supported".

This could alternatively be a disclaimer before the section, or be reflected by separate sections.
Or a combination of the above.
created_at: 2025-03-03T17:33:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,11 +3,14 @@
 In order to work productively on query files, the following is one
 suggested way to work:
 
-1. If you're working on a new language, follow the steps in [the previous chapter](adding-a-new-language.md).
+1. If you're working on a new language, first follow the steps in [the
+   previous chapter](adding-a-new-language.md).
 
-2. Add a snippet of code you want to format to `topiary-cli/tests/samples/input/mylanguage.mlg`.
+2. Add a snippet of code you want to format to
path: docs/book/src/guides/suggested-workflow.md
user: login: nbacquey
body: The previous chapter already suggests adding the input/expected files. Maybe add something like "(if they don't exist already)"?
Also, I'm not sure if it's clear that `.code` is a placeholder for the hypothetical language's extension, given that the previous chapter uses C as a running example.

(For your defense, my previous `.mlg` was even less clear :rofl:)
created_at: 2025-03-03T17:38:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,36 +18,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
path: docs/book/src/guides/adding-a-new-language.md
user: login: Xophmeister
body: Yes, good idea :+1:

...at the moment it's a bit like the "draw the rest of the owl" meme :sweat_smile: 
created_at: 2025-03-04T10:08:53Z
author_association: MEMBER
diff_hunk: @@ -3,11 +3,14 @@
 In order to work productively on query files, the following is one
 suggested way to work:
 
-1. If you're working on a new language, follow the steps in [the previous chapter](adding-a-new-language.md).
+1. If you're working on a new language, first follow the steps in [the
+   previous chapter](adding-a-new-language.md).
 
-2. Add a snippet of code you want to format to `topiary-cli/tests/samples/input/mylanguage.mlg`.
+2. Add a snippet of code you want to format to
path: docs/book/src/guides/suggested-workflow.md
user: login: Xophmeister
body: I read these steps as "add some relevant code to the `{input,expected}/foo.bar` files to exhibit what you're attempting to format", rather than "add these files". I think that makes more sense, but you're right that it's rather unclear.

I'll fix...
created_at: 2025-03-04T10:22:45Z
author_association: MEMBER
diff_hunk: @@ -20,36 +18,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
path: docs/book/src/guides/adding-a-new-language.md
user: login: Xophmeister
body: Done in 5baa3314d7861
created_at: 2025-03-04T10:50:52Z
author_association: MEMBER
diff_hunk: @@ -3,11 +3,14 @@
 In order to work productively on query files, the following is one
 suggested way to work:
 
-1. If you're working on a new language, follow the steps in [the previous chapter](adding-a-new-language.md).
+1. If you're working on a new language, first follow the steps in [the
+   previous chapter](adding-a-new-language.md).
 
-2. Add a snippet of code you want to format to `topiary-cli/tests/samples/input/mylanguage.mlg`.
+2. Add a snippet of code you want to format to
path: docs/book/src/guides/suggested-workflow.md
user: login: Xophmeister
body: Done in 887221cb61ff37
created_at: 2025-03-04T10:51:05Z
author_association: MEMBER
diff_hunk: @@ -20,36 +18,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
path: docs/book/src/guides/adding-a-new-language.md
user: login: nbacquey
body: What I meant is that you can use Topiary perfectly well with just an addition to the Nickel config file and a query file.

Adding tests and registering the query at compile time is not necessary if your goal isn't to publish your formatter.

_i.e._ the sections `## Add the new language to the test suite` and `## Include the query file in Topiary at compile time` are not necessary, strictly speaking
created_at: 2025-03-04T12:52:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,36 +18,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
path: docs/book/src/guides/adding-a-new-language.md
user: login: nbacquey
body: In particular, you can get started on your formatter with a pre-built binary, while having no rust toolchain at all
created_at: 2025-03-04T12:57:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -20,36 +18,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
path: docs/book/src/guides/adding-a-new-language.md
user: login: Xophmeister
body: Right, I see what you mean :+1:
created_at: 2025-03-04T13:20:09Z
author_association: MEMBER
diff_hunk: @@ -20,36 +18,49 @@ The two following steps are enough to jumpstart the formatting of a new language
     },
 ```
 
-#### Create the query file
-```bash
-touch topiary-queries/queries/c.scm
+## Create the query file
+
+```sh
+touch topiary-queries/queries/clang.scm
 ```
 
-#### Testing
+### Testing
 
-You can now check that Topiary is able to "format" your new language with:
+You can now check that Topiary is able to "format" your new language
+with:
 
-```bash
-$ echo 'void main();' | cargo run -- format -s --language c
+```sh
+$ echo 'void main();' | cargo run -- format -s --language clang
 voidmain();
 ```
 
-```bash
-$ echo 'void main();' > foo.c && cargo run -- format -s foo.c && cat foo.c
-voidmain();
-```
+At this point, there are no formatting queries, so no formatting is
+applied and we get mangled output. This is why the `-s`
+(`--skip-idempotence`) flag is set, as Topiary will complain when
+formatting doesn't reach a fixed point (which this output is likely to
+result in).
path: docs/book/src/guides/adding-a-new-language.md
user: login: Xophmeister
body: Done in 93af73e6882ef7f
created_at: 2025-03-04T13:30:17Z
author_association: MEMBER
diff_hunk: @@ -79,5 +94,5 @@ suggested way to work:
    )
    ```
 
-8. Run `cargo test` again, to see if the output is better now, and then
-   return to step 5.
+7. Run `cargo test` again, to see if the output has improved, then
+   return to step 4.
path: docs/book/src/guides/suggested-workflow.md
user: login: nbacquey
body: Maybe add somewhere in this section a link to the `#query_name!` predicate, which can help identify which query does what.
created_at: 2025-03-04T14:04:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -79,5 +94,5 @@ suggested way to work:
    )
    ```
 
-8. Run `cargo test` again, to see if the output is better now, and then
-   return to step 5.
+7. Run `cargo test` again, to see if the output has improved, then
+   return to step 4.
path: docs/book/src/guides/suggested-workflow.md
user: login: Xophmeister
body: Excellent idea :pray:
created_at: 2025-03-04T14:54:07Z
author_association: MEMBER

PR comments:
user: login: dpulls[bot]
created_at: 2025-03-03T10:56:49Z
body: :warning:  Dpulls not installed on repository `tweag/topiary`. Checkout our [quickstart](https://www.dpulls.com/docs#/quickstart) for how to install.
author_association: NONE
user: login: dpulls[bot]
created_at: 2025-03-03T16:51:43Z
body: :warning:  Dpulls not installed on repository `tweag/topiary`. Checkout our [quickstart](https://www.dpulls.com/docs#/quickstart) for how to install.
author_association: NONE