| ... | ... | @@ -760,17 +760,6 @@ fn writeEscaped(out: anytype, input: []const u8) !void { |
| 760 | 760 | //#define VT_BOLD "\x1b[0;1m" |
| 761 | 761 | //#define VT_RESET "\x1b[0m" |
| 762 | 762 | |
| 763 | | const TermState = enum { |
| 764 | | Start, |
| 765 | | Escape, |
| 766 | | LBracket, |
| 767 | | Number, |
| 768 | | AfterNumber, |
| 769 | | Arg, |
| 770 | | ArgNumber, |
| 771 | | ExpectEnd, |
| 772 | | }; |
| 773 | | |
| 774 | 763 | test "term color" { |
| 775 | 764 | const input_bytes = "A\x1b[32;1mgreen\x1b[0mB"; |
| 776 | 765 | const result = try termColor(std.testing.allocator, input_bytes); |
| ... | ... | @@ -787,61 +776,80 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { |
| 787 | 776 | var first_number: usize = undefined; |
| 788 | 777 | var second_number: usize = undefined; |
| 789 | 778 | var i: usize = 0; |
| 790 | | var state = TermState.Start; |
| 779 | var state: enum { |
| 780 | start, |
| 781 | escape, |
| 782 | lbracket, |
| 783 | number, |
| 784 | after_number, |
| 785 | arg, |
| 786 | arg_number, |
| 787 | expect_end, |
| 788 | } = .start; |
| 789 | var last_new_line: usize = 0; |
| 791 | 790 | var open_span_count: usize = 0; |
| 792 | 791 | while (i < input.len) : (i += 1) { |
| 793 | 792 | const c = input[i]; |
| 794 | 793 | switch (state) { |
| 795 | | TermState.Start => switch (c) { |
| 796 | | '\x1b' => state = TermState.Escape, |
| 794 | .start => switch (c) { |
| 795 | '\x1b' => state = .escape, |
| 796 | '\n' => { |
| 797 | try out.writeByte(c); |
| 798 | last_new_line = buf.items.len; |
| 799 | }, |
| 797 | 800 | else => try out.writeByte(c), |
| 798 | 801 | }, |
| 799 | | TermState.Escape => switch (c) { |
| 800 | | '[' => state = TermState.LBracket, |
| 802 | .escape => switch (c) { |
| 803 | '[' => state = .lbracket, |
| 801 | 804 | else => return error.UnsupportedEscape, |
| 802 | 805 | }, |
| 803 | | TermState.LBracket => switch (c) { |
| 806 | .lbracket => switch (c) { |
| 804 | 807 | '0'...'9' => { |
| 805 | 808 | number_start_index = i; |
| 806 | | state = TermState.Number; |
| 809 | state = .number; |
| 807 | 810 | }, |
| 808 | 811 | else => return error.UnsupportedEscape, |
| 809 | 812 | }, |
| 810 | | TermState.Number => switch (c) { |
| 813 | .number => switch (c) { |
| 811 | 814 | '0'...'9' => {}, |
| 812 | 815 | else => { |
| 813 | 816 | first_number = std.fmt.parseInt(usize, input[number_start_index..i], 10) catch unreachable; |
| 814 | 817 | second_number = 0; |
| 815 | | state = TermState.AfterNumber; |
| 818 | state = .after_number; |
| 816 | 819 | i -= 1; |
| 817 | 820 | }, |
| 818 | 821 | }, |
| 819 | 822 | |
| 820 | | TermState.AfterNumber => switch (c) { |
| 821 | | ';' => state = TermState.Arg, |
| 823 | .after_number => switch (c) { |
| 824 | ';' => state = .arg, |
| 825 | 'D' => state = .start, |
| 826 | 'K' => { |
| 827 | buf.items.len = last_new_line; |
| 828 | state = .start; |
| 829 | }, |
| 822 | 830 | else => { |
| 823 | | state = TermState.ExpectEnd; |
| 831 | state = .expect_end; |
| 824 | 832 | i -= 1; |
| 825 | 833 | }, |
| 826 | 834 | }, |
| 827 | | TermState.Arg => switch (c) { |
| 835 | .arg => switch (c) { |
| 828 | 836 | '0'...'9' => { |
| 829 | 837 | number_start_index = i; |
| 830 | | state = TermState.ArgNumber; |
| 838 | state = .arg_number; |
| 831 | 839 | }, |
| 832 | 840 | else => return error.UnsupportedEscape, |
| 833 | 841 | }, |
| 834 | | TermState.ArgNumber => switch (c) { |
| 842 | .arg_number => switch (c) { |
| 835 | 843 | '0'...'9' => {}, |
| 836 | 844 | else => { |
| 837 | 845 | second_number = std.fmt.parseInt(usize, input[number_start_index..i], 10) catch unreachable; |
| 838 | | state = TermState.ExpectEnd; |
| 846 | state = .expect_end; |
| 839 | 847 | i -= 1; |
| 840 | 848 | }, |
| 841 | 849 | }, |
| 842 | | TermState.ExpectEnd => switch (c) { |
| 850 | .expect_end => switch (c) { |
| 843 | 851 | 'm' => { |
| 844 | | state = TermState.Start; |
| 852 | state = .start; |
| 845 | 853 | while (open_span_count != 0) : (open_span_count -= 1) { |
| 846 | 854 | try out.writeAll("</span>"); |
| 847 | 855 | } |