Skip to content

Commit 79a382e

Browse files
authored
Use Bubbletea TUI library (#2923)
This replaces the TUI library used in elastic-package with "github.com/charmbracelet/bubbletea". The previously used library has more limited functionality, and is also currently unmaintained. Switching to bubbletea will support some upcoming improvements to elastic-package, which will involve more user interaction, and will benefit from the improved UI elements that are available with bubbletea. This adds a tui package which contains the TUI components, and converts the existing users of survey to use the tui package.
1 parent 6a4a0d2 commit 79a382e

File tree

20 files changed

+1316
-383
lines changed

20 files changed

+1316
-383
lines changed

cmd/create_data_stream.go

Lines changed: 42 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,12 @@ import (
1010
"maps"
1111
"slices"
1212

13-
"github.com/AlecAivazis/survey/v2"
1413
"github.com/Masterminds/semver/v3"
15-
1614
"github.com/spf13/cobra"
1715

1816
"github.com/elastic/elastic-package/internal/packages"
1917
"github.com/elastic/elastic-package/internal/packages/archetype"
20-
"github.com/elastic/elastic-package/internal/surveyext"
18+
"github.com/elastic/elastic-package/internal/tui"
2119
)
2220

2321
var semver3_2_0 = semver.MustParse("3.2.0")
@@ -64,39 +62,33 @@ func createDataStreamCommandAction(cmd *cobra.Command, args []string) error {
6462
qs := getInitialSurveyQuestionsForVersion(sv)
6563

6664
var answers newDataStreamAnswers
67-
err = survey.Ask(qs, &answers)
65+
err = tui.Ask(qs, &answers)
6866
if err != nil {
6967
return fmt.Errorf("prompt failed: %w", err)
7068
}
7169

7270
if answers.Type == "metrics" {
73-
qs := []*survey.Question{
71+
qs := []*tui.Question{
7472
{
75-
Name: "syntheticAndTimeSeries",
76-
Prompt: &survey.Confirm{
77-
Message: "Enable time series and synthetic source?",
78-
Default: true,
79-
},
80-
Validate: survey.Required,
73+
Name: "syntheticAndTimeSeries",
74+
Prompt: tui.NewConfirm("Enable time series and synthetic source?", true),
75+
Validate: tui.Required,
8176
},
8277
}
83-
err = survey.Ask(qs, &answers)
78+
err = tui.Ask(qs, &answers)
8479
if err != nil {
8580
return fmt.Errorf("prompt failed: %w", err)
8681
}
8782

8883
if !answers.SyntheticAndTimeSeries {
89-
qs := []*survey.Question{
84+
qs := []*tui.Question{
9085
{
91-
Name: "synthetic",
92-
Prompt: &survey.Confirm{
93-
Message: "Enable synthetic source?",
94-
Default: true,
95-
},
96-
Validate: survey.Required,
86+
Name: "synthetic",
87+
Prompt: tui.NewConfirm("Enable synthetic source?", true),
88+
Validate: tui.Required,
9789
},
9890
}
99-
err = survey.Ask(qs, &answers)
91+
err = tui.Ask(qs, &answers)
10092
if err != nil {
10193
return fmt.Errorf("prompt failed: %w", err)
10294
}
@@ -124,24 +116,23 @@ func createDataStreamCommandAction(cmd *cobra.Command, args []string) error {
124116
"udp": "UDP",
125117
"winlog": "WinLogBeat",
126118
}
127-
qs := []*survey.Question{
119+
multiSelect := tui.NewMultiSelect("Select input types which will be used in this data stream. See https://www.elastic.co/docs/reference/fleet/elastic-agent-inputs-list for description of the inputs", slices.Sorted(maps.Keys(inputsMap)), []string{})
120+
multiSelect.SetPageSize(50)
121+
multiSelect.SetDescription(func(value string, index int) string {
122+
val, ok := inputsMap[value]
123+
if ok {
124+
return val
125+
}
126+
return ""
127+
})
128+
129+
qs := []*tui.Question{
128130
{
129-
Name: "inputs",
130-
Prompt: &survey.MultiSelect{
131-
Message: "Select input types which will be used in this data stream. See https://www.elastic.co/docs/reference/fleet/elastic-agent-inputs-list for description of the inputs",
132-
Options: slices.Sorted(maps.Keys(inputsMap)),
133-
PageSize: 50,
134-
Description: func(value string, index int) string {
135-
val, ok := inputsMap[value]
136-
if ok {
137-
return val
138-
}
139-
return ""
140-
},
141-
},
131+
Name: "inputs",
132+
Prompt: multiSelect,
142133
},
143134
}
144-
err = survey.Ask(qs, &answers)
135+
err = tui.Ask(qs, &answers)
145136
if err != nil {
146137
return fmt.Errorf("prompt failed: %w", err)
147138
}
@@ -206,44 +197,31 @@ func createDataStreamDescriptorFromAnswers(answers newDataStreamAnswers, package
206197
}
207198
}
208199

209-
func getInitialSurveyQuestionsForVersion(specVersion *semver.Version) []*survey.Question {
210-
validator := surveyext.Validator{Cwd: "."}
211-
qs := []*survey.Question{
200+
func getInitialSurveyQuestionsForVersion(specVersion *semver.Version) []*tui.Question {
201+
validator := tui.Validator{Cwd: "."}
202+
qs := []*tui.Question{
212203
{
213-
Name: "name",
214-
Prompt: &survey.Input{
215-
Message: "Data stream name:",
216-
Default: "new_data_stream",
217-
},
218-
Validate: survey.ComposeValidators(survey.Required, validator.DataStreamDoesNotExist, validator.DataStreamName),
204+
Name: "name",
205+
Prompt: tui.NewInput("Data stream name", "new_data_stream"),
206+
Validate: tui.ComposeValidators(tui.Required, validator.DataStreamDoesNotExist, validator.DataStreamName),
219207
},
220208
{
221-
Name: "title",
222-
Prompt: &survey.Input{
223-
Message: "Data stream title:",
224-
Default: "New Data Stream",
225-
},
226-
Validate: survey.Required,
209+
Name: "title",
210+
Prompt: tui.NewInput("Data stream title", "New Data Stream"),
211+
Validate: tui.Required,
227212
},
228213
{
229-
Name: "type",
230-
Prompt: &survey.Select{
231-
Message: "Type:",
232-
Options: []string{"logs", "metrics"},
233-
Default: "logs",
234-
},
235-
Validate: survey.Required,
214+
Name: "type",
215+
Prompt: tui.NewSelect("Type", []string{"logs", "metrics"}, "logs"),
216+
Validate: tui.Required,
236217
},
237218
}
238219

239220
if !specVersion.LessThan(semver3_2_0) {
240-
qs = append(qs, &survey.Question{
241-
Name: "subobjects",
242-
Prompt: &survey.Confirm{
243-
Message: "Enable creation of subobjects for fields with dots in their names?",
244-
Default: false,
245-
},
246-
Validate: survey.Required,
221+
qs = append(qs, &tui.Question{
222+
Name: "subobjects",
223+
Prompt: tui.NewConfirm("Enable creation of subobjects for fields with dots in their names?", false),
224+
Validate: tui.Required,
247225
})
248226
}
249227

cmd/create_data_stream_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ package cmd
77
import (
88
"testing"
99

10-
"github.com/AlecAivazis/survey/v2"
1110
"github.com/Masterminds/semver/v3"
1211
"github.com/stretchr/testify/assert"
1312
"github.com/stretchr/testify/require"
13+
14+
"github.com/elastic/elastic-package/internal/tui"
1415
)
1516

1617
func TestGetSurveyQuestionsForVersion_BelowSemver3_2_0(t *testing.T) {
@@ -20,11 +21,11 @@ func TestGetSurveyQuestionsForVersion_BelowSemver3_2_0(t *testing.T) {
2021
require.Len(t, questions, 3, "should return 3 questions for spec version < 3.2.0")
2122

2223
assert.Equal(t, "name", questions[0].Name)
23-
assert.IsType(t, &survey.Input{}, questions[0].Prompt)
24+
assert.IsType(t, &tui.Input{}, questions[0].Prompt)
2425
assert.Equal(t, "title", questions[1].Name)
25-
assert.IsType(t, &survey.Input{}, questions[1].Prompt)
26+
assert.IsType(t, &tui.Input{}, questions[1].Prompt)
2627
assert.Equal(t, "type", questions[2].Name)
27-
assert.IsType(t, &survey.Select{}, questions[2].Prompt)
28+
assert.IsType(t, &tui.Select{}, questions[2].Prompt)
2829
}
2930

3031
func TestGetSurveyQuestionsForVersion_EqualSemver3_2_0(t *testing.T) {
@@ -34,7 +35,7 @@ func TestGetSurveyQuestionsForVersion_EqualSemver3_2_0(t *testing.T) {
3435
require.Len(t, questions, 4, "should return 4 questions for spec version >= 3.2.0")
3536

3637
assert.Equal(t, "subobjects", questions[3].Name)
37-
assert.IsType(t, &survey.Confirm{}, questions[3].Prompt)
38+
assert.IsType(t, &tui.Confirm{}, questions[3].Prompt)
3839
}
3940

4041
func TestGetSurveyQuestionsForVersion_AboveSemver3_2_0(t *testing.T) {
@@ -44,7 +45,7 @@ func TestGetSurveyQuestionsForVersion_AboveSemver3_2_0(t *testing.T) {
4445
require.Len(t, questions, 4, "should return 4 questions for spec version > 3.2.0")
4546

4647
assert.Equal(t, "subobjects", questions[3].Name)
47-
assert.IsType(t, &survey.Confirm{}, questions[3].Prompt)
48+
assert.IsType(t, &tui.Confirm{}, questions[3].Prompt)
4849
}
4950

5051
func TestCreateDataStreamDescriptorFromAnswers_SubobjectsFalseForSpecVersionBelow3_2_0(t *testing.T) {

0 commit comments

Comments
 (0)