package tequat import ( "bufio" "fmt" "strings" blobs "pkg.jfrech.com/brief/internal/transmigratory/pkg_jfrech_com_go_blobs" ) // TODO write some tests to make sure atoms are parsed as expected const dbg = false func Highlight(mark string) string { return "\033[96m" + mark + "\033[m" } func (tqa TQA) Format() string { esc := func(raw string) string { b := new(strings.Builder) for _, c := range raw { if c > ' ' && c != '"' && c != '\'' && c != '\\' && c <= '~' { b.WriteRune(rune(c)) } else { fmt.Fprintf(b, "\\x%02x", int(c)) } } return b.String() } b := new(strings.Builder) emitln := func(unterminated string) { if strings.ContainsRune(unterminated, '\n') { panic("unreachable") } b.WriteString(unterminated) b.WriteRune('\n') } emit := func(prefix string, raw string) { scanner := bufio.NewScanner(strings.NewReader(raw)) scanner.Buffer(nil, 0xffffff) // [2023-07-19, jfrech] TODO especially minified HTML lines can get *very* long. for scanner.Scan() { b.WriteString(prefix) b.Write(scanner.Bytes()) b.WriteRune('\n') } if err := scanner.Err(); err != nil { panic("scanner token probably too long: " + err.Error()) // TODO Is this true? } } if dbg { emitln(Highlight("{{{")) } for j, atom := range []Atom(tqa) { if dbg && j > 0 { emitln(Highlight(";;;")) } switch a := atom.(type) { default: emitln(Highlight("???") + " " + esc(fmt.Sprintf("%T", a))) case Text: emit("", a.Raw) case Quote: emit(Highlight(">"), a.Raw) case DroppedAlternatives: b := new(strings.Builder) for j, t := range a.MediatypeTs { if j != 0 { b.WriteString(", ") } b.WriteString(esc(t)) } emitln(Highlight("dropped-alternatives:") + " " + b.String()) case Attachment: mark := "attached" if a.Inline { mark = "attached-inline" } emitln(Highlight(mark) + " " + esc(a.ContentType()) + " " + esc(blobs.SlurpBytes(a.Data).Short())) case SignatureBlock: emitln(Highlight("-- ")) emit("", a.Raw) } } if dbg { emitln(Highlight("}}}")) } return b.String() }