Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
Hadi
2026-05-19 11:51:38 +02:00
parent 79128bb865
commit 41c0e489cf
8 changed files with 11 additions and 85 deletions
-2
View File
@@ -46,7 +46,6 @@ func NewTextarea(showLineNumbers bool) textarea.Model {
return ta return ta
} }
// SeverityStyle returns a bold lipgloss style coloured by finding severity level.
func SeverityStyle(sev string) lipgloss.Style { func SeverityStyle(sev string) lipgloss.Style {
base := lipgloss.NewStyle().Bold(true) base := lipgloss.NewStyle().Bold(true)
switch sev { switch sev {
@@ -63,7 +62,6 @@ func SeverityStyle(sev string) lipgloss.Style {
} }
} }
// StatusStyle returns a bold lipgloss style coloured by HTTP status code.
func StatusStyle(code, width int) lipgloss.Style { func StatusStyle(code, width int) lipgloss.Style {
base := lipgloss.NewStyle().Bold(true).Width(width) base := lipgloss.NewStyle().Bold(true).Width(width)
switch { switch {
-1
View File
@@ -15,7 +15,6 @@ func Paint(c color.Color, s string) string {
return lipgloss.NewStyle().Foreground(c).Render(s) return lipgloss.NewStyle().Foreground(c).Render(s)
} }
// HighlightHTTP highlights a full raw HTTP message (headers + body).
func HighlightHTTP(raw string) string { func HighlightHTTP(raw string) string {
raw = strings.ReplaceAll(raw, "\r\n", "\n") raw = strings.ReplaceAll(raw, "\r\n", "\n")
raw = strings.ReplaceAll(raw, "\r", "\n") raw = strings.ReplaceAll(raw, "\r", "\n")
+1 -1
View File
@@ -332,7 +332,7 @@ func (m Model) renderHelpLine() string {
} }
parts = append(parts, binding(k.Open)) parts = append(parts, binding(k.Open))
parts = append(parts, binding(k.Delete)) parts = append(parts, binding(k.Delete))
parts = append(parts, item("q", "quit")) parts = append(parts, item(keys.Keys.Global.Quit.Help().Key, "quit"))
} }
return strings.Join(parts, sep) return strings.Join(parts, sep)
+4 -60
View File
@@ -4,7 +4,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"sort"
"strconv" "strconv"
"strings" "strings"
@@ -12,61 +11,6 @@ import (
"github.com/anotherhadi/spilltea/internal/style" "github.com/anotherhadi/spilltea/internal/style"
) )
func formatRawRequest(req *intercept.PendingRequest) string {
r := req.Flow.Request
var sb strings.Builder
fmt.Fprintf(&sb, "%s %s %s\n", r.Method, r.URL.RequestURI(), r.Proto)
keys := make([]string, 0, len(r.Header))
for k := range r.Header {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
for _, v := range r.Header[k] {
fmt.Fprintf(&sb, "%s: %s\n", k, v)
}
}
sb.WriteString("\n")
if len(r.Body) > 0 {
sb.Write(r.Body)
}
return sb.String()
}
func formatRawResponse(resp *intercept.PendingResponse) string {
r := resp.Flow.Response
if r == nil {
return "(no response)"
}
var sb strings.Builder
proto := resp.Flow.Request.Proto
if proto == "" {
proto = "HTTP/1.1"
}
fmt.Fprintf(&sb, "%s %d %s\n", proto, r.StatusCode, http.StatusText(r.StatusCode))
keys := make([]string, 0, len(r.Header))
for k := range r.Header {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
for _, v := range r.Header[k] {
fmt.Fprintf(&sb, "%s: %s\n", k, v)
}
}
sb.WriteString("\n")
if len(r.Body) > 0 {
sb.Write(r.Body)
}
return sb.String()
}
func parseRawRequest(content string, req *intercept.PendingRequest) { func parseRawRequest(content string, req *intercept.PendingRequest) {
r := req.Flow.Request r := req.Flow.Request
lines := strings.Split(strings.ReplaceAll(content, "\r\n", "\n"), "\n") lines := strings.Split(strings.ReplaceAll(content, "\r\n", "\n"), "\n")
@@ -343,7 +287,7 @@ func (m *Model) loadIntoTextarea() {
if edited, ok := m.pendingResponseEdits[resp]; ok { if edited, ok := m.pendingResponseEdits[resp]; ok {
m.textarea.SetValue(edited) m.textarea.SetValue(edited)
} else { } else {
m.textarea.SetValue(formatRawResponse(resp)) m.textarea.SetValue(intercept.FormatRawResponse(resp.Flow))
} }
} else { } else {
if len(m.queue) == 0 { if len(m.queue) == 0 {
@@ -353,7 +297,7 @@ func (m *Model) loadIntoTextarea() {
if edited, ok := m.pendingEdits[req]; ok { if edited, ok := m.pendingEdits[req]; ok {
m.textarea.SetValue(edited) m.textarea.SetValue(edited)
} else { } else {
m.textarea.SetValue(formatRawRequest(req)) m.textarea.SetValue(intercept.FormatRawRequest(req.Flow))
} }
} }
} }
@@ -370,7 +314,7 @@ func (m *Model) refreshBody() {
if edited, ok := m.pendingResponseEdits[resp]; ok { if edited, ok := m.pendingResponseEdits[resp]; ok {
raw = edited raw = edited
} else { } else {
raw = formatRawResponse(resp) raw = intercept.FormatRawResponse(resp.Flow)
} }
} else { } else {
if len(m.queue) == 0 { if len(m.queue) == 0 {
@@ -381,7 +325,7 @@ func (m *Model) refreshBody() {
if edited, ok := m.pendingEdits[req]; ok { if edited, ok := m.pendingEdits[req]; ok {
raw = edited raw = edited
} else { } else {
raw = formatRawRequest(req) raw = intercept.FormatRawRequest(req.Flow)
} }
} }
m.bodyViewport.SetContent(style.HighlightHTTP(raw)) m.bodyViewport.SetContent(style.HighlightHTTP(raw))
+2 -2
View File
@@ -98,7 +98,7 @@ func (m Model) CurrentRaw() string {
if edited, ok := m.pendingResponseEdits[resp]; ok { if edited, ok := m.pendingResponseEdits[resp]; ok {
return edited return edited
} }
return formatRawResponse(resp) return intercept.FormatRawResponse(resp.Flow)
} }
if len(m.queue) == 0 { if len(m.queue) == 0 {
return "" return ""
@@ -107,7 +107,7 @@ func (m Model) CurrentRaw() string {
if edited, ok := m.pendingEdits[req]; ok { if edited, ok := m.pendingEdits[req]; ok {
return edited return edited
} }
return formatRawRequest(req) return intercept.FormatRawRequest(req.Flow)
} }
func (m *Model) SetSize(w, h int) { func (m *Model) SetSize(w, h int) {
+4 -4
View File
@@ -237,10 +237,10 @@ func (m Model) updateNormalMode(msg tea.KeyPressMsg, cmds *[]tea.Cmd) (tea.Model
case key.Matches(msg, keys.Keys.Intercept.EditExternal): case key.Matches(msg, keys.Keys.Intercept.EditExternal):
if !onResponses && len(m.queue) > 0 { if !onResponses && len(m.queue) > 0 {
return m, util.OpenExternalEditor(formatRawRequest(m.queue[m.cursor])) return m, util.OpenExternalEditor(intercept.FormatRawRequest(m.queue[m.cursor].Flow))
} }
if onResponses && len(m.responseQueue) > 0 { if onResponses && len(m.responseQueue) > 0 {
return m, util.OpenExternalEditor(formatRawResponse(m.responseQueue[m.responseCursor])) return m, util.OpenExternalEditor(intercept.FormatRawResponse(m.responseQueue[m.responseCursor].Flow))
} }
case key.Matches(msg, keys.Keys.Global.SendToReplay): case key.Matches(msg, keys.Keys.Global.SendToReplay):
@@ -287,12 +287,12 @@ func (m Model) updateEditMode(msg tea.KeyPressMsg, cmds *[]tea.Cmd) (tea.Model,
if onResponses { if onResponses {
if len(m.responseQueue) > 0 { if len(m.responseQueue) > 0 {
delete(m.pendingResponseEdits, m.responseQueue[m.responseCursor]) delete(m.pendingResponseEdits, m.responseQueue[m.responseCursor])
m.textarea.SetValue(formatRawResponse(m.responseQueue[m.responseCursor])) m.textarea.SetValue(intercept.FormatRawResponse(m.responseQueue[m.responseCursor].Flow))
} }
} else { } else {
if len(m.queue) > 0 { if len(m.queue) > 0 {
delete(m.pendingEdits, m.queue[m.cursor]) delete(m.pendingEdits, m.queue[m.cursor])
m.textarea.SetValue(formatRawRequest(m.queue[m.cursor])) m.textarea.SetValue(intercept.FormatRawRequest(m.queue[m.cursor].Flow))
} }
} }
-1
View File
@@ -112,7 +112,6 @@ func (m *Model) recalcSizes() {
m.syncDetailViewport() m.syncDetailViewport()
} }
// Refresh reloads the plugin list from the manager.
func (m *Model) Refresh() { func (m *Model) Refresh() {
if m.manager == nil { if m.manager == nil {
return return
-14
View File
@@ -6,21 +6,7 @@ import (
"github.com/anotherhadi/spilltea/internal/keys" "github.com/anotherhadi/spilltea/internal/keys"
) )
// PluginsChangedMsg is sent when the plugin list should be refreshed.
type PluginsChangedMsg struct{}
// RefreshCmd returns a command that triggers a list refresh.
func RefreshCmd() tea.Cmd {
return func() tea.Msg { return PluginsChangedMsg{} }
}
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg.(type) {
case PluginsChangedMsg:
m.Refresh()
return m, nil
}
// Route non-key messages to textarea when editing so internal // Route non-key messages to textarea when editing so internal
// textarea messages (e.g. clipboard paste) are handled correctly. // textarea messages (e.g. clipboard paste) are handled correctly.
if m.editing { if m.editing {