mirror of
https://github.com/Slug-Boi/cocommit.git
synced 2026-05-13 12:45:47 +00:00
feat: add groups and start refactor of tree model for tui elements
This commit is contained in:
+65
-10
@@ -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)
|
||||||
|
|||||||
@@ -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
@@ -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, " "))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user