authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-27 22:47:42-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-28 18:30:57-07:00
log9b47dd2028deb45324ca19d909d0cee69f51f1b9
tree1b9cd7bbe8b1f09c77bc8b38458a0c5f745c2934
parent8023f3dcebff06cbf3563bdd09b07462ed43509f

update langref and docs to avoid GenericWriter


6 files changed, 97 insertions(+), 93 deletions(-)

lib/docs/wasm/Decl.zig+5-4
......@@ -6,6 +6,7 @@ const gpa = std.heap.wasm_allocator;
66const assert = std.debug.assert;
77const log = std.log;
88const Oom = error{OutOfMemory};
9const ArrayList = std.ArrayList;
910
1011ast_node: Ast.Node.Index,
1112file: Walk.File.Index,
......@@ -189,7 +190,7 @@ pub fn lookup(decl: *const Decl, name: []const u8) ?Decl.Index {
189190}
190191
191192/// Appends the fully qualified name to `out`.
192pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void {
193pub fn fqn(decl: *const Decl, out: *ArrayList(u8)) Oom!void {
193194 try decl.append_path(out);
194195 if (decl.parent != .none) {
195196 try append_parent_ns(out, decl.parent);
......@@ -199,12 +200,12 @@ pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void {
199200 }
200201}
201202
202pub fn reset_with_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!void {
203pub fn reset_with_path(decl: *const Decl, list: *ArrayList(u8)) Oom!void {
203204 list.clearRetainingCapacity();
204205 try append_path(decl, list);
205206}
206207
207pub fn append_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!void {
208pub fn append_path(decl: *const Decl, list: *ArrayList(u8)) Oom!void {
208209 const start = list.items.len;
209210 // Prefer the module name alias.
210211 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
230231 }
231232}
232233
233pub fn append_parent_ns(list: *std.ArrayListUnmanaged(u8), parent: Decl.Index) Oom!void {
234pub fn append_parent_ns(list: *ArrayList(u8), parent: Decl.Index) Oom!void {
234235 assert(parent != .none);
235236 const decl = parent.get();
236237 if (decl.parent != .none) {
lib/docs/wasm/html_render.zig+10-8
......@@ -1,6 +1,8 @@
11const std = @import("std");
22const Ast = std.zig.Ast;
33const assert = std.debug.assert;
4const ArrayList = std.ArrayList;
5const Writer = std.Io.Writer;
46
57const Walk = @import("Walk");
68const Decl = Walk.Decl;
......@@ -30,7 +32,7 @@ pub const Annotation = struct {
3032
3133pub fn fileSourceHtml(
3234 file_index: Walk.File.Index,
33 out: *std.ArrayListUnmanaged(u8),
35 out: *ArrayList(u8),
3436 root_node: Ast.Node.Index,
3537 options: RenderSourceOptions,
3638) !void {
......@@ -38,7 +40,7 @@ pub fn fileSourceHtml(
3840 const file = file_index.get();
3941
4042 const g = struct {
41 var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty;
43 var field_access_buffer: ArrayList(u8) = .empty;
4244 };
4345
4446 const start_token = ast.firstToken(root_node);
......@@ -88,7 +90,7 @@ pub fn fileSourceHtml(
8890 if (next_annotate_index >= options.source_location_annotations.len) break;
8991 const next_annotation = options.source_location_annotations[next_annotate_index];
9092 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>", .{
9294 options.annotation_prefix, next_annotation.dom_id,
9395 });
9496 next_annotate_index += 1;
......@@ -318,7 +320,7 @@ pub fn fileSourceHtml(
318320 }
319321}
320322
321fn appendUnindented(out: *std.ArrayListUnmanaged(u8), s: []const u8, indent: usize) !void {
323fn appendUnindented(out: *ArrayList(u8), s: []const u8, indent: usize) !void {
322324 var it = std.mem.splitScalar(u8, s, '\n');
323325 var is_first_line = true;
324326 while (it.next()) |line| {
......@@ -332,7 +334,7 @@ fn appendUnindented(out: *std.ArrayListUnmanaged(u8), s: []const u8, indent: usi
332334 }
333335}
334336
335pub fn appendEscaped(out: *std.ArrayListUnmanaged(u8), s: []const u8) !void {
337pub fn appendEscaped(out: *ArrayList(u8), s: []const u8) !void {
336338 for (s) |c| {
337339 try out.ensureUnusedCapacity(gpa, 6);
338340 switch (c) {
......@@ -347,7 +349,7 @@ pub fn appendEscaped(out: *std.ArrayListUnmanaged(u8), s: []const u8) !void {
347349
348350fn walkFieldAccesses(
349351 file_index: Walk.File.Index,
350 out: *std.ArrayListUnmanaged(u8),
352 out: *ArrayList(u8),
351353 node: Ast.Node.Index,
352354) Oom!void {
353355 const ast = file_index.get_ast();
......@@ -371,7 +373,7 @@ fn walkFieldAccesses(
371373
372374fn resolveIdentLink(
373375 file_index: Walk.File.Index,
374 out: *std.ArrayListUnmanaged(u8),
376 out: *ArrayList(u8),
375377 ident_token: Ast.TokenIndex,
376378) Oom!void {
377379 const decl_index = file_index.get().lookup_token(ident_token);
......@@ -391,7 +393,7 @@ fn unindent(s: []const u8, indent: usize) []const u8 {
391393 return s[indent_idx..];
392394}
393395
394pub fn resolveDeclLink(decl_index: Decl.Index, out: *std.ArrayListUnmanaged(u8)) Oom!void {
396pub fn resolveDeclLink(decl_index: Decl.Index, out: *ArrayList(u8)) Oom!void {
395397 const decl = decl_index.get();
396398 switch (decl.categorize()) {
397399 .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;
55const Walk = @import("Walk");
66const markdown = @import("markdown.zig");
77const Decl = Walk.Decl;
8const ArrayList = std.ArrayList;
9const Writer = std.Io.Writer;
810
911const fileSourceHtml = @import("html_render.zig").fileSourceHtml;
1012const appendEscaped = @import("html_render.zig").appendEscaped;
......@@ -66,8 +68,8 @@ export fn unpack(tar_ptr: [*]u8, tar_len: usize) void {
6668 };
6769}
6870
69var query_string: std.ArrayListUnmanaged(u8) = .empty;
70var query_results: std.ArrayListUnmanaged(Decl.Index) = .empty;
71var query_string: ArrayList(u8) = .empty;
72var query_results: ArrayList(Decl.Index) = .empty;
7173
7274/// Resizes the query string to be the correct length; returns the pointer to
7375/// the query string.
......@@ -99,11 +101,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
99101 segments: u16,
100102 };
101103 const g = struct {
102 var full_path_search_text: std.ArrayListUnmanaged(u8) = .empty;
103 var full_path_search_text_lower: std.ArrayListUnmanaged(u8) = .empty;
104 var doc_search_text: std.ArrayListUnmanaged(u8) = .empty;
104 var full_path_search_text: ArrayList(u8) = .empty;
105 var full_path_search_text_lower: ArrayList(u8) = .empty;
106 var doc_search_text: ArrayList(u8) = .empty;
105107 /// Each element matches a corresponding query_results element.
106 var scores: std.ArrayListUnmanaged(Score) = .empty;
108 var scores: ArrayList(Score) = .empty;
107109 };
108110
109111 // First element stores the size of the list.
......@@ -234,7 +236,7 @@ const ErrorIdentifier = packed struct(u64) {
234236 return ast.tokenTag(token_index - 1) == .doc_comment;
235237 }
236238
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 {
238240 const decl_index = ei.decl_index;
239241 const ast = decl_index.get().file.get_ast();
240242 const name = ast.tokenSlice(ei.token_index);
......@@ -260,7 +262,7 @@ const ErrorIdentifier = packed struct(u64) {
260262 }
261263};
262264
263var string_result: std.ArrayListUnmanaged(u8) = .empty;
265var string_result: ArrayList(u8) = .empty;
264266var error_set_result: std.StringArrayHashMapUnmanaged(ErrorIdentifier) = .empty;
265267
266268export 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 {
411413
412414fn ast_decl_fields_fallible(ast: *Ast, ast_index: Ast.Node.Index) ![]Ast.Node.Index {
413415 const g = struct {
414 var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty;
416 var result: ArrayList(Ast.Node.Index) = .empty;
415417 };
416418 g.result.clearRetainingCapacity();
417419 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
429431
430432fn decl_params_fallible(decl_index: Decl.Index) ![]Ast.Node.Index {
431433 const g = struct {
432 var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty;
434 var result: ArrayList(Ast.Node.Index) = .empty;
433435 };
434436 g.result.clearRetainingCapacity();
435437 const decl = decl_index.get();
......@@ -460,7 +462,7 @@ export fn decl_param_html(decl_index: Decl.Index, param_node: Ast.Node.Index) St
460462}
461463
462464fn decl_field_html_fallible(
463 out: *std.ArrayListUnmanaged(u8),
465 out: *ArrayList(u8),
464466 decl_index: Decl.Index,
465467 field_node: Ast.Node.Index,
466468) !void {
......@@ -480,7 +482,7 @@ fn decl_field_html_fallible(
480482}
481483
482484fn decl_param_html_fallible(
483 out: *std.ArrayListUnmanaged(u8),
485 out: *ArrayList(u8),
484486 decl_index: Decl.Index,
485487 param_node: Ast.Node.Index,
486488) !void {
......@@ -649,7 +651,7 @@ export fn decl_docs_html(decl_index: Decl.Index, short: bool) String {
649651}
650652
651653fn collect_docs(
652 list: *std.ArrayListUnmanaged(u8),
654 list: *ArrayList(u8),
653655 ast: *const Ast,
654656 first_doc_comment: Ast.TokenIndex,
655657) Oom!void {
......@@ -667,7 +669,7 @@ fn collect_docs(
667669}
668670
669671fn render_docs(
670 out: *std.ArrayListUnmanaged(u8),
672 out: *ArrayList(u8),
671673 decl_index: Decl.Index,
672674 first_doc_comment: Ast.TokenIndex,
673675 short: bool,
......@@ -691,11 +693,10 @@ fn render_docs(
691693 defer parsed_doc.deinit(gpa);
692694
693695 const g = struct {
694 var link_buffer: std.ArrayListUnmanaged(u8) = .empty;
696 var link_buffer: ArrayList(u8) = .empty;
695697 };
696698
697 const Writer = std.ArrayListUnmanaged(u8).Writer;
698 const Renderer = markdown.Renderer(Writer, Decl.Index);
699 const Renderer = markdown.Renderer(Decl.Index);
699700 const renderer: Renderer = .{
700701 .context = decl_index,
701702 .renderFn = struct {
......@@ -703,8 +704,8 @@ fn render_docs(
703704 r: Renderer,
704705 doc: markdown.Document,
705706 node: markdown.Document.Node.Index,
706 writer: Writer,
707 ) !void {
707 writer: *Writer,
708 ) Writer.Error!void {
708709 const data = doc.nodes.items(.data)[@intFromEnum(node)];
709710 switch (doc.nodes.items(.tag)[@intFromEnum(node)]) {
710711 .code_span => {
......@@ -712,7 +713,7 @@ fn render_docs(
712713 const content = doc.string(data.text.content);
713714 if (resolve_decl_path(r.context, content)) |resolved_decl_index| {
714715 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;
716717
717718 try writer.writeAll("<a href=\"#");
718719 _ = missing_feature_url_escape;
......@@ -730,7 +731,12 @@ fn render_docs(
730731 }
731732 }.render,
732733 };
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 };
734740}
735741
736742fn 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 {
827833}
828834
829835/// Set by `set_input_string`.
830var input_string: std.ArrayListUnmanaged(u8) = .empty;
836var input_string: ArrayList(u8) = .empty;
831837
832838export fn set_input_string(len: usize) [*]u8 {
833839 input_string.resize(gpa, len) catch @panic("OOM");
......@@ -849,7 +855,7 @@ export fn find_decl() Decl.Index {
849855 if (result != .none) return result;
850856
851857 const g = struct {
852 var match_fqn: std.ArrayListUnmanaged(u8) = .empty;
858 var match_fqn: ArrayList(u8) = .empty;
853859 };
854860 for (Walk.decls.items, 0..) |*decl, decl_index| {
855861 g.match_fqn.clearRetainingCapacity();
......@@ -905,7 +911,7 @@ export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl.
905911
906912export fn namespace_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) {
907913 const g = struct {
908 var members: std.ArrayListUnmanaged(Decl.Index) = .empty;
914 var members: ArrayList(Decl.Index) = .empty;
909915 };
910916
911917 g.members.clearRetainingCapacity();
lib/docs/wasm/markdown/renderer.zig+15-16
......@@ -2,25 +2,26 @@ const std = @import("std");
22const Document = @import("Document.zig");
33const Node = Document.Node;
44const assert = std.debug.assert;
5const Writer = std.Io.Writer;
56
67/// A Markdown document renderer.
78///
89/// Each concrete `Renderer` type has a `renderDefault` function, with the
910/// intention that custom `renderFn` implementations can call `renderDefault`
1011/// for node types for which they require no special rendering.
11pub fn Renderer(comptime Writer: type, comptime Context: type) type {
12pub fn Renderer(comptime Context: type) type {
1213 return struct {
1314 renderFn: *const fn (
1415 r: Self,
1516 doc: Document,
1617 node: Node.Index,
17 writer: Writer,
18 writer: *Writer,
1819 ) Writer.Error!void = renderDefault,
1920 context: Context,
2021
2122 const Self = @This();
2223
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 {
2425 try r.renderFn(r, doc, .root, writer);
2526 }
2627
......@@ -28,7 +29,7 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {
2829 r: Self,
2930 doc: Document,
3031 node: Node.Index,
31 writer: Writer,
32 writer: *Writer,
3233 ) Writer.Error!void {
3334 const data = doc.nodes.items(.data)[@intFromEnum(node)];
3435 switch (doc.nodes.items(.tag)[@intFromEnum(node)]) {
......@@ -188,8 +189,8 @@ pub fn Renderer(comptime Writer: type, comptime Context: type) type {
188189pub fn renderInlineNodeText(
189190 doc: Document,
190191 node: Node.Index,
191 writer: anytype,
192) @TypeOf(writer).Error!void {
192 writer: *Writer,
193) Writer.Error!void {
193194 const data = doc.nodes.items(.data)[@intFromEnum(node)];
194195 switch (doc.nodes.items(.tag)[@intFromEnum(node)]) {
195196 .root,
......@@ -234,14 +235,12 @@ pub fn fmtHtml(bytes: []const u8) std.fmt.Formatter([]const u8, formatHtml) {
234235 return .{ .data = bytes };
235236}
236237
237fn formatHtml(bytes: []const u8, writer: *std.io.Writer) std.io.Writer.Error!void {
238 for (bytes) |b| {
239 switch (b) {
240 '<' => try writer.writeAll("&lt;"),
241 '>' => try writer.writeAll("&gt;"),
242 '&' => try writer.writeAll("&amp;"),
243 '"' => try writer.writeAll("&quot;"),
244 else => try writer.writeByte(b),
245 }
246 }
238fn formatHtml(bytes: []const u8, w: *Writer) Writer.Error!void {
239 for (bytes) |b| switch (b) {
240 '<' => try w.writeAll("&lt;"),
241 '>' => try w.writeAll("&gt;"),
242 '&' => try w.writeAll("&amp;"),
243 '"' => try w.writeAll("&quot;"),
244 else => try w.writeByte(b),
245 };
247246}
tools/docgen.zig+21-21
......@@ -1,6 +1,5 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const io = std.io;
43const fs = std.fs;
54const process = std.process;
65const Progress = std.Progress;
......@@ -8,8 +7,10 @@ const print = std.debug.print;
87const mem = std.mem;
98const testing = std.testing;
109const Allocator = std.mem.Allocator;
10const ArrayList = std.ArrayList;
1111const getExternalExecutor = std.zig.system.getExternalExecutor;
1212const fatal = std.process.fatal;
13const Writer = std.Io.Writer;
1314
1415const max_doc_file_size = 10 * 1024 * 1024;
1516
......@@ -344,10 +345,10 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
344345 var last_action: Action = .open;
345346 var last_columns: ?u8 = null;
346347
347 var toc_buf = std.array_list.Managed(u8).init(allocator);
348 var toc_buf: Writer.Allocating = .init(allocator);
348349 defer toc_buf.deinit();
349350
350 var toc = toc_buf.writer();
351 const toc = &toc_buf.writer;
351352
352353 var nodes = std.array_list.Managed(Node).init(allocator);
353354 defer nodes.deinit();
......@@ -422,7 +423,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
422423 }
423424 if (last_action == .open) {
424425 try toc.writeByte('\n');
425 try toc.writeByteNTimes(' ', header_stack_size * 4);
426 try toc.splatByteAll(' ', header_stack_size * 4);
426427 if (last_columns) |n| {
427428 try toc.print("<ul style=\"columns: {d}\">\n", .{n});
428429 } else {
......@@ -432,7 +433,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
432433 last_action = .open;
433434 }
434435 last_columns = columns;
435 try toc.writeByteNTimes(' ', 4 + header_stack_size * 4);
436 try toc.splatByteAll(' ', 4 + header_stack_size * 4);
436437 try toc.print("<li><a id=\"toc-{s}\" href=\"#{s}\">{s}</a>", .{ urlized, urlized, content });
437438 } else if (mem.eql(u8, tag_name, "header_close")) {
438439 if (header_stack_size == 0) {
......@@ -442,7 +443,7 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
442443 _ = try eatToken(tokenizer, .bracket_close);
443444
444445 if (last_action == .close) {
445 try toc.writeByteNTimes(' ', 8 + header_stack_size * 4);
446 try toc.splatByteAll(' ', 8 + header_stack_size * 4);
446447 try toc.writeAll("</ul></li>\n");
447448 } else {
448449 try toc.writeAll("</li>\n");
......@@ -591,30 +592,29 @@ fn genToc(allocator: Allocator, tokenizer: *Tokenizer) !Toc {
591592 }
592593 }
593594
594 return Toc{
595 return .{
595596 .nodes = try nodes.toOwnedSlice(),
596597 .toc = try toc_buf.toOwnedSlice(),
597598 .urls = urls,
598599 };
599600}
600601
601fn urlize(allocator: Allocator, input: []const u8) ![]u8 {
602 var buf = std.array_list.Managed(u8).init(allocator);
603 defer buf.deinit();
602fn urlize(gpa: Allocator, input: []const u8) ![]u8 {
603 var buf: ArrayList(u8) = .empty;
604 defer buf.deinit(gpa);
604605
605 const out = buf.writer();
606606 for (input) |c| {
607607 switch (c) {
608608 'a'...'z', 'A'...'Z', '_', '-', '0'...'9' => {
609 try out.writeByte(c);
609 try buf.append(gpa, c);
610610 },
611611 ' ' => {
612 try out.writeByte('-');
612 try buf.append(gpa, '-');
613613 },
614614 else => {},
615615 }
616616 }
617 return try buf.toOwnedSlice();
617 return try buf.toOwnedSlice(gpa);
618618}
619619
620620fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 {
......@@ -626,7 +626,7 @@ fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 {
626626 return try buf.toOwnedSlice();
627627}
628628
629fn writeEscaped(out: anytype, input: []const u8) !void {
629fn writeEscaped(out: *Writer, input: []const u8) !void {
630630 for (input) |c| {
631631 try switch (c) {
632632 '&' => out.writeAll("&amp;"),
......@@ -662,14 +662,14 @@ fn isType(name: []const u8) bool {
662662 return false;
663663}
664664
665fn writeEscapedLines(out: anytype, text: []const u8) !void {
665fn writeEscapedLines(out: *Writer, text: []const u8) !void {
666666 return writeEscaped(out, text);
667667}
668668
669669fn tokenizeAndPrintRaw(
670670 allocator: Allocator,
671671 docgen_tokenizer: *Tokenizer,
672 out: anytype,
672 out: *Writer,
673673 source_token: Token,
674674 raw_src: []const u8,
675675) !void {
......@@ -907,14 +907,14 @@ fn tokenizeAndPrintRaw(
907907fn tokenizeAndPrint(
908908 allocator: Allocator,
909909 docgen_tokenizer: *Tokenizer,
910 out: anytype,
910 out: *Writer,
911911 source_token: Token,
912912) !void {
913913 const raw_src = docgen_tokenizer.buffer[source_token.start..source_token.end];
914914 return tokenizeAndPrintRaw(allocator, docgen_tokenizer, out, source_token, raw_src);
915915}
916916
917fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: anytype, syntax_block: SyntaxBlock) !void {
917fn printSourceBlock(allocator: Allocator, docgen_tokenizer: *Tokenizer, out: *Writer, syntax_block: SyntaxBlock) !void {
918918 const source_type = @tagName(syntax_block.source_type);
919919
920920 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
932932 try out.writeAll("</pre></figure>");
933933}
934934
935fn printShell(out: anytype, shell_content: []const u8, escape: bool) !void {
935fn printShell(out: *Writer, shell_content: []const u8, escape: bool) !void {
936936 const trimmed_shell_content = mem.trim(u8, shell_content, " \r\n");
937937 try out.writeAll("<figure><figcaption class=\"shell-cap\">Shell</figcaption><pre><samp>");
938938 var cmd_cont: bool = false;
......@@ -984,7 +984,7 @@ fn genHtml(
984984 tokenizer: *Tokenizer,
985985 toc: *Toc,
986986 code_dir: std.fs.Dir,
987 out: anytype,
987 out: *Writer,
988988) !void {
989989 for (toc.nodes) |node| {
990990 switch (node) {
tools/doctest.zig+16-20
......@@ -127,9 +127,9 @@ fn printOutput(
127127 const obj_ext = builtin.object_format.fileExt(builtin.cpu.arch);
128128 const print = std.debug.print;
129129
130 var shell_buffer = std.array_list.Managed(u8).init(arena);
130 var shell_buffer: std.Io.Writer.Allocating = .init(arena);
131131 defer shell_buffer.deinit();
132 var shell_out = shell_buffer.writer();
132 const shell_out = &shell_buffer.writer;
133133
134134 const code_name = std.fs.path.stem(input_path);
135135
......@@ -600,7 +600,7 @@ fn printOutput(
600600 }
601601
602602 if (!code.just_check_syntax) {
603 try printShell(out, shell_buffer.items, false);
603 try printShell(out, shell_buffer.written(), false);
604604 }
605605}
606606
......@@ -975,25 +975,21 @@ fn skipPrefix(line: []const u8) []const u8 {
975975 return line[3..];
976976}
977977
978fn escapeHtml(allocator: Allocator, input: []const u8) ![]u8 {
979 var buf = std.array_list.Managed(u8).init(allocator);
980 defer buf.deinit();
981
982 const out = buf.writer();
983 try writeEscaped(out, input);
984 return try buf.toOwnedSlice();
978fn escapeHtml(gpa: Allocator, input: []const u8) ![]u8 {
979 var allocating: Writer.Allocating = .init(gpa);
980 defer allocating.deinit();
981 try writeEscaped(&allocating.writer, input);
982 return allocating.toOwnedSlice();
985983}
986984
987fn writeEscaped(out: *Writer, input: []const u8) !void {
988 for (input) |c| {
989 try switch (c) {
990 '&' => out.writeAll("&amp;"),
991 '<' => out.writeAll("&lt;"),
992 '>' => out.writeAll("&gt;"),
993 '"' => out.writeAll("&quot;"),
994 else => out.writeByte(c),
995 };
996 }
985fn writeEscaped(w: *Writer, input: []const u8) !void {
986 for (input) |c| try switch (c) {
987 '&' => w.writeAll("&amp;"),
988 '<' => w.writeAll("&lt;"),
989 '>' => w.writeAll("&gt;"),
990 '"' => w.writeAll("&quot;"),
991 else => w.writeByte(c),
992 };
997993}
998994
999995fn termColor(allocator: Allocator, input: []const u8) ![]u8 {