support initial state
This commit is contained in:
parent
3b1b460e6a
commit
33e2961b64
22
lib.go
22
lib.go
@ -23,6 +23,7 @@ type Editor interface {
|
||||
type editorFunc[S any] struct {
|
||||
edit func(rune, S) ([]rune, S)
|
||||
releaseState func(S) []rune
|
||||
init S
|
||||
}
|
||||
|
||||
// Writer implements the io.Writer interface, passing the input to every editor in the configured sequence, and
|
||||
@ -34,6 +35,10 @@ type Writer struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (e editorFunc[S]) initialize() any {
|
||||
return e.init
|
||||
}
|
||||
|
||||
func (e editorFunc[S]) Edit(r rune, state any) ([]rune, any) {
|
||||
s, _ := state.(S)
|
||||
return e.edit(r, s)
|
||||
@ -44,8 +49,9 @@ func (e editorFunc[S]) ReleaseState(state any) []rune {
|
||||
return e.releaseState(s)
|
||||
}
|
||||
|
||||
// Func can be used to define an Editor providing only the edit and releaseState functions.
|
||||
func Func[S any](edit func(r rune, state S) ([]rune, S), releaseState func(S) []rune) Editor {
|
||||
// FuncInit can be used to define an Editor providing only the edit and releaseState functions, and the initial
|
||||
// state.
|
||||
func FuncInit[S any](edit func(r rune, state S) ([]rune, S), releaseState func(S) []rune, init S) Editor {
|
||||
if edit == nil {
|
||||
edit = func(r rune, s S) ([]rune, S) { return []rune{r}, s }
|
||||
}
|
||||
@ -54,7 +60,13 @@ func Func[S any](edit func(r rune, state S) ([]rune, S), releaseState func(S) []
|
||||
releaseState = func(S) []rune { return nil }
|
||||
}
|
||||
|
||||
return editorFunc[S]{edit: edit, releaseState: releaseState}
|
||||
return editorFunc[S]{edit: edit, releaseState: releaseState, init: init}
|
||||
}
|
||||
|
||||
// Func can be used to define an Editor providing only the edit and releaseState functions.
|
||||
func Func[S any](edit func(r rune, state S) ([]rune, S), releaseState func(S) []rune) Editor {
|
||||
var s S
|
||||
return FuncInit(edit, releaseState, s)
|
||||
}
|
||||
|
||||
// Replace is a built-in editor for simple replace operations. The arguments are mapped such that the ones at
|
||||
@ -96,9 +108,11 @@ func SingleLine() Editor {
|
||||
// New initializes an editing writer. The editor instances will be called in the order they are passed in to
|
||||
// New.
|
||||
func New(out io.Writer, e ...Editor) *Writer {
|
||||
seq := sequence(e...)
|
||||
return &Writer{
|
||||
out: out,
|
||||
editor: sequence(e...),
|
||||
editor: seq,
|
||||
state: seq.(interface{ initialize() any }).initialize(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
25
lib_test.go
25
lib_test.go
@ -181,3 +181,28 @@ func TestFlush(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
edit := func(r rune, lineStart bool) ([]rune, bool) {
|
||||
if r == '\n' {
|
||||
return []rune{'\n'}, true
|
||||
}
|
||||
|
||||
if lineStart {
|
||||
return append([]rune("> "), r), false
|
||||
}
|
||||
|
||||
return []rune{r}, false
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
e := textedit.FuncInit(edit, func(bool) []rune { return nil }, true)
|
||||
w := textedit.New(&b, e)
|
||||
if _, err := w.Write([]byte("quoted\nemail")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if b.String() != "> quoted\n> email" {
|
||||
t.Fatal(b.String())
|
||||
}
|
||||
}
|
||||
|
||||
10
sequence.go
10
sequence.go
@ -57,8 +57,16 @@ func sequenceRelease(e []Editor) func([]any) []rune {
|
||||
}
|
||||
|
||||
func sequence(e ...Editor) Editor {
|
||||
return Func(
|
||||
init := make([]any, len(e))
|
||||
for i, ei := range e {
|
||||
if initializer, ok := ei.(interface{ initialize() any }); ok {
|
||||
init[i] = initializer.initialize()
|
||||
}
|
||||
}
|
||||
|
||||
return FuncInit(
|
||||
sequenceEdit(e),
|
||||
sequenceRelease(e),
|
||||
init,
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user