Added OptionBreakLineCallback, to run a callback every time there's a line break

It's useful to run a function everytime there's a line break -- Enter as well as, for example, ControlC.

With this PR, a new option is added to assign a callback that gets
called every time `renderer.BreakLine()` is called.

Added a test that makes sure the renderer doesn't break if the callback is
not specified, as well as to check that it runs ok when the callback executes.

Just to give a bit more of context: in [ABS](https://github.com/abs-lang/abs)
we are trying to implement ControlR (reverse search), and need to clear
the search selection every time the user "clears" the console, either by
pressing enter or by clearing the current line (eg. ControlC).
This commit is contained in:
odino 2019-08-16 04:09:32 +04:00
parent 2492e11b98
commit ea717205ca
3 changed files with 58 additions and 0 deletions

View File

@ -234,6 +234,14 @@ func OptionShowCompletionAtStart() Option {
}
}
// OptionBreakLineCallback to run a callback at every break line
func OptionBreakLineCallback(fn func()) Option {
return func(p *Prompt) error {
p.renderer.BreakLineCallback = fn
return nil
}
}
// New returns a Prompt with powerful auto-completion.
func New(executor Executor, completer Completer, opts ...Option) *Prompt {
defaultWriter := NewStdoutWriter()

View File

@ -12,6 +12,7 @@ type Render struct {
out ConsoleWriter
prefix string
livePrefixCallback func() (prefix string, useLivePrefix bool)
BreakLineCallback func()
title string
row uint16
col uint16
@ -235,6 +236,9 @@ func (r *Render) BreakLine(buffer *Buffer) {
r.out.WriteStr(buffer.Document().Text + "\n")
r.out.SetColor(DefaultColor, DefaultColor, false)
debug.AssertNoError(r.out.Flush())
if r.BreakLineCallback != nil {
r.BreakLineCallback()
}
r.previousCursor = 0
}

View File

@ -2,6 +2,7 @@ package prompt
import (
"reflect"
"syscall"
"testing"
)
@ -65,3 +66,48 @@ func TestFormatCompletion(t *testing.T) {
}
}
}
func TestBreakLineCallback(t *testing.T) {
var i int
r := &Render{
prefix: "> ",
out: &PosixWriter{
fd: syscall.Stdin, // "write" to stdin just so we don't mess with the output of the tests
},
livePrefixCallback: func() (string, bool) { return "", false },
prefixTextColor: Blue,
prefixBGColor: DefaultColor,
inputTextColor: DefaultColor,
inputBGColor: DefaultColor,
previewSuggestionTextColor: Green,
previewSuggestionBGColor: DefaultColor,
suggestionTextColor: White,
suggestionBGColor: Cyan,
selectedSuggestionTextColor: Black,
selectedSuggestionBGColor: Turquoise,
descriptionTextColor: Black,
descriptionBGColor: Turquoise,
selectedDescriptionTextColor: White,
selectedDescriptionBGColor: Cyan,
scrollbarThumbColor: DarkGray,
scrollbarBGColor: Cyan,
col: 1,
}
b := NewBuffer()
r.BreakLine(b)
if i != 0 {
t.Errorf("i should initially be 0, before applying a break line callback")
}
r.BreakLineCallback = func() {
i++
}
r.BreakLine(b)
r.BreakLine(b)
r.BreakLine(b)
if i != 3 {
t.Errorf("BreakLine callback not called, i should be 3")
}
}