mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-03 03:32:37 +00:00
147 lines
3.3 KiB
Odin
147 lines
3.3 KiB
Odin
package odinfmt
|
|
|
|
import "core:os"
|
|
import "core:odin/tokenizer"
|
|
import "core:odin/format"
|
|
import "core:fmt"
|
|
import "core:strings"
|
|
import "core:path/filepath"
|
|
import "core:time"
|
|
import "core:mem"
|
|
|
|
import "flag"
|
|
|
|
Args :: struct {
|
|
write: Maybe(bool) `flag:"w" usage:"write the new format to file"`,
|
|
}
|
|
|
|
print_help :: proc(args: []string) {
|
|
if len(args) == 0 {
|
|
fmt.eprint("odinfmt ");
|
|
} else {
|
|
fmt.eprintf("%s ", args[0]);
|
|
}
|
|
fmt.eprintln();
|
|
}
|
|
|
|
print_arg_error :: proc(args: []string, error: flag.Flag_Error) {
|
|
switch error {
|
|
case .None:
|
|
print_help(args);
|
|
case .No_Base_Struct:
|
|
fmt.eprintln(args[0], "no base struct");
|
|
case .Arg_Error:
|
|
fmt.eprintln(args[0], "argument error");
|
|
case .Arg_Unsupported_Field_Type:
|
|
fmt.eprintln(args[0], "argument: unsupported field type");
|
|
case .Arg_Not_Defined:
|
|
fmt.eprintln(args[0], "argument: no defined");
|
|
case .Arg_Non_Optional:
|
|
fmt.eprintln(args[0], "argument: non optional");
|
|
case .Value_Parse_Error:
|
|
fmt.eprintln(args[0], "argument: value parse error");
|
|
case .Tag_Error:
|
|
fmt.eprintln(args[0], "argument: tag error");
|
|
}
|
|
}
|
|
|
|
format_file :: proc(filepath: string) -> (string, bool) {
|
|
if data, ok := os.read_entire_file(filepath); ok {
|
|
return format.format(filepath, string(data), format.default_style);
|
|
} else {
|
|
return "", false;
|
|
}
|
|
}
|
|
|
|
files: [dynamic]string;
|
|
|
|
walk_files :: proc(info: os.File_Info, in_err: os.Errno) -> (err: os.Errno, skip_dir: bool) {
|
|
if info.is_dir {
|
|
return 0, false;
|
|
}
|
|
|
|
if filepath.ext(info.name) != ".odin" {
|
|
return 0, false;
|
|
}
|
|
|
|
append(&files, strings.clone(info.fullpath));
|
|
|
|
return 0, false;
|
|
}
|
|
|
|
main :: proc() {
|
|
init_global_temporary_allocator(mem.megabytes(100));
|
|
|
|
args: Args;
|
|
|
|
if len(os.args) < 2 {
|
|
print_help(os.args);
|
|
os.exit(1);
|
|
}
|
|
|
|
if res := flag.parse(args, os.args[1:len(os.args) - 1]); res != .None {
|
|
print_arg_error(os.args, res);
|
|
os.exit(1);
|
|
}
|
|
|
|
path := os.args[len(os.args) - 1];
|
|
|
|
tick_time := time.tick_now();
|
|
|
|
write_failure := false;
|
|
|
|
if os.is_file(path) {
|
|
if _, ok := args.write.(bool); ok {
|
|
backup_path := strings.concatenate({path, "_bk"});
|
|
defer delete(backup_path);
|
|
|
|
if data, ok := format_file(path); ok {
|
|
os.rename(path, backup_path);
|
|
|
|
if os.write_entire_file(path, transmute([]byte)data) {
|
|
os.remove(backup_path);
|
|
}
|
|
} else {
|
|
fmt.eprintf("failed to write %v", path);
|
|
write_failure = true;
|
|
}
|
|
} else {
|
|
if data, ok := format_file(path); ok {
|
|
fmt.println(data);
|
|
}
|
|
}
|
|
} else if os.is_dir(path) {
|
|
filepath.walk(path, walk_files);
|
|
|
|
for file in files {
|
|
fmt.println(file);
|
|
|
|
backup_path := strings.concatenate({file, "_bk"});
|
|
defer delete(backup_path);
|
|
|
|
if data, ok := format_file(file); ok {
|
|
|
|
if _, ok := args.write.(bool); ok {
|
|
os.rename(file, backup_path);
|
|
|
|
if os.write_entire_file(file, transmute([]byte)data) {
|
|
os.remove(backup_path);
|
|
}
|
|
} else {
|
|
fmt.println(data);
|
|
}
|
|
} else {
|
|
fmt.eprintf("failed to format %v", file);
|
|
write_failure = true;
|
|
}
|
|
}
|
|
|
|
fmt.printf("formatted %v files in %vms", len(files), time.duration_milliseconds(time.tick_lap_time(&tick_time)));
|
|
} else {
|
|
fmt.eprintf("%v is neither a directory nor a file \n", path);
|
|
os.exit(1);
|
|
}
|
|
|
|
os.exit(1 if write_failure else 0);
|
|
}
|