123 lines
2.3 KiB
Go
123 lines
2.3 KiB
Go
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()
|
|
}
|