73 lines
1.2 KiB
Go
73 lines
1.2 KiB
Go
package textfmt
|
|
|
|
import "fmt"
|
|
|
|
type escapeRange struct {
|
|
from, to rune
|
|
replacement string
|
|
}
|
|
|
|
type escape[S any] struct {
|
|
out writer
|
|
state S
|
|
escape map[rune]string
|
|
escapeRanges []escapeRange
|
|
conditionalEscape map[rune]func(S, rune) (string, bool)
|
|
updateState func(S, rune) S
|
|
}
|
|
|
|
func (e *escape[S]) inEscapeRange(r rune) (string, bool) {
|
|
for _, rng := range e.escapeRanges {
|
|
if r >= rng.from && r <= rng.to {
|
|
return rng.replacement, true
|
|
}
|
|
}
|
|
|
|
return "", false
|
|
}
|
|
|
|
func (e *escape[S]) write(a ...any) {
|
|
for _, ai := range a {
|
|
s := fmt.Sprint(ai)
|
|
r := []rune(s)
|
|
for _, ri := range r {
|
|
var (
|
|
output string
|
|
found bool
|
|
)
|
|
|
|
output, found = e.escape[ri]
|
|
if !found {
|
|
output, found = e.inEscapeRange(ri)
|
|
}
|
|
|
|
if !found {
|
|
conditional := e.conditionalEscape[ri]
|
|
if conditional != nil {
|
|
output, found = conditional(e.state, ri)
|
|
}
|
|
}
|
|
|
|
if !found {
|
|
output = string(ri)
|
|
}
|
|
|
|
e.out.write(output)
|
|
if e.updateState != nil {
|
|
e.state = e.updateState(e.state, ri)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (e *escape[S]) flush() {
|
|
e.out.flush()
|
|
}
|
|
|
|
func (e *escape[S]) error() error {
|
|
return e.out.error()
|
|
}
|
|
|
|
func (e *escape[S]) setErr(err error) {
|
|
}
|