diff options
| author | Daniel Gavin <danielgavin5@hotmail.com> | 2022-08-08 22:09:57 +0200 |
|---|---|---|
| committer | Daniel Gavin <danielgavin5@hotmail.com> | 2022-08-08 22:09:57 +0200 |
| commit | c9a3fba84d9645470b64f2174e56533fbe35c10a (patch) | |
| tree | ac9508927b2164974f9fb57f8188d0a2aff5872c | |
| parent | b7b21f1b56a867a33a27bde0b24ef07d8761fea5 (diff) | |
add support to `odinfmt.json` config for formatter.
| -rw-r--r-- | odinfmt.json | 5 | ||||
| -rw-r--r-- | ols.json | 20 | ||||
| -rw-r--r-- | src/common/config.odin | 7 | ||||
| -rw-r--r-- | src/odin/format/format.odin | 39 | ||||
| -rw-r--r-- | src/odin/printer/printer.odin | 10 | ||||
| -rw-r--r-- | src/server/format.odin | 18 | ||||
| -rw-r--r-- | src/server/requests.odin | 10 | ||||
| -rw-r--r-- | src/server/types.odin | 1 | ||||
| -rw-r--r-- | tools/odinfmt/main.odin | 25 |
9 files changed, 85 insertions, 50 deletions
diff --git a/odinfmt.json b/odinfmt.json new file mode 100644 index 0000000..d9f6c50 --- /dev/null +++ b/odinfmt.json @@ -0,0 +1,5 @@ +{ + "character_width": 80, + "tabs": true, + "tabs_width": 4 +}
\ No newline at end of file @@ -1,10 +1,16 @@ { - "collections": [{ "name": "core", "path": "..\\Odin\\core" }, - { "name": "shared", "path": "c:/Users/danie/OneDrive/Desktop/Computer_Science/ols/src" }], - "thread_pool_count": 4, + "collections": [ + { + "name": "core", + "path": "C:\\Users\\danie\\OneDrive\\Desktop\\Computer_Science\\Odin\\core" + }, + { + "name": "shared", + "path": "src" + } + ], "enable_document_symbols": true, - "enable_semantic_tokens": false, + "enable_semantic_tokens": true, "enable_hover": true, - "enable_global_std": true, - "verbose": true -}
\ No newline at end of file + "enable_snippets": true +} diff --git a/src/common/config.odin b/src/common/config.odin index d90e5fa..b4114c0 100644 --- a/src/common/config.odin +++ b/src/common/config.odin @@ -20,15 +20,8 @@ Config :: struct { enable_std_references: bool, thread_count: int, file_log: bool, - formatter: Format_Config, odin_command: string, checker_args: string, } -Format_Config :: struct { - tabs: bool, - characters: int, - spaces: int, -} - config: Config;
\ No newline at end of file diff --git a/src/odin/format/format.odin b/src/odin/format/format.odin index 2abfbec..eee51b3 100644 --- a/src/odin/format/format.odin +++ b/src/odin/format/format.odin @@ -3,6 +3,10 @@ package odin_format import "shared:odin/printer" import "core:odin/parser" import "core:odin/ast" +import "core:encoding/json" +import "core:os" +import "core:path/filepath" +import "core:fmt" default_style := printer.default_style @@ -10,6 +14,41 @@ simplify :: proc(file: ^ast.File) { } +find_config_file_or_default :: proc(path: string) -> printer.Config { + //go up the directory until we find odinfmt.json + path := path + + ok: bool + if path, ok = filepath.abs(path); !ok { + return default_style + } + + name := fmt.tprintf("%v/odinfmt.json", path) + found := false + config := default_style + + if (os.exists(name)) { + if data, ok := os.read_entire_file(name, context.temp_allocator); ok { + if json.unmarshal(data, &config) == nil { + found = true + } + } + } else { + new_path := filepath.join(elems = {path, ".."}, allocator = context.temp_allocator) + //Currently the filepath implementation seems to stop at the root level, this might not be the best solution. + if new_path == path { + return default_style + } + return find_config_file_or_default(new_path) + } + + if !found { + return default_style + } + + return config +} + format :: proc(filepath: string, source: string, config: printer.Config, parser_flags := parser.Flags{.Optional_Semicolons}, allocator := context.allocator) -> (string, bool) { config := config diff --git a/src/odin/printer/printer.odin b/src/odin/printer/printer.odin index c37e0fa..7c444a1 100644 --- a/src/odin/printer/printer.odin +++ b/src/odin/printer/printer.odin @@ -35,7 +35,7 @@ Disabled_Info :: struct { } Config :: struct { - max_characters: int, + character_width: int, spaces: int, //Spaces per indentation newline_limit: int, //The limit of newlines between statements and declarations. tabs: bool, //Enable or disable tabs @@ -91,7 +91,7 @@ when ODIN_OS == .Windows { brace_style = ._1TBS, indent_cases = false, newline_style = .CRLF, - max_characters = 100, + character_width = 100, } } else { default_style := Config { @@ -103,7 +103,7 @@ when ODIN_OS == .Windows { brace_style = ._1TBS, indent_cases = false, newline_style = .LF, - max_characters = 100, + character_width = 100, } } @@ -167,7 +167,7 @@ print_expr :: proc(p: ^Printer, expr: ^ast.Expr) -> string { indentation = 0, }) - format(p.config.max_characters, &list, &p.string_builder, p) + format(p.config.character_width, &list, &p.string_builder, p) return strings.to_string(p.string_builder) } @@ -220,7 +220,7 @@ print_file :: proc(p: ^Printer, file: ^ast.File) -> string { indentation = 0, }) - format(p.config.max_characters, &list, &p.string_builder, p) + format(p.config.character_width, &list, &p.string_builder, p) return strings.to_string(p.string_builder) } diff --git a/src/server/format.odin b/src/server/format.odin index 57243ff..236bee2 100644 --- a/src/server/format.odin +++ b/src/server/format.odin @@ -2,6 +2,8 @@ package server import "shared:common" import "shared:odin/printer" +import "shared:odin/format" +import "core:path/filepath" import "core:log" @@ -19,19 +21,6 @@ DocumentFormattingParams :: struct { } get_complete_format :: proc(document: ^Document, config: ^common.Config) -> ([]TextEdit, bool) { - style := printer.default_style - style.tabs = config.formatter.tabs - - if config.formatter.characters != 0 { - style.max_characters = config.formatter.characters - } - - if config.formatter.spaces != 0 { - style.spaces = config.formatter.spaces - } - - prnt := printer.make_printer(style, context.temp_allocator) - if document.ast.syntax_error_count > 0 { return {}, true } @@ -40,6 +29,9 @@ get_complete_format :: proc(document: ^Document, config: ^common.Config) -> ([]T return {}, true } + style := format.find_config_file_or_default(filepath.dir(document.fullpath, context.temp_allocator)) + prnt := printer.make_printer(style, context.temp_allocator) + src := printer.print(&prnt, &document.ast) log.error(src) diff --git a/src/server/requests.odin b/src/server/requests.odin index b7774d5..d89263b 100644 --- a/src/server/requests.odin +++ b/src/server/requests.odin @@ -384,13 +384,8 @@ request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.C read_ols_config :: proc(file: string, config: ^common.Config, uri: common.Uri) { if data, ok := os.read_entire_file(file, context.temp_allocator); ok { if value, err := json.parse(data = data, allocator = context.temp_allocator, parse_integers = true); err == .None { - ols_config := OlsConfig { - formatter = { - characters = 90, - tabs = true, - }, - } - + ols_config: OlsConfig + if unmarshal(value, ols_config, context.temp_allocator) == nil { config.thread_count = ols_config.thread_pool_count config.enable_document_symbols = ols_config.enable_document_symbols @@ -402,7 +397,6 @@ request_initialize :: proc (params: json.Value, id: RequestId, config: ^common.C config.enable_references = false config.verbose = ols_config.verbose config.file_log = ols_config.file_log - config.formatter = ols_config.formatter config.odin_command = strings.clone(ols_config.odin_command, context.allocator) config.checker_args = ols_config.checker_args config.enable_inlay_hints = ols_config.enable_inlay_hints diff --git a/src/server/types.odin b/src/server/types.odin index 78e7241..0c50ad5 100644 --- a/src/server/types.odin +++ b/src/server/types.odin @@ -329,7 +329,6 @@ OlsConfig :: struct { enable_inlay_hints: bool, verbose: bool, file_log: bool, - formatter: common.Format_Config, odin_command: string, checker_args: string, } diff --git a/tools/odinfmt/main.odin b/tools/odinfmt/main.odin index 77f1379..60e4f82 100644 --- a/tools/odinfmt/main.odin +++ b/tools/odinfmt/main.odin @@ -2,12 +2,14 @@ package odinfmt import "core:os" import "core:odin/tokenizer" +import "shared:odin/printer" import "shared:odin/format" import "core:fmt" import "core:strings" import "core:path/filepath" import "core:time" import "core:mem" +import "core:encoding/json" import "flag" Args :: struct { @@ -39,9 +41,10 @@ print_arg_error :: proc(args: []string, error: flag.Flag_Error) { } } -format_file :: proc(filepath: string, allocator := context.allocator) -> (string, bool) { + +format_file :: proc(filepath: string, config: printer.Config, allocator := context.allocator) -> (string, bool) { if data, ok := os.read_entire_file(filepath, allocator); ok { - return format.format(filepath, string(data), format.default_style, {.Optional_Semicolons}, allocator); + return format.format(filepath, string(data), config, {.Optional_Semicolons}, allocator); } else { return "", false; } @@ -69,6 +72,8 @@ main :: proc() { arena_allocator := mem.arena_allocator(&arena); + init_global_temporary_allocator(mem.Megabyte*20) //enough space for the walk + args: Args; if len(os.args) < 2 { @@ -90,26 +95,28 @@ main :: proc() { watermark := 0 if os.is_file(path) { + config := format.find_config_file_or_default(path); if _, ok := args.write.(bool); ok { backup_path := strings.concatenate({path, "_bk"}); defer delete(backup_path); - if data, ok := format_file(path, arena_allocator); ok { + if data, ok := format_file(path, config, arena_allocator); 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); + fmt.eprintf("Failed to write %v", path); write_failure = true; } } else { - if data, ok := format_file(path, arena_allocator); ok { + if data, ok := format_file(path, config, arena_allocator); ok { fmt.println(data); } } } else if os.is_dir(path) { + config := format.find_config_file_or_default(path); filepath.walk(path, walk_files); for file in files { @@ -118,7 +125,7 @@ main :: proc() { backup_path := strings.concatenate({file, "_bk"}); defer delete(backup_path); - if data, ok := format_file(file, arena_allocator); ok { + if data, ok := format_file(file, config, arena_allocator); ok { if _, ok := args.write.(bool); ok { os.rename(file, backup_path); @@ -129,7 +136,7 @@ main :: proc() { fmt.println(data); } } else { - fmt.eprintf("failed to format %v", file); + fmt.eprintf("Failed to format %v", file); write_failure = true; } @@ -138,8 +145,8 @@ main :: proc() { free_all(arena_allocator); } - fmt.printf("formatted %v files in %vms \n", len(files), time.duration_milliseconds(time.tick_lap_time(&tick_time))); - fmt.printf("peak used memory: %v \n", watermark / mem.Megabyte) + fmt.printf("Formatted %v files in %vms \n", len(files), time.duration_milliseconds(time.tick_lap_time(&tick_time))); + fmt.printf("Peak memory used: %v \n", watermark / mem.Megabyte) } else { fmt.eprintf("%v is neither a directory nor a file \n", path); os.exit(1); |