diff --git a/cmd/main.go b/cmd/main.go index 5ac904a..fe47dc4 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -10,9 +10,9 @@ import ( "github.com/sirupsen/logrus" flag "github.com/spf13/pflag" - "github.com/idlephysicist/cave-logger/internal/register" "github.com/idlephysicist/cave-logger/internal/gui" "github.com/idlephysicist/cave-logger/internal/model" + "github.com/idlephysicist/cave-logger/internal/register" ) var version, date string @@ -46,7 +46,6 @@ func main() { } log.SetLevel(level) - // Read config file cfg := func(_file string) *model.Config { var _cfg model.Config diff --git a/internal/gui/cud.go b/internal/gui/cud.go index e1736a7..0811c74 100644 --- a/internal/gui/cud.go +++ b/internal/gui/cud.go @@ -2,8 +2,8 @@ package gui import ( "fmt" - "time" "strings" + "time" tview "gitlab.com/tslocum/cview" ) @@ -35,10 +35,51 @@ func (g *Gui) createTripForm() { return }) + // Caver Field + caverField := tview.NewInputField(). + SetLabel("Names"). + SetFieldWidth(inputWidth) + caverField.SetAutocompleteFunc(func(current string) (matches []string) { + if len(current) == 0 { + return []string{``} + } + + names := strings.Split(current, `,`) + + // Process preceeding names + for _, n := range names { + n = strings.TrimSpace(n) + } + + var lastPart string + if len(names) == 0 { // Then we're still on the first name + lastPart = current + } else { + lastPart = names[len(names)-1] // To get the last name + } + + lastPart = strings.TrimPrefix(lastPart, ` `) // We should still trim whitespace + + if len(lastPart) == 0 { + return []string{``} + } + + for _, caver := range g.state.resources.people { + if strings.HasPrefix(strings.ToLower(caver.Name), strings.ToLower(lastPart)) { + matches = append( + matches, + fmt.Sprintf("%s%s", textFactory(names[0:len(names)-1], `, `), caver.Name), + ) + } + } + + return + }) + form. AddInputField("Date", time.Now().Format(`2006-01-02`), inputWidth, nil, nil). AddFormItem(caveField). - AddInputField("Names", "", inputWidth, nil, nil). + AddFormItem(caverField). AddInputField("Notes", "", inputWidth, nil, nil). AddButton("Add", func() { g.createTrip(form) @@ -47,7 +88,8 @@ func (g *Gui) createTripForm() { g.closeAndSwitchPanel("form", "trips") }) - g.pages.AddAndSwitchToPage("form", g.modal(form, 80, 29), true) + g.pages.AddAndSwitchToPage("form", g.modal(form, 80, 29), true) //.ShowPage("main") + //REVIEW: main or trips ? ^^ } func (g *Gui) createTrip(form *tview.Form) { @@ -58,7 +100,7 @@ func (g *Gui) createTrip(form *tview.Form) { form.GetFormItemByLabel("Notes").(*tview.InputField).GetText(), ) if err != nil { // NOTE: Needs fixing - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } @@ -129,7 +171,7 @@ func (g *Gui) createLocation(form *tview.Form) { form.GetFormItemByLabel("SRT").(*tview.CheckBox).IsChecked(), ) if err != nil { // NOTE: Needs fixing - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } @@ -181,7 +223,7 @@ func (g *Gui) createPerson(form *tview.Form) { form.GetFormItemByLabel("Notes").(*tview.InputField).GetText(), ) if err != nil { // NOTE: Needs fixing - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } @@ -216,18 +258,60 @@ func (g *Gui) modifyTripForm() { } } - if len(matches) <= 1 || matches[0] == current { + if len(matches) <= 1 || matches[0] == current { matches = nil } return }) + // Caver Field + caverField := tview.NewInputField(). + SetLabel("Names"). + SetFieldWidth(inputWidth). + SetText(selectedTrip.Names) + caverField.SetAutocompleteFunc(func(current string) (matches []string) { + if len(current) == 0 { + return []string{``} + } + + names := strings.Split(current, `,`) + + // Process preceeding names + for _, n := range names { + n = strings.TrimSpace(n) + } + + var lastPart string + if len(names) == 0 { // Then we're still on the first name + lastPart = current + } else { + lastPart = names[len(names)-1] // To get the last name + } + + lastPart = strings.TrimPrefix(lastPart, ` `) // We should still trim whitespace + + if len(lastPart) == 0 { + return []string{``} + } + + for _, caver := range g.state.resources.people { + if strings.HasPrefix(strings.ToLower(caver.Name), strings.ToLower(lastPart)) { + matches = append( + matches, + fmt.Sprintf("%s%s", textFactory(names[0:len(names)-1], `, `), caver.Name), + ) + } + } + + return + }) + form. AddInputField("Date", selectedTrip.Date, inputWidth, nil, nil). AddFormItem(caveField). - AddInputField("Names", selectedTrip.Names, inputWidth, nil, nil). - AddInputField("Notes", selectedTrip.Notes, inputWidth, nil, nil). + AddFormItem(caverField). + AddInputField("Notes", selectedTrip.Notes, inputWidth, nil, nil). AddButton("Apply", func() { g.modifyTrip(selectedTrip.ID, form) }). @@ -247,7 +331,7 @@ func (g *Gui) modifyTrip(id string, form *tview.Form) { form.GetFormItemByLabel("Notes").(*tview.InputField).GetText(), ) if err != nil { - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } @@ -255,7 +339,6 @@ func (g *Gui) modifyTrip(id string, form *tview.Form) { g.tripsPanel().updateEntries(g) } - func (g *Gui) modifyPersonForm() { // First - what trip is selected? selectedPerson := g.selectedPerson() @@ -287,7 +370,7 @@ func (g *Gui) modifyPersonForm() { form. AddInputField("Name", selectedPerson.Name, inputWidth, nil, nil). AddFormItem(clubField). - AddInputField("Notes", selectedPerson.Notes, inputWidth, nil, nil). + AddInputField("Notes", selectedPerson.Notes, inputWidth, nil, nil). AddButton("Apply", func() { g.modifyPerson(selectedPerson.ID, form) }). @@ -306,7 +389,7 @@ func (g *Gui) modifyPerson(id string, form *tview.Form) { form.GetFormItemByLabel("Notes").(*tview.InputField).GetText(), ) if err != nil { - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } @@ -314,7 +397,6 @@ func (g *Gui) modifyPerson(id string, form *tview.Form) { g.caversPanel().updateEntries(g) } - func (g *Gui) modifyLocationForm() { // First - what trip is selected? selectedLocation := g.selectedLocation() @@ -359,13 +441,12 @@ func (g *Gui) modifyLocationForm() { return }) - form. AddInputField("Name", selectedLocation.Name, inputWidth, nil, nil). AddFormItem(regionField). AddFormItem(countryField). AddCheckBox("SRT", "", selectedLocation.SRT, nil). - AddInputField("Notes", selectedLocation.Notes, inputWidth, nil, nil). + AddInputField("Notes", selectedLocation.Notes, inputWidth, nil, nil). AddButton("Apply", func() { g.modifyLocation(selectedLocation.ID, form) }). @@ -386,7 +467,7 @@ func (g *Gui) modifyLocation(id string, form *tview.Form) { form.GetFormItemByLabel("SRT").(*tview.CheckBox).IsChecked(), ) if err != nil { - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } @@ -394,7 +475,6 @@ func (g *Gui) modifyLocation(id string, form *tview.Form) { g.cavesPanel().updateEntries(g) } - // // DELETE FUNCS func (g *Gui) deleteTrip() { @@ -407,7 +487,7 @@ func (g *Gui) deleteTrip() { g.warning(message, `trips`, []string{`Yes`, `No`}, func() { if err := g.reg.RemoveTrip(selectedTrip.ID); err != nil { - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } g.tripsPanel().updateEntries(g) @@ -424,7 +504,7 @@ func (g *Gui) deleteLocation() { g.warning(message, `locations`, []string{`Yes`, `No`}, func() { if err := g.reg.RemoveCave(selectedLocation.ID); err != nil { - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } g.cavesPanel().updateEntries(g) @@ -441,9 +521,26 @@ func (g *Gui) deletePerson() { g.warning(message, `people`, []string{`Yes`, `No`}, func() { if err := g.reg.RemoveCaver(selectedPerson.ID); err != nil { - g.warning(err.Error(), `form`, []string{`OK`}, func() {return}) + g.warning(err.Error(), `form`, []string{`OK`}, func() { return }) return } g.caversPanel().updateEntries(g) }) } + +func textFactory(sl []string, sep string) string { + s := `` + numEl := len(sl) + if numEl == 0 { + return s + } + + for i, el := range sl { + el = strings.TrimSpace(el) + s += el + if i < numEl { + s += sep + } + } + return s +} diff --git a/internal/gui/gui.go b/internal/gui/gui.go index 39f0bb6..25d5a92 100644 --- a/internal/gui/gui.go +++ b/internal/gui/gui.go @@ -5,11 +5,11 @@ import ( "strconv" "strings" - tview "gitlab.com/tslocum/cview" "github.com/gdamore/tcell/v2" + tview "gitlab.com/tslocum/cview" - "github.com/idlephysicist/cave-logger/internal/register" "github.com/idlephysicist/cave-logger/internal/model" + "github.com/idlephysicist/cave-logger/internal/register" ) type panels struct { @@ -18,9 +18,9 @@ type panels struct { } type resources struct { - trips []*model.Log - people []*model.Caver - locations []*model.Cave + trips []*model.Log + people []*model.Caver + locations []*model.Cave //statsLocations []*model.Statistic } @@ -39,19 +39,19 @@ func newState() *state { } type Gui struct { - app *tview.Application - pages *tview.Pages - state *state - reg *register.Register + app *tview.Application + pages *tview.Pages + state *state + reg *register.Register //statsLocations *statsLocations } func New(reg *register.Register) *Gui { return &Gui{ - app: tview.NewApplication(), + app: tview.NewApplication(), pages: tview.NewPages(), state: newState(), - reg: reg, + reg: reg, } } @@ -143,17 +143,16 @@ func (g *Gui) caversPanel() *cavers { } */ - func (g *Gui) initPanels() { g.state.tabBar = newTabBar(g) // Page definitions - trips := newTrips(g) + trips := newTrips(g) cavers := newCavers(g) - caves := newCaves(g) + caves := newCaves(g) - /* + /* // NOTE: I would really like to get this working as it would be far neater. // The issue is with the three pages being of different types. // cannot use pg (type panel) as type tview.Primitive in argument to g.pages.AddPage: @@ -252,7 +251,6 @@ func (g *Gui) warning(message, page string, labels []string, doneFunc func()) { g.pages.AddAndSwitchToPage("modal", g.modal(modal, 80, 29), true) } - // // Functions for returning the selected item in the table // REVIEW: There might be better ways of doing this. @@ -291,4 +289,3 @@ func (g *Gui) selectedPerson() *model.Caver { return g.state.resources.people[row-1] } - diff --git a/internal/gui/navigate.go b/internal/gui/navigate.go index 94143f8..b7a04d8 100644 --- a/internal/gui/navigate.go +++ b/internal/gui/navigate.go @@ -11,8 +11,8 @@ func newNavigate() *navigate { navi := &navigate{ TextView: tview.NewTextView().SetTextColor(tview.Styles.PrimaryTextColor), keybindings: map[string]string{ - "trips" : " n: New Trip, m: Modify Trip, d: Remove Trip, /: Filter, Enter: Inspect Detail ", - "caves" : " n: New Cave, m: Modify Cave, d: Remove Cave, /: Filter, Enter: Inspect Detail ", + "trips": " n: New Trip, m: Modify Trip, d: Remove Trip, /: Filter, Enter: Inspect Detail ", + "caves": " n: New Cave, m: Modify Cave, d: Remove Cave, /: Filter, Enter: Inspect Detail ", "cavers": " n: New Caver, m: Modify Caver, d: Remove Caver, /: Filter, Enter: Inspect Detail ", "detail": " q | ESC: Exit Detail ", }, diff --git a/internal/gui/tabbar.go b/internal/gui/tabbar.go index b89983f..33a0da1 100644 --- a/internal/gui/tabbar.go +++ b/internal/gui/tabbar.go @@ -8,8 +8,5 @@ func newTabBar(g *Gui) *tview.TextView { return tview.NewTextView(). SetDynamicColors(true). SetRegions(true). - SetWrap(false)/*. - SetHighlightedFunc(func(added, removed, remaining []string) { - g.pages.SwitchToPage(added[0]) - })*/ + SetWrap(false) } diff --git a/internal/model/config.go b/internal/model/config.go index 980b225..7b2e2c8 100644 --- a/internal/model/config.go +++ b/internal/model/config.go @@ -2,9 +2,8 @@ package model type Config struct { Database struct { - Created string `json:"created"` + Created string `json:"created"` Filename string `json:"filename"` } `json:"database"` Colors map[string]string `json:"colors"` } - diff --git a/internal/register/helper.go b/internal/register/helper.go index 7c6a548..3f23e3e 100644 --- a/internal/register/helper.go +++ b/internal/register/helper.go @@ -6,7 +6,6 @@ import ( "time" ) - // For retrieving the ID of a cave from the `locations` table. func (reg *Register) getCaveID(cave string) (int, error) { result, err := reg.db.Query(`SELECT id FROM locations WHERE name == ?`, cave) @@ -29,8 +28,7 @@ func (reg *Register) getCaveID(cave string) (int, error) { return caveID, err } - -// For formatting the ids for a new +// For formatting the ids for a new func (reg *Register) getCaverIDs(names string) ([]string, error) { var caverIDs []string @@ -58,7 +56,7 @@ func (reg *Register) getCaverIDs(names string) ([]string, error) { // For processing dates into UNIX timestamps func unixTimestamp(date string) (int64, error) { - d, err := time.Parse(datetime, strings.Join([]string{date,`12:00:00Z`},`T`)) + d, err := time.Parse(datetime, strings.Join([]string{date, `12:00:00Z`}, `T`)) if err != nil { return -1, err }