From ea717205ca73412c085f2b2296f11c674f359f5c Mon Sep 17 00:00:00 2001 From: odino Date: Fri, 16 Aug 2019 04:09:32 +0400 Subject: [PATCH 1/3] 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). --- option.go | 8 ++++++++ render.go | 4 ++++ render_test.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/option.go b/option.go index 9d843a7..cecdf5e 100644 --- a/option.go +++ b/option.go @@ -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() diff --git a/render.go b/render.go index c3c89b4..2a38d19 100644 --- a/render.go +++ b/render.go @@ -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 } diff --git a/render_test.go b/render_test.go index a87aea3..8968af3 100644 --- a/render_test.go +++ b/render_test.go @@ -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") + } +} From dbd5467376115fc7cf936d30f65e3cd5cf46303c Mon Sep 17 00:00:00 2001 From: odino Date: Fri, 16 Aug 2019 14:37:33 +0400 Subject: [PATCH 2/3] Added document as an argument to the LineBreakCallback --- go.mod | 2 +- option.go | 2 +- render.go | 4 ++-- render_test.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 45f3b12..570b588 100644 --- a/go.mod +++ b/go.mod @@ -6,5 +6,5 @@ require ( github.com/mattn/go-runewidth v0.0.3 github.com/mattn/go-tty v0.0.0-20180219170247-931426f7535a github.com/pkg/term v0.0.0-20180423043932-cda20d4ac917 - golang.org/x/sys v0.0.0-20180620133508-ad87a3a340fa // indirect + golang.org/x/sys v0.0.0-20180620133508-ad87a3a340fa ) diff --git a/option.go b/option.go index cecdf5e..e8f73d1 100644 --- a/option.go +++ b/option.go @@ -235,7 +235,7 @@ func OptionShowCompletionAtStart() Option { } // OptionBreakLineCallback to run a callback at every break line -func OptionBreakLineCallback(fn func()) Option { +func OptionBreakLineCallback(fn func(*Document)) Option { return func(p *Prompt) error { p.renderer.BreakLineCallback = fn return nil diff --git a/render.go b/render.go index 2a38d19..ac65f76 100644 --- a/render.go +++ b/render.go @@ -12,7 +12,7 @@ type Render struct { out ConsoleWriter prefix string livePrefixCallback func() (prefix string, useLivePrefix bool) - BreakLineCallback func() + BreakLineCallback func(*Document) title string row uint16 col uint16 @@ -237,7 +237,7 @@ func (r *Render) BreakLine(buffer *Buffer) { r.out.SetColor(DefaultColor, DefaultColor, false) debug.AssertNoError(r.out.Flush()) if r.BreakLineCallback != nil { - r.BreakLineCallback() + r.BreakLineCallback(buffer.Document()) } r.previousCursor = 0 diff --git a/render_test.go b/render_test.go index 8968af3..63dd0bd 100644 --- a/render_test.go +++ b/render_test.go @@ -100,7 +100,7 @@ func TestBreakLineCallback(t *testing.T) { t.Errorf("i should initially be 0, before applying a break line callback") } - r.BreakLineCallback = func() { + r.BreakLineCallback = func(doc *Document) { i++ } r.BreakLine(b) From c7735f732df3783cc2c5b8cfde35755236b2c13c Mon Sep 17 00:00:00 2001 From: odino Date: Mon, 26 Aug 2019 17:41:23 +0400 Subject: [PATCH 3/3] make BreaklineCallback private (`breaklineCallback`) --- option.go | 2 +- render.go | 6 +++--- render_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/option.go b/option.go index e8f73d1..abce19a 100644 --- a/option.go +++ b/option.go @@ -237,7 +237,7 @@ func OptionShowCompletionAtStart() Option { // OptionBreakLineCallback to run a callback at every break line func OptionBreakLineCallback(fn func(*Document)) Option { return func(p *Prompt) error { - p.renderer.BreakLineCallback = fn + p.renderer.breakLineCallback = fn return nil } } diff --git a/render.go b/render.go index ac65f76..90bdf9d 100644 --- a/render.go +++ b/render.go @@ -12,7 +12,7 @@ type Render struct { out ConsoleWriter prefix string livePrefixCallback func() (prefix string, useLivePrefix bool) - BreakLineCallback func(*Document) + breakLineCallback func(*Document) title string row uint16 col uint16 @@ -236,8 +236,8 @@ 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(buffer.Document()) + if r.breakLineCallback != nil { + r.breakLineCallback(buffer.Document()) } r.previousCursor = 0 diff --git a/render_test.go b/render_test.go index 63dd0bd..98cb27c 100644 --- a/render_test.go +++ b/render_test.go @@ -100,7 +100,7 @@ func TestBreakLineCallback(t *testing.T) { t.Errorf("i should initially be 0, before applying a break line callback") } - r.BreakLineCallback = func(doc *Document) { + r.breakLineCallback = func(doc *Document) { i++ } r.BreakLine(b)