From: christiangoeschel <cndjomouo@icloud.com> Date: Thu, 3 Oct 2024 19:03:46 +0000 (-0400) Subject: Added 'checkapi' command to shell X-Git-Url: https://git.christiangoeschel.com/?a=commitdiff_plain;h=ea9ebd848acf23d326df9cd154138966a35c7076;p=repoman-cli.git Added 'checkapi' command to shell --- diff --git a/main b/main index 2cb362b..22fcefb 100755 Binary files a/main and b/main differ diff --git a/screens/shell.go b/screens/shell.go new file mode 100644 index 0000000..f3da40b --- /dev/null +++ b/screens/shell.go @@ -0,0 +1,259 @@ +package screens + +// A simple program demonstrating the text area component from the Bubbles +// component library. + +import ( + "fmt" + "strings" + "os" + "github.com/repoman-cli/ui" + "github.com/repoman-cli/api" + "github.com/charmbracelet/bubbles/textarea" + "github.com/charmbracelet/bubbles/viewport" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" +) + + +type ( + errMsg error +) + +type cmdReturn struct { + ReturnCode int + Terminated bool +} + +type CmdExecMsg cmdReturn + +type RepomanShellModel struct { + APIStatus api.APIStatusMsg + viewport viewport.Model + messages []string + textarea textarea.Model + senderStyle lipgloss.Style + err error + Width int + Height int + topBar string + footer string + CmdExecStatus CmdExecMsg +} + +func NewShellScreenModel() RepomanShellModel { + // Get terminal size + w, h, err := ui.GetWindowSize() + if err != nil { + fmt.Printf("Could not get terminal window size.") + os.Exit(1) + } + + // Top bar styling + roundLabelCorner := ui.RoundLabelCornerStyle.Render("î¶") + labelArrow := ui.LabelArrowStyle.Render("î°") + titleBlock := ui.TitleStyle.Render(" Repoman CLI ") + rightTopBarBlock := ui.TopBarRightLabel.Render(" Repoman Shell ") + + topBarBlock := ui.TopBarStyle.Render(lipgloss.JoinHorizontal(lipgloss.Center, + ui.TopBarLeftStyle.Width((w / 2 ) - 1).Render(roundLabelCorner + titleBlock + labelArrow), + ui.TopBarRightStyle.Width((w / 2 ) - 1).Render(rightTopBarBlock))) + + topBarBlockHeight := lipgloss.Height(topBarBlock) + + // Footer styling + copyrightBlock := ui.SubtleStyle.Render("2024 Copyright - Repoman") + + helpBlock := fmt.Sprintf("%s\n%s\n%s", + ui.SubtleStyle.Render("Ctrl+C, Esc - Exit program"), + ui.SubtleStyle.Render("Ctrl+D - Main menu"), + ui.SubtleStyle.Render("Ctrl+L - Clear Screen")) + + footerBlock := ui.FooterStyle.Render(lipgloss.JoinHorizontal(lipgloss.Center, + ui.FooterLeftStyle.Width((w / 2 ) - 1).Render(copyrightBlock), + ui.FooterRightStyle.Width((w / 2 ) - 1).Render(helpBlock))) + + footerBlockHeight := lipgloss.Height(footerBlock) + + + ta := textarea.New() + ta.Placeholder = "Type in a command or enter 'help' if you are lost" + ta.Focus() + + ta.Prompt = "â repoman $ ⯠" + ta.CharLimit = 280 + + ta.SetWidth(w - 2) + ta.SetHeight(1) + + // Remove cursor line styling + ta.FocusedStyle.CursorLine = lipgloss.NewStyle() + + ta.ShowLineNumbers = false + + var initialViewportMsg []string + initialViewportMsg = append(initialViewportMsg, ui.SubtleStyle.Render(fmt.Sprintf("No, you can't run any scripts here\nThis is not Bash, Zshhh or any type of fish ó°º\nHowever, you can manage your self-hosted git repos from here, isn't that even better ?! ( ^ . ^ )"))) + + vp := viewport.New(w - 2, h - topBarBlockHeight - footerBlockHeight - 1) + vp.SetContent(strings.Join(initialViewportMsg, "\n")) + + ta.KeyMap.InsertNewline.SetEnabled(false) + + return RepomanShellModel{ + APIStatus: api.APIStatusMsg{}, + textarea: ta, + messages: initialViewportMsg, + viewport: vp, + senderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("5")), + err: nil, + Width: w, + Height: h, + topBar: topBarBlock, + footer: footerBlock, + CmdExecStatus: CmdExecMsg{ Terminated: true }, + } +} + +func (m *RepomanShellModel) Init() tea.Cmd { + return textarea.Blink +} + +func (m *RepomanShellModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + var ( + tiCmd tea.Cmd + vpCmd tea.Cmd + ) + + m.textarea, tiCmd = m.textarea.Update(msg) + m.viewport, vpCmd = m.viewport.Update(msg) + + switch msg := msg.(type) { + case tea.KeyMsg: + switch msg.Type { + case tea.KeyCtrlC, tea.KeyEsc: + fmt.Println(m.textarea.Value()) + return m, tea.Quit + + case tea.KeyCtrlD: + mainMenu := MainMenu() + return RootScreen().SwitchScreen(&mainMenu) + + case tea.KeyEnter: + if m.CmdExecStatus.Terminated { + m, cmd := parseCmd(m, m.textarea.Value()) + return m, tea.Batch(cmd, ExecNotify(0, false)) + } + + case tea.KeyCtrlL: + m.messages = []string{} + m.viewport.SetContent("$ ⯠") + } + + // We handle errors just like any other message + case errMsg: + m.err = msg + return m, nil + + case tea.WindowSizeMsg: + w, h, _ := ui.GetWindowSize() + m.Width = w + m.Height = h + m.textarea.SetWidth(w - 2) + m.viewport = viewport.New(w - 2, h - lipgloss.Height(m.topBar) - lipgloss.Height(m.footer) - 1) + m.viewport.SetContent(strings.Join(m.messages, "\n")) + + case api.APIStatusMsg: + m.APIStatus = msg + cmdResult := fmt.Sprintf("%s\n%s", m.senderStyle.Render("$ ⯠") + m.textarea.Value(), m.APIStatus ) + m.messages = append(m.messages, cmdResult) + m.viewport.SetContent(strings.Join(m.messages, "\n")) + m.textarea.Reset() + //m.CmdExecStatus.Terminated = true + return m, ExecNotify(0, true) + + case CmdExecMsg: + m.CmdExecStatus.Terminated = msg.Terminated + } + + return m, tea.Batch(tiCmd, vpCmd) +} + +func (m *RepomanShellModel) View() string { + + // Top bar styling + roundLabelCorner := ui.RoundLabelCornerStyle.Render("î¶") + labelArrow := ui.LabelArrowStyle.Render("î°") + titleBlock := ui.TitleStyle.Render(" Repoman CLI ") + rightTopBarBlock := ui.TopBarRightLabel.Render(" Repoman Shell ") + + topBarBlock := ui.TopBarStyle.Render(lipgloss.JoinHorizontal(lipgloss.Center, + ui.TopBarLeftStyle.Width((m.Width / 2 ) - 1).Render(roundLabelCorner + titleBlock + labelArrow), + ui.TopBarRightStyle.Width((m.Width / 2 ) - 1).Render(rightTopBarBlock))) + + m.topBar = topBarBlock + +// Footer styling + copyrightBlock := ui.SubtleStyle.Render("2024 Copyright - Repoman") + + helpBlock := fmt.Sprintf("%s\n%s\n%s", + ui.SubtleStyle.Render("Ctrl+C, Esc - Exit program"), + ui.SubtleStyle.Render("Ctrl+D - Main menu"), + ui.SubtleStyle.Render("Ctrl+L - Clear Screen")) + + footerBlock := ui.FooterStyle.Render(lipgloss.JoinHorizontal(lipgloss.Center, + ui.FooterLeftStyle.Width((m.Width / 2 ) - 1).Render(copyrightBlock), + ui.FooterRightStyle.Width((m.Width / 2 ) - 1).Render(helpBlock))) + + m.footer = footerBlock + + + return lipgloss.PlaceHorizontal(m.Width, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Left, m.topBar, m.viewport.View(), m.textarea.View(), m.footer )) +} + + +func parseCmd(m *RepomanShellModel, cmd string) (tea.Model, tea.Cmd){ + var cmdReturn string + + if cmd != "" { + switch cmd { + case "help", "?": + cmdReturn = "Well I can't help you neither buddy" + m.messages = append(m.messages, m.senderStyle.Render(fmt.Sprintf("$ ⯠%s\n%s", m.textarea.Value(), cmdReturn))) + + case "checkapi": + return m, api.HandleAPIStatusRequest(api.StatusUrl) + + case "menu", "quit": + mainMenuModel := MainMenu() + return RootScreen().SwitchScreen(&mainMenuModel) + + case "clear": + m.messages = []string{} + m.viewport.SetContent("$ ⯠") + + case "exit": + return m, tea.Quit + + default: + m.messages = append(m.messages, m.senderStyle.Render("$ ⯠Unknown command: " + m.textarea.Value())) + + } + } else { + m.messages = append(m.messages, m.senderStyle.Render("$ ⯠")) + } + + m.viewport.SetContent(strings.Join(m.messages, "\n")) + m.textarea.Reset() + m.viewport.GotoBottom() + + return m, ExecNotify(0, true) +} + +func ExecNotify(returnCode int, terminated bool ) tea.Cmd { + cmdReturn := CmdExecMsg{ ReturnCode: returnCode, + Terminated: terminated, } + return func() tea.Msg { + return cmdReturn + } + } + diff --git a/screens/viewport.go b/screens/viewport.go deleted file mode 100644 index a3f337e..0000000 --- a/screens/viewport.go +++ /dev/null @@ -1,176 +0,0 @@ -package screens - -// A simple program demonstrating the text area component from the Bubbles -// component library. - -import ( - "fmt" - "strings" - "os" - "github.com/repoman-cli/ui" - "github.com/charmbracelet/bubbles/textarea" - "github.com/charmbracelet/bubbles/viewport" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - - -type ( - errMsg error -) - -type RepomanShellModel struct { - viewport viewport.Model - messages []string - textarea textarea.Model - senderStyle lipgloss.Style - err error - Width int - Height int - topBar string -} - -func NewShellScreenModel() RepomanShellModel { - // Get terminal size - w, h, err := ui.GetWindowSize() - if err != nil { - fmt.Printf("Could not get terminal window size.") - os.Exit(1) - } - - // Top bar styling - roundLabelCorner := ui.RoundLabelCornerStyle.Render("î¶") - labelArrow := ui.LabelArrowStyle.Render("î°") - titleBlock := ui.TitleStyle.Render(" Repoman CLI ") - rightTopBarBlock := ui.TopBarRightLabel.Render(" Repoman Shell ") - - topBarBlock := ui.TopBarStyle.Render(lipgloss.JoinHorizontal(lipgloss.Center, - ui.TopBarLeftStyle.Width((w / 2 ) - 1).Render(roundLabelCorner + titleBlock + labelArrow), - ui.TopBarRightStyle.Width((w / 2 ) - 1).Render(rightTopBarBlock))) - - topBarBlockHeight := lipgloss.Height(topBarBlock) - - ta := textarea.New() - ta.Placeholder = "Type in a command or enter 'help' if you are lost" - ta.Focus() - - ta.Prompt = "â repoman $ ⯠" - ta.CharLimit = 280 - - ta.SetWidth(w) - ta.SetHeight(1) - - // Remove cursor line styling - ta.FocusedStyle.CursorLine = lipgloss.NewStyle() - - ta.ShowLineNumbers = false - - vp := viewport.New(w, h - topBarBlockHeight - 1) - vp.SetContent(ui.SubtleStyle.Render(`This is not Bash, Zshhh or some type of fish ó°º`)) - - ta.KeyMap.InsertNewline.SetEnabled(false) - - return RepomanShellModel{ - textarea: ta, - messages: []string{}, - viewport: vp, - senderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("5")), - err: nil, - Width: w, - Height: h, - topBar: topBarBlock, - } -} - -func (m *RepomanShellModel) Init() tea.Cmd { - return textarea.Blink -} - -func (m *RepomanShellModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - var ( - tiCmd tea.Cmd - vpCmd tea.Cmd - ) - - m.textarea, tiCmd = m.textarea.Update(msg) - m.viewport, vpCmd = m.viewport.Update(msg) - - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.Type { - case tea.KeyCtrlC, tea.KeyEsc: - fmt.Println(m.textarea.Value()) - return m, tea.Quit - - case tea.KeyEnter: - m, cmd := parseCmd(m, m.textarea.Value()) - return m, cmd - case tea.KeyCtrlL: - m.messages = []string{} - m.viewport.SetContent("$ ⯠") - } - - // We handle errors just like any other message - case errMsg: - m.err = msg - return m, nil - - case tea.WindowSizeMsg: - w, h, _ := ui.GetWindowSize() - m.Width = w - m.Height = h - m.textarea.SetWidth(w) - m.viewport = viewport.New(w, h - lipgloss.Height(m.topBar) - 1) - m.viewport.SetContent(strings.Join(m.messages, "\n")) - } - - return m, tea.Batch(tiCmd, vpCmd) -} - -func (m *RepomanShellModel) View() string { - - // Top bar styling - roundLabelCorner := ui.RoundLabelCornerStyle.Render("î¶") - labelArrow := ui.LabelArrowStyle.Render("î°") - titleBlock := ui.TitleStyle.Render(" Repoman CLI ") - rightTopBarBlock := ui.TopBarRightLabel.Render(" Repoman Shell ") - - topBarBlock := ui.TopBarStyle.Render(lipgloss.JoinHorizontal(lipgloss.Center, - ui.TopBarLeftStyle.Width((m.Width / 2 ) - 1).Render(roundLabelCorner + titleBlock + labelArrow), - ui.TopBarRightStyle.Width((m.Width / 2 ) - 1).Render(rightTopBarBlock))) - - m.topBar = topBarBlock - - return lipgloss.PlaceHorizontal(m.Width, lipgloss.Center, lipgloss.JoinVertical(lipgloss.Left, m.topBar, m.viewport.View(), m.textarea.View())) -} - - -func parseCmd(m *RepomanShellModel, cmd string) (tea.Model, tea.Cmd){ - var cmdReturn string - if cmd != "" { - switch cmd { - case "help", "?": - cmdReturn = "Well I can't help you neither buddy" - m.messages = append(m.messages, m.senderStyle.Render(fmt.Sprintf("$ ⯠%s\n%s", m.textarea.Value(), cmdReturn))) - - case "menu", "quit": - mainMenuModel := MainMenu() - return RootScreen().SwitchScreen(&mainMenuModel) - - case "exit": - return m, tea.Quit - - default: - m.messages = append(m.messages, m.senderStyle.Render("$ ⯠Unknown command: " + m.textarea.Value())) - - } - } else { - m.messages = append(m.messages, m.senderStyle.Render("$ ⯠")) - } - - m.viewport.SetContent(strings.Join(m.messages, "\n")) - m.textarea.Reset() - m.viewport.GotoBottom() - - return m, nil -}