diff --git a/ascii/ascii.go b/ascii/ascii.go index d862715..77e77e5 100644 --- a/ascii/ascii.go +++ b/ascii/ascii.go @@ -26,14 +26,14 @@ func NewASCII(dat string) (*ASCII, error) { var row []Cell chompState, fg, bg, fgs, bgs := 0, -1, -1, 0, 0 var bold, underline, italic, strikethrough bool - for _, v := range dat { + for i, v := range dat { switch v { case '\r': continue case '\n': bold, underline, strikethrough, italic = false, false, false, false cells = append(cells, row) - chompState, fg, bg = 0, -1, -1 + chompState, fg, bg, fgs, bgs = 0, -1, -1, 0, 0 row = nil continue case '\x02': @@ -60,6 +60,13 @@ func NewASCII(dat string) (*ASCII, error) { continue } case 1: + if v == '\x03' { + if fgs == 0 { + bg = -1 + } + fg, fgs = -1, 0 + continue + } if v >= '0' && v <= '9' && fgs < 2 { if fg == -1 { fg = 0 @@ -74,8 +81,11 @@ func NewASCII(dat string) (*ASCII, error) { break } if v == ',' { - chompState, bg = 2, -1 - continue + if len(dat) > i+1 && dat[i+1] >= '0' && dat[i+1] <= '9' { + chompState, bg = 2, -1 + continue + } + chompState = 0 } case 2: if v >= '0' && v <= '9' && bgs < 2 { @@ -90,7 +100,7 @@ func NewASCII(dat string) (*ASCII, error) { } bgs, chompState = 0, 0 if bg == -1 { - return nil, ErrBadMircCode + // return nil, ErrBadMircCode } } fgc, err := MircColor(fg) diff --git a/ascii/ascii_test.go b/ascii/ascii_test.go index 999e6ae..e0d8908 100644 --- a/ascii/ascii_test.go +++ b/ascii/ascii_test.go @@ -1,6 +1,7 @@ package ascii import ( + "strings" "testing" ) @@ -31,6 +32,274 @@ func TestControlCodes(t *testing.T) { } } +func PrettyFormat(ircText string) string { + out := strings.ReplaceAll(ircText, "\x03", "\x1b[033m[C]\x1b[0m") + out = strings.ReplaceAll(out, "\x02", "\x1b[034m[B]\x1b[0m") + out = strings.ReplaceAll(out, "\x1F", "\x1b[035m[U]\x1b[0m") + out = strings.ReplaceAll(out, "\x1D", "\x1b[036m[I]\x1b[0m") + return out +} + +func PrintExpectedVsParsed(expected string, ascii *ASCII, t *testing.T) { + t.Errorf(" Input : %s", PrettyFormat(expected)) + t.Errorf(" Parsed : %s", PrettyFormat(string(ascii.Bytes()))) +} + +func TestColorCodes(t *testing.T) { + s := "hello \x0315,01hello" + // 012345 6789 + a, _ := NewASCII(s) + if c := a.Get(2, 0); c == nil || c.Value != 'l' { + t.Errorf("Expected l but found %c", c.Value) + } + if c := a.Get(2, 0); c == nil || c.Foreground != nil { + t.Errorf("Expected nil but found %v", c.Foreground) + } + if c := a.Get(2, 0); c == nil || c.Background != nil { + t.Errorf("Expected nil but found %v", c.Background) + } + + if c := a.Get(7, 0); c == nil || c.Value != 'e' { + t.Errorf("Expected e but found %c", c.Value) + } + fg, _ := MircColor(15) + if c := a.Get(7, 0); c == nil || c.Foreground != fg { + t.Errorf("Expected 15 but found %v", c.Foreground) + } + bg, _ := MircColor(1) + if c := a.Get(7, 0); c == nil || c.Background != bg { + t.Errorf("Expected 1 but found %v", c.Background) + } +} + +func TestColorCodesBackToBack(t *testing.T) { + s := "he\x037,01he\x03\x0315lo" + // 01 23 45 + a, _ := NewASCII(s) + + c := a.Get(4, 0) + if c == nil { + t.Error("Expected l at pos 4 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'l' { + t.Errorf("Expected l at pos 4 but found '%c'", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(15) + if c.Foreground != fg { + t.Errorf("Expected color 4 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + } + + c = a.Get(5, 0) + if c == nil { + t.Error("Expected o at pos 5 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Background != nil { + t.Errorf("Expected nil but found %v", c.Background) + } + } +} + +func TestColorCodesNoText(t *testing.T) { + s := "ab\x037\x034cd" + // 01 23 + a, _ := NewASCII(s) + + c := a.Get(2, 0) + if c == nil { + t.Error("Expected c at pos 2 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'c' { + t.Errorf("Expected c at pos 2 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(4) + if c.Foreground != fg { + t.Errorf("Expected color 4 at pos 2 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + } +} +func TestColorCodesNoText2d(t *testing.T) { + s := "ab\x0315\x0314cd" + // 01 23 + a, _ := NewASCII(s) + + c := a.Get(2, 0) + if c == nil { + t.Error("Expected c at pos 2 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'c' { + t.Errorf("Expected c at pos 2 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(14) + if c.Foreground != fg { + t.Errorf("Expected color 4 at pos 2 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + } +} + +func TestBoldAfterColorCode(t *testing.T) { + s := "ab\x0315\x02cd" + // 01 23 + a, _ := NewASCII(s) + + c := a.Get(2, 0) + if c == nil { + t.Error("Expected c at pos 2 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'c' { + t.Errorf("Expected c at pos 2 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(15) + if c.Foreground != fg { + t.Errorf("Expected color 4 at pos 2 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + if !c.Bold { + t.Errorf("Expected bold pos 2 but found %v", c.Bold) + PrintExpectedVsParsed(s, a, t) + } + } +} + +func TestColorAfterBoldAfterColorCode(t *testing.T) { + s := "ab\x0315\x02\x0314cd" + // 01 23 + a, _ := NewASCII(s) + + c := a.Get(2, 0) + if c == nil { + t.Error("Expected c at pos 2 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'c' { + t.Errorf("Expected c at pos 2 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(14) + if c.Foreground != fg { + t.Errorf("Expected color 4 at pos 2 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + if !c.Bold { + t.Errorf("Expected bold pos 2 but found %v", c.Bold) + PrintExpectedVsParsed(s, a, t) + } + } +} + +func TestLeadingColorAfterItalicAfterColorCode(t *testing.T) { + s := "\x0315\x1D\x0314cd" + // 01 + a, _ := NewASCII(s) + + c := a.Get(0, 0) + if c == nil { + t.Error("Expected c at pos 2 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'c' { + t.Errorf("Expected c at pos 2 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(14) + if c.Foreground != fg { + t.Errorf("Expected color 4 at pos 2 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + if !c.Italic { + t.Errorf("Expected bold pos 2 but found %v", c.Bold) + PrintExpectedVsParsed(s, a, t) + } + } +} + +func TestLeadingColorAfterItalicAfterColorCodeAfterNewlineAfterColor(t *testing.T) { + s := "\x0315\n\x0313\x1D\x0314cd" + // 01 + a, _ := NewASCII(s) + + c := a.Get(0, 1) + if c == nil { + t.Error("Expected c at pos 2 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'c' { + t.Errorf("Expected c at pos 2 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(14) + if c.Foreground != fg { + t.Errorf("Expected color 4 at pos 2 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + if !c.Italic { + t.Errorf("Expected italic pos 2 but found %v", c.Bold) + PrintExpectedVsParsed(s, a, t) + } + } +} + +func TestColoredComma(t *testing.T) { + s := "\x0315, " + // 01 + a, _ := NewASCII(s) + + c := a.Get(0, 0) + if c == nil { + t.Error("Expected , at pos 0 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != ',' { + t.Errorf("Expected , at pos 0 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(15) + if c.Foreground != fg { + t.Errorf("Expected color 15 at pos 0 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + } +} + +func TestBackgroundPersistsAfterBackToBack(t *testing.T) { + s := "\x0315,01\x0303\x0304moo" + // 012 + a, _ := NewASCII(s) + + c := a.Get(0, 0) + if c == nil { + t.Error("Expected m at pos 0 but found nil") + PrintExpectedVsParsed(s, a, t) + } else { + if c.Value != 'm' { + t.Errorf("Expected m at pos 0 but found %c", c.Value) + PrintExpectedVsParsed(s, a, t) + } + fg, _ := MircColor(4) + if c.Foreground != fg { + t.Errorf("Expected color 4 at pos 0 but found %v", c.Foreground) + PrintExpectedVsParsed(s, a, t) + } + bg, _ := MircColor(1) + if c.Background != bg { + t.Errorf("Expected color 1 at pos 0 but found %v", c.Background) + PrintExpectedVsParsed(s, a, t) + } + } +} + func TestColorCancelAteChars(t *testing.T) { s := `11,11 test` // 01 2345