From 42156f1aea5ad69fc14977b343c88acfc8e5d454 Mon Sep 17 00:00:00 2001 From: Lucas dos Santos Abreu Date: Mon, 28 Jun 2021 21:31:27 -0300 Subject: [PATCH] (feat): allow prompt callback on rune input and initial input --- terminal/runereader.go | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/terminal/runereader.go b/terminal/runereader.go index a9a43ba3..6ab158a0 100644 --- a/terminal/runereader.go +++ b/terminal/runereader.go @@ -31,7 +31,13 @@ func (rr *RuneReader) printChar(char rune, mask rune) { } } -func (rr *RuneReader) ReadLine(mask rune, onRunes ...func(rune) bool) ([]rune, error) { +type OnRuneFn func(rune, []rune) ([]rune, bool, error) + +func (rr *RuneReader) ReadLine(mask rune, onRunes ...OnRuneFn) ([]rune, error) { + return rr.ReadLineWithDefault(mask, []rune{}, onRunes...) +} + +func (rr *RuneReader) ReadLineWithDefault(mask rune, d []rune, onRunes ...OnRuneFn) ([]rune, error) { line := []rune{} // we only care about horizontal displacements from the origin so start counting at 0 index := 0 @@ -41,11 +47,26 @@ func (rr *RuneReader) ReadLine(mask rune, onRunes ...func(rune) bool) ([]rune, e Out: rr.stdio.Out, } + onRune := func(r rune, line []rune) ([]rune, bool, error) { + return line, false, nil + } + + // if the user pressed a key the caller was interested in capturing + if len(onRunes) > 0 { + onRune = onRunes[0] + } + // we get the terminal width and height (if resized after this point the property might become invalid) terminalSize, _ := cursor.Size(rr.Buffer()) // we set the current location of the cursor once cursorCurrent, _ := cursor.Location(rr.Buffer()) + if len(d) > 0 { + index = len(d) + fmt.Fprint(rr.stdio.Out, string(d)) + line = d + } + for { // wait for some input r, _, err := rr.ReadRune() @@ -55,10 +76,10 @@ func (rr *RuneReader) ReadLine(mask rune, onRunes ...func(rune) bool) ([]rune, e // increment cursor location cursorCurrent.X++ - // if the user pressed a key the caller was interested in capturing - if len(onRunes) > 0 && onRunes[0](r) { - return line, nil - } + if l, stop, err := onRune(r, line); stop || err != nil { + return l, err + } + // if the user pressed enter or some other newline/termination like ctrl+d if r == '\r' || r == '\n' || r == KeyEndTransmission { // delete what's printed out on the console screen (cleanup)