• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jedib0t / go-prompter / 6355076892

29 Sep 2023 05:32PM UTC coverage: 96.836% (+4.6%) from 92.25%
6355076892

push

github

web-flow
prompt: support custom io (Reader/Writer) (#7)

94 of 94 new or added lines in 4 files covered. (100.0%)

2357 of 2434 relevant lines covered (96.84%)

57.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.11
/prompt/prompt_render.go
1
package prompt
2

3
import (
4
        "context"
5
        "fmt"
6
        "time"
7

8
        "github.com/jedib0t/go-pretty/v6/text"
9
        "github.com/muesli/termenv"
10
)
11

12
//gocyclo:ignore
13
func (p *prompt) render(ctx context.Context, output *termenv.Output) (rsp string, err error) {
1✔
14
        p.init(ctx)
1✔
15

1✔
16
        // set up cleanup
1✔
17
        defer func() {
2✔
18
                p.pauseRender()
1✔
19
                p.updateModel(false)
1✔
20
                p.renderView(output, "done", true)
1✔
21
                p.buffer.Reset()
1✔
22
        }()
1✔
23

24
        // instantiate an input reader and begin looking for inputs
25
        p.readerMutex.Lock()
1✔
26
        go p.reader.Begin(ctx)
1✔
27
        defer func() {
2✔
28
                p.reader.End()
1✔
29
                p.readerMutex.Unlock()
1✔
30
        }()
1✔
31

32
        // first time render
33
        p.updateModel(true)
1✔
34

1✔
35
        // start handling input events and rendering to screen
1✔
36
        tick := time.Tick(p.refreshInterval)
1✔
37
        tickCursor := time.Tick(p.style.Cursor.BlinkInterval)
1✔
38
        for {
9✔
39
                select {
8✔
40
                case <-ctx.Done():
×
41
                        return "", ctx.Err()
×
42
                case <-tick:
6✔
43
                        if p.buffer.HasChanges() {
7✔
44
                                p.updateModel(true)
1✔
45
                        }
1✔
46
                        p.renderView(output, "tick")
6✔
47
                case <-tickCursor:
×
48
                        p.updateModel(true)
×
49
                case err = <-p.reader.Errors():
×
50
                        return "", err
×
51
                case key := <-p.reader.KeyEvents():
2✔
52
                        if err = p.handleKey(output, key); err != nil {
2✔
53
                                return "", err
×
54
                        }
×
55
                        if p.buffer.IsDone() {
3✔
56
                                return p.buffer.String(), nil
1✔
57
                        }
1✔
58
                case resize := <-p.reader.WindowSizeEvents():
×
59
                        p.updateDisplayWidth(resize.Width)
×
60
                }
61
        }
62
}
63

64
func (p *prompt) renderView(output *termenv.Output, reason string, forced ...bool) {
19✔
65
        p.linesMutex.Lock()
19✔
66
        defer p.linesMutex.Unlock()
19✔
67

19✔
68
        // if paused, don't do anything
19✔
69
        if p.isRenderPaused() && len(forced) == 0 {
19✔
70
                return
×
71
        }
×
72
        p.setDebugData("reason", reason)
19✔
73

19✔
74
        timeStart := time.Now()
19✔
75
        defer func() {
38✔
76
                p.linesRendered = p.linesToRender
19✔
77
        }()
19✔
78

79
        // calculate movement
80
        numLinesToRender, numLinesRendered := len(p.linesToRender), len(p.linesRendered)
19✔
81

19✔
82
        // move cursor up and clear printed lines
19✔
83
        if numLinesRendered > 0 {
31✔
84
                if numLinesToRender < numLinesRendered {
13✔
85
                        for idx := numLinesRendered; idx > numLinesToRender; idx-- {
3✔
86
                                output.CursorUp(1)
2✔
87
                                output.ClearLine()
2✔
88
                        }
2✔
89
                        output.CursorUp(numLinesToRender)
1✔
90
                } else {
11✔
91
                        output.CursorUp(numLinesRendered)
11✔
92
                }
11✔
93
                if p.debug { // for the final debug footer
12✔
94
                        output.CursorUp(1)
×
95
                }
×
96
        }
97

98
        // print all the changed lines
99
        for idx, line := range p.linesToRender {
63✔
100
                if idx < len(p.linesRendered) && p.linesRendered[idx] == line { // nothing changed
59✔
101
                        output.CursorDown(1)
15✔
102
                        continue
15✔
103
                }
104

105
                // something is different, clear and reprint
106
                output.ClearLine()
29✔
107
                if p.debug { // render the "second" this line was rendered to screen
32✔
108
                        _, _ = output.WriteString(p.style.Colors.Debug.Sprintf(" %02d ", time.Now().Second()))
3✔
109
                }
3✔
110
                _, _ = output.WriteString(fmt.Sprintf("%s\n", line))
29✔
111
        }
112

113
        if p.debug {
20✔
114
                stats := fmt.Sprintf("%s; time=%v [gen=sh:%v/bf:%v/ac:%v/%v]",
1✔
115
                        p.debugDataAsString(), time.Since(timeStart).Round(time.Microsecond),
1✔
116
                        p.timeSyntaxGen, p.timeBufferGen, p.timeAutoComplete, p.timeGen,
1✔
117
                )
1✔
118

1✔
119
                output.ClearLine()
1✔
120
                _, _ = output.WriteString(p.style.Colors.Debug.Sprintf(" %02d ", time.Now().Second()))
1✔
121
                _, _ = output.WriteString(p.style.Colors.Debug.Sprintf(
1✔
122
                        text.AlignCenter.Apply(stats, p.getDisplayWidth())) + "\n",
1✔
123
                )
1✔
124
        }
1✔
125
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc