package odin_html_docs import doc "core:odin/doc-format" import "core:fmt" import "core:io" import "core:os" import "core:strings" import "core:path/slashpath" import "core:sort" import "core:slice" GITHUB_CORE_URL :: "https://github.com/odin-lang/Odin/tree/master/core" header: ^doc.Header files: []doc.File pkgs: []doc.Pkg entities: []doc.Entity types: []doc.Type pkgs_to_use: map[string]^doc.Pkg // trimmed path pkg_to_path: map[^doc.Pkg]string // trimmed path array :: proc(a: $A/doc.Array($T)) -> []T { return doc.from_array(header, a) } str :: proc(s: $A/doc.String) -> string { return doc.from_string(header, s) } errorf :: proc(format: string, args: ..any) -> ! { fmt.eprintf("%s ", os.args[0]) fmt.eprintf(format, ..args) fmt.eprintln() os.exit(1) } base_type :: proc(t: doc.Type) -> doc.Type { t := t for { if t.kind != .Named { break } t = types[array(t.types)[0]] } return t } common_prefix :: proc(strs: []string) -> string { if len(strs) == 0 { return "" } n := max(int) for str in strs { n = min(n, len(str)) } prefix := strs[0][:n] for str in strs[1:] { for len(prefix) != 0 && str[:len(prefix)] != prefix { prefix = prefix[:len(prefix)-1] } if len(prefix) == 0 { break } } return prefix } recursive_make_directory :: proc(path: string, prefix := "") { head, _, tail := strings.partition(path, "/") path_to_make := head if prefix != "" { path_to_make = fmt.tprintf("%s/%s", prefix, head) } os.make_directory(path_to_make, 0) if tail != "" { recursive_make_directory(tail, path_to_make) } } write_html_header :: proc(w: io.Writer, title: string) { fmt.wprintf(w, `
`, dir.dir) } else { fmt.wprintf(w, ` | |
`, dir.dir) } if dir.pkg != nil { fmt.wprintf(w, `%s`, dir.path, dir.name) } else { fmt.wprintf(w, "%s", dir.name) } fmt.wprintf(w, " | ") if dir.pkg != nil { 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) } } fmt.wprintf(w, "
`, str(child.pkg.name)) fmt.wprintf(w, `%s`, child.path, child.name) fmt.wprintf(w, " | ") 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) } fmt.wprintf(w, "
`)
}
fmt.wprintf(w, "%s\n", strings.trim_prefix(line, "\t"))
continue
} else if was_code {
was_code = false
fmt.wprintln(w, "
")
continue
}
text := strings.trim_space(line)
if text == "" {
if was_paragraph {
was_paragraph = false
fmt.wprintln(w, "")
}
continue
}
if !was_paragraph {
fmt.wprintln(w, "") } assert(!was_code) was_paragraph = true fmt.wprintln(w, text) } if was_code { // assert(!was_paragraph, str(pkg.name)) was_code = false fmt.wprintln(w, "") } if was_paragraph { fmt.wprintln(w, "
") } } write_pkg :: proc(w: io.Writer, path: string, pkg: ^doc.Pkg) { fmt.wprintf(w, "This section is empty.
\n") } else { fmt.wprintln(w, "") the_type := types[e.type] if the_type.kind == .Basic && .Untyped in (transmute(doc.Type_Flags_Basic)the_type.flags) { fmt.wprintf(w, "%s :: ", name) } else { fmt.wprintf(w, "%s: ", name) write_type(writer, the_type, {.Allow_Indent}) fmt.wprintf(w, " : ") } init_string := str(e.init_string) assert(init_string != "") io.write_string(w, init_string) fmt.wprintln(w, "") case .Variable: fmt.wprint(w, "
") write_attributes(w, e) fmt.wprintf(w, "%s: ", name) write_type(writer, types[e.type], {.Allow_Indent}) init_string := str(e.init_string) if init_string != "" { io.write_string(w, " = ") io.write_string(w, init_string) } fmt.wprintln(w, "") case .Type_Name: fmt.wprint(w, "
") fmt.wprintf(w, "%s :: ", name) the_type := types[e.type] type_to_print := the_type if the_type.kind == .Named && .Type_Alias not_in e.flags { if e.pos == entities[array(the_type.entities)[0]].pos { bt := base_type(the_type) #partial switch bt.kind { case .Struct, .Union, .Proc, .Enum: // Okay case: io.write_string(w, "distinct ") } type_to_print = bt } } write_type(writer, type_to_print, {.Allow_Indent}) fmt.wprintln(w, "") case .Procedure: 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)) } } fmt.wprint(w, " {…}") fmt.wprintln(w, "") case .Proc_Group: fmt.wprint(w, "
") fmt.wprintf(w, "%s :: proc{{\n", name) for entity_index in array(e.grouped_entities) { this_proc := &entities[entity_index] this_pkg := files[this_proc.pos.file].pkg io.write_byte(w, '\t') if this_pkg != pkg_index { fmt.wprintf(w, "%s.", str(pkgs[this_pkg].name)) } name := str(this_proc.name) fmt.wprintf(w, ``, pkg_to_path[&pkgs[this_pkg]], name) io.write_string(w, name) io.write_string(w, ``) io.write_byte(w, ',') io.write_byte(w, '\n') } fmt.wprintln(w, "}") fmt.wprintln(w, "") } write_docs(w, pkg, strings.trim_space(str(e.docs))) } print_entities :: proc(w: io.Writer, title: string, entities: []^doc.Entity) { fmt.wprintf(w, "
This section is empty.
\n") } else { for e in entities { print_entity(w, e) } } fmt.wprintln(w, "