diff options
| -rw-r--r-- | doc/docgen.zig | 258 | ||||
| -rw-r--r-- | doc/langref.html.in | 20 |
2 files changed, 243 insertions, 35 deletions
diff --git a/doc/docgen.zig b/doc/docgen.zig index e7663cdfe2..6f2438c857 100644 --- a/doc/docgen.zig +++ b/doc/docgen.zig @@ -793,28 +793,37 @@ fn writeEscaped(out: anytype, input: []const u8) !void { } } -//#define VT_RED "\x1b[31;1m" -//#define VT_GREEN "\x1b[32;1m" -//#define VT_CYAN "\x1b[36;1m" -//#define VT_WHITE "\x1b[37;1m" -//#define VT_BOLD "\x1b[0;1m" -//#define VT_RESET "\x1b[0m" - -test "term color" { - const input_bytes = "A\x1b[32;1mgreen\x1b[0mB"; - const result = try termColor(std.testing.allocator, input_bytes); - defer std.testing.allocator.free(result); - try testing.expectEqualSlices(u8, "A<span class=\"t32_1\">green</span>B", result); +// Returns true if number is in slice. +fn in(slice: []const u8, number: u8) bool { + for (slice) |n| { + if (number == n) return true; + } + return false; } fn termColor(allocator: Allocator, input: []const u8) ![]u8 { + // The SRG sequences generates by the Zig compiler are in the format: + // ESC [ <foreground-color> ; <n> m + // or + // ESC [ <n> m + // + // where + // foreground-color is 31 (red), 32 (green), 36 (cyan) + // n is 0 (reset), 1 (bold), 2 (dim) + // + // Note that 37 (white) is currently not used by the compiler. + // + // See std.debug.TTY.Color. + const supported_sgr_colors = [_]u8{ 31, 32, 36 }; + const supported_sgr_numbers = [_]u8{ 0, 1, 2 }; + var buf = std.ArrayList(u8).init(allocator); defer buf.deinit(); var out = buf.writer(); - var number_start_index: usize = undefined; - var first_number: usize = undefined; - var second_number: usize = undefined; + var sgr_param_start_index: usize = undefined; + var sgr_num: u8 = undefined; + var sgr_color: u8 = undefined; var i: usize = 0; var state: enum { start, @@ -845,7 +854,7 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { }, .lbracket => switch (c) { '0'...'9' => { - number_start_index = i; + sgr_param_start_index = i; state = .number; }, else => return error.UnsupportedEscape, @@ -853,13 +862,12 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { .number => switch (c) { '0'...'9' => {}, else => { - first_number = std.fmt.parseInt(usize, input[number_start_index..i], 10) catch unreachable; - second_number = 0; + sgr_num = try std.fmt.parseInt(u8, input[sgr_param_start_index..i], 10); + sgr_color = 0; state = .after_number; i -= 1; }, }, - .after_number => switch (c) { ';' => state = .arg, 'D' => state = .start, @@ -874,7 +882,7 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { }, .arg => switch (c) { '0'...'9' => { - number_start_index = i; + sgr_param_start_index = i; state = .arg_number; }, else => return error.UnsupportedEscape, @@ -882,7 +890,15 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { .arg_number => switch (c) { '0'...'9' => {}, else => { - second_number = std.fmt.parseInt(usize, input[number_start_index..i], 10) catch unreachable; + // Keep the sequence consistent, foreground color first. + // 32;1m is equivalent to 1;32m, but the latter will + // generate an incorrect HTML class without notice. + sgr_color = sgr_num; + if (!in(&supported_sgr_colors, sgr_color)) return error.UnsupportedForegroundColor; + + sgr_num = try std.fmt.parseInt(u8, input[sgr_param_start_index..i], 10); + if (!in(&supported_sgr_numbers, sgr_num)) return error.UnsupportedNumber; + state = .expect_end; i -= 1; }, @@ -893,10 +909,16 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { while (open_span_count != 0) : (open_span_count -= 1) { try out.writeAll("</span>"); } - if (first_number != 0 or second_number != 0) { - try out.print("<span class=\"t{d}_{d}\">", .{ first_number, second_number }); - open_span_count += 1; + if (sgr_num == 0) { + if (sgr_color != 0) return error.UnsupportedColor; + continue; + } + if (sgr_color != 0) { + try out.print("<span class=\"sgr-{d}_{d}m\">", .{ sgr_color, sgr_num }); + } else { + try out.print("<span class=\"sgr-{d}m\">", .{sgr_num}); } + open_span_count += 1; }, else => return error.UnsupportedEscape, }, @@ -1874,7 +1896,193 @@ fn dumpArgs(args: []const []const u8) void { print("\n", .{}); } -test "shell parsed" { +test "term supported colors" { + const test_allocator = testing.allocator; + + { + const input = "A\x1b[31;1mred\x1b[0mB"; + const expect = "A<span class=\"sgr-31_1m\">red</span>B"; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + const input = "A\x1b[32;1mgreen\x1b[0mB"; + const expect = "A<span class=\"sgr-32_1m\">green</span>B"; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + const input = "A\x1b[36;1mcyan\x1b[0mB"; + const expect = "A<span class=\"sgr-36_1m\">cyan</span>B"; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + const input = "A\x1b[1mbold\x1b[0mB"; + const expect = "A<span class=\"sgr-1m\">bold</span>B"; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + const input = "A\x1b[2mdim\x1b[0mB"; + const expect = "A<span class=\"sgr-2m\">dim</span>B"; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } +} + +test "term output from zig" { + // Use data generated by https://github.com/perillo/zig-tty-test-data, + // with zig version 0.11.0-dev.1898+36d47dd19. + const test_allocator = testing.allocator; + + { + // 1.1-with-build-progress.out + const input = "Semantic Analysis [1324] \x1b[25D\x1b[0KLLVM Emit Object... \x1b[20D\x1b[0KLLVM Emit Object... \x1b[20D\x1b[0KLLD Link... \x1b[12D\x1b[0K"; + const expect = ""; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + // 2.1-with-reference-traces.out + const input = "\x1b[1msrc/2.1-with-reference-traces.zig:3:7: \x1b[31;1merror: \x1b[0m\x1b[1mcannot assign to constant\n\x1b[0m x += 1;\n \x1b[32;1m~~^~~~\n\x1b[0m\x1b[0m\x1b[2mreferenced by:\n main: src/2.1-with-reference-traces.zig:7:5\n callMain: /usr/local/lib/zig/lib/std/start.zig:607:17\n remaining reference traces hidden; use '-freference-trace' to see all reference traces\n\n\x1b[0m"; + const expect = + \\<span class="sgr-1m">src/2.1-with-reference-traces.zig:3:7: </span><span class="sgr-31_1m">error: </span><span class="sgr-1m">cannot assign to constant + \\</span> x += 1; + \\ <span class="sgr-32_1m">~~^~~~ + \\</span><span class="sgr-2m">referenced by: + \\ main: src/2.1-with-reference-traces.zig:7:5 + \\ callMain: /usr/local/lib/zig/lib/std/start.zig:607:17 + \\ remaining reference traces hidden; use '-freference-trace' to see all reference traces + \\ + \\</span> + ; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + // 2.2-without-reference-traces.out + const input = "\x1b[1m/usr/local/lib/zig/lib/std/io/fixed_buffer_stream.zig:128:29: \x1b[31;1merror: \x1b[0m\x1b[1minvalid type given to fixedBufferStream\n\x1b[0m else => @compileError(\"invalid type given to fixedBufferStream\"),\n \x1b[32;1m^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\x1b[0m\x1b[1m/usr/local/lib/zig/lib/std/io/fixed_buffer_stream.zig:116:66: \x1b[36;1mnote: \x1b[0m\x1b[1mcalled from here\n\x1b[0mpub fn fixedBufferStream(buffer: anytype) FixedBufferStream(Slice(@TypeOf(buffer))) {\n; \x1b[32;1m~~~~~^~~~~~~~~~~~~~~~~\n\x1b[0m"; + const expect = + \\<span class="sgr-1m">/usr/local/lib/zig/lib/std/io/fixed_buffer_stream.zig:128:29: </span><span class="sgr-31_1m">error: </span><span class="sgr-1m">invalid type given to fixedBufferStream + \\</span> else => @compileError("invalid type given to fixedBufferStream"), + \\ <span class="sgr-32_1m">^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + \\</span><span class="sgr-1m">/usr/local/lib/zig/lib/std/io/fixed_buffer_stream.zig:116:66: </span><span class="sgr-36_1m">note: </span><span class="sgr-1m">called from here + \\</span>pub fn fixedBufferStream(buffer: anytype) FixedBufferStream(Slice(@TypeOf(buffer))) { + \\; <span class="sgr-32_1m">~~~~~^~~~~~~~~~~~~~~~~ + \\</span> + ; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + // 2.3-with-notes.out + const input = "\x1b[1msrc/2.3-with-notes.zig:6:9: \x1b[31;1merror: \x1b[0m\x1b[1mexpected type '*2.3-with-notes.Derp', found '*2.3-with-notes.Wat'\n\x1b[0m bar(w);\n \x1b[32;1m^\n\x1b[0m\x1b[1msrc/2.3-with-notes.zig:6:9: \x1b[36;1mnote: \x1b[0m\x1b[1mpointer type child '2.3-with-notes.Wat' cannot cast into pointer type child '2.3-with-notes.Derp'\n\x1b[0m\x1b[1msrc/2.3-with-notes.zig:2:13: \x1b[36;1mnote: \x1b[0m\x1b[1mopaque declared here\n\x1b[0mconst Wat = opaque {};\n \x1b[32;1m^~~~~~~~~\n\x1b[0m\x1b[1msrc/2.3-with-notes.zig:1:14: \x1b[36;1mnote: \x1b[0m\x1b[1mopaque declared here\n\x1b[0mconst Derp = opaque {};\n \x1b[32;1m^~~~~~~~~\n\x1b[0m\x1b[1msrc/2.3-with-notes.zig:4:18: \x1b[36;1mnote: \x1b[0m\x1b[1mparameter type declared here\n\x1b[0mextern fn bar(d: *Derp) void;\n \x1b[32;1m^~~~~\n\x1b[0m\x1b[0m\x1b[2mreferenced by:\n main: src/2.3-with-notes.zig:10:5\n callMain: /usr/local/lib/zig/lib/std/start.zig:607:17\n remaining reference traces hidden; use '-freference-trace' to see all reference traces\n\n\x1b[0m"; + const expect = + \\<span class="sgr-1m">src/2.3-with-notes.zig:6:9: </span><span class="sgr-31_1m">error: </span><span class="sgr-1m">expected type '*2.3-with-notes.Derp', found '*2.3-with-notes.Wat' + \\</span> bar(w); + \\ <span class="sgr-32_1m">^ + \\</span><span class="sgr-1m">src/2.3-with-notes.zig:6:9: </span><span class="sgr-36_1m">note: </span><span class="sgr-1m">pointer type child '2.3-with-notes.Wat' cannot cast into pointer type child '2.3-with-notes.Derp' + \\</span><span class="sgr-1m">src/2.3-with-notes.zig:2:13: </span><span class="sgr-36_1m">note: </span><span class="sgr-1m">opaque declared here + \\</span>const Wat = opaque {}; + \\ <span class="sgr-32_1m">^~~~~~~~~ + \\</span><span class="sgr-1m">src/2.3-with-notes.zig:1:14: </span><span class="sgr-36_1m">note: </span><span class="sgr-1m">opaque declared here + \\</span>const Derp = opaque {}; + \\ <span class="sgr-32_1m">^~~~~~~~~ + \\</span><span class="sgr-1m">src/2.3-with-notes.zig:4:18: </span><span class="sgr-36_1m">note: </span><span class="sgr-1m">parameter type declared here + \\</span>extern fn bar(d: *Derp) void; + \\ <span class="sgr-32_1m">^~~~~ + \\</span><span class="sgr-2m">referenced by: + \\ main: src/2.3-with-notes.zig:10:5 + \\ callMain: /usr/local/lib/zig/lib/std/start.zig:607:17 + \\ remaining reference traces hidden; use '-freference-trace' to see all reference traces + \\ + \\</span> + ; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + // 3.1-with-error-return-traces.out + + const input = "error: Error\n\x1b[1m/home/zig/src/3.1-with-error-return-traces.zig:5:5\x1b[0m: \x1b[2m0x20b008 in callee (3.1-with-error-return-traces)\x1b[0m\n return error.Error;\n \x1b[32;1m^\x1b[0m\n\x1b[1m/home/zig/src/3.1-with-error-return-traces.zig:9:5\x1b[0m: \x1b[2m0x20b113 in caller (3.1-with-error-return-traces)\x1b[0m\n try callee();\n \x1b[32;1m^\x1b[0m\n\x1b[1m/home/zig/src/3.1-with-error-return-traces.zig:13:5\x1b[0m: \x1b[2m0x20b153 in main (3.1-with-error-return-traces)\x1b[0m\n try caller();\n \x1b[32;1m^\x1b[0m\n"; + const expect = + \\error: Error + \\<span class="sgr-1m">/home/zig/src/3.1-with-error-return-traces.zig:5:5</span>: <span class="sgr-2m">0x20b008 in callee (3.1-with-error-return-traces)</span> + \\ return error.Error; + \\ <span class="sgr-32_1m">^</span> + \\<span class="sgr-1m">/home/zig/src/3.1-with-error-return-traces.zig:9:5</span>: <span class="sgr-2m">0x20b113 in caller (3.1-with-error-return-traces)</span> + \\ try callee(); + \\ <span class="sgr-32_1m">^</span> + \\<span class="sgr-1m">/home/zig/src/3.1-with-error-return-traces.zig:13:5</span>: <span class="sgr-2m">0x20b153 in main (3.1-with-error-return-traces)</span> + \\ try caller(); + \\ <span class="sgr-32_1m">^</span> + \\ + ; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } + + { + // 3.2-with-stack-trace.out + const input = "\x1b[1m/usr/local/lib/zig/lib/std/debug.zig:561:19\x1b[0m: \x1b[2m0x22a107 in writeCurrentStackTrace__anon_5898 (3.2-with-stack-trace)\x1b[0m\n while (it.next()) |return_address| {\n \x1b[32;1m^\x1b[0m\n\x1b[1m/usr/local/lib/zig/lib/std/debug.zig:157:80\x1b[0m: \x1b[2m0x20bb23 in dumpCurrentStackTrace (3.2-with-stack-trace)\x1b[0m\n writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(io.getStdErr()), start_addr) catch |err| {\n \x1b[32;1m^\x1b[0m\n\x1b[1m/home/zig/src/3.2-with-stack-trace.zig:5:36\x1b[0m: \x1b[2m0x20d3b2 in foo (3.2-with-stack-trace)\x1b[0m\n std.debug.dumpCurrentStackTrace(null);\n \x1b[32;1m^\x1b[0m\n\x1b[1m/home/zig/src/3.2-with-stack-trace.zig:9:8\x1b[0m: \x1b[2m0x20b458 in main (3.2-with-stack-trace)\x1b[0m\n foo();\n \x1b[32;1m^\x1b[0m\n\x1b[1m/usr/local/lib/zig/lib/std/start.zig:607:22\x1b[0m: \x1b[2m0x20a965 in posixCallMainAndExit (3.2-with-stack-trace)\x1b[0m\n root.main();\n \x1b[32;1m^\x1b[0m\n\x1b[1m/usr/local/lib/zig/lib/std/start.zig:376:5\x1b[0m: \x1b[2m0x20a411 in _start (3.2-with-stack-trace)\x1b[0m\n @call(.never_inline, posixCallMainAndExit, .{});\n \x1b[32;1m^\x1b[0m\n"; + const expect = + \\<span class="sgr-1m">/usr/local/lib/zig/lib/std/debug.zig:561:19</span>: <span class="sgr-2m">0x22a107 in writeCurrentStackTrace__anon_5898 (3.2-with-stack-trace)</span> + \\ while (it.next()) |return_address| { + \\ <span class="sgr-32_1m">^</span> + \\<span class="sgr-1m">/usr/local/lib/zig/lib/std/debug.zig:157:80</span>: <span class="sgr-2m">0x20bb23 in dumpCurrentStackTrace (3.2-with-stack-trace)</span> + \\ writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(io.getStdErr()), start_addr) catch |err| { + \\ <span class="sgr-32_1m">^</span> + \\<span class="sgr-1m">/home/zig/src/3.2-with-stack-trace.zig:5:36</span>: <span class="sgr-2m">0x20d3b2 in foo (3.2-with-stack-trace)</span> + \\ std.debug.dumpCurrentStackTrace(null); + \\ <span class="sgr-32_1m">^</span> + \\<span class="sgr-1m">/home/zig/src/3.2-with-stack-trace.zig:9:8</span>: <span class="sgr-2m">0x20b458 in main (3.2-with-stack-trace)</span> + \\ foo(); + \\ <span class="sgr-32_1m">^</span> + \\<span class="sgr-1m">/usr/local/lib/zig/lib/std/start.zig:607:22</span>: <span class="sgr-2m">0x20a965 in posixCallMainAndExit (3.2-with-stack-trace)</span> + \\ root.main(); + \\ <span class="sgr-32_1m">^</span> + \\<span class="sgr-1m">/usr/local/lib/zig/lib/std/start.zig:376:5</span>: <span class="sgr-2m">0x20a411 in _start (3.2-with-stack-trace)</span> + \\ @call(.never_inline, posixCallMainAndExit, .{}); + \\ <span class="sgr-32_1m">^</span> + \\ + ; + + const result = try termColor(test_allocator, input); + defer test_allocator.free(result); + try testing.expectEqualSlices(u8, expect, result); + } +} + +test "printShell" { const test_allocator = std.testing.allocator; { diff --git a/doc/langref.html.in b/doc/langref.html.in index 907464867e..c88c91560c 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -71,19 +71,19 @@ text-align: left; font-weight: normal; } - .t0_1, .t37, .t37_1 { + .sgr-1m { font-weight: bold; } - .t2_0 { + .sgr-2m { color: #575757; } - .t31_1 { + .sgr-31_1m { color: #b40000; } - .t32_1 { + .sgr-32_1m { color: green; } - .t36_1 { + .sgr-36_1m { color: #005C7A; } .file { @@ -114,7 +114,7 @@ line-height: normal; } kbd { - font-weight: bold; + font-weight: normal; } .table-wrapper { width: 100%; @@ -232,16 +232,16 @@ table, th, td { border-color: grey; } - .t2_0 { + .sgr-2m { color: grey; } - .t31_1 { + .sgr-31_1m { color: red; } - .t32_1 { + .sgr-32_1m { color: #00B800; } - .t36_1 { + .sgr-36_1m { color: #0086b3; } code { |
