Checkpoint commit
Have got a basic table select model working. Now will try to setup modal models to support prompts and confirmations
This commit is contained in:
parent
33115c7c13
commit
6ac22aad1f
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: 1.17
|
go-version: 1.18
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
git config --global url."https://${{ secrets.GO_MODULES_TOKEN }}:x-oauth-basic@github.com/lmika".insteadOf "https://github.com/lmika"
|
git config --global url."https://${{ secrets.GO_MODULES_TOKEN }}:x-oauth-basic@github.com/lmika".insteadOf "https://github.com/lmika"
|
||||||
|
|
|
@ -4,8 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/config"
|
"github.com/aws/aws-sdk-go-v2/config"
|
||||||
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
@ -17,6 +15,8 @@ import (
|
||||||
"github.com/lmika/awstools/internal/dynamo-browse/services/tables"
|
"github.com/lmika/awstools/internal/dynamo-browse/services/tables"
|
||||||
"github.com/lmika/awstools/internal/dynamo-browse/ui"
|
"github.com/lmika/awstools/internal/dynamo-browse/ui"
|
||||||
"github.com/lmika/gopkgs/cli"
|
"github.com/lmika/gopkgs/cli"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -58,6 +58,18 @@ func main() {
|
||||||
p := tea.NewProgram(uiModel, tea.WithAltScreen())
|
p := tea.NewProgram(uiModel, tea.WithAltScreen())
|
||||||
loopback.program = p
|
loopback.program = p
|
||||||
|
|
||||||
|
// TEMP -- profiling
|
||||||
|
//cf, err := os.Create("trace.out")
|
||||||
|
//if err != nil {
|
||||||
|
// log.Fatal("could not create CPU profile: ", err)
|
||||||
|
//}
|
||||||
|
//defer cf.Close() // error handling omitted for example
|
||||||
|
//if err := trace.Start(cf); err != nil {
|
||||||
|
// log.Fatal("could not start CPU profile: ", err)
|
||||||
|
//}
|
||||||
|
//defer trace.Stop()
|
||||||
|
// END TEMP
|
||||||
|
|
||||||
f, err := tea.LogToFile("debug.log", "debug")
|
f, err := tea.LogToFile("debug.log", "debug")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("fatal:", err)
|
fmt.Println("fatal:", err)
|
||||||
|
@ -65,6 +77,7 @@ func main() {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
log.Println("launching")
|
||||||
if err := p.Start(); err != nil {
|
if err := p.Start(); err != nil {
|
||||||
fmt.Printf("Alas, there's been an error: %v", err)
|
fmt.Printf("Alas, there's been an error: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
6
docker-compose.yml
Normal file
6
docker-compose.yml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
dynamo:
|
||||||
|
image: amazon/dynamodb-local:latest
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
13
go.mod
13
go.mod
|
@ -1,27 +1,30 @@
|
||||||
module github.com/lmika/awstools
|
module github.com/lmika/awstools
|
||||||
|
|
||||||
go 1.17
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/alecthomas/participle/v2 v2.0.0-alpha7
|
||||||
|
github.com/asdine/storm v2.1.2+incompatible
|
||||||
github.com/aws/aws-sdk-go-v2 v1.15.0
|
github.com/aws/aws-sdk-go-v2 v1.15.0
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.13.1
|
github.com/aws/aws-sdk-go-v2/config v1.13.1
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.8.0
|
github.com/aws/aws-sdk-go-v2/credentials v1.8.0
|
||||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.8.0
|
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.8.0
|
||||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.15.0
|
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.15.0
|
||||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.16.0
|
github.com/aws/aws-sdk-go-v2/service/sqs v1.16.0
|
||||||
|
github.com/brianvoe/gofakeit/v6 v6.15.0
|
||||||
github.com/calyptia/go-bubble-table v0.1.0
|
github.com/calyptia/go-bubble-table v0.1.0
|
||||||
github.com/charmbracelet/bubbles v0.10.3
|
github.com/charmbracelet/bubbles v0.10.3
|
||||||
github.com/charmbracelet/bubbletea v0.20.0
|
github.com/charmbracelet/bubbletea v0.20.0
|
||||||
github.com/charmbracelet/lipgloss v0.5.0
|
github.com/charmbracelet/lipgloss v0.5.0
|
||||||
|
github.com/google/uuid v1.3.0
|
||||||
github.com/lmika/events v0.0.0-20200906102219-a2269cd4394e
|
github.com/lmika/events v0.0.0-20200906102219-a2269cd4394e
|
||||||
github.com/lmika/gopkgs v0.0.0-20211210041137-0dc91e939890
|
github.com/lmika/gopkgs v0.0.0-20211210041137-0dc91e939890
|
||||||
|
github.com/lmika/shellwords v0.0.0-20140714114018-ce258dd729fe
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/stretchr/testify v1.7.1
|
github.com/stretchr/testify v1.7.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/participle/v2 v2.0.0-alpha7 // indirect
|
|
||||||
github.com/asdine/storm v2.1.2+incompatible // indirect
|
|
||||||
github.com/atotto/clipboard v0.1.4 // indirect
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0 // indirect
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.6 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.6 // indirect
|
||||||
|
@ -34,13 +37,10 @@ require (
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.9.0 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sso v1.9.0 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 // indirect
|
github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 // indirect
|
||||||
github.com/aws/smithy-go v1.11.1 // indirect
|
github.com/aws/smithy-go v1.11.1 // indirect
|
||||||
github.com/brianvoe/gofakeit/v6 v6.15.0 // indirect
|
|
||||||
github.com/containerd/console v1.0.3 // indirect
|
github.com/containerd/console v1.0.3 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
|
||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc // indirect
|
github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc // indirect
|
||||||
github.com/lmika/shellwords v0.0.0-20140714114018-ce258dd729fe // indirect
|
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
|
@ -50,6 +50,7 @@ require (
|
||||||
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect
|
github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/sahilm/fuzzy v0.1.0 // indirect
|
||||||
go.etcd.io/bbolt v1.3.6 // indirect
|
go.etcd.io/bbolt v1.3.6 // indirect
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
|
|
1
go.sum
1
go.sum
|
@ -116,6 +116,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
|
||||||
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
|
|
@ -34,10 +34,12 @@ type uiModel struct {
|
||||||
table table.Model
|
table table.Model
|
||||||
viewport viewport.Model
|
viewport viewport.Model
|
||||||
|
|
||||||
|
// TEMP
|
||||||
|
tableSelect tea.Model
|
||||||
|
|
||||||
tableWidth, tableHeight int
|
tableWidth, tableHeight int
|
||||||
|
|
||||||
ready bool
|
ready bool
|
||||||
//resultSet *models.ResultSet
|
|
||||||
state controllers.State
|
state controllers.State
|
||||||
message string
|
message string
|
||||||
|
|
||||||
|
@ -62,6 +64,11 @@ func NewModel(dispatcher *dispatcher.Dispatcher, commandController *commandctrl.
|
||||||
message: "Press s to scan",
|
message: "Press s to scan",
|
||||||
textInput: textInput,
|
textInput: textInput,
|
||||||
|
|
||||||
|
// TEMP
|
||||||
|
tableSelect: newSizeWaitModel(func(w, h int) tea.Model {
|
||||||
|
return newTableSelectModel(w, h)
|
||||||
|
}),
|
||||||
|
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
commandController: commandController,
|
commandController: commandController,
|
||||||
tableReadController: tableReadController,
|
tableReadController: tableReadController,
|
||||||
|
@ -72,7 +79,7 @@ func NewModel(dispatcher *dispatcher.Dispatcher, commandController *commandctrl.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m uiModel) Init() tea.Cmd {
|
func (m uiModel) Init() tea.Cmd {
|
||||||
m.invokeOperation(context.Background(), m.tableReadController.Scan())
|
//m.invokeOperation(context.Background(), m.tableReadController.Scan())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,11 +222,13 @@ func (m uiModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
|
||||||
updatedTable, tableMsgs := m.table.Update(msg)
|
updatedTable, tableMsgs := m.table.Update(msg)
|
||||||
updatedViewport, viewportMsgs := m.viewport.Update(msg)
|
updatedViewport, viewportMsgs := m.viewport.Update(msg)
|
||||||
|
updatedTableSelectModel, tableSelectMsgs := m.tableSelect.Update(msg)
|
||||||
|
|
||||||
m.table = updatedTable
|
m.table = updatedTable
|
||||||
m.viewport = updatedViewport
|
m.viewport = updatedViewport
|
||||||
|
m.tableSelect = updatedTableSelectModel
|
||||||
|
|
||||||
return m, tea.Batch(textInputCommands, tableMsgs, viewportMsgs)
|
return m, tea.Batch(textInputCommands, tableMsgs, viewportMsgs, tableSelectMsgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m uiModel) invokeOperation(ctx context.Context, op uimodels.Operation) {
|
func (m uiModel) invokeOperation(ctx context.Context, op uimodels.Operation) {
|
||||||
|
@ -233,6 +242,10 @@ func (m uiModel) invokeOperation(ctx context.Context, op uimodels.Operation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m uiModel) View() string {
|
func (m uiModel) View() string {
|
||||||
|
// TEMP
|
||||||
|
return m.tableSelect.View()
|
||||||
|
|
||||||
|
/*
|
||||||
if !m.ready {
|
if !m.ready {
|
||||||
return "Initializing"
|
return "Initializing"
|
||||||
}
|
}
|
||||||
|
@ -254,6 +267,7 @@ func (m uiModel) View() string {
|
||||||
m.viewport.View(),
|
m.viewport.View(),
|
||||||
m.footerView(),
|
m.footerView(),
|
||||||
)
|
)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m uiModel) headerView() string {
|
func (m uiModel) headerView() string {
|
||||||
|
|
48
internal/dynamo-browse/ui/sizewaitmodel.go
Normal file
48
internal/dynamo-browse/ui/sizewaitmodel.go
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// sizeWaitModel is a model which waits until the first screen size message comes through. It then creates the
|
||||||
|
// submodel and delegates calls to that model
|
||||||
|
type sizeWaitModel struct {
|
||||||
|
constr func(width, height int) tea.Model
|
||||||
|
model tea.Model
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSizeWaitModel(constr func(width, height int) tea.Model) tea.Model {
|
||||||
|
return sizeWaitModel{constr: constr}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sizeWaitModel) Init() tea.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sizeWaitModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch m := msg.(type) {
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
log.Println("got window size message")
|
||||||
|
if s.model == nil {
|
||||||
|
log.Println("creating model")
|
||||||
|
s.model = s.constr(m.Width, m.Height)
|
||||||
|
s.model.Init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var submodelCmds tea.Cmd
|
||||||
|
if s.model != nil {
|
||||||
|
log.Println("starting update")
|
||||||
|
s.model, submodelCmds = s.model.Update(msg)
|
||||||
|
log.Println("ending update")
|
||||||
|
}
|
||||||
|
return s, submodelCmds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s sizeWaitModel) View() string {
|
||||||
|
if s.model == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return s.model.View()
|
||||||
|
}
|
95
internal/dynamo-browse/ui/tableselectmodel.go
Normal file
95
internal/dynamo-browse/ui/tableselectmodel.go
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
titleStyle = lipgloss.NewStyle().MarginLeft(2)
|
||||||
|
itemStyle = lipgloss.NewStyle().PaddingLeft(4)
|
||||||
|
selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170"))
|
||||||
|
paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4)
|
||||||
|
helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1)
|
||||||
|
quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4)
|
||||||
|
)
|
||||||
|
|
||||||
|
type tableSelectModel struct {
|
||||||
|
list list.Model
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t tableSelectModel) Init() tea.Cmd {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t tableSelectModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
t.list.SetHeight(msg.Height)
|
||||||
|
t.list.SetWidth(msg.Width)
|
||||||
|
return t, nil
|
||||||
|
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch keypress := msg.String(); keypress {
|
||||||
|
case "ctrl+c":
|
||||||
|
return t, tea.Quit
|
||||||
|
|
||||||
|
case "enter":
|
||||||
|
//i, ok := m.list.SelectedItem().(item)
|
||||||
|
//if ok {
|
||||||
|
// m.choice = string(i)
|
||||||
|
//}
|
||||||
|
return t, tea.Quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cmd tea.Cmd
|
||||||
|
t.list, cmd = t.list.Update(msg)
|
||||||
|
return t, cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t tableSelectModel) View() string {
|
||||||
|
return t.list.View()
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTableSelectModel(w, h int) tableSelectModel {
|
||||||
|
tableItems := []tableItem{
|
||||||
|
{name: "alpha"},
|
||||||
|
{name: "beta"},
|
||||||
|
{name: "gamma"},
|
||||||
|
}
|
||||||
|
|
||||||
|
items := toListItems(tableItems)
|
||||||
|
|
||||||
|
delegate := list.NewDefaultDelegate()
|
||||||
|
delegate.ShowDescription = false
|
||||||
|
|
||||||
|
return tableSelectModel{
|
||||||
|
list: list.New(items, delegate, w, h),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type tableItem struct {
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ti tableItem) FilterValue() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ti tableItem) Title() string {
|
||||||
|
return ti.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ti tableItem) Description() string {
|
||||||
|
return "abc"
|
||||||
|
}
|
||||||
|
|
||||||
|
func toListItems[T list.Item](xs []T) []list.Item {
|
||||||
|
ls := make([]list.Item, len(xs))
|
||||||
|
for i, x := range xs {
|
||||||
|
ls[i] = x
|
||||||
|
}
|
||||||
|
return ls
|
||||||
|
}
|
Loading…
Reference in a new issue