Automatically add New Line(s) after 80th character in a string containing ANSI Escape Codes

187 Views Asked by At

I want a Go program to display a CP437-encoded 'ANSI art file', 80 columns wide, that contains ANSI escape codes -- color, cursor placement, etc. and extended ANSI (CP437) box drawing codes.

When viewing the ANSI file in a linux terminal (see Playground link below) with a 80 col CP437-capable terminal, the file displays properly, e.g. line breaks are implicitly read; however, when viewing with a wider terminal (which is the goal), new lines are not implicitly processed/added and the file may display improperly, without required line breaks.

How do I iterate through the .ans file and manually add new lines after the 80th character, counting only the actual characters displayed (not the escape codes)?

I've tried go libraries like ansiwrap and reflow. Ansiwrap is really just for text wrapping, but Reflow gets the closest to the goal, but the line breaks are not quite right.

Playground link of my test code with Reflow.

How it renders (in a CP437 terminal, 132x37):

Viewed in Terminal application 132x37

How it should look (from art program):

reference image

1

There are 1 best solutions below

0
Zombo On

To solve this, first I pulled visualLength function from the golang.org/x/term package [1], then I wrote a bufio.SplitFunc [2] for this use case.

package main

func ansi(data []byte, eof bool) (int, []byte, error) {
   var s []rune
   for i, r := range string(data) {
      if s = append(s, r); visualLength(s) == 80 {
         width := len(string(r))
         return i+width, data[:i+width], nil
      }
   }
   return 0, nil, nil
}

Result:

package main

import (
   "bufio"
   "golang.org/x/text/encoding/charmap"
   "os"
)

func main() {
   f, err := os.Open("LDA-PHASE90.ANS")
   if err != nil {
      panic(err)
   }
   defer f.Close()
   s := bufio.NewScanner(charmap.CodePage437.NewDecoder().Reader(f))
   s.Split(ansi)
   for s.Scan() {
      println(s.Text())
   }
}
  1. https://github.com/golang/term/blob/6886f2df/terminal.go#L431-L450
  2. https://golang.org/pkg/bufio#SplitFunc