Tools
burnfmt
burnfmt gives every Burn file the same layout. It is a Burn program: the source lives in
lib/tools/fmt.bn, and it runs on bvm. It produces exactly
the same output as the formatter built into the compiler (burn fmt and the language server's format command);
the test suite checks this for every file in the repository.
Usage
burnfmt file.bn # print the formatted file
burnfmt -w file.bn other.bn # rewrite files in place
burnfmt --check src/*.bn # list files that are not formatted, exit code 1 if any
cat file.bn | burnfmt # format standard input to standard output| Option | Description |
|---|---|
-w, --write |
write the result back to the files |
-l, --check |
only report unformatted files |
-h, --help |
show the help |
-v, --version |
show the version |
Without an installed burnfmt, the same program runs on the interpreter:
burni lib/tools/fmt.bn -w file.bnFrom code
The formatter is also a module that programs can import. lib/tools/ holds the tools written in Burn; each one is
a library first, and its command is the same file's main:
import "tools/fmt"
print(format("fun f(){\nreturn 1\n}"))format(src) returns the formatted source. Only format is public; the rest of the module is private, so
importing it adds nothing else to your program.
The older Go build from bnfmt (go install github.com/burnlang/burnfmt) is
deprecated. Remove it with rm "$(go env GOPATH)/bin/burnfmt" and use this one: it takes the same options and
always matches your Burn version.
Rules
- Indentation is 4 spaces per open brace, bracket or parenthesis.
- A line that opens a block and continues is split after the
{; a}that closes an earlier line starts its own line. - A blank line separates a closing
}from the declaration that follows it. - Consecutive blank lines become one; leading blank lines are removed.
- One space around binary operators and after
,,:and;, none before them. In a struct header the:and::that name what the struct extends get a space on both sides:def struct Puppy(name: string) : Dog(name) :: Named. - Doc comments (
/** ... */) are indented with the code they document, with*lines aligned under the opening/**. - No space inside
()and[], after unary-and!, around.and ranges (0..10), or before?and!!. - A space after keywords such as
if,while,forandreturn, and before{. - Braces keep the padding of the source, so both
{ name: "x" }and{string: int}stay as written. - Strings, comments and block comments are never changed.
fun area(w: float, h: float): float {
return w * h
}
def struct Rect(w: float, h: float) {
fun scale(k: float) {
w *= k
h *= k
}
}
for i in 0..3 {
print(i, -i, area(i, 2))
}How it works
burnfmt works line by line, which keeps comments and the user's line structure intact:
- Each line is split into tokens (words, numbers, strings, comments, operators and brackets). Every opening and closing brace remembers whether it touched the neighbouring character in the source.
- Lines that open a block and keep going, or close one after other code, are split into segments.
- Each segment is indented by the current nesting depth, minus the closing brackets it starts with.
- Tokens are joined with the spacing rules above.
Because it only uses the standard built-ins (readFile, writeFile, readStdin, args, string and array
functions and the character class checks isLetter, isAlphanumeric and isWhitespace), it is also a compact
example of a real command line program written in Burn.