diff --git a/app/app.go b/app/app.go index 31e8c13..94096c6 100644 --- a/app/app.go +++ b/app/app.go @@ -261,7 +261,9 @@ func (a *App) GetResponse(call *Call) tea.Cmd { if err == nil { defer response.Body.Close() body, err := io.ReadAll(response.Body) - return OnResponseMsg{Call: call, Body: string(body), Err: err, Response: response} + // get response size in bytes + bytes := int64(len(body)) + return OnResponseMsg{Call: call, Body: string(body), Bytes: bytes, Err: err, Response: response} } return OnResponseMsg{Call: call, Err: err, Response: response} }) diff --git a/app/message.go b/app/message.go index c4b60be..a40ab95 100644 --- a/app/message.go +++ b/app/message.go @@ -15,6 +15,7 @@ type CallUpdatedMsg struct{ Call *Call } type OnResponseMsg struct { Call *Call Body string + Bytes int64 Err error Response *http.Response } diff --git a/cmds.go b/cmds.go index e4bd799..548c60e 100644 --- a/cmds.go +++ b/cmds.go @@ -7,10 +7,10 @@ import ( "os" "restman/app" "restman/components/collections" + "restman/components/config" "restman/components/footer" "restman/components/request" "restman/components/results" - "restman/components/tabs" "restman/components/url" tea "github.com/charmbracelet/bubbletea" @@ -47,6 +47,7 @@ Restman is a CLI tool for RESTful API.`, }, Run: func(cmd *cobra.Command, args []string) { + config.SetVersion(version) call := app.NewCall() if len(args) >= 1 { call.Url = args[0] @@ -93,34 +94,38 @@ Restman is a CLI tool for RESTful API.`, zone.NewGlobal() // layout-tree defintion - m := Model{tui: boxer.Boxer{}, focused: "url", initalCall: call} + m := Model{tui: boxer.Boxer{}, focused: "url", initialCall: call} url := url.New() resultsBox := results.New() requestBox := request.New() footerBox := footer.New() colBox := collections.New() - tabs := tabs.New() + + splitNode := boxer.CreateNoBorderNode() + splitNode.SizeFunc = func(node boxer.Node, widthOrHeight int) []int { + paramsSize := int(float64(widthOrHeight) * 0.4) + return []int{ + paramsSize, + widthOrHeight - paramsSize, + } + } + splitNode.Children = []boxer.Node{ + stripErr(m.tui.CreateLeaf("request", requestBox)), + stripErr(m.tui.CreateLeaf("results", resultsBox)), + } centerNode := boxer.CreateNoBorderNode() centerNode.VerticalStacked = true centerNode.SizeFunc = func(node boxer.Node, widthOrHeight int) []int { - size := widthOrHeight - 5 - paramsSize := int(float64(size) * 0.4) - resultsSize := size - paramsSize - return []int{ - 2, 3, - paramsSize, - resultsSize, + widthOrHeight - 3, } } centerNode.Children = []boxer.Node{ - stripErr(m.tui.CreateLeaf("tabs", tabs)), stripErr(m.tui.CreateLeaf("url", url)), - stripErr(m.tui.CreateLeaf("request", requestBox)), - stripErr(m.tui.CreateLeaf("results", resultsBox)), + splitNode, } // middle Node diff --git a/components/collections/calls.go b/components/collections/calls.go index 94f25e0..2973958 100644 --- a/components/collections/calls.go +++ b/components/collections/calls.go @@ -111,7 +111,7 @@ func (m callModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } switch msg.String() { - case "ctrl+h": + case "esc": return m, app.GetInstance().SetSelectedCollection(nil) case "enter": diff --git a/components/collections/collections.go b/components/collections/collections.go index e4fc013..cf612a7 100644 --- a/components/collections/collections.go +++ b/components/collections/collections.go @@ -18,6 +18,7 @@ var ( minified = lipgloss.NewStyle(). Border(lipgloss.NormalBorder()). BorderForeground(config.COLOR_SUBTLE). + Foreground(config.COLOR_FOREGROUND). PaddingLeft(1) focused = lipgloss.NewStyle(). @@ -124,7 +125,7 @@ func (m Collections) View() string { // if the collection is minified, render the minified version if m.minified { - return zone.Mark("collections_minified", style.Render("")) + return zone.Mark("collections_minified", style.Render(" \n\nC\nO\nL\nL\nE\nC\nT\nI\nO\nN\nS")) } if m.collection != nil { diff --git a/components/collections/list.go b/components/collections/list.go index fb2d464..38ebba0 100644 --- a/components/collections/list.go +++ b/components/collections/list.go @@ -21,6 +21,7 @@ var ( ) type listKeyMap struct { + esc key.Binding toggleSpinner key.Binding toggleTitleBar key.Binding toggleStatusBar key.Binding @@ -31,6 +32,9 @@ type listKeyMap struct { func newListKeyMap() *listKeyMap { return &listKeyMap{ + esc: key.NewBinding( + key.WithKeys("esc"), + ), insertItem: key.NewBinding( key.WithKeys("a"), key.WithHelp("a", "add item"), @@ -127,6 +131,9 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } switch { + case key.Matches(msg, m.keys.esc): + // do nothing + return m, nil case key.Matches(msg, m.keys.toggleSpinner): cmd := m.list.ToggleSpinner() return m, cmd diff --git a/components/config/config.go b/components/config/config.go index 24e8c31..7c1fa5e 100644 --- a/components/config/config.go +++ b/components/config/config.go @@ -5,6 +5,8 @@ import ( "github.com/charmbracelet/lipgloss" ) +var version = "dev" + var ( // App Colors COLOR_SUBTLE = lipgloss.AdaptiveColor{Light: "#D9DCCF", Dark: "#383838"} @@ -99,6 +101,14 @@ type KeyMap struct { ChangeToggle key.Binding } +func SetVersion(v string) { + version = v +} + +func GetVersion() string { + return version +} + func (k KeyMap) ShortHelp() []key.Binding { return []key.Binding{k.Help, k.Quit} } diff --git a/components/footer/footer.go b/components/footer/footer.go index 276e109..863c6fa 100644 --- a/components/footer/footer.go +++ b/components/footer/footer.go @@ -3,6 +3,7 @@ package footer import ( "restman/app" "restman/components/config" + "restman/utils" "strconv" "time" @@ -12,16 +13,18 @@ import ( ) var ( - container = lipgloss.NewStyle(). - BorderForeground(config.COLOR_SUBTLE). - Background(config.COLOR_SUBTLE). - Border(lipgloss.NormalBorder()). - BorderBottom(false). - BorderTop(false) - - stopwatchStyle = lipgloss.NewStyle(). - Background(config.COLOR_HIGHLIGHT). - Padding(0, 1) + container = lipgloss.NewStyle() + // BorderForeground(config.COLOR_SUBTLE). + // Background(config.COLOR_SUBTLE). + // Border(lipgloss.NormalBorder()). + // BorderBottom(false). + // BorderTop(false) + + versionStyle = lipgloss.NewStyle(). + Foreground(config.COLOR_HIGHLIGHT) + + nameStyle = lipgloss.NewStyle(). + Foreground(config.COLOR_HIGHLIGHT).Underline(true) ) // model represents the properties of the UI. @@ -30,6 +33,7 @@ type model struct { height int width int url string + bytes int64 loading bool statusCode int error error @@ -52,7 +56,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { case tea.WindowSizeMsg: m.height = msg.Height - m.width = msg.Width - 2 + m.width = msg.Width case app.OnLoadingMsg: m.error = nil @@ -64,6 +68,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if msg.Err == nil { m.statusCode = msg.Response.StatusCode } + m.bytes = msg.Bytes m.error = msg.Err m.loading = false return m, m.stopwatch.Stop() @@ -86,6 +91,10 @@ func (m model) View() string { color = "#EF4444" } else if m.statusCode > 0 { status = "󰞉 STATUS: " + strconv.Itoa(m.statusCode) + if m.bytes > 0 { + status = status + "  SIZE: " + utils.ByteCountIEC(m.bytes) + } + if m.statusCode >= 200 && m.statusCode < 300 { color = "#34D399" } else if m.statusCode >= 300 && m.statusCode < 400 { @@ -101,8 +110,8 @@ func (m model) View() string { } statusToRender := lipgloss.NewStyle(). - Background(lipgloss.Color(color)). - Foreground(config.COLOR_SUBTLE). + Foreground(lipgloss.Color(color)). + // Foreground(config.COLOR_SUBTLE). Padding(0, 1). Render(status) @@ -113,10 +122,11 @@ func (m model) View() string { lipgloss.Left, statusToRender, lipgloss.PlaceHorizontal( - m.width-statusWidth, + m.width-statusWidth-1, lipgloss.Right, - stopwatchStyle.Render(" "+m.stopwatch.View()), - lipgloss.WithWhitespaceBackground(config.COLOR_SUBTLE), + nameStyle.Render("Restman")+ + + versionStyle.Render(" v."+config.GetVersion()), ), ), ) diff --git a/components/request/box.go b/components/request/box.go index 3d6ca03..c58e2af 100644 --- a/components/request/box.go +++ b/components/request/box.go @@ -7,7 +7,6 @@ import ( "restman/components/config" "restman/components/headers" "restman/components/params" - "restman/components/tabs" "strings" tea "github.com/charmbracelet/bubbletea" @@ -29,9 +28,9 @@ var ( docStyle = lipgloss.NewStyle() highlightColor = lipgloss.AdaptiveColor{Light: "#874BFD", Dark: "#7D56F4"} inactiveTabStyle = lipgloss.NewStyle().Border(inactiveTabBorder, true).BorderForeground(highlightColor).Padding(0, 1) - activeTabStyle = inactiveTabStyle.Copy().Border(activeTabBorder, true) + activeTabStyle = inactiveTabStyle.Border(activeTabBorder, true) windowStyle = lipgloss.NewStyle().BorderForeground(highlightColor).Border(lipgloss.NormalBorder()).UnsetBorderTop() - tabGap = inactiveTabStyle.Copy(). + tabGap = inactiveTabStyle. BorderTop(false). BorderLeft(false). BorderRight(false) @@ -86,9 +85,10 @@ func (b Request) GetContent() tea.Model { func (b Request) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { - case tabs.TabFocusedMsg: - b.call = msg.Tab.Call - b.body = msg.Tab.Results + case app.CallSelectedMsg: + b.call = msg.Call + // TODO: + // b.body = msg.Tab.Results b.content = b.GetContent() case tea.WindowSizeMsg: @@ -134,24 +134,24 @@ func (b Request) View() string { var renderedTabs []string if b.focused { - inactiveTabStyle.BorderForeground(config.COLOR_HIGHLIGHT) - activeTabStyle.BorderForeground(config.COLOR_HIGHLIGHT) - windowStyle.BorderForeground(config.COLOR_HIGHLIGHT) - tabGap.BorderForeground(config.COLOR_HIGHLIGHT) + inactiveTabStyle = inactiveTabStyle.BorderForeground(config.COLOR_HIGHLIGHT) + activeTabStyle = activeTabStyle.BorderForeground(config.COLOR_HIGHLIGHT) + windowStyle = windowStyle.BorderForeground(config.COLOR_HIGHLIGHT) + tabGap = tabGap.BorderForeground(config.COLOR_HIGHLIGHT) } else { - inactiveTabStyle.BorderForeground(config.COLOR_SUBTLE) - activeTabStyle.BorderForeground(config.COLOR_SUBTLE) - windowStyle.BorderForeground(config.COLOR_SUBTLE) - tabGap.BorderForeground(config.COLOR_SUBTLE) + inactiveTabStyle = inactiveTabStyle.BorderForeground(config.COLOR_SUBTLE) + activeTabStyle = activeTabStyle.BorderForeground(config.COLOR_SUBTLE) + windowStyle = windowStyle.BorderForeground(config.COLOR_SUBTLE) + tabGap = tabGap.BorderForeground(config.COLOR_SUBTLE) } for i, t := range b.Tabs { var style lipgloss.Style isFirst, isActive := i == 0, i == b.activeTab if isActive { - style = activeTabStyle.Copy() + style = activeTabStyle } else { - style = inactiveTabStyle.Copy() + style = inactiveTabStyle } border, _, _, _, _ := style.GetBorder() if isFirst && isActive { diff --git a/components/results/box.go b/components/results/box.go index 1820c67..27ca45f 100644 --- a/components/results/box.go +++ b/components/results/box.go @@ -1,57 +1,24 @@ package results import ( + "encoding/json" "restman/app" "restman/components/config" - "restman/components/tabs" + "restman/utils" + "strconv" "strings" + "github.com/TylerBrock/colorjson" "github.com/charmbracelet/bubbles/viewport" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" - zone "github.com/lrstanley/bubblezone" ) -func tabBorderWithBottom(left, middle, right string) lipgloss.Border { - border := lipgloss.RoundedBorder() - border.BottomLeft = left - border.Bottom = middle - border.BottomRight = right - return border -} - var ( - inactiveTabBorder = tabBorderWithBottom("┴", "─", "┴") - activeTabBorder = tabBorderWithBottom("┘", " ", "└") - docStyle = lipgloss.NewStyle() - highlightColor = lipgloss.AdaptiveColor{Light: "#874BFD", Dark: "#7D56F4"} - inactiveTabStyle = lipgloss.NewStyle().Border(inactiveTabBorder, true).BorderForeground(highlightColor).Padding(0, 1) - activeTabStyle = inactiveTabStyle.Copy().Border(activeTabBorder, true) - windowStyle = lipgloss.NewStyle().BorderForeground(highlightColor).Border(lipgloss.NormalBorder()).UnsetBorderTop() - tabGap = inactiveTabStyle.Copy(). - BorderTop(false). - BorderLeft(false). - BorderRight(false) - - emptyMessage = lipgloss.NewStyle().Padding(2, 2).Foreground(config.COLOR_GRAY) - - testStyle = lipgloss.NewStyle(). - Bold(true). - Border(lipgloss.NormalBorder()). - BorderForeground(config.COLOR_SUBTLE). - PaddingLeft(1) - - testStyleFocused = lipgloss.NewStyle(). - Bold(true). - Border(lipgloss.NormalBorder()). - BorderForeground(config.COLOR_HIGHLIGHT). - PaddingLeft(1) - - listHeader = lipgloss.NewStyle(). - BorderStyle(lipgloss.NormalBorder()). - BorderBottom(true). - BorderForeground(config.COLOR_SUBTLE). - Render + inactiveStyle = lipgloss.NewStyle().BorderForeground(config.COLOR_SUBTLE).Border(lipgloss.NormalBorder()) + activeStyle = lipgloss.NewStyle().BorderForeground(config.COLOR_HIGHLIGHT).Border(lipgloss.NormalBorder()) + emptyMessage = lipgloss.NewStyle().Padding(2, 2).Foreground(config.COLOR_GRAY) + statusStyle = lipgloss.NewStyle().Padding(0, 1).Background(config.COLOR_GRAY) ) type Results struct { @@ -65,6 +32,7 @@ type Results struct { activeTab int content tea.Model call *app.Call + status int } func New() Results { @@ -84,14 +52,38 @@ func (b Results) Init() tea.Cmd { func (b Results) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { - case tabs.TabFocusedMsg: - b.call = msg.Tab.Call - b.body = msg.Tab.Results - b.viewport.SetContent(string(b.body)) + case app.CallSelectedMsg: + b.call = msg.Call + + case app.OnResponseMsg: + if msg.Body != "" { + f := colorjson.NewFormatter() + f.Indent = 2 + + var obj interface{} + json.Unmarshal([]byte(msg.Body), &obj) + if obj == nil { + b.body = msg.Body + } else { + s, _ := f.Marshal(obj) + b.body = string(s) + } + // prepend line numbers to each line + lines := utils.SplitLines(b.body) + numberOfLines := len(lines) + maxDigits := len(strconv.Itoa(numberOfLines)) + for i, line := range lines { + // pad line number with spaces + linenr := strconv.Itoa(i + 1) + line = strings.Repeat(" ", maxDigits-len(linenr)) + linenr + " " + line + lines[i] = lipgloss.NewStyle().Foreground(config.COLOR_GRAY).Render(line) + "\n" + } + b.body = strings.Join(lines, "") + b.viewport.SetContent(string(b.body)) + b.status = msg.Response.StatusCode + } case tea.WindowSizeMsg: - testStyle = testStyle.Width(msg.Width - 2).Height(msg.Height - 2) - testStyleFocused = testStyleFocused.Width(msg.Width - 2).Height(msg.Height - 2) b.width = msg.Width b.height = msg.Height @@ -126,63 +118,21 @@ func (b *Results) SetActiveTab(tab int) { } func (b Results) View() string { - doc := strings.Builder{} - - var renderedTabs []string - + var style lipgloss.Style if b.focused { - inactiveTabStyle.BorderForeground(config.COLOR_HIGHLIGHT) - activeTabStyle.BorderForeground(config.COLOR_HIGHLIGHT) - windowStyle.BorderForeground(config.COLOR_HIGHLIGHT) - tabGap.BorderForeground(config.COLOR_HIGHLIGHT) + style = activeStyle } else { - inactiveTabStyle.BorderForeground(config.COLOR_SUBTLE) - activeTabStyle.BorderForeground(config.COLOR_SUBTLE) - windowStyle.BorderForeground(config.COLOR_SUBTLE) - tabGap.BorderForeground(config.COLOR_SUBTLE) - } - - for i, t := range b.Tabs { - var style lipgloss.Style - isFirst, isActive := i == 0, i == b.activeTab - if isActive { - style = activeTabStyle.Copy() - } else { - style = inactiveTabStyle.Copy() - } - border, _, _, _, _ := style.GetBorder() - if isFirst && isActive { - border.BottomLeft = "│" - } else if isFirst && !isActive { - border.BottomLeft = "├" - } - - style = style.Border(border) - renderedTabs = append(renderedTabs, zone.Mark("tab_"+t, style.Render(t))) + style = inactiveStyle } - renderedTabs = append(renderedTabs, tabGap.Render(strings.Repeat(" ", b.width-54))) - - windowStyle.Height(b.height - 2) - - style := inactiveTabStyle.Copy() - border, _, _, _, _ := style.GetBorder() - border.Right = " " - border.BottomRight = "┐" - style = style.Border(border).BorderTop(false).BorderLeft(false) - renderedTabs = append(renderedTabs, style.Render(" ")) - row := lipgloss.JoinHorizontal(lipgloss.Bottom, renderedTabs...) - doc.WriteString(row) - doc.WriteString("\n") b.viewport.Width = b.width - 2 b.viewport.Height = b.height - 4 var content string - if b.activeTab == 0 { - if b.body != "" { - content = b.viewport.View() - } else { - icon := ` + if b.body != "" { + content = b.viewport.View() + } else { + icon := ` ____ /\___\ /\ \___\ @@ -190,18 +140,21 @@ func (b Results) View() string { \/_/_/ ` - message := lipgloss.JoinVertical( - lipgloss.Center, - lipgloss.NewStyle().Foreground(config.COLOR_HIGHLIGHT).Render(icon), - "Not sent yet") + message := lipgloss.JoinVertical( + lipgloss.Center, + lipgloss.NewStyle().Foreground(config.COLOR_HIGHLIGHT).Render(icon), + "Not sent yet") - center := lipgloss.PlaceHorizontal(b.viewport.Width, lipgloss.Center, message) - content = lipgloss.NewStyle(). - Foreground(config.COLOR_GRAY). - Bold(true). - Render(lipgloss.PlaceVertical(b.viewport.Height, lipgloss.Center, center)) - } + center := lipgloss.PlaceHorizontal(b.viewport.Width, lipgloss.Center, message) + content = lipgloss.NewStyle(). + Foreground(config.COLOR_GRAY). + Bold(true). + Render(lipgloss.PlaceVertical(b.viewport.Height-1, lipgloss.Center, center)) + } + + header := "Response" + if b.status != 0 { + header += " " + statusStyle.Render(strconv.Itoa(b.status)) } - doc.WriteString(windowStyle.Width((lipgloss.Width(row) - windowStyle.GetHorizontalFrameSize())).Render(content)) - return docStyle.Render(doc.String()) + return style.Render(" " + header + "\n\n" + content) } diff --git a/components/tabs/message.go b/components/tabs/message.go deleted file mode 100644 index 95d9fb3..0000000 --- a/components/tabs/message.go +++ /dev/null @@ -1,3 +0,0 @@ -package tabs - -type TabFocusedMsg struct{ Tab *Tab } diff --git a/components/tabs/tab.go b/components/tabs/tab.go deleted file mode 100644 index 02b0906..0000000 --- a/components/tabs/tab.go +++ /dev/null @@ -1,23 +0,0 @@ -package tabs - -import "restman/app" - -type Tab struct { - Name string - Call *app.Call - Results string -} - -func NewTab() Tab { - return Tab{ - Name: "untitled", - Call: app.NewCall(), - } -} - -func NewTabWithCall(call *app.Call) Tab { - return Tab{ - Name: call.Title(), - Call: call, - } -} diff --git a/components/tabs/tabs.go b/components/tabs/tabs.go deleted file mode 100644 index 1c2ec7d..0000000 --- a/components/tabs/tabs.go +++ /dev/null @@ -1,219 +0,0 @@ -package tabs - -import ( - "encoding/json" - "restman/app" - "restman/components/config" - "restman/utils" - "strings" - - "github.com/TylerBrock/colorjson" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - zone "github.com/lrstanley/bubblezone" -) - -var ( - normal = lipgloss.NewStyle(). - Border(lipgloss.RoundedBorder()). - BorderBottom(false). - Padding(0, 1). - BorderForeground(config.COLOR_SUBTLE). - Foreground(config.COLOR_SUBTLE) - - focused = normal.Copy(). - BorderForeground(config.COLOR_HIGHLIGHT). - Foreground(config.COLOR_HIGHLIGHT). - Bold(true) - - plus = normal.Copy() - - more = normal.Copy(). - Border(lipgloss.HiddenBorder()). - BorderBottom(false). - Foreground(config.COLOR_GRAY) -) - -type Tabs struct { - height int - width int - tabs []Tab - focused int -} - -func New() Tabs { - return Tabs{ - tabs: []Tab{}, - focused: 0, - } -} - -func (m Tabs) Init() tea.Cmd { - return nil -} - -func (m *Tabs) AddTab() (tea.Model, tea.Cmd) { - m.tabs = append(m.tabs, NewTab()) - return m.setFocused(len(m.tabs) - 1) -} - -func (m *Tabs) setFocused(index int) (tea.Model, tea.Cmd) { - m.focused = index - tab := m.tabs[m.focused] - return m, func() tea.Msg { - return TabFocusedMsg{Tab: &tab} - } -} - -func (m *Tabs) removeTab(index int) (tea.Model, tea.Cmd) { - if len(m.tabs) > 1 { - m.tabs = append(m.tabs[:index], m.tabs[index+1:]...) - } - if m.focused >= index { - newIndex := m.focused - 1 - if newIndex < 0 { - newIndex = 0 - } - return m.setFocused(newIndex) - } - return m, nil -} - -func (m *Tabs) setName(index int, name string) { - m.tabs[index].Name = name -} - -func (m Tabs) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case app.OnResponseMsg: - if msg.Body != "" { - _, index := m.GetTab(msg.Call) - f := colorjson.NewFormatter() - f.Indent = 2 - - var obj interface{} - json.Unmarshal([]byte(msg.Body), &obj) - if obj == nil { - m.tabs[index].Results = msg.Body - } else { - s, _ := f.Marshal(obj) - m.tabs[index].Results = string(s) - } - return m.setFocused(index) - } - case tea.MouseMsg: - if msg.Type == tea.MouseLeft { - if zone.Get("add-tab").InBounds(msg) { - return m.AddTab() - } - - for i := range m.tabs { - if zone.Get(utils.Join("tab-", i)).InBounds(msg) { - return m.setFocused(i) - } - } - - for i := range m.tabs { - if zone.Get(utils.Join("remove-tab-", i)).InBounds(msg) { - return m.removeTab(i) - } - } - } - case tea.WindowSizeMsg: - m.height = msg.Height - m.width = msg.Width - - case app.CallSelectedMsg: - return m.GetOrCreateTab(msg.Call) - - case app.CallUpdatedMsg: - tab, index := m.GetTab(msg.Call) - if tab != nil { - m.tabs[index].Name = msg.Call.Title() - m.tabs[index].Call = msg.Call - return m.setFocused(index) - } - } - - var cmd tea.Cmd - return m, cmd -} - -func (m *Tabs) GetOrCreateTab(call *app.Call) (tea.Model, tea.Cmd) { - for i, tab := range m.tabs { - if tab.Call != nil && tab.Call.ID == call.ID { - return m.setFocused(i) - } - } - m.tabs = append(m.tabs, NewTabWithCall(call)) - return m.setFocused(len(m.tabs) - 1) -} - -func (m *Tabs) GetTab(call *app.Call) (*Tab, int) { - for i, tab := range m.tabs { - if tab.Call != nil && tab.Call.ID == call.ID { - return &tab, i - } - } - return nil, 0 -} - -func (m Tabs) View() string { - tabs := []string{} - - add := zone.Mark("add-tab", plus.Render("")) - for i, tab := range m.tabs { - close := zone.Mark(utils.Join("remove-tab-", i), "󰅙") - icon := " " - if tab.Call.Collection() == nil { - icon = "" - } - title := zone.Mark(utils.Join("tab-", i), icon+" "+tab.Name) - - style := normal - if m.focused == i { - style = focused - } - newTab := style.Render(lipgloss.JoinHorizontal(lipgloss.Left, title, " ", close)) - - // if string length of newTab is greater than width of m.width append "..." - tmpTabs := tabs - tmpTabs = append(tmpTabs, newTab) - tmpTabs = append(tmpTabs, add) - - rendered := lipgloss.JoinHorizontal( - lipgloss.Left, - tmpTabs..., - ) - finalWidth := lipgloss.Width(rendered) - if finalWidth > m.width { - tmpTabs := tabs - tmpTabs = append(tmpTabs, add) - rendered = lipgloss.JoinHorizontal( - lipgloss.Left, - tmpTabs..., - ) - finalWidth = lipgloss.Width(rendered) - if m.width-finalWidth < 7 { - finalWidth = finalWidth - lipgloss.Width(tabs[len(tabs)-1]) - tabs = tabs[:len(tabs)-1] - } - // add spacer - tabs = append(tabs, more.Render("...")) - count := m.width - finalWidth - 7 - if count > 0 { - tabs = append(tabs, strings.Repeat(" ", count)) - } - break - } else { - tabs = append(tabs, newTab) - } - } - - tabs = append(tabs, add) - - return lipgloss.JoinHorizontal( - lipgloss.Left, - tabs..., - ) -} diff --git a/components/url/url.go b/components/url/url.go index 01da8de..674ee91 100644 --- a/components/url/url.go +++ b/components/url/url.go @@ -3,7 +3,6 @@ package url import ( "restman/app" "restman/components/config" - "restman/components/tabs" "restman/utils" "strings" @@ -97,9 +96,9 @@ func (m Url) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { - case tabs.TabFocusedMsg: - if msg.Tab.Call != nil { - m.call = msg.Tab.Call + case app.CallSelectedMsg: + if msg.Call != nil { + m.call = msg.Call m.defaultText = m.call.Url m.t.SetValue(m.defaultText) m.method = m.call.Method @@ -134,19 +133,6 @@ func (m Url) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m.Submit() case "ctrl+r": m.CycleOverMethods() - - default: - var cmds []tea.Cmd - - newModel, cmd := m.t.Update(msg) - cmds = append(cmds, cmd) - - m.t = newModel - - m.call.Url = m.t.Value() - cmds = append(cmds, func() tea.Msg { return app.CallUpdatedMsg{Call: m.call} }) - - return m, tea.Batch(cmds...) } } diff --git a/go.mod b/go.mod index 70bb9ce..8d892fc 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,6 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/charmbracelet/x/ansi v0.4.0 // indirect github.com/charmbracelet/x/term v0.2.0 // indirect - github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/fatih/color v1.16.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -55,7 +54,6 @@ require ( golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.26.0 // indirect - golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.18.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index de8962b..dcf4d3b 100644 --- a/go.sum +++ b/go.sum @@ -1,32 +1,21 @@ +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4= github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/charmbracelet/bubbles v0.17.1 h1:0SIyjOnkrsfDo88YvPgAWvZMwXe26TP6drRvmkjyUu4= -github.com/charmbracelet/bubbles v0.17.1/go.mod h1:9HxZWlkCqz2PRwsCbYl7a3KXvGzFaDHpYbSYMJ+nE3o= github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= -github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM= -github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg= -github.com/charmbracelet/bubbletea v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c= -github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= github.com/charmbracelet/bubbletea v1.1.2 h1:naQXF2laRxyLyil/i7fxdpiz1/k06IKquhm4vBfHsIc= github.com/charmbracelet/bubbletea v1.1.2/go.mod h1:9HIU/hBV24qKjlehyj8z1r/tR9TYTQEag+cWZnuXo8E= -github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg= -github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I= -github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= -github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= github.com/charmbracelet/lipgloss v0.13.1 h1:Oik/oqDTMVA01GetT4JdEC033dNzWoQHdWnHnQmXE2A= github.com/charmbracelet/lipgloss v0.13.1/go.mod h1:zaYVJ2xKSKEnTEEbX6uAHabh2d975RJ+0yfkFpRBz5U= github.com/charmbracelet/x/ansi v0.4.0 h1:NqwHA4B23VwsDn4H3VcNX1W1tOmgnvY1NDx5tOXdnOU= github.com/charmbracelet/x/ansi v0.4.0/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -34,8 +23,6 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= -github.com/evertras/bubble-table v0.15.6 h1:CBty0j5kYJoT40dI0/FDg2PlxAEuwUhw7KK0cziBmzw= -github.com/evertras/bubble-table v0.15.6/go.mod h1:SPOZKbIpyYWPHBNki3fyNpiPBQkvkULAtOT7NTD5fKY= github.com/evertras/bubble-table v0.17.0 h1:qQU4bi3IRxuZ5+Fvm3esyU/ucH9ufRXWhWL0fFuMn9c= github.com/evertras/bubble-table v0.17.0/go.mod h1:ifHujS1YxwnYSOgcR2+m3GnJ84f7CVU/4kUOxUCjEbQ= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= @@ -46,8 +33,6 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= @@ -62,8 +47,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lrstanley/bubblezone v0.0.0-20230911164824-e3824f1adde9 h1:+7bxeCzFs4bfFPAnIZrjNmRt/MCffIy7aw2mPc9mxkU= -github.com/lrstanley/bubblezone v0.0.0-20230911164824-e3824f1adde9/go.mod h1:v5lEwWaguF1o2MW/ucO0ZIA/IZymdBYJJ+2cMRLE7LU= github.com/lrstanley/bubblezone v0.0.0-20240914071701-b48c55a5e78e h1:OLwZ8xVaeVrru0xyeuOX+fne0gQTFEGlzfNjipCbxlU= github.com/lrstanley/bubblezone v0.0.0-20240914071701-b48c55a5e78e/go.mod h1:NQ34EGeu8FAYGBMDzwhfNJL8YQYoWZP5xYJPRDAwN3E= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= @@ -78,8 +61,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -92,8 +73,6 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -101,8 +80,6 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= @@ -112,8 +89,6 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y= -github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= @@ -122,14 +97,10 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -139,8 +110,8 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= @@ -152,23 +123,13 @@ go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/help.go b/help.go index da758c4..99d7ce9 100644 --- a/help.go +++ b/help.go @@ -68,9 +68,9 @@ func (c Help) View() string { icon, " https://github.com/jackMort/Restman, version: "+version, "", - general.Width(c.overlay.Width()).Render(helpView)), + general.Width(c.overlay.Width()-2).Render(helpView)), ) - dialog := lipgloss.Place(c.overlay.Width()-2, c.overlay.Height(), lipgloss.Left, lipgloss.Top, ui) + dialog := lipgloss.Place(c.overlay.Width(), c.overlay.Height(), lipgloss.Left, lipgloss.Top, ui) return c.overlay.WrapView(dialog) } diff --git a/main.go b/main.go index 53b0609..cc9a492 100644 --- a/main.go +++ b/main.go @@ -6,7 +6,6 @@ import ( "restman/components/config" "restman/components/popup" "restman/components/request" - "restman/components/tabs" "restman/components/url" "restman/utils" @@ -56,27 +55,34 @@ type Model struct { focused string popup tea.Model collections collections.Collections - initalCall *app.Call + initialCall *app.Call width int height int } func (m Model) Init() tea.Cmd { var ( - cmd tea.Cmd - cmd2 tea.Cmd + focusCmd tea.Cmd + initalCallCmd tea.Cmd + runCmd tea.Cmd ) m.focused = "url" - m.tui.ModelMap[m.focused], cmd = m.tui.ModelMap[m.focused].Update(config.WindowFocusedMsg{State: true}) + m.tui.ModelMap[m.focused], focusCmd = m.tui.ModelMap[m.focused].Update(config.WindowFocusedMsg{State: true}) - tabs := m.tui.ModelMap["tabs"].(tabs.Tabs) - m.tui.ModelMap["tabs"], cmd2 = tabs.GetOrCreateTab(m.initalCall) + // set initial call if provided + if m.initialCall != nil { + initalCallCmd = func() tea.Msg { + return app.CallSelectedMsg{Call: m.initialCall} + } + runCmd = app.GetInstance().GetResponse(m.initialCall) + } - return tea.Batch( + return tea.Sequence( app.GetInstance().ReadCollectionsFromJSON(), - cmd, - cmd2, + focusCmd, + initalCallCmd, + runCmd, ) } @@ -94,7 +100,7 @@ func (m *Model) Next() (tea.Model, tea.Cmd) { switch m.focused { case "collections": - m.focused = "tabs" + m.focused = "url" case "tabs": m.focused = "url" case "url": @@ -286,8 +292,13 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.popup = collections.NewCreate(m.View(), utils.MinInt(70, 100)) return m, m.popup.Init() - case "ctrl+h": - m.popup = NewHelp(m.View(), 70) + case "ctrl+a": + + bg := config.FullscreenStyle. + Width(m.width - 2). + Height(m.height - 2). + Render() + m.popup = NewHelp(bg, 70) return m, m.popup.Init() case "ctrl+s": @@ -327,7 +338,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case tea.WindowSizeMsg: m.width = msg.Width m.height = msg.Height - println("Width: ", m.width, " Height: ", m.height) m.tui.UpdateSize(msg) default: @@ -343,7 +353,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (m Model) SizeIsTooSmall() bool { - return m.width < 60 || m.height < 30 + return m.width < 140 || m.height < 30 } func (m Model) View() string { @@ -355,7 +365,7 @@ func (m Model) View() string { lipgloss.JoinVertical( lipgloss.Left, config.BoxHeader.Render("Restman "+version), - "Please resize the window to at least 60x20"), + "Please resize the window to at least 140x30"), ) } diff --git a/utils/byte-count.go b/utils/byte-count.go new file mode 100644 index 0000000..ee03985 --- /dev/null +++ b/utils/byte-count.go @@ -0,0 +1,17 @@ +package utils + +import "fmt" + +func ByteCountIEC(b int64) string { + const unit = 1024 + if b < unit { + return fmt.Sprintf("%d B", b) + } + div, exp := int64(unit), 0 + for n := b / unit; n >= unit; n /= unit { + div *= unit + exp++ + } + return fmt.Sprintf("%.1f %ciB", + float64(b)/float64(div), "KMGTPE"[exp]) +} diff --git a/utils/strings.go b/utils/strings.go index 2a9e33a..5a73a27 100644 --- a/utils/strings.go +++ b/utils/strings.go @@ -1,8 +1,14 @@ package utils +import "strings" + func Truncate(s string, n int) string { if len(s) <= n { return s } return s[:n-5] + "[...]" } + +func SplitLines(s string) []string { + return strings.Split(s, "\n") +}