mirror of https://github.com/mum4k/termdash.git
Merge branch 'devel' into 243-formdemo
This commit is contained in:
commit
db2fcdcffc
|
@ -65,6 +65,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- the `textinput` widget can now be configured to request keyboard events
|
- the `textinput` widget can now be configured to request keyboard events
|
||||||
exclusively when focused.
|
exclusively when focused.
|
||||||
|
- the `textinput` widget can now be initialized with a default text in the
|
||||||
|
input box.
|
||||||
|
|
||||||
## [0.13.0] - 17-Nov-2020
|
## [0.13.0] - 17-Nov-2020
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ package textinput
|
||||||
// options.go contains configurable options for TextInput.
|
// options.go contains configurable options for TextInput.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/mum4k/termdash/align"
|
"github.com/mum4k/termdash/align"
|
||||||
|
@ -58,6 +59,7 @@ type options struct {
|
||||||
|
|
||||||
placeHolder string
|
placeHolder string
|
||||||
hideTextWith rune
|
hideTextWith rune
|
||||||
|
defaultText string
|
||||||
|
|
||||||
filter FilterFn
|
filter FilterFn
|
||||||
onSubmit SubmitFn
|
onSubmit SubmitFn
|
||||||
|
@ -81,6 +83,16 @@ func (o *options) validate() error {
|
||||||
return fmt.Errorf("invalid HideTextWidth rune %c(%d), has rune width of %d cells, only runes with width of %d are accepted", r, r, got, want)
|
return fmt.Errorf("invalid HideTextWidth rune %c(%d), has rune width of %d cells, only runes with width of %d are accepted", r, r, got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if o.defaultText != "" {
|
||||||
|
if err := wrap.ValidText(o.defaultText); err != nil {
|
||||||
|
return fmt.Errorf("invalid DefaultText: %v", err)
|
||||||
|
}
|
||||||
|
for _, r := range o.defaultText {
|
||||||
|
if r == '\n' {
|
||||||
|
return errors.New("invalid DefaultText: newline characters aren't allowed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,3 +284,12 @@ func ExclusiveKeyboardOnFocus() Option {
|
||||||
opts.exclusiveKeyboardOnFocus = true
|
opts.exclusiveKeyboardOnFocus = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultText sets the text to be present in a newly created input field.
|
||||||
|
// The text must not contain any control or space characters other than ' '.
|
||||||
|
// The user can edit this text as normal.
|
||||||
|
func DefaultText(text string) Option {
|
||||||
|
return option(func(opts *options) {
|
||||||
|
opts.defaultText = text
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -69,10 +69,15 @@ func New(opts ...Option) (*TextInput, error) {
|
||||||
if err := opt.validate(); err != nil {
|
if err := opt.validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &TextInput{
|
ti := &TextInput{
|
||||||
editor: newFieldEditor(),
|
editor: newFieldEditor(),
|
||||||
opts: opt,
|
opts: opt,
|
||||||
}, nil
|
}
|
||||||
|
|
||||||
|
for _, r := range ti.opts.defaultText {
|
||||||
|
ti.editor.insert(r)
|
||||||
|
}
|
||||||
|
return ti, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vars to be replaced from tests.
|
// Vars to be replaced from tests.
|
||||||
|
|
|
@ -117,6 +117,20 @@ func TestTextInput(t *testing.T) {
|
||||||
},
|
},
|
||||||
wantNewErr: true,
|
wantNewErr: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "fails on invalid DefaultText which has control characters",
|
||||||
|
opts: []Option{
|
||||||
|
DefaultText("\r"),
|
||||||
|
},
|
||||||
|
wantNewErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "fails on invalid DefaultText which has newline",
|
||||||
|
opts: []Option{
|
||||||
|
DefaultText("\n"),
|
||||||
|
},
|
||||||
|
wantNewErr: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "takes all space without label",
|
desc: "takes all space without label",
|
||||||
canvas: image.Rect(0, 0, 10, 1),
|
canvas: image.Rect(0, 0, 10, 1),
|
||||||
|
@ -559,6 +573,62 @@ func TestTextInput(t *testing.T) {
|
||||||
return ft
|
return ft
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "displays default text",
|
||||||
|
opts: []Option{
|
||||||
|
DefaultText("text"),
|
||||||
|
},
|
||||||
|
canvas: image.Rect(0, 0, 10, 1),
|
||||||
|
meta: &widgetapi.Meta{},
|
||||||
|
want: func(size image.Point) *faketerm.Terminal {
|
||||||
|
ft := faketerm.MustNew(size)
|
||||||
|
cvs := testcanvas.MustNew(ft.Area())
|
||||||
|
|
||||||
|
testcanvas.MustSetAreaCells(
|
||||||
|
cvs,
|
||||||
|
image.Rect(0, 0, 10, 1),
|
||||||
|
textFieldRune,
|
||||||
|
cell.BgColor(cell.ColorNumber(DefaultFillColorNumber)),
|
||||||
|
)
|
||||||
|
testdraw.MustText(
|
||||||
|
cvs,
|
||||||
|
"text",
|
||||||
|
image.Point{0, 0},
|
||||||
|
)
|
||||||
|
testcanvas.MustApply(cvs, ft)
|
||||||
|
return ft
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "default text can be edited",
|
||||||
|
opts: []Option{
|
||||||
|
DefaultText("text"),
|
||||||
|
},
|
||||||
|
canvas: image.Rect(0, 0, 10, 1),
|
||||||
|
meta: &widgetapi.Meta{},
|
||||||
|
events: []terminalapi.Event{
|
||||||
|
&terminalapi.Keyboard{Key: keyboard.KeyBackspace},
|
||||||
|
&terminalapi.Keyboard{Key: 'a'},
|
||||||
|
},
|
||||||
|
want: func(size image.Point) *faketerm.Terminal {
|
||||||
|
ft := faketerm.MustNew(size)
|
||||||
|
cvs := testcanvas.MustNew(ft.Area())
|
||||||
|
|
||||||
|
testcanvas.MustSetAreaCells(
|
||||||
|
cvs,
|
||||||
|
image.Rect(0, 0, 10, 1),
|
||||||
|
textFieldRune,
|
||||||
|
cell.BgColor(cell.ColorNumber(DefaultFillColorNumber)),
|
||||||
|
)
|
||||||
|
testdraw.MustText(
|
||||||
|
cvs,
|
||||||
|
"texa",
|
||||||
|
image.Point{0, 0},
|
||||||
|
)
|
||||||
|
testcanvas.MustApply(cvs, ft)
|
||||||
|
return ft
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "displays written text",
|
desc: "displays written text",
|
||||||
canvas: image.Rect(0, 0, 10, 1),
|
canvas: image.Rect(0, 0, 10, 1),
|
||||||
|
|
Loading…
Reference in New Issue