diff --git a/main.go b/main.go old mode 100755 new mode 100644 diff --git a/utils/tui/model.go b/utils/tui/model.go index 00333af..319ce76 100644 --- a/utils/tui/model.go +++ b/utils/tui/model.go @@ -13,7 +13,7 @@ import ( // Model represents the main application model type Model struct { // State variables - State string // Current state: "FileSelection", "ModeSelection", "ActionSelection", "LabelInput", "ApplyChanges", "Error" + State string // Current state: "FileSelection", "ModeSelection", "ActionSelection", "LabelInput", "ApplyChanges", "Error", "Final" Files []string Actions []string Labels []string @@ -28,6 +28,11 @@ type Model struct { LabelInput modelutils.LabelInput } +// applyChangesMsg represents a message indicating that changes have been applied. +type applyChangesMsg struct { + err error +} + // Init initializes the model func (m Model) Init() tea.Cmd { return m.FilesSelector.Init() @@ -40,6 +45,20 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Quit } + switch msg := msg.(type) { + case applyChangesMsg: + if msg.err != nil { + m.Error = msg.err + } + m.State = "Final" + return m, nil + + case tea.KeyMsg: + if m.State == "Final" { + return m, tea.Quit + } + } + switch m.State { case "FileSelection": newFilesSelector, cmd := m.FilesSelector.Update(msg) @@ -61,6 +80,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.Files = m.FilesSelector.FilesPath if len(m.Files) == 0 { m.State = "ApplyChanges" + return m, m.applyChanges() } else { m.State = "ActionSelection" m.ActionSelector = modelutils.NewModeSelector([]string{"toggle", "comment", "uncomment"}, filepath.Base(m.Files[0]), m.SpeedSelector.Selected) @@ -113,6 +133,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.LabelType = append(m.LabelType, m.LabelInput.IsLabel) if len(m.Labels) == len(m.Files) { m.State = "ApplyChanges" + return m, m.applyChanges() } else { m.LabelInput = modelutils.NewLabelInput(filepath.Base(m.Files[counter])) counter++ @@ -128,27 +149,23 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.Labels = append(m.Labels, m.LabelInput.Input) } m.State = "ApplyChanges" + return m, m.applyChanges() } return m, cmd } case "ApplyChanges": - err := m.applyChanges() - m.Error = err - m.State = "Final" - case "Final": - - return m, tea.Quit // Quit the program after applying changes + return m, m.applyChanges() + case "Final": + return m, nil } + return m, nil } // View renders the view based on the current state func (m Model) View() string { - if m.Error != nil { - return fmt.Sprintf("An error occurred: %v", m.Error) - } switch m.State { case "FileSelection": return m.FilesSelector.View() @@ -158,41 +175,50 @@ func (m Model) View() string { return m.ActionSelector.View() case "LabelInput": return m.LabelInput.View() + case "ApplyChanges": + return "Applying changes..." + case "Final": + if m.Error != nil { + return modelutils.Paint("red").Render(fmt.Sprintf("An error occurred: %v\nPress any key to exit.", m.Error)) + } + return "Changes applied successfully!\nPress any key to exit." } return "" } // applyChanges applies changes to selected files based on user inputs -func (m *Model) applyChanges() error { - for i := 0; i < len(m.Files); i++ { - currentFilePath, err := AbsToRel(m.Files[i]) - if err != nil { - return fmt.Errorf("failed to convert to relative path: %w", err) - } - if !m.LabelType[i] { - conf := modfile.Config{ - Filename: currentFilePath, - LineNum: m.Labels[i], - Action: m.Actions[i], +func (m *Model) applyChanges() tea.Cmd { + return func() tea.Msg { + for i := 0; i < len(m.Files); i++ { + currentFilePath, err := AbsToRel(m.Files[i]) + if err != nil { + return applyChangesMsg{err: fmt.Errorf("failed to convert to relative path: %w", err)} } - err = modfile.ChangeFile(conf) - } else { - parts := strings.Split(m.Labels[i], ";") - conf := modfile.Config{ - Filename: currentFilePath, - StartLabel: parts[0], - EndLabel: parts[1], - Action: m.Actions[i], + if !m.LabelType[i] { + conf := modfile.Config{ + Filename: currentFilePath, + LineNum: m.Labels[i], + Action: m.Actions[i], + } + err = modfile.ChangeFile(conf) + } else { + parts := strings.Split(m.Labels[i], ";") + conf := modfile.Config{ + Filename: currentFilePath, + StartLabel: parts[0], + EndLabel: parts[1], + Action: m.Actions[i], + } + err = modfile.ChangeFile(conf) } - err = modfile.ChangeFile(conf) - } - if err != nil { - return fmt.Errorf("failed to apply changes to file %s: %w", m.Files[i], err) + if err != nil { + return applyChangesMsg{err: fmt.Errorf("failed to apply changes to file %s: %w", m.Files[i], err)} + } } - } - return nil + return applyChangesMsg{err: nil} + } } // Helper function to convert absolute path to relative path diff --git a/utils/tui/modelutils/file.go b/utils/tui/modelutils/file.go index 00a7858..c756f2a 100644 --- a/utils/tui/modelutils/file.go +++ b/utils/tui/modelutils/file.go @@ -111,13 +111,13 @@ func (m FilesSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m FilesSelector) View() string { if m.Error != nil { - return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) + return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) } - s := paint("silver").Render("\n Select the files you want to modify...") + "\n" - s += paint("silver").Render("\n Selected files till now:") + "\n" + s := Paint("silver").Render("\n Select the files you want to modify...") + "\n" + s += Paint("silver").Render("\n Selected files till now:") + "\n" for i := 0; i < len(m.FilesPath); i++ { - s += fmt.Sprintf(" %s\n", paint("green").Render(m.FilesPath[i])) + s += fmt.Sprintf(" %s\n", Paint("green").Render(m.FilesPath[i])) } s += "\n" @@ -126,28 +126,28 @@ func (m FilesSelector) View() string { checkDir, err := IsDirectory(choice) if err != nil { m.Error = fmt.Errorf("error checking directory: %w", err) - return paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) + return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) } if checkDir { - choice = paint("blue").Render("❒ " + choice) + choice = Paint("blue").Render("❒ " + choice) } else if Contains(m.FilesPath, choice) { - choice = paint("lime").Render("❒ " + choice) + choice = Paint("lime").Render("❒ " + choice) } else { - choice = paint("silver").Render("❒ " + choice) + choice = Paint("silver").Render("❒ " + choice) } cursor := " " if m.cursor == i { - cursor = paint("red").Render(" ➪") + cursor = Paint("red").Render(" ➪") } s += fmt.Sprintf("%s %s\n", cursor, choice) } - s += paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") + s += Paint("silver").Render("\n 'q' to quit 'esc' to move to parent directory\n '↑' to go up 'x' to modify selected files\n '↓' to go down 'enter' to select pointed file/move to pointed sub folder") return s } -func paint(color string) lipgloss.Style { +func Paint(color string) lipgloss.Style { switch color { case "lime": lime := lipgloss.Color("#00FF00") diff --git a/utils/tui/modelutils/option.go b/utils/tui/modelutils/option.go index 2076c52..eebef66 100644 --- a/utils/tui/modelutils/option.go +++ b/utils/tui/modelutils/option.go @@ -51,7 +51,7 @@ func (m ModeSelector) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m ModeSelector) View() string { if len(m.Choices) == 2 { - s := paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" + s := Paint("silver").Render("Select 'Fast mode' if you want to toggle all your files by giving just indications about start label and end label.\nSelect 'Slow mode' if you want to specify what action to perform file by file.") + "\n" for i, choice := range m.Choices { cursor := " " if m.cursor == i { @@ -65,7 +65,7 @@ func (m ModeSelector) View() string { switch m.Speed { case "Slow mode": - s += paint("silver").Render("Select action for file: "+m.File) + "\n\n" + s += Paint("silver").Render("Select action for file: "+m.File) + "\n\n" for i, choice := range m.Choices { cursor := " " if m.cursor == i { @@ -75,7 +75,7 @@ func (m ModeSelector) View() string { } case "Fast mode": - s += paint("silver").Render("Select action:") + "\n\n" + s += Paint("silver").Render("Select action:") + "\n\n" for i, choice := range m.Choices { cursor := " " if m.cursor == i { @@ -84,7 +84,7 @@ func (m ModeSelector) View() string { s += cursor + " " + choice + "\n" } } - return s + paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") + return s + Paint("silver").Render("\n 'q' to quit 'enter' to modify selected files\n '↑' to go up\n '↓' to go down") } } diff --git a/utils/tui/modelutils/text.go b/utils/tui/modelutils/text.go index 7673745..7c39d26 100644 --- a/utils/tui/modelutils/text.go +++ b/utils/tui/modelutils/text.go @@ -60,23 +60,26 @@ func (m LabelInput) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m LabelInput) View() string { + if m.Error != nil { + return Paint("red").Render(fmt.Sprintf("An error occurred: %v", m.Error)) + } flash := "" if m.flash { - flash = paint("green").Render("▎") + flash = Paint("green").Render("▎") } - s := paint("silver").Render("Type below the section to modify. You can insert your start label\nand your end label using the syntax 'start';'end' or you can modify\n a single line by entering the line number or a range of lines using the syntax x-y") + "\n\n" + s := Paint("silver").Render("Type below the section to modify. You can insert your start label\nand your end label using the syntax 'start';'end' or you can modify\n a single line by entering the line number or a range of lines using the syntax x-y") + "\n\n" if m.File != "" { - s += paint("green").Render(m.File+": ✏ "+m.Input) + flash + "\n" + s += Paint("green").Render(m.File+": ✏ "+m.Input) + flash + "\n" } else { - s += paint("green").Render("✏ "+m.Input) + flash + "\n" + s += Paint("green").Render("✏ "+m.Input) + flash + "\n" } if m.Error != nil { - s += paint("red").Render("\nError: "+m.Error.Error()) + "\n" + s += Paint("red").Render("\nError: "+m.Error.Error()) + "\n" } - s += paint("silver").Render("\n 'q' to quit 'enter' to select the lines/labels indicated\n '↑' to go up\n '↓' to go down") + s += Paint("silver").Render("\n 'q' to quit 'enter' to select the lines/labels indicated\n '↑' to go up\n '↓' to go down") return s }