| author | |
| committer | |
| log | 9b47dd2028deb45324ca19d909d0cee69f51f1b9 |
| tree | 1b9cd7bbe8b1f09c77bc8b38458a0c5f745c2934 |
| parent | 8023f3dcebff06cbf3563bdd09b07462ed43509f |
6 files changed, 97 insertions(+), 93 deletions(-)
lib/docs/wasm/Decl.zig+5-4| ... | @@ -6,6 +6,7 @@ const gpa = std.heap.wasm_allocator; | ... | @@ -6,6 +6,7 @@ const gpa = std.heap.wasm_allocator; |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const log = std.log; | 7 | const log = std.log; |
| 8 | const Oom = error{OutOfMemory}; | 8 | const Oom = error{OutOfMemory}; |
| 9 | const ArrayList = std.ArrayList; | ||
| 9 | 10 | ||
| 10 | ast_node: Ast.Node.Index, | 11 | ast_node: Ast.Node.Index, |
| 11 | file: Walk.File.Index, | 12 | file: Walk.File.Index, |
| ... | @@ -189,7 +190,7 @@ pub fn lookup(decl: *const Decl, name: []const u8) ?Decl.Index { | ... | @@ -189,7 +190,7 @@ pub fn lookup(decl: *const Decl, name: []const u8) ?Decl.Index { |
| 189 | } | 190 | } |
| 190 | 191 | ||
| 191 | /// Appends the fully qualified name to `out`. | 192 | /// Appends the fully qualified name to `out`. |
| 192 | pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void { | 193 | pub fn fqn(decl: *const Decl, out: *ArrayList(u8)) Oom!void { |
| 193 | try decl.append_path(out); | 194 | try decl.append_path(out); |
| 194 | if (decl.parent != .none) { | 195 | if (decl.parent != .none) { |
| 195 | try append_parent_ns(out, decl.parent); | 196 | try append_parent_ns(out, decl.parent); |
| ... | @@ -199,12 +200,12 @@ pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void { | ... | @@ -199,12 +200,12 @@ pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void { |
| 199 | } | 200 | } |
| 200 | } | 201 | } |
| 201 | 202 | ||
| 202 | pub fn reset_with_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!void { | 203 | pub fn reset_with_path(decl: *const Decl, list: *ArrayList(u8)) Oom!void { |
| 203 | list.clearRetainingCapacity(); | 204 | list.clearRetainingCapacity(); |
| 204 | try append_path(decl, list); | 205 | try append_path(decl, list); |
| 205 | } | 206 | } |
| 206 | 207 | ||
| 207 | pub fn append_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!void { | 208 | pub fn append_path(decl: *const Decl, list: *ArrayList(u8)) Oom!void { |
| 208 | const start = list.items.len; | 209 | const start = list.items.len; |
| 209 | // Prefer the module name alias. | 210 | // Prefer the module name alias. |
| 210 | for (Walk.modules.keys(), Walk.modules.values()) |pkg_name, pkg_file| { | 211 | for (Walk.modules.keys(), Walk.modules.values()) |pkg_name, pkg_file| { |
| ... | @@ -230,7 +231,7 @@ pub fn append_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!voi | ... | @@ -230,7 +231,7 @@ pub fn append_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!voi |
| 230 | } | 231 | } |
| 231 | } | 232 | } |
| 232 | 233 | ||
| 233 | pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) Oom!void { | 234 | pub fn append_parent_ns(list: *ArrayList(u8), parent: Decl.Index) Oom!void { |
| 234 | assert(parent != .none); | 235 | assert(parent != .none); |
| 235 | const decl = parent.get(); | 236 | const decl = parent.get(); |
| 236 | if (decl.parent != .none) { | 237 | if (decl.parent != .none) { |
lib/docs/wasm/html_render.zig+10-8| ... | @@ -1,6 +1,8 @@ | ... | @@ -1,6 +1,8 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const Ast = std.zig.Ast; | 2 | const Ast = std.zig.Ast; |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const ArrayList = std.ArrayList; | ||
| 5 | const Writer = std.Io.Writer; | ||
| 4 | 6 | ||
| 5 | const Walk = @import("Walk"); | 7 | const Walk = @import("Walk"); |
| 6 | const Decl = Walk.Decl; | 8 | const Decl = Walk.Decl; |
| ... | @@ -30,7 +32,7 @@ pub const Annotation = struct { | ... | @@ -30,7 +32,7 @@ pub const Annotation = struct { |
| 30 | 32 | ||
| 31 | pub fn fileSourceHtml( | 33 | pub fn fileSourceHtml( |
| 32 | file_index: Walk.File.Index, | 34 | file_index: Walk.File.Index, |
| 33 | out: *std.ArrayListUnmanaged(u8), | 35 | out: *ArrayList(u8), |
| 34 | root_node: Ast.Node.Index, | 36 | root_node: Ast.Node.Index, |
| 35 | options: RenderSourceOptions, | 37 | options: RenderSourceOptions, |
| 36 | ) !void { | 38 | ) !void { |
| ... | @@ -38,7 +40,7 @@ pub fn fileSourceHtml( | ... | @@ -38,7 +40,7 @@ pub fn fileSourceHtml( |
| 38 | const file = file_index.get(); | 40 | const file = file_index.get(); |
| 39 | 41 | ||
| 40 | const g = struct { | 42 | const g = struct { |
| 41 | var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty; | 43 | var field_access_buffer: ArrayList(u8) = .empty; |
| 42 | }; | 44 | }; |
| 43 | 45 | ||
| 44 | const start_token = ast.firstToken(root_node); | 46 | const start_token = ast.firstToken(root_node); |
| ... | @@ -88,7 +90,7 @@ pub fn fileSourceHtml( | ... | @@ -88,7 +90,7 @@ pub fn fileSourceHtml( |
| 88 | if (next_annotate_index >= options.source_location_annotations.len) break; | 90 | if (next_annotate_index >= options.source_location_annotations.len) break; |
| 89 | const next_annotation = options.source_location_annotations[next_annotate_index]; | 91 | const next_annotation = options.source_location_annotations[next_annotate_index]; |
| 90 | if (cursor <= next_annotation.file_byte_offset) break; | 92 | if (cursor <= next_annotation.file_byte_offset) break; |
| 91 | try out.writer(gpa).print("<span id=\"{s}{d}\"></span>", .{ | 93 | try out.print(gpa, "<span id=\"{s}{d}\"></span>", .{ |
| 92 | options.annotation_prefix, next_annotation.dom_id, | 94 | options.annotation_prefix, next_annotation.dom_id, |
| 93 | }); | 95 | }); |
| 94 | next_annotate_index += 1; | 96 | next_annotate_index += 1; |
| ... | @@ -318,7 +320,7 @@ pub fn fileSourceHtml( | ... | @@ -318,7 +320,7 @@ pub fn fileSourceHtml( |
| 318 | } | 320 | } |
| 319 | } | 321 | } |
| 320 | 322 | ||
| 321 | fn appendUnindented(out: *std.ArrayListUnmanaged(u8), s: []const u8, indent: usize) !void { | 323 | fn appendUnindented(out: *ArrayList(u8), s: []const u8, indent: usize) !void { |
| 322 | var it = std.mem.splitScalar(u8, s, '\n'); | 324 | var it = std.mem.splitScalar(u8, s, '\n'); |
| 323 | var is_first_line = true; | 325 | var is_first_line = true; |
| 324 | while (it.next()) |line| { | 326 | while (it.next()) |line| { |
| ... | @@ -332,7 +334,7 @@ fn appendUnindented(out: *std.ArrayListUnmanaged(u8), s: []const u8, indent: usi | ... | @@ -332,7 +334,7 @@ fn appendUnindented(out: *std.ArrayListUnmanaged(u8), s: []const u8, indent: usi |
| 332 | } | 334 | } |
| 333 | } | 335 | } |
| 334 | 336 | ||
| 335 | pub fn appendEscaped(out: *std.ArrayListUnmanaged(u8), s: []const u8) !void { | 337 | pub fn appendEscaped(out: *ArrayList(u8), s: []const u8) !void { |
| 336 | for (s) |c| { | 338 | for (s) |c| { |
| 337 | try out.ensureUnusedCapacity(gpa, 6); | 339 | try out.ensureUnusedCapacity(gpa, 6); |
| 338 | switch (c) { | 340 | switch (c) { |
| ... | @@ -347,7 +349,7 @@ pub fn appendEscaped(out: *std.ArrayListUnmanaged(u8), s: []const u8) !void { | ... | @@ -347,7 +349,7 @@ pub fn appendEscaped(out: *std.ArrayListUnmanaged(u8), s: []const u8) !void { |
| 347 | 349 | ||
| 348 | fn walkFieldAccesses( | 350 | fn walkFieldAccesses( |
| 349 | file_index: Walk.File.Index, | 351 | file_index: Walk.File.Index, |
| 350 | out: *std.ArrayListUnmanaged(u8), | 352 | out: *ArrayList(u8), |
| 351 | node: Ast.Node.Index, | 353 | node: Ast.Node.Index, |
| 352 | ) Oom!void { | 354 | ) Oom!void { |
| 353 | const ast = file_index.get_ast(); | 355 | const ast = file_index.get_ast(); |
| ... | @@ -371,7 +373,7 @@ fn walkFieldAccesses( | ... | @@ -371,7 +373,7 @@ fn walkFieldAccesses( |
| 371 | 373 | ||
| 372 | fn resolveIdentLink( | 374 | fn resolveIdentLink( |
| 373 | file_index: Walk.File.Index, | 375 | file_index: Walk.File.Index, |
| 374 | out: *std.ArrayListUnmanaged(u8), | 376 | out: *ArrayList(u8), |
| 375 | ident_token: Ast.TokenIndex, | 377 | ident_token: Ast.TokenIndex, |
| 376 | ) Oom!void { | 378 | ) Oom!void { |
| 377 | const decl_index = file_index.get().lookup_token(ident_token); | 379 | const decl_index = file_index.get().lookup_token(ident_token); |
| ... | @@ -391,7 +393,7 @@ fn unindent(s: []const u8, indent: usize) []const u8 { | ... | @@ -391,7 +393,7 @@ fn unindent(s: []const u8, indent: usize) []const u8 { |
| 391 | return s[indent_idx..]; | 393 | return s[indent_idx..]; |
| 392 | } | 394 | } |
| 393 | 395 | ||
| 394 | pub fn resolveDeclLink(decl_index: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void { | 396 | pub fn resolveDeclLink(decl_index: Decl.Index, out: *ArrayList(u8)) Oom!void { |
| 395 | const decl = decl_index.get(); | 397 | const decl = decl_index.get(); |
| 396 | switch (decl.categorize()) { | 398 | switch (decl.categorize()) { |
| 397 | .alias => |alias_decl| try alias_decl.get().fqn(out), | 399 | .alias => |alias_decl| try alias_decl.get().fqn(out), |
lib/docs/wasm/main.zig+30-24| ... | @@ -5,6 +5,8 @@ const Ast = std.zig.Ast; | ... | @@ -5,6 +5,8 @@ const Ast = std.zig.Ast; |
| 5 | const Walk = @import("Walk"); | 5 | const Walk = @import("Walk"); |
| 6 | const markdown = @import("markdown.zig"); | 6 | const markdown = @import("markdown.zig"); |
| 7 | const Decl = Walk.Decl; | 7 | const Decl = Walk.Decl; |
| 8 | const ArrayList = std.ArrayList; | ||
| 9 | const Writer = std.Io.Writer; | ||
| 8 | 10 | ||
| 9 | const fileSourceHtml = @import("html_render.zig").fileSourceHtml; | 11 | const fileSourceHtml = @import("html_render.zig").fileSourceHtml; |
| 10 | const appendEscaped = @import("html_render.zig").appendEscaped; | 12 | const appendEscaped = @import("html_render.zig").appendEscaped; |
| ... | @@ -66,8 +68,8 @@ export fn unpack(tar_ptr: [*]u8, tar_len: usize) void { | ... | @@ -66,8 +68,8 @@ export fn unpack(tar_ptr: [*]u8, tar_len: usize) void { |
| 66 | }; | 68 | }; |
| 67 | } | 69 | } |
| 68 | 70 | ||
| 69 | var query_string: std.ArrayListUnmanaged(u8) = .empty; | 71 | var query_string: ArrayList(u8) = .empty; |
| 70 | var query_results: std.ArrayListUnmanaged(Decl.Index) = .empty; | 72 | var query_results: ArrayList(Decl.Index) = .empty; |
| 71 | 73 | ||
| 72 | /// Resizes the query string to be the correct length; returns the pointer to | 74 | /// Resizes the query string to be the correct length; returns the pointer to |
| 73 | /// the query string. | 75 | /// the query string. |
| ... | @@ -99,11 +101,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void { | ... | @@ -99,11 +101,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void { |
| 99 | segments: u16, | 101 | segments: u16, |
| 100 | }; | 102 | }; |
| 101 | const g = struct { | 103 | const g = struct { |
| 102 | var full_path_search_text: std.ArrayListUnmanaged(u8) = .empty; | 104 | var full_path_search_text: ArrayList(u8) = .empty; |
| 103 | var full_path_search_text_lower: std.ArrayListUnmanaged(u8) = .empty; | 105 | var full_path_search_text_lower: ArrayList(u8) = .empty; |
| 104 | var doc_search_text: std.ArrayListUnmanaged(u8) = .empty; | 106 | var doc_search_text: ArrayList(u8) = .empty; |
| 105 | /// Each element matches a corresponding query_results element. | 107 | /// Each element matches a corresponding query_results element. |
| 106 | var scores: std.ArrayListUnmanaged(Score) = .empty; | 108 | var scores: ArrayList(Score) = .empty; |
| 107 | }; | 109 | }; |
| 108 | 110 | ||
| 109 | // First element stores the size of the list. | 111 | // First element stores the size of the list. |
| ... | @@ -234,7 +236,7 @@ const ErrorIdentifier = packed struct(u64) { | ... | @@ -234,7 +236,7 @@ const ErrorIdentifier = packed struct(u64) { |
| 234 | return ast.tokenTag(token_index - 1) == .doc_comment; | 236 | return ast.tokenTag(token_index - 1) == .doc_comment; |
| 235 | } | 237 | } |
| 236 | 238 | ||
| 237 | fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void { | 239 | fn html(ei: ErrorIdentifier, base_decl: Decl.Index, out: *ArrayList(u8)) Oom!void { |
| 238 | const decl_index = ei.decl_index; | 240 | const decl_index = ei.decl_index; |
| 239 | const ast = decl_index.get().file.get_ast(); | 241 | const ast = decl_index.get().file.get_ast(); |
| 240 | const name = ast.tokenSlice(ei.token_index); | 242 | const name = ast.tokenSlice(ei.token_index); |
| ... | @@ -260,7 +262,7 @@ const ErrorIdentifier = packed struct(u64) { | ... | @@ -260,7 +262,7 @@ const ErrorIdentifier = packed struct(u64) { |
| 260 | } | 262 | } |
| 261 | }; | 263 | }; |
| 262 | 264 | ||
| 263 | var string_result: std.ArrayListUnmanaged(u8) = .empty; | 265 | var string_result: ArrayList(u8) = .empty; |
| 264 | var error_set_result: std.StringArrayHashMapUnmanaged(ErrorIdentifier) = .empty; | 266 | var error_set_result: std.StringArrayHashMapUnmanaged(ErrorIdentifier) = .empty; |
| 265 | 267 | ||
| 266 | export fn decl_error_set(decl_index: Decl.Index) Slice(ErrorIdentifier) { | 268 | export fn decl_error_set(decl_index: Decl.Index) Slice(ErrorIdentifier) { |
| ... | @@ -411,7 +413,7 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { | ... | @@ -411,7 +413,7 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { |
| 411 | 413 | ||
| 412 | fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.Index { | 414 | fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.Index { |
| 413 | const g = struct { | 415 | const g = struct { |
| 414 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; | 416 | var result: ArrayList(Ast.Node.Index) = .empty; |
| 415 | }; | 417 | }; |
| 416 | g.result.clearRetainingCapacity(); | 418 | g.result.clearRetainingCapacity(); |
| 417 | var buf: [2]Ast.Node.Index = undefined; | 419 | var buf: [2]Ast.Node.Index = undefined; |
| ... | @@ -429,7 +431,7 @@ fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.In | ... | @@ -429,7 +431,7 @@ fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.In |
| 429 | 431 | ||
| 430 | fn decl_params_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { | 432 | fn decl_params_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { |
| 431 | const g = struct { | 433 | const g = struct { |
| 432 | var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; | 434 | var result: ArrayList(Ast.Node.Index) = .empty; |
| 433 | }; | 435 | }; |
| 434 | g.result.clearRetainingCapacity(); | 436 | g.result.clearRetainingCapacity(); |
| 435 | const decl = decl_index.get(); | 437 | const decl = decl_index.get(); |
| ... | @@ -460,7 +462,7 @@ export fn decl_param_html(decl_index: Decl.Index, param_node: Ast.Node.Index) St | ... | @@ -460,7 +462,7 @@ export fn decl_param_html(decl_index: Decl.Index, param_node: Ast.Node.Index) St |
| 460 | } | 462 | } |
| 461 | 463 | ||
| 462 | fn decl_field_html_fallible( | 464 | fn decl_field_html_fallible( |
| 463 | out: *std.ArrayListUnmanaged(u8), | 465 | out: *ArrayList(u8), |
| 464 | decl_index: Decl.Index, | 466 | decl_index: Decl.Index, |
| 465 | field_node: Ast.Node.Index, | 467 | field_node: Ast.Node.Index, |
| 466 | ) !void { | 468 | ) !void { |
| ... | @@ -480,7 +482,7 @@ fn decl_field_html_fallible( | ... | @@ -480,7 +482,7 @@ fn decl_field_html_fallible( |
| 480 | } | 482 | } |
| 481 | 483 | ||
| 482 | fn decl_param_html_fallible( | 484 | fn decl_param_html_fallible( |
| 483 | out: *std.ArrayListUnmanaged(u8), | 485 | out: *ArrayList(u8), |
| 484 | decl_index: Decl.Index, | 486 | decl_index: Decl.Index, |
| 485 | param_node: Ast.Node.Index, | 487 | param_node: Ast.Node.Index, |
| 486 | ) !void { | 488 | ) !void { |
| ... | @@ -649,7 +651,7 @@ export fn decl_docs_html(decl_index: Decl.Index, short: bool) String { | ... | @@ -649,7 +651,7 @@ export fn decl_docs_html(decl_index: Decl.Index, short: bool) String { |
| 649 | } | 651 | } |
| 650 | 652 | ||
| 651 | fn collect_docs( | 653 | fn collect_docs( |
| 652 | list: *std.ArrayListUnmanaged(u8), | 654 | list: *ArrayList(u8), |
| 653 | ast: *const Ast, | 655 | ast: *const Ast, |
| 654 | first_doc_comment: Ast.TokenIndex, | 656 | first_doc_comment: Ast.TokenIndex, |
| 655 | ) Oom!void { | 657 | ) Oom!void { |
| ... | @@ -667,7 +669,7 @@ fn collect_docs( | ... | @@ -667,7 +669,7 @@ fn collect_docs( |
| 667 | } | 669 | } |
| 668 | 670 | ||
| 669 | fn render_docs( | 671 | fn render_docs( |
| 670 | out: *std.ArrayListUnmanaged(u8), | 672 | out: *ArrayList(u8), |
| 671 | decl_index: Decl.Index, | 673 | decl_index: Decl.Index, |
| 672 | first_doc_comment: Ast.TokenIndex, | 674 | first_doc_comment: Ast.TokenIndex, |
| 673 | short: bool, | 675 | short: bool, |
| ... | @@ -691,11 +693,10 @@ fn render_docs( | ... | @@ -691,11 +693,10 @@ fn render_docs( |
| 691 | defer parsed_doc.deinit(gpa); | 693 | defer parsed_doc.deinit(gpa); |
| 692 | 694 | ||
| 693 | const g = struct { | 695 | const g = struct { |
| 694 | var link_buffer: std.ArrayListUnmanaged(u8) = .empty; | 696 | var link_buffer: ArrayList(u8) = .empty; |
| 695 | }; | 697 | }; |
| 696 | 698 | ||
| 697 | const Writer = std.ArrayListUnmanaged(u8).Writer; | 699 | const Renderer = markdown.Renderer(Decl.Index); |
| 698 | const Renderer = markdown.Renderer(Writer, Decl.Index); | ||
| 699 | const renderer: Renderer = .{ | 700 | const renderer: Renderer = .{ |
| 700 | .context = decl_index, | 701 | .context = decl_index, |
| 701 | .renderFn = struct { | 702 | .renderFn = struct { |
| ... | @@ -703,8 +704,8 @@ fn render_docs( | ... | @@ -703,8 +704,8 @@ fn render_docs( |
| 703 | r: Renderer, | 704 | r: Renderer, |
| 704 | doc: markdown.Document, | 705 | doc: markdown.Document, |
| 705 | node: markdown.Document.Node.Index, | 706 | node: markdown.Document.Node.Index, |
| 706 | writer: Writer, | 707 | writer: *Writer, |
| 707 | ) !void { | 708 | ) Writer.Error!void { |
| 708 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; | 709 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; |
| 709 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { | 710 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { |
| 710 | .code_span => { | 711 | .code_span => { |
| ... | @@ -712,7 +713,7 @@ fn render_docs( | ... | @@ -712,7 +713,7 @@ fn render_docs( |
| 712 | const content = doc.string(data.text.content); | 713 | const content = doc.string(data.text.content); |
| 713 | if (resolve_decl_path(r.context, content)) |resolved_decl_index| { | 714 | if (resolve_decl_path(r.context, content)) |resolved_decl_index| { |
| 714 | g.link_buffer.clearRetainingCapacity(); | 715 | g.link_buffer.clearRetainingCapacity(); |
| 715 | try resolveDeclLink(resolved_decl_index, &g.link_buffer); | 716 | resolveDeclLink(resolved_decl_index, &g.link_buffer) catch return error.WriteFailed; |
| 716 | 717 | ||
| 717 | try writer.writeAll("<a href=\"#"); | 718 | try writer.writeAll("<a href=\"#"); |
| 718 | _ = missing_feature_url_escape; | 719 | _ = missing_feature_url_escape; |
| ... | @@ -730,7 +731,12 @@ fn render_docs( | ... | @@ -730,7 +731,12 @@ fn render_docs( |
| 730 | } | 731 | } |
| 731 | }.render, | 732 | }.render, |
| 732 | }; | 733 | }; |
| 733 | try renderer.render(parsed_doc, out.writer(gpa)); | 734 | |
| 735 | var allocating = Writer.Allocating.fromArrayList(gpa, out); | ||
| 736 | defer out.* = allocating.toArrayList(); | ||
| 737 | renderer.render(parsed_doc, &allocating.writer) catch |err| switch (err) { | ||
| 738 | error.WriteFailed => return error.OutOfMemory, | ||
| 739 | }; | ||
| 734 | } | 740 | } |
| 735 | 741 | ||
| 736 | fn resolve_decl_path(decl_index: Decl.Index, path: []const u8) ?Decl.Index { | 742 | fn resolve_decl_path(decl_index: Decl.Index, path: []const u8) ?Decl.Index { |
| ... | @@ -827,7 +833,7 @@ export fn find_module_root(pkg: Walk.ModuleIndex) Decl.Index { | ... | @@ -827,7 +833,7 @@ export fn find_module_root(pkg: Walk.ModuleIndex) Decl.Index { |
| 827 | } | 833 | } |
| 828 | 834 | ||
| 829 | /// Set by `set_input_string`. | 835 | /// Set by `set_input_string`. |
| 830 | var input_string: std.ArrayListUnmanaged(u8) = .empty; | 836 | var input_string: ArrayList(u8) = .empty; |
| 831 | 837 | ||
| 832 | export fn set_input_string(len: usize) [*]u8 { | 838 | export fn set_input_string(len: usize) [*]u8 { |
| 833 | input_string.resize(gpa, len) catch @panic("OOM"); | 839 | input_string.resize(gpa, len) catch @panic("OOM"); |
| ... | @@ -849,7 +855,7 @@ export fn find_decl() Decl.Index { | ... | @@ -849,7 +855,7 @@ export fn find_decl() Decl.Index { |
| 849 | if (result != .none) return result; | 855 | if (result != .none) return result; |
| 850 | 856 | ||
| 851 | const g = struct { | 857 | const g = struct { |
| 852 | var match_fqn: std.ArrayListUnmanaged(u8) = .empty; | 858 | var match_fqn: ArrayList(u8) = .empty; |
| 853 | }; | 859 | }; |
| 854 | for (Walk.decls.items, 0..) |*decl, decl_index| { | 860 | for (Walk.decls.items, 0..) |*decl, decl_index| { |
| 855 | g.match_fqn.clearRetainingCapacity(); | 861 | g.match_fqn.clearRetainingCapacity(); |
| ... | @@ -905,7 +911,7 @@ export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl. | ... | @@ -905,7 +911,7 @@ export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl. |
| 905 | 911 | ||
| 906 | export fn namespace_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) { | 912 | export fn namespace_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) { |
| 907 | const g = struct { | 913 | const g = struct { |
| 908 | var members: std.ArrayListUnmanaged(Decl.Index) = .empty; | 914 | var members: ArrayList(Decl.Index) = .empty; |
| 909 | }; | 915 | }; |
| 910 | 916 | ||
| 911 | g.members.clearRetainingCapacity(); | 917 | g.members.clearRetainingCapacity(); |
lib/docs/wasm/markdown/renderer.zig+15-16| ... | @@ -2,25 +2,26 @@ const std = @import("std"); | ... | @@ -2,25 +2,26 @@ const std = @import("std"); |
| 2 | const Document = @import("Document.zig"); | 2 | const Document = @import("Document.zig"); |
| 3 | const Node = Document.Node; | 3 | const Node = Document.Node; |
| 4 | const assert = std.debug.assert; | 4 | const assert = std.debug.assert; |
| 5 | const Writer = std.Io.Writer; | ||
| 5 | 6 | ||
| 6 | /// A Markdown document renderer. | 7 | /// A Markdown document renderer. |
| 7 | /// | 8 | /// |
| 8 | /// Each concrete `Renderer` type has a `renderDefault` function, with the | 9 | /// Each concrete `Renderer` type has a `renderDefault` function, with the |
| 9 | /// intention that custom `renderFn` implementations can call `renderDefault` | 10 | /// intention that custom `renderFn` implementations can call `renderDefault` |
| 10 | /// for node types for which they require no special rendering. | 11 | /// for node types for which they require no special rendering. |
| 11 | pub fn Renderer(comptime Writer: type, comptime Context: type) type { | 12 | pub fn Renderer(comptime Context: type) type { |
| 12 | return struct { | 13 | return struct { |
| 13 | renderFn: *const fn ( | 14 | renderFn: *const fn ( |
| 14 | r: Self, | 15 | r: Self, |
| 15 | doc: Document, | 16 | doc: Document, |
| 16 | node: Node.Index, | 17 | node: Node.Index, |
| 17 | writer: Writer, | 18 | writer: *Writer, |
| 18 | ) Writer.Error!void = renderDefault, | 19 | ) Writer.Error!void = renderDefault, |
| 19 | context: Context, | 20 | context: Context, |
| 20 | 21 | ||
| 21 | const Self = @This(); | 22 | const Self = @This(); |
| 22 | 23 | ||
| 23 | pub fn render(r: Self, doc: Document, writer: Writer) Writer.Error!void { | 24 | pub fn render(r: Self, doc: Document, writer: *Writer) Writer.Error!void { |
| 24 | try r.renderFn(r, doc, .root, writer); | 25 | try r.renderFn(r, doc, .root, writer); |
| 25 | } | 26 | } |
| 26 | 27 | ||
| ... | @@ -28,7 +29,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { | ... | @@ -28,7 +29,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 28 | r: Self, | 29 | r: Self, |
| 29 | doc: Document, | 30 | doc: Document, |
| 30 | node: Node.Index, | 31 | node: Node.Index, |
| 31 | writer: Writer, | 32 | writer: *Writer, |
| 32 | ) Writer.Error!void { | 33 | ) Writer.Error!void { |
| 33 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; | 34 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; |
| 34 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { | 35 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { |
| ... | @@ -188,8 +189,8 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { | ... | @@ -188,8 +189,8 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type { |
| 188 | pub fn renderInlineNodeText( | 189 | pub fn renderInlineNodeText( |
| 189 | doc: Document, | 190 | doc: Document, |
| 190 | node: Node.Index, | 191 | node: Node.Index, |
| 191 | writer: anytype, | 192 | writer: *Writer, |
| 192 | ) @TypeOf(writer).Error!void { | 193 | ) Writer.Error!void { |
| 193 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; | 194 | const data = doc.nodes.items(.data)[@intFromEnum(node)]; |
| 194 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { | 195 | switch (doc.nodes.items(.tag)[@intFromEnum(node)]) { |
| 195 | .root, | 196 | .root, |
| ... | @@ -234,14 +235,12 @@ pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) { | ... | @@ -234,14 +235,12 @@ pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) { |
| 234 | return .{ .data = bytes }; | 235 | return .{ .data = bytes }; |
| 235 | } | 236 | } |
| 236 | 237 | ||
| 237 | fn formatHtml(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void { | 238 | fn formatHtml(bytes: []const u8, w: *Writer) Writer.Error!void { |
| 238 | for (bytes) |b| { | 239 | for (bytes) |b| switch (b) { |
| 239 | switch (b) { | 240 | '<' => try w.writeAll("&lt;"), |
| 240 | '<' => try writer.writeAll("&lt;"), | 241 | '>' => try w.writeAll("&gt;"), |
| 241 | '>' => try writer.writeAll("&gt;"), | 242 | '&' => try w.writeAll("&amp;"), |
| 242 | '&' => try writer.writeAll("&amp;"), | 243 | '"' => try w.writeAll("&quot;"), |
| 243 | '"' => try writer.writeAll("&quot;"), | 244 | else => try w.writeByte(b), |
| 244 | else => try writer.writeByte(b), | 245 | }; |
| 245 | } | ||
| 246 | } | ||
| 247 | } | 246 | } |
tools/docgen.zig+21-21| ... | @@ -1,6 +1,5 @@ | ... | @@ -1,6 +1,5 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const io = std.io; | ||
| 4 | const fs = std.fs; | 3 | const fs = std.fs; |
| 5 | const process = std.process; | 4 | const process = std.process; |
| 6 | const Progress = std.Progress; | 5 | const Progress = std.Progress; |
| ... | @@ -8,8 +7,10 @@ const print = std.debug.print; | ... | @@ -8,8 +7,10 @@ const print = std.debug.print; |
| 8 | const mem = std.mem; | 7 | const mem = std.mem; |
| 9 | const testing = std.testing; | 8 | const testing = std.testing; |
| 10 | const Allocator = std.mem.Allocator; | 9 | const Allocator = std.mem.Allocator; |
| 10 | const ArrayList = std.ArrayList; | ||
| 11 | const getExternalExecutor = std.zig.system.getExternalExecutor; | 11 | const getExternalExecutor = std.zig.system.getExternalExecutor; |
| 12 | const fatal = std.process.fatal; | 12 | const fatal = std.process.fatal; |
| 13 | const Writer = std.Io.Writer; | ||
| 13 | 14 | ||
| 14 | const max_doc_file_size = 10 * 1024 * 1024; | 15 | const max_doc_file_size = 10 * 1024 * 1024; |
| 15 | 16 | ||
| ... | @@ -344,10 +345,10 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { | ... | @@ -344,10 +345,10 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 344 | var last_action: Action = .open; | 345 | var last_action: Action = .open; |
| 345 | var last_columns: ?u8 = null; | 346 | var last_columns: ?u8 = null; |
| 346 | 347 | ||
| 347 | var toc_buf = std.array_list.Managed(u8).init(allocator); | 348 | var toc_buf: Writer.Allocating = .init(allocator); |
| 348 | defer toc_buf.deinit(); | 349 | defer toc_buf.deinit(); |
| 349 | 350 | ||
| 350 | var toc = toc_buf.writer(); | 351 | const toc = &toc_buf.writer; |
| 351 | 352 | ||
| 352 | var nodes = std.array_list.Managed(Node).init(allocator); | 353 | var nodes = std.array_list.Managed(Node).init(allocator); |
| 353 | defer nodes.deinit(); | 354 | defer nodes.deinit(); |
| ... | @@ -422,7 +423,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { | ... | @@ -422,7 +423,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 422 | } | 423 | } |
| 423 | if (last_action == .open) { | 424 | if (last_action == .open) { |
| 424 | try toc.writeByte('\n'); | 425 | try toc.writeByte('\n'); |
| 425 | try toc.writeByteNTimes(' ', header_stack_size * 4); | 426 | try toc.splatByteAll(' ', header_stack_size * 4); |
| 426 | if (last_columns) |n| { | 427 | if (last_columns) |n| { |
| 427 | try toc.print("<ul style=\"columns: {d}\">\n", .{n}); | 428 | try toc.print("<ul style=\"columns: {d}\">\n", .{n}); |
| 428 | } else { | 429 | } else { |
| ... | @@ -432,7 +433,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { | ... | @@ -432,7 +433,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 432 | last_action = .open; | 433 | last_action = .open; |
| 433 | } | 434 | } |
| 434 | last_columns = columns; | 435 | last_columns = columns; |
| 435 | try toc.writeByteNTimes(' ', 4 + header_stack_size * 4); | 436 | try toc.splatByteAll(' ', 4 + header_stack_size * 4); |
| 436 | try toc.print("<li><a id=\"toc-{s}\" href=\"#{s}\">{s}</a>", .{ urlized, urlized, content }); | 437 | try toc.print("<li><a id=\"toc-{s}\" href=\"#{s}\">{s}</a>", .{ urlized, urlized, content }); |
| 437 | } else if (mem.eql(u8, tag_name, "header_close")) { | 438 | } else if (mem.eql(u8, tag_name, "header_close")) { |
| 438 | if (header_stack_size == 0) { | 439 | if (header_stack_size == 0) { |
| ... | @@ -442,7 +443,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { | ... | @@ -442,7 +443,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 442 | _ = try eatToken(tokenizer, .bracket_close); | 443 | _ = try eatToken(tokenizer, .bracket_close); |
| 443 | 444 | ||
| 444 | if (last_action == .close) { | 445 | if (last_action == .close) { |
| 445 | try toc.writeByteNTimes(' ', 8 + header_stack_size * 4); | 446 | try toc.splatByteAll(' ', 8 + header_stack_size * 4); |
| 446 | try toc.writeAll("</ul></li>\n"); | 447 | try toc.writeAll("</ul></li>\n"); |
| 447 | } else { | 448 | } else { |
| 448 | try toc.writeAll("</li>\n"); | 449 | try toc.writeAll("</li>\n"); |
| ... | @@ -591,30 +592,29 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { | ... | @@ -591,30 +592,29 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc { |
| 591 | } | 592 | } |
| 592 | } | 593 | } |
| 593 | 594 | ||
| 594 | return Toc{ | 595 | return .{ |
| 595 | .nodes = try nodes.toOwnedSlice(), | 596 | .nodes = try nodes.toOwnedSlice(), |
| 596 | .toc = try toc_buf.toOwnedSlice(), | 597 | .toc = try toc_buf.toOwnedSlice(), |
| 597 | .urls = urls, | 598 | .urls = urls, |
| 598 | }; | 599 | }; |
| 599 | } | 600 | } |
| 600 | 601 | ||
| 601 | fn urlize(allocator: Allocator, input: []const u8) ![]u8 { | 602 | fn urlize(gpa: Allocator, input: []const u8) ![]u8 { |
| 602 | var buf = std.array_list.Managed(u8).init(allocator); | 603 | var buf: ArrayList(u8) = .empty; |
| 603 | defer buf.deinit(); | 604 | defer buf.deinit(gpa); |
| 604 | 605 | ||
| 605 | const out = buf.writer(); | ||
| 606 | for (input) |c| { | 606 | for (input) |c| { |
| 607 | switch (c) { | 607 | switch (c) { |
| 608 | 'a'...'z', 'A'...'Z', '_', '-', '0'...'9' => { | 608 | 'a'...'z', 'A'...'Z', '_', '-', '0'...'9' => { |
| 609 | try out.writeByte(c); | 609 | try buf.append(gpa, c); |
| 610 | }, | 610 | }, |
| 611 | ' ' => { | 611 | ' ' => { |
| 612 | try out.writeByte('-'); | 612 | try buf.append(gpa, '-'); |
| 613 | }, | 613 | }, |
| 614 | else => {}, | 614 | else => {}, |
| 615 | } | 615 | } |
| 616 | } | 616 | } |
| 617 | return try buf.toOwnedSlice(); | 617 | return try buf.toOwnedSlice(gpa); |
| 618 | } | 618 | } |
| 619 | 619 | ||
| 620 | fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { | 620 | fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { |
| ... | @@ -626,7 +626,7 @@ fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { | ... | @@ -626,7 +626,7 @@ fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { |
| 626 | return try buf.toOwnedSlice(); | 626 | return try buf.toOwnedSlice(); |
| 627 | } | 627 | } |
| 628 | 628 | ||
| 629 | fn writeEscaped(out: anytype, input: []const u8) !void { | 629 | fn writeEscaped(out: *Writer, input: []const u8) !void { |
| 630 | for (input) |c| { | 630 | for (input) |c| { |
| 631 | try switch (c) { | 631 | try switch (c) { |
| 632 | '&' => out.writeAll("&amp;"), | 632 | '&' => out.writeAll("&amp;"), |
| ... | @@ -662,14 +662,14 @@ fn isType(name: []const u8) bool { | ... | @@ -662,14 +662,14 @@ fn isType(name: []const u8) bool { |
| 662 | return false; | 662 | return false; |
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | fn writeEscapedLines(out: anytype, text: []const u8) !void { | 665 | fn writeEscapedLines(out: *Writer, text: []const u8) !void { |
| 666 | return writeEscaped(out, text); | 666 | return writeEscaped(out, text); |
| 667 | } | 667 | } |
| 668 | 668 | ||
| 669 | fn tokenizeAndPrintRaw( | 669 | fn tokenizeAndPrintRaw( |
| 670 | allocator: Allocator, | 670 | allocator: Allocator, |
| 671 | docgen_tokenizer: *Tokenizer, | 671 | docgen_tokenizer: *Tokenizer, |
| 672 | out: anytype, | 672 | out: *Writer, |
| 673 | source_token: Token, | 673 | source_token: Token, |
| 674 | raw_src: []const u8, | 674 | raw_src: []const u8, |
| 675 | ) !void { | 675 | ) !void { |
| ... | @@ -907,14 +907,14 @@ fn tokenizeAndPrintRaw( | ... | @@ -907,14 +907,14 @@ fn tokenizeAndPrintRaw( |
| 907 | fn tokenizeAndPrint( | 907 | fn tokenizeAndPrint( |
| 908 | allocator: Allocator, | 908 | allocator: Allocator, |
| 909 | docgen_tokenizer: *Tokenizer, | 909 | docgen_tokenizer: *Tokenizer, |
| 910 | out: anytype, | 910 | out: *Writer, |
| 911 | source_token: Token, | 911 | source_token: Token, |
| 912 | ) !void { | 912 | ) !void { |
| 913 | const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end]; | 913 | const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end]; |
| 914 | return tokenizeAndPrintRaw(allocator, docgen_tokenizer, out, source_token, raw_src); | 914 | return tokenizeAndPrintRaw(allocator, docgen_tokenizer, out, source_token, raw_src); |
| 915 | } | 915 | } |
| 916 | 916 | ||
| 917 | fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: anytype, syntax_block: SyntaxBlock) !void { | 917 | fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: *Writer, syntax_block: SyntaxBlock) !void { |
| 918 | const source_type = @tagName(syntax_block.source_type); | 918 | const source_type = @tagName(syntax_block.source_type); |
| 919 | 919 | ||
| 920 | try out.print("<figure><figcaption class=\"{s}-cap\"><cite class=\"file\">{s}</cite></figcaption><pre>", .{ source_type, syntax_block.name }); | 920 | try out.print("<figure><figcaption class=\"{s}-cap\"><cite class=\"file\">{s}</cite></figcaption><pre>", .{ source_type, syntax_block.name }); |
| ... | @@ -932,7 +932,7 @@ fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: any | ... | @@ -932,7 +932,7 @@ fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: any |
| 932 | try out.writeAll("</pre></figure>"); | 932 | try out.writeAll("</pre></figure>"); |
| 933 | } | 933 | } |
| 934 | 934 | ||
| 935 | fn printShell(out: anytype, shell_content: []const u8, escape: bool) !void { | 935 | fn printShell(out: *Writer, shell_content: []const u8, escape: bool) !void { |
| 936 | const trimmed_shell_content = mem.trim(u8, shell_content, " \r\n"); | 936 | const trimmed_shell_content = mem.trim(u8, shell_content, " \r\n"); |
| 937 | try out.writeAll("<figure><figcaption class=\"shell-cap\">Shell</figcaption><pre><samp>"); | 937 | try out.writeAll("<figure><figcaption class=\"shell-cap\">Shell</figcaption><pre><samp>"); |
| 938 | var cmd_cont: bool = false; | 938 | var cmd_cont: bool = false; |
| ... | @@ -984,7 +984,7 @@ fn genHtml( | ... | @@ -984,7 +984,7 @@ fn genHtml( |
| 984 | tokenizer: *Tokenizer, | 984 | tokenizer: *Tokenizer, |
| 985 | toc: *Toc, | 985 | toc: *Toc, |
| 986 | code_dir: std.fs.Dir, | 986 | code_dir: std.fs.Dir, |
| 987 | out: anytype, | 987 | out: *Writer, |
| 988 | ) !void { | 988 | ) !void { |
| 989 | for (toc.nodes) |node| { | 989 | for (toc.nodes) |node| { |
| 990 | switch (node) { | 990 | switch (node) { |
tools/doctest.zig+16-20| ... | @@ -127,9 +127,9 @@ fn printOutput( | ... | @@ -127,9 +127,9 @@ fn printOutput( |
| 127 | const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch); | 127 | const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch); |
| 128 | const print = std.debug.print; | 128 | const print = std.debug.print; |
| 129 | 129 | ||
| 130 | var shell_buffer = std.array_list.Managed(u8).init(arena); | 130 | var shell_buffer: std.Io.Writer.Allocating = .init(arena); |
| 131 | defer shell_buffer.deinit(); | 131 | defer shell_buffer.deinit(); |
| 132 | var shell_out = shell_buffer.writer(); | 132 | const shell_out = &shell_buffer.writer; |
| 133 | 133 | ||
| 134 | const code_name = std.fs.path.stem(input_path); | 134 | const code_name = std.fs.path.stem(input_path); |
| 135 | 135 | ||
| ... | @@ -600,7 +600,7 @@ fn printOutput( | ... | @@ -600,7 +600,7 @@ fn printOutput( |
| 600 | } | 600 | } |
| 601 | 601 | ||
| 602 | if (!code.just_check_syntax) { | 602 | if (!code.just_check_syntax) { |
| 603 | try printShell(out, shell_buffer.items, false); | 603 | try printShell(out, shell_buffer.written(), false); |
| 604 | } | 604 | } |
| 605 | } | 605 | } |
| 606 | 606 | ||
| ... | @@ -975,25 +975,21 @@ fn skipPrefix(line: []const u8) []const u8 { | ... | @@ -975,25 +975,21 @@ fn skipPrefix(line: []const u8) []const u8 { |
| 975 | return line[3..]; | 975 | return line[3..]; |
| 976 | } | 976 | } |
| 977 | 977 | ||
| 978 | fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 { | 978 | fn escapeHtml(gpa: Allocator, input: []const u8) ![]u8 { |
| 979 | var buf = std.array_list.Managed(u8).init(allocator); | 979 | var allocating: Writer.Allocating = .init(gpa); |
| 980 | defer buf.deinit(); | 980 | defer allocating.deinit(); |
| 981 | 981 | try writeEscaped(&allocating.writer, input); | |
| 982 | const out = buf.writer(); | 982 | return allocating.toOwnedSlice(); |
| 983 | try writeEscaped(out, input); | ||
| 984 | return try buf.toOwnedSlice(); | ||
| 985 | } | 983 | } |
| 986 | 984 | ||
| 987 | fn writeEscaped(out: *Writer, input: []const u8) !void { | 985 | fn writeEscaped(w: *Writer, input: []const u8) !void { |
| 988 | for (input) |c| { | 986 | for (input) |c| try switch (c) { |
| 989 | try switch (c) { | 987 | '&' => w.writeAll("&amp;"), |
| 990 | '&' => out.writeAll("&amp;"), | 988 | '<' => w.writeAll("&lt;"), |
| 991 | '<' => out.writeAll("&lt;"), | 989 | '>' => w.writeAll("&gt;"), |
| 992 | '>' => out.writeAll("&gt;"), | 990 | '"' => w.writeAll("&quot;"), |
| 993 | '"' => out.writeAll("&quot;"), | 991 | else => w.writeByte(c), |
| 994 | else => out.writeByte(c), | 992 | }; |
| 995 | }; | ||
| 996 | } | ||
| 997 | } | 993 | } |
| 998 | 994 | ||
| 999 | fn termColor(allocator: Allocator, input: []const u8) ![]u8 { | 995 | fn termColor(allocator: Allocator, input: []const u8) ![]u8 { |