mirror of
https://github.com/bearlanguageorg/bear.git
synced 2026-08-26 14:17:18 +00:00
Adds floats, bitwise ops, UTF-8 strings with methods, try/catch, closures, generics validation, a compile-time type checker, a mark-and-sweep GC, source-level debug info, constant folding, and the repl/fmt/package-manager commands. 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
105 lines
2.4 KiB
V
105 lines
2.4 KiB
V
// fmt.v — `vr fmt`: a source formatter for VuurRaaf.
|
|
//
|
|
// Works line-by-line: it fixes indentation from brace depth, trims stray
|
|
// whitespace, collapses space runs outside string literals, and preserves
|
|
// every comment (whole-line and inline). It never reorders or rewrites code.
|
|
//
|
|
// vr fmt file.vr print the formatted source to stdout
|
|
// vr fmt -w file.vr rewrite the file in place
|
|
module main
|
|
|
|
import os
|
|
|
|
fn toolchain_fmt(args []string) ! {
|
|
if args.len == 0 {
|
|
return error('usage: vr fmt [-w] <file.vr>')
|
|
}
|
|
mut write := false
|
|
mut files := []string{}
|
|
for a in args {
|
|
if a == '-w' || a == '--write' {
|
|
write = true
|
|
} else {
|
|
files << a
|
|
}
|
|
}
|
|
if files.len == 0 {
|
|
return error('usage: vr fmt [-w] <file.vr>')
|
|
}
|
|
for f in files {
|
|
src := os.read_file(f) or { return error('cannot read "${f}": ${err.msg()}') }
|
|
formatted := fmt_source(src)
|
|
if write {
|
|
os.write_file(f, formatted) or { return error('cannot write "${f}": ${err.msg()}') }
|
|
println('formatted ${f}')
|
|
} else {
|
|
print(formatted)
|
|
}
|
|
}
|
|
}
|
|
|
|
// fmt_source normalizes a whole source file. Comment lines are indented with
|
|
// the surrounding depth; closing braces drop one level like the code does.
|
|
fn fmt_source(src string) string {
|
|
mut out := ''
|
|
mut depth := 0
|
|
for raw in src.split_into_lines() {
|
|
line := raw.trim_space()
|
|
if line == '' {
|
|
out += '\n'
|
|
continue
|
|
}
|
|
d := brace_delta(line)
|
|
mut indent := depth
|
|
if line.starts_with('}') && depth > 0 {
|
|
indent = depth - 1
|
|
}
|
|
out += '\t'.repeat(indent) + collapse_spaces(line) + '\n'
|
|
depth += d
|
|
if depth < 0 {
|
|
depth = 0
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// collapse_spaces replaces runs of spaces outside of string literals with a
|
|
// single space, so indentation and padding become canonical without touching
|
|
// string contents.
|
|
fn collapse_spaces(line string) string {
|
|
mut out := ''
|
|
mut in_str := false
|
|
mut i := 0
|
|
for i < line.len {
|
|
c := line[i]
|
|
if c == `"` {
|
|
in_str = !in_str
|
|
out += c.ascii_str()
|
|
i++
|
|
continue
|
|
}
|
|
if in_str && c == `\\` {
|
|
out += c.ascii_str()
|
|
i++
|
|
if i < line.len {
|
|
out += line[i].ascii_str()
|
|
i++
|
|
}
|
|
continue
|
|
}
|
|
if !in_str && c == ` ` {
|
|
for i < line.len && line[i] == ` ` {
|
|
i++
|
|
}
|
|
out += ' '
|
|
continue
|
|
}
|
|
out += c.ascii_str()
|
|
i++
|
|
}
|
|
return out
|
|
}
|
|
|
|
// brace_delta is shared with the REPL (repl.v): it tokenizes the line so
|
|
// braces inside string literals do not affect depth.
|