feat: add groups and start refactor of tree model for tui elements

This commit is contained in:
Slug-Boi
2024-11-08 16:19:02 +01:00
parent 49692669b8
commit 56cf60e071
4 changed files with 246 additions and 19 deletions
+65 -10
View File
@@ -37,7 +37,11 @@ type model_ca struct {
exclude bool exclude bool
} }
func createAuthorModel() model_ca { var parent_m *model
func createAuthorModel(old_m *model) model_ca {
parent_m = old_m
m := model_ca{ m := model_ca{
inputs: make([]textinput.Model, 5), inputs: make([]textinput.Model, 5),
} }
@@ -100,11 +104,13 @@ func tempAuthorModel() model_ca {
} }
func initialModel(model string) model_ca { func initialModel(model string) model_ca {
if model == "author" { // if model == "author" {
return createAuthorModel() // return createAuthorModel()
} else { // } else {
return tempAuthorModel() // return tempAuthorModel()
} // }
return tempAuthorModel()
} }
@@ -118,18 +124,18 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.String() { switch msg.String() {
case "ctrl+c", "esc": case "ctrl+c", "esc":
m.inputs = nil m.inputs = nil
return m, tea.Quit return nil, nil
// Set focus to next input // Set focus to next input
case "tab", "shift+tab", "enter", "up", "down": case "tab", "shift+tab", "enter", "up", "down":
s := msg.String() s := msg.String()
// Did the user press enter while the submit button was focused? // Did the user press enter while the submit button was focused?
// If so, exit. // If so, exit.
if !removeButton { if !removeButton {
if s == "enter" && m.focusIndex == len(m.inputs)+1 { if s == "enter" && m.focusIndex == len(m.inputs)+1 {
m.quitting = true m.quitting = true
return m, tea.Quit m.AddAuthor()
return model{list: parent_m.list}, tea.ClearScreen
} else if s == "enter" && m.focusIndex == len(m.inputs) { } else if s == "enter" && m.focusIndex == len(m.inputs) {
// toggle exclude // toggle exclude
m.exclude = !m.exclude m.exclude = !m.exclude
@@ -138,7 +144,7 @@ func (m model_ca) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} else { } else {
if s == "enter" && m.focusIndex == len(m.inputs) { if s == "enter" && m.focusIndex == len(m.inputs) {
m.quitting = true m.quitting = true
return m, tea.Quit return nil, nil
} }
} }
@@ -238,6 +244,53 @@ func (m model_ca) View() string {
return b.String() return b.String()
} }
func (m *model_ca) AddAuthor() {
if len(m.inputs) > 0 &&
m.inputs[0].Value() != "" &&
m.inputs[1].Value() != "" &&
m.inputs[2].Value() != "" &&
m.inputs[3].Value() != "" {
author_file := utils.Find_authorfile()
f, err := os.OpenFile(author_file, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
panic(err)
}
defer f.Close()
sb := strings.Builder{}
sb.WriteRune('\n')
sb.WriteString(fmt.Sprintf("%s|%s|%s|%s",
m.inputs[0].Value(),
m.inputs[1].Value(),
m.inputs[2].Value(),
m.inputs[3].Value()))
if m.exclude {
sb.WriteString(fmt.Sprintf("|%s", "ex"))
}
if m.inputs[4].Value() != "" {
sb.WriteString(fmt.Sprintf(";;%s", m.inputs[4].Value()))
}
//sb.WriteRune('\n')
if _, err = f.WriteString(sb.String()); err != nil {
panic(err)
}
utils.Define_users(utils.Find_authorfile())
author := m.inputs[0].Value()
item_str := utils.Users[author].Username + " - " + utils.Users[author].Email
dupProtect[item_str] = author
parent_m.list.InsertItem(len(parent_m.list.Items())+1, item(item_str))
}
}
func Entry_CA() string { func Entry_CA() string {
m, err := tea.NewProgram(initialModel("author")).Run() m, err := tea.NewProgram(initialModel("author")).Run()
if err != nil { if err != nil {
@@ -287,6 +340,8 @@ func Entry_CA() string {
} }
func Entry_TA() string { func Entry_TA() string {
//old_m = old_m
m, err := tea.NewProgram(initialModel("temp")).Run() m, err := tea.NewProgram(initialModel("temp")).Run()
if err != nil { if err != nil {
fmt.Printf("could not start program: %s\n", err) fmt.Printf("could not start program: %s\n", err)
+148
View File
@@ -0,0 +1,148 @@
package tui
import (
"log"
"slices"
"strings"
"github.com/Slug-Boi/cocommit/src/cmd/utils"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
)
// sessionState is used to track which model is focused
var (
modelStyle = lipgloss.NewStyle().
Width(20).
Height(8).
Align(lipgloss.Center, lipgloss.Center).
BorderStyle(lipgloss.NormalBorder()).
BorderForeground(lipgloss.Color("241"))
focusedModelStyle = lipgloss.NewStyle().
Width(20).
Height(8).
Align(lipgloss.Center, lipgloss.Center).
BorderStyle(lipgloss.DoubleBorder()).
BorderForeground(lipgloss.Color("170"))
)
type mainModel struct {
content []string
index int
}
func newModel() mainModel {
groups := utils.Groups
content := []string{}
for name, users := range groups {
newUser := strings.Builder{}
newUser.WriteString(name + ":\n")
for _, user := range users {
newUser.WriteString(user.Username + "\n")
}
content = append(content, newUser.String())
}
slices.Sort(content)
m := mainModel{content: content}
return m
}
func (m mainModel) Init() tea.Cmd {
// start the timer and spinner on program start
return nil
}
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
//var cmd tea.Cmd
var cmds []tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q", "esc":
m.content = nil
return nil, nil
case "enter":
var group string
if m.currentFocusedModel() != "" {
group = strings.Split(m.currentFocusedModel(), ":")[0]
}
if group != "" {
for _, sel := range selected {
delete(selected, string(sel))
}
users := utils.Groups[group]
for k, v := range dupProtect {
if _, ok := selected[k]; !ok {
for _, user := range users {
if strings.Contains(user.Names, v) {
selected[k] = item(k)
}
}
}
}
}
return nil, nil
case "tab", "right":
m.Next()
case "left":
if m.index == 0 {
m.index = len(m.content) - 1
} else {
m.index--
}
}
}
return m, tea.Batch(cmds...)
}
func (m mainModel) View() string {
var s string
var squares []string
for i, c := range m.content {
// uses joinhorizontal to create a grid of squares
if i == m.index {
squares = append(squares, focusedModelStyle.Render(c))
} else {
squares = append(squares, modelStyle.Render(c))
}
}
s += lipgloss.JoinHorizontal(lipgloss.Top, squares...)
s += helpStyle.Render("\ntab/right: focus next • left: focus previous • enter: select group • q/esq: exit\n")
return s
}
func (m mainModel) currentFocusedModel() string {
if m.index < len(m.content) {
return m.content[m.index]
}
return ""
}
func (m *mainModel) Next() {
if m.index == len(m.content)-1 {
m.index = 0
} else {
m.index++
}
}
func Entry_GR() string {
p := tea.NewProgram(newModel())
m, err := p.Run()
if err != nil {
log.Fatal(err)
}
if m.(mainModel).currentFocusedModel() != "" {
// returns the group name
return strings.Split(m.(mainModel).currentFocusedModel(), ":")[0]
}
return ""
}
+31 -7
View File
@@ -37,6 +37,8 @@ var negation = false
var dupProtect = map[string]string{} var dupProtect = map[string]string{}
var sub_model tea.Model
type listKeyMap struct { type listKeyMap struct {
selectAll key.Binding selectAll key.Binding
negation key.Binding negation key.Binding
@@ -147,6 +149,17 @@ func toggleNegation() {
var deletion bool var deletion bool
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if sub_model != nil {
var cmd tea.Cmd
sub_model, cmd = sub_model.Update(msg)
if sub_model_mod, ok := sub_model.(model); ok {
m.list = sub_model_mod.list
sub_model = nil
return m, nil
}
return m, cmd
}
switch msg := msg.(type) { switch msg := msg.(type) {
case tea.WindowSizeMsg: case tea.WindowSizeMsg:
m.list.SetWidth(msg.Width) m.list.SetWidth(msg.Width)
@@ -183,7 +196,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
case key.Matches(msg, m.keys.groupSelect): case key.Matches(msg, m.keys.groupSelect):
// group code goes here // TODO: Look into how to select multiple groups
sub_model = newModel()
//group := Entry_GR()
return m, tea.ClearScreen
case key.Matches(msg, m.keys.tempAdd): case key.Matches(msg, m.keys.tempAdd):
screen.Clear() screen.Clear()
@@ -202,12 +218,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case key.Matches(msg, m.keys.createAuthor): case key.Matches(msg, m.keys.createAuthor):
screen.Clear() screen.Clear()
screen.MoveTopLeft() screen.MoveTopLeft()
author := Entry_CA() sub_model = createAuthorModel(&m)
if author != "" {
item_str := utils.Users[author].Username + " - " + utils.Users[author].Email
dupProtect[item_str] = author
m.list.InsertItem(len(m.list.Items())+1, item(item_str))
}
return m, tea.ClearScreen return m, tea.ClearScreen
case key.Matches(msg, m.keys.deleteAuthor): case key.Matches(msg, m.keys.deleteAuthor):
if deletion { if deletion {
@@ -224,11 +235,21 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
// extra key options // extra key options
switch keypress := msg.String(); keypress { switch keypress := msg.String(); keypress {
case "q", "ctrl+c", "esc": case "q", "ctrl+c", "esc":
if sub_model != nil {
var cmd tea.Cmd
sub_model, cmd = sub_model.Update(msg)
return m, cmd
}
m.quitting = true m.quitting = true
selected = nil selected = nil
return m, tea.Quit return m, tea.Quit
case "enter": case "enter":
if sub_model != nil {
var cmd tea.Cmd
sub_model, cmd = sub_model.Update(msg)
return m, cmd
}
m.quitting = true m.quitting = true
return m, tea.Quit return m, tea.Quit
} }
@@ -241,6 +262,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
} }
func (m model) View() string { func (m model) View() string {
if sub_model != nil {
return sub_model.View()
}
if m.quitting { if m.quitting {
return "" //quitTextStyle.Render(strings.Join(m.choice, " ")) return "" //quitTextStyle.Render(strings.Join(m.choice, " "))
} }
+2 -2
View File
@@ -57,7 +57,8 @@ func Define_users(author_file string) {
if info[4] == "ex" { if info[4] == "ex" {
DefExclude = append(DefExclude, info[2]) DefExclude = append(DefExclude, info[2])
} }
} else if len(group_info) > 0 { }
if len(group_info) > 0 {
// Group assignment // Group assignment
for _, group := range group_info { for _, group := range group_info {
if Groups[group] == nil { if Groups[group] == nil {
@@ -89,4 +90,3 @@ func TempAddUser(username, email string) {
Users[username] = usr Users[username] = usr
} }