Skip to content

Commit 31e33dd

Browse files
authored
auto-complete tweaks and misc fixes (#5)
1 parent 576cac0 commit 31e33dd

34 files changed

+886
-362
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ A SQL prompt demo with most of the major features in play:
1818
* Single-line and Multi-line prompt with line numbers
1919
* [Syntax-Highlighting](prompt/syntax_highlighter.go) - use [Chroma](https://github.com/alecthomas/chroma) or roll-your-own
2020
* Flexible [Auto-Complete](prompt/auto_completer.go) drop-downs
21-
* Start with built-in `AutoCompleter` for simple Keywords `Prompter.SetAutoCompleter(...)`
22-
* Expand to context based additional Keywords using `Prompter.SetAutoCompleterContextual(...)`
21+
* Start with built-in `AutoCompleter` for simple Keywords `SetAutoCompleter(...)`
22+
* Expand to context based additional Keywords using `SetAutoCompleterContextual(...)`
2323
* Generate prompts with or without a "prefix"
2424
* Header and Footer generator functions for dynamic content
2525
* History integration with built-in go-back/go-forward/list/rerun

examples/prompt/sql/auto_complete.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@ import "github.com/jedib0t/go-prompter/prompt"
44

55
var (
66
tableAndColumnNames = []prompt.Suggestion{
7-
{Value: "employees", Hint: "Table of Employees"},
8-
{Value: "id", Hint: "ID (primary key)"},
9-
{Value: "username", Hint: "User ID"},
10-
{Value: "first_name", Hint: "First Name"},
11-
{Value: "last_name", Hint: "Last Name"},
12-
{Value: "salary", Hint: "Salary Per Month in USD"},
13-
{Value: "notes", Hint: "Notes"},
14-
{Value: "date_applied", Hint: "Application Date"},
15-
{Value: "date_onboarded", Hint: "Onboarding Date"},
7+
{Value: "employees", Hint: "Table: Table of Employees"},
8+
{Value: "id", Hint: "Column: ID (primary key)"},
9+
{Value: "username", Hint: "Column: User ID"},
10+
{Value: "first_name", Hint: "Column: First Name"},
11+
{Value: "last_name", Hint: "Column: Last Name"},
12+
{Value: "salary", Hint: "Column: Salary Per Month in USD"},
13+
{Value: "notes", Hint: "Column: Notes"},
14+
{Value: "date_applied", Hint: "Column: Application Date"},
15+
{Value: "date_onboarded", Hint: "Column: Onboarding Date"},
1616
}
1717
)

examples/prompt/sql/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func main() {
6161
os.Exit(1)
6262
}
6363
p.SetAutoCompleter(prompt.AutoCompleteSQLKeywords())
64-
p.SetAutoCompleterContextual(prompt.AutoCompleteSimple(tableAndColumnNames, 2, true))
64+
p.SetAutoCompleterContextual(prompt.AutoCompleteSimple(tableAndColumnNames, true))
6565
p.SetCommandShortcuts(shortcuts)
6666
p.SetDebug(*flagDebug)
6767
if !*flagDemo {

powerline/powerline.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ func (p *Powerline) Render(maxWidth int) string {
7474
nsLeft, nsRight, paddingSpace := p.autoAdjustNumSegments(maxWidth)
7575

7676
left := p.renderLeft(maxWidth, nsLeft, nsRight, paddingSpace)
77-
if len(p.right) == 0 {
78-
return left
79-
}
80-
leftLen := text.RuneWidthWithoutEscSequences(left)
81-
right := p.renderRight(maxWidth, nsLeft, nsRight, paddingSpace)
82-
rightLen := text.RuneWidthWithoutEscSequences(right)
83-
padding := p.renderPadding(maxWidth - (leftLen + rightLen))
84-
return fmt.Sprintf("%s%s%s", left, padding, right)
77+
if len(p.right) > 0 {
78+
leftLen := text.RuneWidthWithoutEscSequences(left)
79+
right := p.renderRight(maxWidth, nsLeft, nsRight, paddingSpace)
80+
rightLen := text.RuneWidthWithoutEscSequences(right)
81+
padding := p.renderPadding(maxWidth - (leftLen + rightLen))
82+
return fmt.Sprintf("%s%s%s", left, padding, right)
83+
}
84+
return left
8585
}
8686

8787
func (p *Powerline) SetStyle(style Style) {

powerline/powerline_test.go

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func BenchmarkPowerline_Render(b *testing.B) {
5151
}
5252
}
5353

54-
func TestPowerline_Render(t *testing.T) {
54+
func TestPowerlineRender(t *testing.T) {
5555
segUser := &Segment{}
5656
segUser.SetContent("username")
5757
segUser.SetIcon("👤")
@@ -71,13 +71,17 @@ func TestPowerline_Render(t *testing.T) {
7171
style := StyleNonPatched
7272
style.Color = prompt.Color{Foreground: termenv.ANSI256Color(235), Background: termenv.ANSI256Color(235)}
7373

74-
p := Powerline{}
75-
p.Append(segUser)
76-
p.Append(segHost)
77-
p.Append(segCmdNum)
78-
p.AppendRight(segHostIP)
79-
p.AppendRight(segTime)
80-
p.SetStyle(style)
74+
t.Run("with segments on one side", func(t *testing.T) {
75+
p := Powerline{}
76+
p.Append(segUser)
77+
p.Append(segHost)
78+
p.Append(segCmdNum)
79+
80+
assert.Equal(t,
81+
segUser.Render()+segHost.Render()+segCmdNum.Render(),
82+
p.Render(0),
83+
)
84+
})
8185

8286
expectedOut120 := segUser.Render() +
8387
"\x1b[38;5;205;48;5;17m" + style.SeparatorLeft + "\x1b[0m" +
@@ -104,6 +108,13 @@ func TestPowerline_Render(t *testing.T) {
104108
segTime.Render()
105109

106110
t.Run("without auto-adjusting width", func(t *testing.T) {
111+
p := Powerline{}
112+
p.Append(segUser)
113+
p.Append(segHost)
114+
p.Append(segCmdNum)
115+
p.AppendRight(segHostIP)
116+
p.AppendRight(segTime)
117+
p.SetStyle(style)
107118
p.AutoAdjustWidth(false)
108119

109120
assert.Equal(t, expectedOut120, p.Render(120))
@@ -120,20 +131,30 @@ func TestPowerline_Render(t *testing.T) {
120131
segHostIP.Render()+
121132
"\x1b[38;5;201;48;5;239m"+style.SeparatorRight+"\x1b[0m"+
122133
segTime.Render(),
123-
p.Render(25))
134+
p.Render(25),
135+
)
124136
})
125137

126138
t.Run("with auto-adjusting width", func(t *testing.T) {
139+
p := Powerline{}
140+
p.Append(segUser)
141+
p.Append(segHost)
142+
p.Append(segCmdNum)
143+
p.AppendRight(segHostIP)
144+
p.AppendRight(segTime)
145+
p.SetStyle(style)
127146
p.AutoAdjustWidth(true)
128147

129148
assert.Equal(t, expectedOut120, p.Render(120))
130149
assert.Equal(t, expectedOut50, p.Render(50))
150+
assert.Equal(t, expectedOut50, p.Render(50)) // to check cache
131151
assert.Equal(t,
132152
segUser.Render()+
133153
"\x1b[38;5;235;48;5;17m"+style.SeparatorLeft+"\x1b[0m"+
134154
style.Color.Sprint("")+
135155
"\x1b[38;5;235;48;5;239m"+style.SeparatorRight+"\x1b[0m"+
136156
segTime.Render(),
137-
p.Render(25))
157+
p.Render(25),
158+
)
138159
})
139160
}

powerline/segment.go

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ func (s *Segment) Color() prompt.Color {
3838
return *s.contentColor
3939
}
4040
return prompt.Color{
41-
Foreground: termenv.ANSI256Color(7),
42-
Background: termenv.ANSI256Color(16),
41+
Foreground: termenv.ForegroundColor(),
42+
Background: termenv.BackgroundColor(),
4343
}
4444
}
4545

@@ -52,19 +52,50 @@ func (s *Segment) HasChanges() bool {
5252
return s.hasChanges
5353
}
5454

55-
// SetIcon sets the optional Icon/Emoji to be rendered before the text.
56-
func (s *Segment) SetIcon(icon string) {
55+
// Render returns the segment rendered in appropriate colors.
56+
func (s *Segment) Render() string {
5757
s.mutex.Lock()
5858
defer s.mutex.Unlock()
59-
if s.icon == icon {
60-
return
59+
60+
if s.content == "" {
61+
return ""
6162
}
62-
defer func() {
63-
s.width = s.calculateWidth()
64-
}()
6563

66-
s.hasChanges = true
67-
s.icon = icon
64+
if s.hasChanges {
65+
color := s.color
66+
if color == nil {
67+
color = s.contentColor
68+
}
69+
70+
out := strings.Builder{}
71+
if s.paddingLeft != nil {
72+
out.WriteString(*s.paddingLeft)
73+
} else {
74+
out.WriteRune(' ')
75+
}
76+
if s.icon != "" {
77+
out.WriteString(s.icon)
78+
out.WriteRune(' ')
79+
}
80+
out.WriteString(s.content)
81+
if s.paddingRight != nil {
82+
out.WriteString(*s.paddingRight)
83+
} else {
84+
out.WriteRune(' ')
85+
}
86+
87+
s.rendered = color.Sprint(out.String())
88+
}
89+
s.hasChanges = false
90+
return s.rendered
91+
}
92+
93+
// ResetColor resets the color of the content to defaults.
94+
func (s *Segment) ResetColor() {
95+
s.mutex.Lock()
96+
defer s.mutex.Unlock()
97+
98+
s.color = nil
6899
}
69100

70101
// SetColor sets the colors to be used for the segment. If not set, the hash of
@@ -121,50 +152,19 @@ func (s *Segment) SetContent(content string, tags ...string) {
121152
}
122153
}
123154

124-
// Render returns the segment rendered in appropriate colors.
125-
func (s *Segment) Render() string {
155+
// SetIcon sets the optional Icon/Emoji to be rendered before the text.
156+
func (s *Segment) SetIcon(icon string) {
126157
s.mutex.Lock()
127158
defer s.mutex.Unlock()
128-
129-
if s.content == "" {
130-
return ""
131-
}
132-
133-
if s.hasChanges {
134-
color := s.color
135-
if color == nil {
136-
color = s.contentColor
137-
}
138-
139-
out := strings.Builder{}
140-
if s.paddingLeft != nil {
141-
out.WriteString(*s.paddingLeft)
142-
} else {
143-
out.WriteRune(' ')
144-
}
145-
if s.icon != "" {
146-
out.WriteString(s.icon)
147-
out.WriteRune(' ')
148-
}
149-
out.WriteString(s.content)
150-
if s.paddingRight != nil {
151-
out.WriteString(*s.paddingRight)
152-
} else {
153-
out.WriteRune(' ')
154-
}
155-
156-
s.rendered = color.Sprint(out.String())
159+
if s.icon == icon {
160+
return
157161
}
158-
s.hasChanges = false
159-
return s.rendered
160-
}
161-
162-
// ResetColor resets the color of the content to defaults.
163-
func (s *Segment) ResetColor() {
164-
s.mutex.Lock()
165-
defer s.mutex.Unlock()
162+
defer func() {
163+
s.width = s.calculateWidth()
164+
}()
166165

167-
s.color = nil
166+
s.hasChanges = true
167+
s.icon = icon
168168
}
169169

170170
// Width returns the width of the segment when printed on screen.

0 commit comments

Comments
 (0)