package textedit import "io" type Editor interface { Edit(r rune, state any) ([]rune, any) ReleaseState(state any) []rune } type editorFunc[S any] struct { edit func(rune, S) ([]rune, S) releaseState func(S) []rune } type Writer struct { out io.Writer editor Editor state any err error } func (e editorFunc[S]) Edit(r rune, state any) ([]rune, any) { s, _ := state.(S) return e.edit(r, s) } func (e editorFunc[S]) ReleaseState(state any) []rune { s, _ := state.(S) r := e.releaseState(s) return r } func Func[S any](edit func(r rune, state S) ([]rune, S), releaseState func(S) []rune) Editor { if edit == nil { edit = func(r rune, s S) ([]rune, S) { return []rune{r}, s } } if releaseState == nil { releaseState = func(S) []rune { return nil } } return editorFunc[S]{edit: edit, releaseState: releaseState} } func Replace(a ...string) Editor { return replace(a...) } func Escape(esc rune, chars ...rune) Editor { return escape(esc, chars...) } func Indent(first, rest string) Editor { return wrapIndent([]rune(first), []rune(rest), 0, 0) } func Wrap(firstWidth, restWidth int) Editor { return wrapIndent(nil, nil, firstWidth, restWidth) } func WrapIndent(firstIndent, restIndent string, firstWidth, restWidth int) Editor { return wrapIndent([]rune(firstIndent), []rune(restIndent), firstWidth, restWidth) } func SingleLine() Editor { return sequence( replace("\n", " "), wrapIndent(nil, nil, 0, 0), ) } func New(out io.Writer, e ...Editor) *Writer { return &Writer{ out: out, editor: sequence(e...), } } func (w *Writer) write(r []rune) error { if w.err != nil { return w.err } for _, ri := range r { rr, s := w.editor.Edit(ri, w.state) if _, err := w.out.Write([]byte(string(rr))); err != nil { w.err = err return w.err } w.state = s } return nil } func (w *Writer) flush() error { if w.err != nil { return w.err } r := w.editor.ReleaseState(w.state) w.state = nil if _, err := w.out.Write([]byte(string(r))); err != nil { w.err = err return w.err } return nil } func (w *Writer) Write(p []byte) (int, error) { return len(p), w.write([]rune(string(p))) } func (w *Writer) WriteRune(r rune) (int, error) { return len([]byte(string(r))), w.write([]rune{r}) } func (w *Writer) Flush() error { return w.flush() }