From c7a9c8274fc212ec421d46c2c58f36afdc949898 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 17 Jan 2022 22:16:32 +0000 Subject: [PATCH] Improve type printing --- tools/odin-html-docs/odin_html_docs_main.odin | 243 +++++++++++++----- tools/odin-html-docs/style.css | 32 ++- 2 files changed, 205 insertions(+), 70 deletions(-) diff --git a/tools/odin-html-docs/odin_html_docs_main.odin b/tools/odin-html-docs/odin_html_docs_main.odin index 4260bd697..988c54d9d 100644 --- a/tools/odin-html-docs/odin_html_docs_main.odin +++ b/tools/odin-html-docs/odin_html_docs_main.odin @@ -45,6 +45,14 @@ base_type :: proc(t: doc.Type) -> doc.Type { return t } +is_type_untyped :: proc(type: doc.Type) -> bool { + if type.kind == .Basic { + flags := transmute(doc.Type_Flags_Basic)type.flags + return .Untyped in flags + } + return false +} + common_prefix :: proc(strs: []string) -> string { if len(strs) == 0 { return "" @@ -275,7 +283,9 @@ write_core_directory :: proc(w: io.Writer) { line_doc, _, _ := strings.partition(str(dir.pkg.docs), "\n") line_doc = strings.trim_space(line_doc) if line_doc != "" { - fmt.wprintf(w, `%s`, line_doc) + io.write_string(w, ``) + write_doc_line(w, line_doc) + io.write_string(w, ``) } } fmt.wprintf(w, "\n") @@ -289,7 +299,9 @@ write_core_directory :: proc(w: io.Writer) { line_doc, _, _ := strings.partition(str(child.pkg.docs), "\n") line_doc = strings.trim_space(line_doc) if line_doc != "" { - fmt.wprintf(w, `%s`, line_doc) + io.write_string(w, ``) + write_doc_line(w, line_doc) + io.write_string(w, ``) } fmt.wprintf(w, "\n") @@ -305,16 +317,31 @@ is_entity_blank :: proc(e: doc.Entity_Index) -> bool { return name == "" || name == "_" } +write_where_clauses :: proc(w: io.Writer, where_clauses: []doc.String) { + if len(where_clauses) != 0 { + io.write_string(w, " where ") + for clause, i in where_clauses { + if i > 0 { + io.write_string(w, ", ") + } + io.write_string(w, str(clause)) + } + } +} + + Write_Type_Flag :: enum { Is_Results, Variadic, Allow_Indent, + Poly_Names, } Write_Type_Flags :: distinct bit_set[Write_Type_Flag] Type_Writer :: struct { w: io.Writer, pkg: doc.Pkg_Index, indent: int, + generic_scope: map[string]bool, } write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type_Flags) { @@ -329,30 +356,65 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type if .Param_Any_Int in e.flags { io.write_string(w, "#any_int ") } init_string := str(e.init_string) - switch init_string { - case "#caller_location": + switch { + case init_string == "#caller_location": assert(name != "") io.write_string(w, name) io.write_string(w, " := ") io.write_string(w, ``) io.write_string(w, init_string) io.write_string(w, ``) - + case strings.has_prefix(init_string, "context."): + io.write_string(w, name) + io.write_string(w, " := ") + io.write_string(w, ``) + io.write_string(w, init_string) + io.write_string(w, ``) case: - if name != "" { - io.write_string(w, name) - io.write_string(w, ": ") - } - padding := max(name_width-len(name), 0) - for _ in 0..%s`, str(type.name)) @@ -408,17 +469,23 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type case .Named: e := entities[type_entites[0]] name := str(type.name) - fmt.wprintf(w, ``) tn_pkg := files[e.pos.file].pkg if tn_pkg != pkg { fmt.wprintf(w, `%s.`, str(pkgs[tn_pkg].name)) } - fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name) + if n := strings.contains_rune(name, '('); n >= 0 { + fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name[:n]) + io.write_string(w, name[n:]) + } else { + fmt.wprintf(w, `{1:s}`, pkg_to_path[&pkgs[tn_pkg]], name) + } case .Generic: name := str(type.name) - io.write_byte(w, '$') + if name not_in generic_scope { + io.write_byte(w, '$') + } io.write_string(w, name) - if len(array(type.types)) == 1 { + if name not_in generic_scope && len(array(type.types)) == 1 { io.write_byte(w, '/') write_type(writer, types[type_types[0]], flags) } @@ -454,9 +521,7 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type case .Struct: type_flags := transmute(doc.Type_Flags_Struct)type.flags io.write_string(w, "struct") - if .Polymorphic in type_flags { - write_poly_params(writer, type, flags) - } + write_poly_params(writer, type, flags) if .Packed in type_flags { io.write_string(w, " #packed") } if .Raw_Union in type_flags { io.write_string(w, " #raw_union") } if custom_align := str(type.custom_align); custom_align != "" { @@ -483,9 +548,7 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type case .Union: type_flags := transmute(doc.Type_Flags_Union)type.flags io.write_string(w, "union") - if .Polymorphic in type_flags { - write_poly_params(writer, type, flags) - } + write_poly_params(writer, type, flags) if .No_Nil in type_flags { io.write_string(w, " #no_nil") } if .Maybe in type_flags { io.write_string(w, " #maybe") } if custom_align := str(type.custom_align); custom_align != "" { @@ -631,6 +694,25 @@ write_type :: proc(using writer: ^Type_Writer, type: doc.Type, flags: Write_Type } } +write_doc_line :: proc(w: io.Writer, text: string) { + text := text + for len(text) != 0 { + if strings.count(text, "`") >= 2 { + n := strings.index_byte(text, '`') + io.write_string(w, text[:n]) + io.write_string(w, "") + remaining := text[n+1:] + m := strings.index_byte(remaining, '`') + io.write_string(w, remaining[:m]) + io.write_string(w, "") + text = remaining[m+1:] + } else { + io.write_string(w, text) + return + } + } +} + write_docs :: proc(w: io.Writer, pkg: ^doc.Pkg, docs: string) { if docs == "" { return @@ -663,8 +745,11 @@ write_docs :: proc(w: io.Writer, pkg: ^doc.Pkg, docs: string) { fmt.wprintln(w, "

") } assert(!was_code) + was_paragraph = true - fmt.wprintln(w, text) + write_doc_line(w, text) + + io.write_byte(w, '\n') } if was_code { // assert(!was_paragraph, str(pkg.name)) @@ -677,6 +762,24 @@ write_docs :: proc(w: io.Writer, pkg: ^doc.Pkg, docs: string) { } write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { + write_breadcrumbs :: proc(w: io.Writer, path: string) { + dirs := strings.split(path, "/") + io.write_string(w, "

\n") + + } + write_breadcrumbs(w, fmt.tprintf("core/%s", path)) + + fmt.wprintf(w, "

package core:%s

\n", path) fmt.wprintln(w, "

Documentation

") docs := strings.trim_space(str(pkg.docs)) @@ -723,7 +826,7 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { slice.sort_by_key(pkg_vars[:], entity_key) slice.sort_by_key(pkg_consts[:], entity_key) - print_index :: proc(w: io.Writer, name: string, entities: []^doc.Entity) { + write_index :: proc(w: io.Writer, name: string, entities: []^doc.Entity) { fmt.wprintf(w, "

%s

\n", name) fmt.wprintln(w, `
`) if len(entities) == 0 { @@ -740,16 +843,16 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { } - print_index(w, "Procedures", pkg_procs[:]) - print_index(w, "Procedure Groups", pkg_proc_groups[:]) - print_index(w, "Types", pkg_types[:]) - print_index(w, "Variables", pkg_vars[:]) - print_index(w, "Constants", pkg_consts[:]) + write_index(w, "Procedures", pkg_procs[:]) + write_index(w, "Procedure Groups", pkg_proc_groups[:]) + write_index(w, "Types", pkg_types[:]) + write_index(w, "Variables", pkg_vars[:]) + write_index(w, "Constants", pkg_consts[:]) fmt.wprintln(w, "
") - print_entity :: proc(w: io.Writer, e: ^doc.Entity) { + write_entity :: proc(w: io.Writer, e: ^doc.Entity) { write_attributes :: proc(w: io.Writer, e: ^doc.Entity) { for attr in array(e.attributes) { io.write_string(w, "@(") @@ -764,23 +867,24 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { } } - pkg_index := files[e.pos.file].pkg pkg := &pkgs[pkg_index] writer := &Type_Writer{ w = w, pkg = pkg_index, } + defer delete(writer.generic_scope) name := str(e.name) path := pkg_to_path[pkg] filename := slashpath.base(str(files[e.pos.file].name)) - fmt.wprintf(w, "

{0:s}", name) - fmt.wprintf(w, " ¶

\n") - defer if e.pos.file != 0 && e.pos.line > 0 { + fmt.wprintf(w, "

{0:s}", name) + fmt.wprintf(w, " ¶") + if e.pos.file != 0 && e.pos.line > 0 { src_url := fmt.tprintf("%s/%s/%s#L%d", GITHUB_CORE_URL, path, filename, e.pos.line) - fmt.wprintf(w, "Source: {0:s}", src_url) + fmt.wprintf(w, "", src_url) } + fmt.wprintf(w, "

\n") switch e.kind { case .Invalid, .Import_Name, .Library_Name: @@ -788,7 +892,21 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { case .Constant: fmt.wprint(w, "
")
 			the_type := types[e.type]
-			if the_type.kind == .Basic && .Untyped in (transmute(doc.Type_Flags_Basic)the_type.flags) {
+
+			init_string := str(e.init_string)
+			assert(init_string != "")
+
+			ignore_type := true
+			if the_type.kind == .Basic && is_type_untyped(the_type) {
+			} else {
+				ignore_type = false
+				type_name := str(the_type.name)
+				if type_name != "" && strings.has_prefix(init_string, type_name) {
+					ignore_type = true
+				}
+			}
+
+			if ignore_type {
 				fmt.wprintf(w, "%s :: ", name)
 			} else {
 				fmt.wprintf(w, "%s: ", name)
@@ -796,8 +914,7 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) {
 				fmt.wprintf(w, " : ")
 			}
 
-			init_string := str(e.init_string)
-			assert(init_string != "")
+
 			io.write_string(w, init_string)
 			fmt.wprintln(w, "
") case .Variable: @@ -835,17 +952,7 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { fmt.wprint(w, "
")
 			fmt.wprintf(w, "%s :: ", name)
 			write_type(writer, types[e.type], nil)
-			where_clauses := array(e.where_clauses)
-			if len(where_clauses) != 0 {
-				io.write_string(w, " where ")
-				for clause, i in where_clauses {
-					if i > 0 {
-						io.write_string(w, ", ")
-					}
-					io.write_string(w, str(clause))
-				}
-			}
-
+			write_where_clauses(w, array(e.where_clauses))
 			fmt.wprint(w, " {…}")
 			fmt.wprintln(w, "
") case .Proc_Group: @@ -872,24 +979,24 @@ write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { write_docs(w, pkg, strings.trim_space(str(e.docs))) } - print_entities :: proc(w: io.Writer, title: string, entities: []^doc.Entity) { + write_entities :: proc(w: io.Writer, title: string, entities: []^doc.Entity) { fmt.wprintf(w, "

%s

\n", title) fmt.wprintln(w, `
`) if len(entities) == 0 { io.write_string(w, "

This section is empty.

\n") } else { for e in entities { - print_entity(w, e) + write_entity(w, e) } } fmt.wprintln(w, "
") } - print_entities(w, "Procedures", pkg_procs[:]) - print_entities(w, "Procedure Groups", pkg_proc_groups[:]) - print_entities(w, "Types", pkg_types[:]) - print_entities(w, "Variables", pkg_vars[:]) - print_entities(w, "Constants", pkg_consts[:]) + write_entities(w, "Procedures", pkg_procs[:]) + write_entities(w, "Procedure Groups", pkg_proc_groups[:]) + write_entities(w, "Types", pkg_types[:]) + write_entities(w, "Variables", pkg_vars[:]) + write_entities(w, "Constants", pkg_consts[:]) fmt.wprintln(w, "

Source Files

") diff --git a/tools/odin-html-docs/style.css b/tools/odin-html-docs/style.css index 61cab3e8c..cf43a7199 100644 --- a/tools/odin-html-docs/style.css +++ b/tools/odin-html-docs/style.css @@ -21,7 +21,7 @@ pre { white-space: pre-wrap; - word-break: break-all; + word-break: keep-all; word-wrap: break-word; tab-size: 8; font-family: Consolas,Liberation Mono,Menlo,monospace!important; @@ -44,10 +44,15 @@ pre a { } .documentation-source { + display: inline; + float: right; +} + +.documentation-source a { text-decoration: none; color: #666666; } -.documentation-source:hover { +.documentation-source a:hover { text-decoration: underline; } @@ -56,4 +61,27 @@ a > .a-hidden { } a:hover > .a-hidden { opacity: 100; +} + +ul.documentation-breadcrumb { + list-style: none; +} + +ul.documentation-breadcrumb li { + display: inline; +} + +ul.documentation-breadcrumb li+li:before { + padding: 0.2rem; + color: black; + content: "/\00a0"; +} + +.code-inline { + font-family: Consolas,Liberation Mono,Menlo,monospace!important; + background-color: #f8f8f8; + color: #202224; + border: 1px solid #c6c8ca; + border-radius: 0.25rem; + padding: 0.125rem; } \ No newline at end of file