use ilovetui colors & styles

This commit is contained in:
Hadi
2026-05-26 16:12:10 +02:00
parent 0b395e018a
commit aa458c142f
37 changed files with 295 additions and 686 deletions
-20
View File
@@ -1,20 +0,0 @@
package config
type Colors struct {
Base00 string `mapstructure:"base00"`
Base01 string `mapstructure:"base01"`
Base02 string `mapstructure:"base02"`
Base03 string `mapstructure:"base03"`
Base04 string `mapstructure:"base04"`
Base05 string `mapstructure:"base05"`
Base06 string `mapstructure:"base06"`
Base07 string `mapstructure:"base07"`
Base08 string `mapstructure:"base08"`
Base09 string `mapstructure:"base09"`
Base0A string `mapstructure:"base0a"`
Base0B string `mapstructure:"base0b"`
Base0C string `mapstructure:"base0c"`
Base0D string `mapstructure:"base0d"`
Base0E string `mapstructure:"base0e"`
Base0F string `mapstructure:"base0f"`
}
-1
View File
@@ -31,7 +31,6 @@ type Config struct {
} `mapstructure:"app"`
TUI struct {
Colors Colors `mapstructure:"colors"`
UseNerdfontIcons bool `mapstructure:"use_nerdfont_icons"`
DefaultSidebarState string `mapstructure:"default_sidebar_state"`
PrettyPrintBody bool `mapstructure:"pretty_print_body"`
-17
View File
@@ -27,23 +27,6 @@ tui:
use_nerdfont_icons: false
default_sidebar_state: "expanded" # hidden, collapsed, expanded
pretty_print_body: true # auto-indent JSON and HTML response bodies
colors:
base00: "110F12" # Default Background
base01: "1C1920" # Lighter Background (status bars, line numbers)
base02: "1D1A26" # Selection Background
base03: "514D63" # Comments, Invisibles, faint text
base04: "8E8AA0" # Dark Foreground (status bars)
base05: "C2BED6" # Default Foreground, Caret, Delimiters
base06: "D8D5EA" # Light Foreground (rarely used)
base07: "EAE7F7" # Light Background (rarely used)
base08: "E07080" # Red: errors, diff deleted
base09: "D49070" # Orange: integers, constants, warnings
base0a: "C4B060" # Yellow: classes, search highlight
base0b: "80B880" # Green: strings, diff inserted, success
base0c: "70B8C0" # Cyan: support, regex, escape chars
base0d: "9E97F8" # Blue/Accent: functions, headings, primary
base0e: "C090E8" # Purple: keywords, storage
base0f: "D080A0" # Pink: deprecated, embedded language tags
keybindings:
global:
-43
View File
@@ -1,43 +0,0 @@
package style
import (
"strings"
"charm.land/lipgloss/v2"
)
// PanelContentH returns the usable inner content height for a panel rendered by
// RenderWithTitle. It subtracts the two border lines (top + bottom) from the
// total panel height.
func PanelContentH(totalH int) int {
h := totalH - 2
if h < 0 {
return 0
}
return h
}
// RenderWithTitle renders a lipgloss bordered box with a title embedded in the
// top border, matching the border's own foreground color. height is the total
// desired output height (including both border lines).
func RenderWithTitle(border lipgloss.Style, title, content string, width, height int) string {
boxH := height - 1
if contentH := boxH - 1; contentH > 0 {
lines := strings.Split(content, "\n")
if len(lines) > contentH {
content = strings.Join(lines[:contentH], "\n")
}
}
box := border.BorderTop(false).Width(width).Height(boxH).Render(content)
boxWidth := lipgloss.Width(strings.SplitN(box, "\n", 2)[0])
label := " " + title + " "
fillW := boxWidth - lipgloss.Width(label) - 2
if fillW < 0 {
fillW = 0
}
bc := lipgloss.NewStyle().Foreground(border.GetBorderTopForeground())
topLine := bc.Render("╭ ") + bc.Render(title) + bc.Render(" "+strings.Repeat("─", fillW)+"╮")
return lipgloss.JoinVertical(lipgloss.Left, topLine, box)
}
+21 -20
View File
@@ -7,6 +7,7 @@ import (
"charm.land/bubbles/v2/textarea"
"charm.land/bubbles/v2/viewport"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
)
func NewViewport() viewport.Model {
@@ -24,7 +25,7 @@ func ViewportView(vp *viewport.Model) string {
if len(lines) == 0 {
return v
}
arrow := lipgloss.NewStyle().Foreground(S.Subtle).Render("↓")
arrow := lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).Render("↓")
arrowW := lipgloss.Width(arrow)
inner := vp.Width() - 2*arrowW
if inner < 0 {
@@ -51,16 +52,16 @@ func NewTextarea(showLineNumbers bool) textarea.Model {
ts := ta.Styles()
ts.Focused.Base = lipgloss.NewStyle()
ts.Blurred.Base = lipgloss.NewStyle()
ts.Focused.Text = lipgloss.NewStyle().Foreground(S.Text)
ts.Focused.CursorLine = lipgloss.NewStyle().Background(S.Selection).Foreground(S.Text)
ts.Focused.CursorLineNumber = lipgloss.NewStyle().Background(S.Selection).Foreground(S.Primary).Bold(true)
ts.Focused.LineNumber = lipgloss.NewStyle().Foreground(S.Subtle)
ts.Focused.Placeholder = lipgloss.NewStyle().Foreground(S.Subtle)
ts.Focused.EndOfBuffer = lipgloss.NewStyle().Foreground(S.SubtleBg)
ts.Blurred.Text = lipgloss.NewStyle().Foreground(S.MutedFg)
ts.Blurred.LineNumber = lipgloss.NewStyle().Foreground(S.SubtleBg)
ts.Blurred.Placeholder = lipgloss.NewStyle().Foreground(S.Subtle)
ts.Blurred.EndOfBuffer = lipgloss.NewStyle().Foreground(S.SubtleBg)
ts.Focused.Text = lipgloss.NewStyle().Foreground(ilovetui.S.Text)
ts.Focused.CursorLine = lipgloss.NewStyle().Background(ilovetui.S.Selection).Foreground(ilovetui.S.Text)
ts.Focused.CursorLineNumber = lipgloss.NewStyle().Background(ilovetui.S.Selection).Foreground(ilovetui.S.Primary).Bold(true)
ts.Focused.LineNumber = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
ts.Focused.Placeholder = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
ts.Focused.EndOfBuffer = lipgloss.NewStyle().Foreground(ilovetui.S.SubtleBg)
ts.Blurred.Text = lipgloss.NewStyle().Foreground(ilovetui.S.Muted)
ts.Blurred.LineNumber = lipgloss.NewStyle().Foreground(ilovetui.S.SubtleBg)
ts.Blurred.Placeholder = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
ts.Blurred.EndOfBuffer = lipgloss.NewStyle().Foreground(ilovetui.S.SubtleBg)
ta.SetStyles(ts)
return ta
}
@@ -69,15 +70,15 @@ func SeverityStyle(sev string) lipgloss.Style {
base := lipgloss.NewStyle().Bold(true)
switch sev {
case "critical":
return base.Foreground(S.Error)
return base.Foreground(ilovetui.S.Error)
case "high":
return base.Foreground(S.Warning)
return base.Foreground(ilovetui.S.Warning)
case "medium":
return base.Foreground(S.Primary)
return base.Foreground(ilovetui.S.Primary)
case "low":
return base.Foreground(S.Success)
return base.Foreground(ilovetui.S.Success)
default:
return base.Foreground(S.Subtle)
return base.Foreground(ilovetui.S.Subtle)
}
}
@@ -85,13 +86,13 @@ func StatusStyle(code, width int) lipgloss.Style {
base := lipgloss.NewStyle().Bold(true).Width(width)
switch {
case code >= 500:
return base.Foreground(S.Error)
return base.Foreground(ilovetui.S.Error)
case code >= 400:
return base.Foreground(S.Warning)
return base.Foreground(ilovetui.S.Warning)
case code >= 300:
return base.Foreground(S.Primary)
return base.Foreground(ilovetui.S.Primary)
default:
return base.Foreground(S.Success)
return base.Foreground(ilovetui.S.Success)
}
}
-236
View File
@@ -1,236 +0,0 @@
package style
import (
"github.com/anotherhadi/spilltea/internal/config"
"charm.land/glamour/v2/ansi"
)
func GlamourStyleConfig(cfg *config.Config) ansi.StyleConfig {
c := cfg.TUI.Colors
str := func(s string) *string { return &s }
hex := func(base string) *string { return str("#" + base) }
boolPtr := func(b bool) *bool { return &b }
uintPtr := func(u uint) *uint { return &u }
return ansi.StyleConfig{
Document: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
BlockPrefix: "\n",
BlockSuffix: "\n",
Color: hex(c.Base05),
},
Margin: uintPtr(2),
},
BlockQuote: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Color: hex(c.Base03),
Italic: boolPtr(true),
},
Indent: uintPtr(1),
IndentToken: str("│ "),
},
List: ansi.StyleList{
LevelIndent: 2,
},
Heading: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
BlockSuffix: "\n",
Color: hex(c.Base0D),
Bold: boolPtr(true),
},
},
H1: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Prefix: " ",
Suffix: " ",
Color: hex(c.Base07),
BackgroundColor: hex(c.Base0D),
Bold: boolPtr(true),
},
},
H2: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Prefix: "## ",
Color: hex(c.Base0D),
Bold: boolPtr(true),
},
},
H3: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Prefix: "### ",
Color: hex(c.Base0C),
},
},
H4: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Prefix: "#### ",
Color: hex(c.Base0B),
},
},
H5: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Prefix: "##### ",
Color: hex(c.Base09),
},
},
H6: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Prefix: "###### ",
Color: hex(c.Base08),
Bold: boolPtr(false),
},
},
Strikethrough: ansi.StylePrimitive{
CrossedOut: boolPtr(true),
},
Emph: ansi.StylePrimitive{
Italic: boolPtr(true),
},
Strong: ansi.StylePrimitive{
Bold: boolPtr(true),
},
HorizontalRule: ansi.StylePrimitive{
Color: hex(c.Base03),
Format: "\n--------\n",
},
Item: ansi.StylePrimitive{
BlockPrefix: "• ",
},
Enumeration: ansi.StylePrimitive{
BlockPrefix: ". ",
},
Task: ansi.StyleTask{
Ticked: "[✓] ",
Unticked: "[ ] ",
},
Link: ansi.StylePrimitive{
Color: hex(c.Base0C),
Underline: boolPtr(true),
},
LinkText: ansi.StylePrimitive{
Color: hex(c.Base0D),
Bold: boolPtr(true),
},
Image: ansi.StylePrimitive{
Color: hex(c.Base0C),
Underline: boolPtr(true),
},
ImageText: ansi.StylePrimitive{
Color: hex(c.Base04),
Format: "Image: {{.text}} ->",
},
Code: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Prefix: " ",
Suffix: " ",
Color: hex(c.Base0B),
BackgroundColor: hex(c.Base01),
},
},
CodeBlock: ansi.StyleCodeBlock{
StyleBlock: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{
Color: hex(c.Base04),
},
Margin: uintPtr(2),
},
Chroma: &ansi.Chroma{
Text: ansi.StylePrimitive{
Color: hex(c.Base05),
},
Error: ansi.StylePrimitive{
Color: hex(c.Base07),
BackgroundColor: hex(c.Base08),
},
Comment: ansi.StylePrimitive{
Color: hex(c.Base03),
Italic: boolPtr(true),
},
CommentPreproc: ansi.StylePrimitive{
Color: hex(c.Base09),
},
Keyword: ansi.StylePrimitive{
Color: hex(c.Base0E),
},
KeywordReserved: ansi.StylePrimitive{
Color: hex(c.Base0E),
},
KeywordNamespace: ansi.StylePrimitive{
Color: hex(c.Base0D),
},
KeywordType: ansi.StylePrimitive{
Color: hex(c.Base0A),
},
Operator: ansi.StylePrimitive{
Color: hex(c.Base05),
},
Punctuation: ansi.StylePrimitive{
Color: hex(c.Base05),
},
Name: ansi.StylePrimitive{
Color: hex(c.Base05),
},
NameBuiltin: ansi.StylePrimitive{
Color: hex(c.Base0D),
},
NameTag: ansi.StylePrimitive{
Color: hex(c.Base08),
},
NameAttribute: ansi.StylePrimitive{
Color: hex(c.Base0A),
},
NameClass: ansi.StylePrimitive{
Color: hex(c.Base0A),
Bold: boolPtr(true),
Underline: boolPtr(true),
},
NameConstant: ansi.StylePrimitive{
Color: hex(c.Base09),
},
NameDecorator: ansi.StylePrimitive{
Color: hex(c.Base0C),
},
NameFunction: ansi.StylePrimitive{
Color: hex(c.Base0D),
},
LiteralNumber: ansi.StylePrimitive{
Color: hex(c.Base09),
},
LiteralString: ansi.StylePrimitive{
Color: hex(c.Base0B),
},
LiteralStringEscape: ansi.StylePrimitive{
Color: hex(c.Base0C),
},
GenericDeleted: ansi.StylePrimitive{
Color: hex(c.Base08),
},
GenericEmph: ansi.StylePrimitive{
Italic: boolPtr(true),
},
GenericInserted: ansi.StylePrimitive{
Color: hex(c.Base0B),
},
GenericStrong: ansi.StylePrimitive{
Bold: boolPtr(true),
},
GenericSubheading: ansi.StylePrimitive{
Color: hex(c.Base04),
},
Background: ansi.StylePrimitive{
BackgroundColor: hex(c.Base01),
},
},
},
Table: ansi.StyleTable{
StyleBlock: ansi.StyleBlock{
StylePrimitive: ansi.StylePrimitive{},
},
},
DefinitionDescription: ansi.StylePrimitive{
BlockPrefix: "\n> ",
},
}
}
+26 -25
View File
@@ -3,12 +3,13 @@ package style
import (
"bytes"
"encoding/json"
"image/color"
"strings"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/config"
"golang.org/x/net/html"
"image/color"
)
func Paint(c color.Color, s string) string {
@@ -75,8 +76,8 @@ func highlightHeaders(raw string) string {
} else if trimmed == "" {
out.WriteString(line)
} else if idx := strings.Index(trimmed, ": "); idx != -1 {
out.WriteString(Paint(S.Subtle, trimmed[:idx+2]))
out.WriteString(Paint(S.Text, trimmed[idx+2:]))
out.WriteString(Paint(ilovetui.S.Subtle, trimmed[:idx+2]))
out.WriteString(Paint(ilovetui.S.Text, trimmed[idx+2:]))
} else {
out.WriteString(line)
}
@@ -95,16 +96,16 @@ func highlightStatusLine(line string) string {
switch parts[0] {
case "GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "CONNECT", "TRACE":
result := S.Method(parts[0]).Width(0).Render(parts[0]) + " "
result += Paint(S.Primary, parts[1])
result += Paint(ilovetui.S.Primary, parts[1])
if len(parts) == 3 {
result += " " + Paint(S.Subtle, parts[2])
result += " " + Paint(ilovetui.S.Subtle, parts[2])
}
return result
}
result := Paint(S.Subtle, parts[0]) + " "
result += Paint(S.Warning, parts[1])
result := Paint(ilovetui.S.Subtle, parts[0]) + " "
result += Paint(ilovetui.S.Warning, parts[1])
if len(parts) == 3 {
result += " " + Paint(S.MutedFg, parts[2])
result += " " + Paint(ilovetui.S.Muted, parts[2])
}
return result
}
@@ -134,9 +135,9 @@ func highlightJSON(s string) string {
k++
}
if k < n && s[k] == ':' {
out.WriteString(Paint(S.Primary, str))
out.WriteString(Paint(ilovetui.S.Primary, str))
} else {
out.WriteString(Paint(S.Success, str))
out.WriteString(Paint(ilovetui.S.Success, str))
}
i = j
case (ch >= '0' && ch <= '9') || (ch == '-' && i+1 < n && s[i+1] >= '0' && s[i+1] <= '9'):
@@ -147,19 +148,19 @@ func highlightJSON(s string) string {
for j < n && ((s[j] >= '0' && s[j] <= '9') || s[j] == '.' || s[j] == 'e' || s[j] == 'E' || s[j] == '+' || s[j] == '-') {
j++
}
out.WriteString(Paint(S.Warning, s[i:j]))
out.WriteString(Paint(ilovetui.S.Warning, s[i:j]))
i = j
case i+4 <= n && s[i:i+4] == "true":
out.WriteString(Paint(S.Error, "true"))
out.WriteString(Paint(ilovetui.S.Error, "true"))
i += 4
case i+5 <= n && s[i:i+5] == "false":
out.WriteString(Paint(S.Error, "false"))
out.WriteString(Paint(ilovetui.S.Error, "false"))
i += 5
case i+4 <= n && s[i:i+4] == "null":
out.WriteString(Paint(S.Error, "null"))
out.WriteString(Paint(ilovetui.S.Error, "null"))
i += 4
case ch == '{' || ch == '}' || ch == '[' || ch == ']' || ch == ':' || ch == ',':
out.WriteString(Paint(S.Subtle, string(ch)))
out.WriteString(Paint(ilovetui.S.Subtle, string(ch)))
i++
default:
out.WriteByte(ch)
@@ -265,11 +266,11 @@ func highlightHTML(s string) string {
if i+4 <= n && s[i:i+4] == "<!--" {
end := strings.Index(s[i:], "-->")
if end == -1 {
out.WriteString(Paint(S.Subtle, s[i:]))
out.WriteString(Paint(ilovetui.S.Subtle, s[i:]))
break
}
end = i + end + 3
out.WriteString(Paint(S.Subtle, s[i:end]))
out.WriteString(Paint(ilovetui.S.Subtle, s[i:end]))
i = end
continue
}
@@ -278,10 +279,10 @@ func highlightHTML(s string) string {
i++
continue
}
out.WriteString(Paint(S.Subtle, "<"))
out.WriteString(Paint(ilovetui.S.Subtle, "<"))
i++
if i < n && (s[i] == '/' || s[i] == '!') {
out.WriteString(Paint(S.Subtle, string(s[i])))
out.WriteString(Paint(ilovetui.S.Subtle, string(s[i])))
i++
}
j := i
@@ -289,7 +290,7 @@ func highlightHTML(s string) string {
j++
}
if j > i {
out.WriteString(Paint(S.Primary, s[i:j]))
out.WriteString(Paint(ilovetui.S.Primary, s[i:j]))
i = j
}
for i < n && s[i] != '>' {
@@ -299,10 +300,10 @@ func highlightHTML(s string) string {
out.WriteByte(ch)
i++
case ch == '/':
out.WriteString(Paint(S.Subtle, "/"))
out.WriteString(Paint(ilovetui.S.Subtle, "/"))
i++
case ch == '=':
out.WriteString(Paint(S.Subtle, "="))
out.WriteString(Paint(ilovetui.S.Subtle, "="))
i++
case ch == '"' || ch == '\'':
q := ch
@@ -313,19 +314,19 @@ func highlightHTML(s string) string {
if j < n {
j++
}
out.WriteString(Paint(S.Success, s[i:j]))
out.WriteString(Paint(ilovetui.S.Success, s[i:j]))
i = j
default:
j = i
for j < n && s[j] != '=' && s[j] != ' ' && s[j] != '>' && s[j] != '/' && s[j] != '\t' && s[j] != '\n' {
j++
}
out.WriteString(Paint(S.Warning, s[i:j]))
out.WriteString(Paint(ilovetui.S.Warning, s[i:j]))
i = j
}
}
if i < n && s[i] == '>' {
out.WriteString(Paint(S.Subtle, ">"))
out.WriteString(Paint(ilovetui.S.Subtle, ">"))
i++
}
}
+17 -68
View File
@@ -1,29 +1,12 @@
package style
import (
"image/color"
"charm.land/bubbles/v2/help"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/config"
ilovetui "github.com/anotherhadi/ilovetui"
)
type Styles struct {
Primary color.Color
Success color.Color
Error color.Color
Warning color.Color
SubtleBg color.Color
Selection color.Color
Text color.Color
MutedFg color.Color
Subtle color.Color
Bold lipgloss.Style
Faint lipgloss.Style
Panel lipgloss.Style
PanelFocused lipgloss.Style
PanelEditing lipgloss.Style
PagerDotActive string
@@ -38,67 +21,33 @@ type Styles struct {
var S *Styles
func Init(cfg *config.Config) {
c := cfg.TUI.Colors
subtleBg := lipgloss.Color("#" + c.Base01) // Lighter Background (status bars)
selection := lipgloss.Color("#" + c.Base02) // Selection Background
subtle := lipgloss.Color("#" + c.Base03) // Faint text, borders
mutedFg := lipgloss.Color("#" + c.Base04) // Muted foreground
text := lipgloss.Color("#" + c.Base05) // Default Foreground
errCol := lipgloss.Color("#" + c.Base08) // Red: errors
warning := lipgloss.Color("#" + c.Base09) // Orange: warnings
success := lipgloss.Color("#" + c.Base0B) // Green: success
primary := lipgloss.Color("#" + c.Base0D) // Accent: primary
purple := lipgloss.Color("#" + c.Base0E) // Purple: editing
func Init() {
methodBase := lipgloss.NewStyle().Bold(true).Width(7)
S = &Styles{
Primary: primary,
Success: success,
Error: errCol,
Warning: warning,
SubtleBg: subtleBg,
Selection: selection,
MutedFg: mutedFg,
Text: text,
Subtle: subtle,
Bold: lipgloss.NewStyle().Bold(true),
Faint: lipgloss.NewStyle().Foreground(subtle).Faint(true),
Panel: lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(subtle),
PanelFocused: lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(primary),
PanelEditing: lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(purple),
BorderForeground(ilovetui.S.Base0E),
PagerDotActive: lipgloss.NewStyle().Foreground(primary).SetString("•").String(),
PagerDotInactive: lipgloss.NewStyle().Foreground(subtle).SetString("•").String(),
PagerDotActive: lipgloss.NewStyle().Foreground(ilovetui.S.Primary).SetString("•").String(),
PagerDotInactive: lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).SetString("•").String(),
methodGet: methodBase.Foreground(success),
methodPost: methodBase.Foreground(warning),
methodPutPatch: methodBase.Foreground(primary),
methodDelete: methodBase.Foreground(errCol),
methodDefault: methodBase.Foreground(text),
methodGet: methodBase.Foreground(ilovetui.S.Success),
methodPost: methodBase.Foreground(ilovetui.S.Warning),
methodPutPatch: methodBase.Foreground(ilovetui.S.Primary),
methodDelete: methodBase.Foreground(ilovetui.S.Error),
methodDefault: methodBase.Foreground(ilovetui.S.Text),
}
}
func NewHelp() help.Model {
h := help.New()
h.Styles.ShortKey = lipgloss.NewStyle().Foreground(S.Primary)
h.Styles.ShortDesc = lipgloss.NewStyle().Foreground(S.MutedFg)
h.Styles.ShortSeparator = lipgloss.NewStyle().Foreground(S.Subtle)
h.Styles.FullKey = lipgloss.NewStyle().Foreground(S.Primary)
h.Styles.FullDesc = lipgloss.NewStyle().Foreground(S.MutedFg)
h.Styles.FullSeparator = lipgloss.NewStyle().Foreground(S.Subtle)
h.Styles.Ellipsis = lipgloss.NewStyle().Foreground(S.Subtle)
h.Styles.ShortKey = lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
h.Styles.ShortDesc = lipgloss.NewStyle().Foreground(ilovetui.S.Muted)
h.Styles.ShortSeparator = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
h.Styles.FullKey = lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
h.Styles.FullDesc = lipgloss.NewStyle().Foreground(ilovetui.S.Muted)
h.Styles.FullSeparator = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
h.Styles.Ellipsis = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
return h
}
+10 -11
View File
@@ -5,7 +5,7 @@ import (
"strings"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
)
type sidebarState string
@@ -42,7 +42,6 @@ func (m *Model) renderSidebar() string {
if m.sidebarState == sidebarHidden {
return ""
}
s := style.S
// content width inside bordered panel
inner := m.getSidebarWidth() - 2
@@ -50,18 +49,18 @@ func (m *Model) renderSidebar() string {
if m.sidebarState == sidebarCollapsed {
titleText = "SPLT"
}
title := lipgloss.NewStyle().Width(inner).Bold(true).Foreground(s.Primary).Padding(0, 1).Render(titleText)
title := lipgloss.NewStyle().Width(inner).Bold(true).Foreground(ilovetui.S.Primary).Padding(0, 1).Render(titleText)
divider := strings.Repeat("─", inner)
badgeSelected := lipgloss.NewStyle().Foreground(s.Primary).Bold(true)
badgeNormal := lipgloss.NewStyle().Foreground(s.Subtle)
textSelected := lipgloss.NewStyle().Foreground(s.Primary)
textNormal := lipgloss.NewStyle().Foreground(s.Text)
badgeSelected := lipgloss.NewStyle().Foreground(ilovetui.S.Primary).Bold(true)
badgeNormal := lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
textSelected := lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
textNormal := lipgloss.NewStyle().Foreground(ilovetui.S.Text)
lineStyle := lipgloss.NewStyle().Width(inner).Padding(0, 1)
var items strings.Builder
badgeUnread := lipgloss.NewStyle().Foreground(s.Warning).Bold(true)
badgeUnread := lipgloss.NewStyle().Foreground(ilovetui.S.Warning).Bold(true)
for i, entry := range sidebarEntries {
selected := entry.id == m.page
@@ -95,13 +94,13 @@ func (m *Model) renderSidebar() string {
}
parts := []string{
title,
lipgloss.NewStyle().Width(inner).Foreground(s.Subtle).Padding(0, 1).Render(name),
lipgloss.NewStyle().Width(inner).Foreground(ilovetui.S.Subtle).Padding(0, 1).Render(name),
}
parts = append(parts,
lipgloss.NewStyle().Foreground(s.Subtle).Render(divider),
lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).Render(divider),
items.String(),
)
body := lipgloss.JoinVertical(lipgloss.Left, parts...)
return s.Panel.Width(m.getSidebarWidth()).Height(m.height).Render(body)
return ilovetui.S.Panel.Width(m.getSidebarWidth()).Height(m.height).Render(body)
}
+2 -2
View File
@@ -3,7 +3,7 @@ package app
import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
)
func (m Model) View() tea.View {
@@ -52,5 +52,5 @@ func (m *Model) renderActivePage() string {
return e.render(m)
}
}
return style.S.Faint.Render("Work in progress")
return ilovetui.S.Faint.Render("Work in progress")
}
+8 -10
View File
@@ -6,7 +6,7 @@ import (
"charm.land/bubbles/v2/list"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
)
const (
@@ -47,20 +47,18 @@ type Model struct {
}
func New() Model {
s := style.S
delegate := list.NewDefaultDelegate()
delegate.SetSpacing(0)
delegate.Styles.NormalTitle = lipgloss.NewStyle().Foreground(s.Text).PaddingLeft(2)
delegate.Styles.NormalDesc = lipgloss.NewStyle().Foreground(s.Subtle).PaddingLeft(2)
delegate.Styles.NormalTitle = lipgloss.NewStyle().Foreground(ilovetui.S.Text).PaddingLeft(2)
delegate.Styles.NormalDesc = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).PaddingLeft(2)
delegate.Styles.SelectedTitle = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, false, true).
BorderForeground(s.Primary).
Foreground(s.Primary).Bold(true).PaddingLeft(1)
BorderForeground(ilovetui.S.Primary).
Foreground(ilovetui.S.Primary).Bold(true).PaddingLeft(1)
delegate.Styles.SelectedDesc = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, false, true).
BorderForeground(s.Primary).
Foreground(s.MutedFg).PaddingLeft(1)
BorderForeground(ilovetui.S.Primary).
Foreground(ilovetui.S.Muted).PaddingLeft(1)
l := list.New(allItems, delegate, popupW, 8)
l.SetShowTitle(false)
@@ -125,7 +123,7 @@ func (m Model) popupHeight() int {
}
func (m Model) listHeight() int {
return style.PanelContentH(m.popupHeight()) - 1
return ilovetui.ContentHeight(m.popupHeight()) - 1
}
func (m Model) extract(id string) string {
+4 -6
View File
@@ -2,14 +2,12 @@ package copy
import (
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
copyasUI "github.com/anotherhadi/spilltea/internal/ui/components/copyas"
)
func (m *Model) View(background string) string {
s := style.S
hint := lipgloss.NewStyle().Foreground(s.Subtle).
hint := lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).
Render(" enter: copy • /: filter • esc: cancel")
inner := lipgloss.JoinVertical(lipgloss.Left,
@@ -19,10 +17,10 @@ func (m *Model) View(background string) string {
border := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(s.Primary)
BorderForeground(ilovetui.S.Primary)
popupH := m.popupHeight()
popup := style.RenderWithTitle(border, "Copy", inner, m.popupInnerWidth()+2, popupH)
popup := ilovetui.RenderWithTitle(border, "Copy", inner, m.popupInnerWidth()+2, popupH)
return copyasUI.OverlayCenter(background, popup, m.width, m.height)
}
+8 -10
View File
@@ -4,7 +4,7 @@ import (
"charm.land/bubbles/v2/list"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
)
const (
@@ -48,20 +48,18 @@ type Model struct {
}
func New() Model {
s := style.S
delegate := list.NewDefaultDelegate()
delegate.SetSpacing(0)
delegate.Styles.NormalTitle = lipgloss.NewStyle().Foreground(s.Text).PaddingLeft(2)
delegate.Styles.NormalDesc = lipgloss.NewStyle().Foreground(s.Subtle).PaddingLeft(2)
delegate.Styles.NormalTitle = lipgloss.NewStyle().Foreground(ilovetui.S.Text).PaddingLeft(2)
delegate.Styles.NormalDesc = lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).PaddingLeft(2)
delegate.Styles.SelectedTitle = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, false, true).
BorderForeground(s.Primary).
Foreground(s.Primary).Bold(true).PaddingLeft(1)
BorderForeground(ilovetui.S.Primary).
Foreground(ilovetui.S.Primary).Bold(true).PaddingLeft(1)
delegate.Styles.SelectedDesc = lipgloss.NewStyle().
Border(lipgloss.NormalBorder(), false, false, false, true).
BorderForeground(s.Primary).
Foreground(s.MutedFg).PaddingLeft(1)
BorderForeground(ilovetui.S.Primary).
Foreground(ilovetui.S.Muted).PaddingLeft(1)
l := list.New(allFormats, delegate, popupW, 8)
l.SetShowTitle(false)
@@ -116,5 +114,5 @@ func (m Model) popupHeight() int {
// listHeight = panel content area - hint line (1)
func (m Model) listHeight() int {
return style.PanelContentH(m.popupHeight()) - 1
return ilovetui.ContentHeight(m.popupHeight()) - 1
}
+5 -9
View File
@@ -4,14 +4,12 @@ import (
"strings"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/charmbracelet/x/ansi"
)
func (m *Model) View(background string) string {
s := style.S
hint := lipgloss.NewStyle().Foreground(s.Subtle).
hint := lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).
Render(" enter: copy • /: filter • esc: cancel")
inner := lipgloss.JoinVertical(lipgloss.Left,
@@ -21,17 +19,15 @@ func (m *Model) View(background string) string {
border := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(s.Primary)
BorderForeground(ilovetui.S.Primary)
popupH := m.popupHeight()
popup := style.RenderWithTitle(border, "Copy as", inner, m.popupInnerWidth()+2, popupH)
popup := ilovetui.RenderWithTitle(border, "Copy as", inner, m.popupInnerWidth()+2, popupH)
return OverlayCenter(background, popup, m.width, m.height)
}
func OverlayCenter(bg, popup string, w, h int) string {
s := style.S
stripped := ansi.Strip(bg)
rawLines := strings.Split(stripped, "\n")
bgRunes := make([][]rune, h)
@@ -67,7 +63,7 @@ func OverlayCenter(bg, popup string, w, h int) string {
startX = 0
}
dim := lipgloss.NewStyle().Foreground(s.Subtle).Faint(true)
dim := lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).Faint(true)
result := make([]string, h)
for y := 0; y < h; y++ {
@@ -7,7 +7,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/charmbracelet/x/ansi"
)
@@ -76,7 +76,6 @@ func (m Model) View(background string) string {
return background
}
s := style.S
const popupW = 34
var popups []string
@@ -89,17 +88,17 @@ func (m Model) View(background string) string {
var accent color.Color
switch n.kind {
case KindSuccess:
accent = s.Success
accent = ilovetui.S.Success
case KindWarning:
accent = s.Warning
accent = ilovetui.S.Warning
case KindError:
accent = s.Error
accent = ilovetui.S.Error
default:
accent = s.Primary
accent = ilovetui.S.Primary
}
titleStr := lipgloss.NewStyle().Foreground(accent).Bold(true).Render(n.title)
bodyStr := lipgloss.NewStyle().Foreground(s.Text).Width(popupW).Render(n.body)
bodyStr := lipgloss.NewStyle().Foreground(ilovetui.S.Text).Width(popupW).Render(n.body)
inner := lipgloss.JoinVertical(lipgloss.Left, titleStr, bodyStr)
box := lipgloss.NewStyle().
+7 -9
View File
@@ -8,6 +8,7 @@ import (
"charm.land/bubbles/v2/viewport"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/anotherhadi/spilltea/internal/util"
@@ -85,10 +86,9 @@ func wordDiff(leftLine, rightLine string) (leftRendered, rightRendered string) {
segs[lo], segs[hi] = segs[hi], segs[lo]
}
s := style.S
boldErr := lipgloss.NewStyle().Foreground(s.Error).Bold(true)
boldOk := lipgloss.NewStyle().Foreground(s.Success).Bold(true)
dim := lipgloss.NewStyle().Foreground(s.Subtle)
boldErr := lipgloss.NewStyle().Foreground(ilovetui.S.Error).Bold(true)
boldOk := lipgloss.NewStyle().Foreground(ilovetui.S.Success).Bold(true)
dim := lipgloss.NewStyle().Foreground(ilovetui.S.Subtle)
var lb, rb strings.Builder
for _, seg := range segs {
@@ -255,7 +255,7 @@ func (m *Model) recalcSizes() {
rightInner = 0
}
viewportH := style.PanelContentH(panelH)
viewportH := ilovetui.ContentHeight(panelH)
m.leftViewport.SetWidth(leftInner)
m.leftViewport.SetHeight(viewportH)
@@ -296,13 +296,11 @@ func hlLines(raw string) []string {
}
func (m *Model) refreshViewports() {
s := style.S
if m.left.raw == "" {
placeholder := lipgloss.Place(
m.leftViewport.Width(), m.leftViewport.Height(),
lipgloss.Center, lipgloss.Center,
s.Faint.Render(util.CenterLines("<(^_^)>", "send two entries here to compare")),
ilovetui.S.Faint.Render(util.CenterLines("<(^_^)>", "send two entries here to compare")),
)
m.leftViewport.SetContent(placeholder)
m.rightViewport.SetContent("")
@@ -314,7 +312,7 @@ func (m *Model) refreshViewports() {
placeholder := lipgloss.Place(
m.rightViewport.Width(), m.rightViewport.Height(),
lipgloss.Center, lipgloss.Center,
s.Faint.Render(util.CenterLines("(・3・)", "waiting for second entry…")),
ilovetui.S.Faint.Render(util.CenterLines("(・3・)", "waiting for second entry…")),
)
m.rightViewport.SetContent(placeholder)
return
+11 -14
View File
@@ -5,6 +5,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/icons"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/charmbracelet/x/ansi"
@@ -26,8 +27,6 @@ func (m Model) View() tea.View {
}
func (m *Model) renderPanels(panelH int) string {
s := style.S
leftW := m.width / 2
rightW := m.width - leftW
@@ -46,20 +45,20 @@ func (m *Model) renderPanels(panelH int) string {
rightTitle = ansi.Truncate(rightTitle, maxW, "…")
}
leftBorder := s.Panel
rightBorder := s.Panel
leftBorder := ilovetui.S.Panel
rightBorder := ilovetui.S.Panel
switch m.focus {
case bothSlots:
leftBorder = s.PanelFocused
rightBorder = s.PanelFocused
leftBorder = ilovetui.S.PanelFocused
rightBorder = ilovetui.S.PanelFocused
case leftSlot:
leftBorder = s.PanelFocused
leftBorder = ilovetui.S.PanelFocused
case rightSlot:
rightBorder = s.PanelFocused
rightBorder = ilovetui.S.PanelFocused
}
left := style.RenderWithTitle(leftBorder, leftTitle, style.ViewportView(&m.leftViewport), leftW, panelH)
right := style.RenderWithTitle(rightBorder, rightTitle, style.ViewportView(&m.rightViewport), rightW, panelH)
left := ilovetui.RenderWithTitle(leftBorder, leftTitle, style.ViewportView(&m.leftViewport), leftW, panelH)
right := ilovetui.RenderWithTitle(rightBorder, rightTitle, style.ViewportView(&m.rightViewport), rightW, panelH)
return lipgloss.JoinHorizontal(lipgloss.Top, left, right)
}
@@ -69,12 +68,11 @@ func (m *Model) renderStatusBar() string {
}
func renderLeftLines(lines []diffLine) string {
s := style.S
var sb strings.Builder
for _, l := range lines {
switch l.kind {
case lineRemoved:
sb.WriteString(style.Paint(s.Error, "- ") + l.text + "\n")
sb.WriteString(style.Paint(ilovetui.S.Error, "- ") + l.text + "\n")
case lineAdded:
sb.WriteString("\n")
default:
@@ -85,12 +83,11 @@ func renderLeftLines(lines []diffLine) string {
}
func renderRightLines(lines []diffLine) string {
s := style.S
var sb strings.Builder
for _, l := range lines {
switch l.kind {
case lineAdded:
sb.WriteString(style.Paint(s.Success, "+ ") + l.text + "\n")
sb.WriteString(style.Paint(ilovetui.S.Success, "+ ") + l.text + "\n")
case lineRemoved:
sb.WriteString("\n")
default:
+4 -3
View File
@@ -14,6 +14,7 @@ import (
"charm.land/bubbles/v2/viewport"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
)
@@ -58,7 +59,7 @@ func New() Model {
ti := textinput.New()
ti.Prompt = "/"
s := ti.Styles()
s.Focused.Prompt = lipgloss.NewStyle().Foreground(style.S.Primary)
s.Focused.Prompt = lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
ti.SetStyles(s)
return Model{
@@ -182,8 +183,8 @@ func injectHighlightsInLine(ansiLine string, intervals [][]int, currentIdx int)
return ansiLine
}
normalOpen, normalClose := lipglossAnsiCodes(lipgloss.NewStyle().Background(style.S.SubtleBg))
currentOpen, currentClose := lipglossAnsiCodes(lipgloss.NewStyle().Background(style.S.Primary).Foreground(style.S.Text))
normalOpen, normalClose := lipglossAnsiCodes(lipgloss.NewStyle().Background(ilovetui.S.SubtleBg))
currentOpen, currentClose := lipglossAnsiCodes(lipgloss.NewStyle().Background(ilovetui.S.Primary).Foreground(ilovetui.S.Text))
type injection struct {
visPos int
+4 -4
View File
@@ -9,15 +9,15 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/glamour/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/config"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/charmbracelet/x/ansi"
)
func windowStyle() lipgloss.Style {
return lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(style.S.Subtle).
BorderForeground(ilovetui.S.Subtle).
Padding(0, 0)
}
@@ -31,7 +31,7 @@ func (e Model) View() tea.View {
countText = fmt.Sprintf("%d/%d", e.matchIndex+1, len(e.matches))
}
count := lipgloss.NewStyle().Padding(0, 1).
Foreground(style.S.MutedFg).
Foreground(ilovetui.S.Muted).
Render(countText)
statusBar = lipgloss.JoinHorizontal(lipgloss.Top, statusBar, count)
}
@@ -61,7 +61,7 @@ func (m *Model) renderMarkdown() {
width := m.viewport.Width() - 2
renderer, _ := glamour.NewTermRenderer(
glamour.WithStyles(style.GlamourStyleConfig(cfg)),
glamour.WithStyles(ilovetui.GlamourStyleConfig()),
glamour.WithWordWrap(width),
)
+5 -5
View File
@@ -11,7 +11,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/glamour/v2"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/config"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/db"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
@@ -78,7 +78,7 @@ func (m *Model) recalcSizes() {
listH, bodyH := style.SplitH(m.height, m.renderStatusBar(), 0.35)
listVH := style.PanelContentH(listH) - 1 // -1 for the pager dots row
listVH := ilovetui.ContentHeight(listH) - 1 // -1 for the pager dots row
if listVH < 0 {
listVH = 0
}
@@ -89,7 +89,7 @@ func (m *Model) recalcSizes() {
m.pager.PerPage = 1
}
bodyVH := style.PanelContentH(bodyH)
bodyVH := ilovetui.ContentHeight(bodyH)
m.bodyViewport.SetWidth(inner)
m.bodyViewport.SetHeight(bodyVH)
@@ -148,7 +148,7 @@ func (m *Model) refreshBodyScroll(reset bool) {
func (m *Model) renderMarkdownCached(src string, width int) string {
if src == "" {
return style.S.Faint.Render(util.CenterLines("(ㆆ _ ㆆ)", "no description"))
return ilovetui.S.Faint.Render(util.CenterLines("(ㆆ _ ㆆ)", "no description"))
}
tmpl, err := template.New("").Parse(src)
if err != nil {
@@ -164,7 +164,7 @@ func (m *Model) renderMarkdownCached(src string, width int) string {
// Rebuild renderer if width changed or not yet built.
if m.renderer == nil || m.rendererWidth != width {
r, err := glamour.NewTermRenderer(
glamour.WithStyles(style.GlamourStyleConfig(config.Global)),
glamour.WithStyles(ilovetui.GlamourStyleConfig()),
glamour.WithWordWrap(width),
)
if err == nil {
+13 -15
View File
@@ -6,6 +6,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/icons"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/anotherhadi/spilltea/internal/util"
@@ -27,34 +28,31 @@ func (m Model) View() tea.View {
}
func (m *Model) renderListPanel(w, h int) string {
s := style.S
var dots string
if len(m.findings) > 0 {
dots = s.Faint.Render(m.pager.View())
dots = ilovetui.S.Faint.Render(m.pager.View())
}
inner := lipgloss.JoinVertical(lipgloss.Left,
m.listViewport.View(),
lipgloss.PlaceHorizontal(m.listViewport.Width(), lipgloss.Center, dots),
)
return style.RenderWithTitle(s.PanelFocused, icons.I.Findings+"Findings", inner, w, h)
return ilovetui.RenderWithTitle(ilovetui.S.PanelFocused, icons.I.Findings+"Findings", inner, w, h)
}
func (m *Model) renderBodyPanel(h int) string {
s := style.S
title := "Description"
if len(m.findings) > 0 {
title = m.findings[m.cursor].Title
}
return style.RenderWithTitle(s.Panel, title, style.ViewportView(&m.bodyViewport), m.width, h)
return ilovetui.RenderWithTitle(ilovetui.S.Panel, title, style.ViewportView(&m.bodyViewport), m.width, h)
}
func (m *Model) renderList() string {
s := style.S
if len(m.findings) == 0 {
return lipgloss.Place(
m.listViewport.Width(), m.listViewport.Height(),
lipgloss.Center, lipgloss.Center,
s.Faint.Render(util.CenterLines("(҂◡_◡) ᕤ", "no findings")),
ilovetui.S.Faint.Render(util.CenterLines("(҂◡_◡) ᕤ", "no findings")),
)
}
@@ -76,18 +74,18 @@ func (m *Model) renderList() string {
titleW = 0
}
pluginStr := s.Faint.Width(8).Render(util.Truncate(f.PluginName, 8))
pluginStr := ilovetui.S.Faint.Width(8).Render(util.Truncate(f.PluginName, 8))
var line string
if selected {
bg := lipgloss.NewStyle().Background(s.Selection)
bg := lipgloss.NewStyle().Background(ilovetui.S.Selection)
line = lipgloss.JoinHorizontal(lipgloss.Top,
bg.Bold(true).Foreground(s.Primary).Width(2).Render(">"),
sevStyle.Background(s.Selection).Width(8).Render(f.Severity),
bg.Bold(true).Foreground(ilovetui.S.Primary).Width(2).Render(">"),
sevStyle.Background(ilovetui.S.Selection).Width(8).Render(f.Severity),
bg.Width(1).Render(""),
bg.Foreground(s.Subtle).Width(8).Render(util.Truncate(f.PluginName, 8)),
bg.Foreground(ilovetui.S.Subtle).Width(8).Render(util.Truncate(f.PluginName, 8)),
bg.Width(1).Render(""),
bg.Foreground(s.Subtle).Width(10).Render(ts),
bg.Foreground(ilovetui.S.Subtle).Width(10).Render(ts),
bg.Width(1).Render(""),
bg.Bold(true).Width(titleW).Render(f.Title),
)
@@ -98,9 +96,9 @@ func (m *Model) renderList() string {
" ",
pluginStr,
" ",
s.Faint.Width(10).Render(ts),
ilovetui.S.Faint.Width(10).Render(ts),
" ",
s.Bold.Render(f.Title),
ilovetui.S.Bold.Render(f.Title),
)
}
sb.WriteString(fmt.Sprintf("%s\n", line))
+3 -2
View File
@@ -7,6 +7,7 @@ import (
"charm.land/bubbles/v2/textinput"
"charm.land/bubbles/v2/viewport"
tea "charm.land/bubbletea/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/db"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
@@ -131,7 +132,7 @@ func (m *Model) recalcSizes() {
inner = 0
}
listVH := style.PanelContentH(listH) - 1 // -1 for the pager dots row
listVH := ilovetui.ContentHeight(listH) - 1 // -1 for the pager dots row
if listVH < 0 {
listVH = 0
}
@@ -142,7 +143,7 @@ func (m *Model) recalcSizes() {
m.pager.PerPage = 1
}
bodyVH := style.PanelContentH(bodyH)
bodyVH := ilovetui.ContentHeight(bodyH)
m.bodyViewport.SetWidth(inner)
m.bodyViewport.SetHeight(bodyVH)
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"charm.land/bubbles/v2/key"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/db"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
@@ -345,7 +346,7 @@ func (m *Model) refreshBody() {
}
if raw == "" {
w, h := m.bodyViewport.Width(), m.bodyViewport.Height()
m.bodyViewport.SetContent(lipgloss.Place(w, h, lipgloss.Center, lipgloss.Center, style.S.Faint.Render(util.CenterLines("(˘・_・˘)", "no response stored"))))
m.bodyViewport.SetContent(lipgloss.Place(w, h, lipgloss.Center, lipgloss.Center, ilovetui.S.Faint.Render(util.CenterLines("(˘・_・˘)", "no response stored"))))
return
}
m.bodyViewport.SetContent(style.HighlightHTTP(raw))
+22 -25
View File
@@ -6,6 +6,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/icons"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
@@ -28,60 +29,56 @@ func (m Model) View() tea.View {
}
func (m *Model) renderListPanel(w, h int) string {
s := style.S
var dots string
if len(m.entries) > 0 {
dots = s.Faint.Render(m.pager.View())
dots = ilovetui.S.Faint.Render(m.pager.View())
}
inner := lipgloss.JoinVertical(lipgloss.Left,
m.listViewport.View(),
lipgloss.PlaceHorizontal(m.listViewport.Width(), lipgloss.Center, dots),
)
return style.RenderWithTitle(s.PanelFocused, icons.I.History+"History", inner, w, h)
return ilovetui.RenderWithTitle(ilovetui.S.PanelFocused, icons.I.History+"History", inner, w, h)
}
func (m *Model) renderBodyPanel(h int) string {
s := style.S
title := icons.I.Request + "Request"
if m.focusedPanel == panelResponse {
title = icons.I.Response + "Response"
}
return style.RenderWithTitle(s.Panel, title, style.ViewportView(&m.bodyViewport), m.width, h)
return ilovetui.RenderWithTitle(ilovetui.S.Panel, title, style.ViewportView(&m.bodyViewport), m.width, h)
}
func (m *Model) renderStatusBar() string {
s := style.S
pad := lipgloss.NewStyle().Padding(0, 1)
escKey := keys.Keys.Global.Escape.Help().Key
switch m.searchKind {
case searchKindFulltext:
filterKey := keys.Keys.History.Filter.Help().Key
if m.searchAccepted {
accent := lipgloss.NewStyle().Foreground(s.Primary)
filterLine := pad.Render(accent.Render(filterKey) + " " + s.Bold.Render(m.searchInput.Value()) + s.Faint.Render(" "+escKey+" to clear"))
accent := lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
filterLine := pad.Render(accent.Render(filterKey) + " " + ilovetui.S.Bold.Render(m.searchInput.Value()) + ilovetui.S.Faint.Render(" "+escKey+" to clear"))
return lipgloss.JoinVertical(lipgloss.Left, filterLine, pad.Render(m.help.View(historyKeyMap{width: m.width})))
}
return pad.Render(s.Faint.Render(filterKey) + " " + m.searchInput.View())
return pad.Render(ilovetui.S.Faint.Render(filterKey) + " " + m.searchInput.View())
case searchKindSQL:
sqlKey := keys.Keys.History.SqlQuery.Help().Key
if m.searchAccepted {
accent := lipgloss.NewStyle().Foreground(s.Primary)
filterLine := pad.Render(accent.Render(sqlKey) + " " + s.Bold.Render(m.searchInput.Value()) + s.Faint.Render(" "+escKey+" to clear"))
accent := lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
filterLine := pad.Render(accent.Render(sqlKey) + " " + ilovetui.S.Bold.Render(m.searchInput.Value()) + ilovetui.S.Faint.Render(" "+escKey+" to clear"))
return lipgloss.JoinVertical(lipgloss.Left, filterLine, pad.Render(m.help.View(historyKeyMap{width: m.width})))
}
return pad.Render(s.Faint.Render(sqlKey) + " " + m.searchInput.View())
return pad.Render(ilovetui.S.Faint.Render(sqlKey) + " " + m.searchInput.View())
default:
return pad.Render(m.help.View(historyKeyMap{width: m.width}))
}
}
func (m *Model) renderList() string {
s := style.S
if m.searchErr != "" {
return lipgloss.Place(
m.listViewport.Width(), m.listViewport.Height(),
lipgloss.Center, lipgloss.Center,
lipgloss.NewStyle().Foreground(s.Error).Render(m.searchErr),
lipgloss.NewStyle().Foreground(ilovetui.S.Error).Render(m.searchErr),
)
}
if len(m.entries) == 0 {
@@ -92,7 +89,7 @@ func (m *Model) renderList() string {
return lipgloss.Place(
m.listViewport.Width(), m.listViewport.Height(),
lipgloss.Center, lipgloss.Center,
s.Faint.Render(msg),
ilovetui.S.Faint.Render(msg),
)
}
@@ -103,7 +100,7 @@ func (m *Model) renderList() string {
globalIdx := start + i
selected := globalIdx == m.cursor
selBg := s.Selection
selBg := ilovetui.S.Selection
w := m.listViewport.Width()
statusStr := fmt.Sprintf("%3d", e.StatusCode)
@@ -115,7 +112,7 @@ func (m *Model) renderList() string {
ts := e.Timestamp.Format("15:04:05")
statusSt := style.StatusStyle(e.StatusCode, 3)
flagSt := lipgloss.NewStyle().Foreground(s.Primary)
flagSt := lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
var line string
if selected {
@@ -128,13 +125,13 @@ func (m *Model) renderList() string {
}
}
line = lipgloss.JoinHorizontal(lipgloss.Top,
bg.Bold(true).Foreground(s.Primary).Width(2).Render(">"),
bg.Foreground(s.Primary).Width(2).Render(flagStr),
s.Method(e.Method).Background(selBg).Render(e.Method),
bg.Bold(true).Foreground(ilovetui.S.Primary).Width(2).Render(">"),
bg.Foreground(ilovetui.S.Primary).Width(2).Render(flagStr),
style.S.Method(e.Method).Background(selBg).Render(e.Method),
bg.Width(1).Render(""),
statusSt.Background(selBg).Render(statusStr),
bg.Width(1).Render(""),
bg.Foreground(s.Subtle).Width(10).Render(ts),
bg.Foreground(ilovetui.S.Subtle).Width(10).Render(ts),
bg.Width(1).Render(""),
bg.Bold(true).Width(hostPathW).Render(e.Host+e.Path),
)
@@ -149,14 +146,14 @@ func (m *Model) renderList() string {
line = lipgloss.JoinHorizontal(lipgloss.Top,
" ",
flagSt.Width(2).Render(flagStr),
s.Method(e.Method).Render(e.Method),
style.S.Method(e.Method).Render(e.Method),
" ",
statusSt.Render(statusStr),
" ",
s.Faint.Width(10).Render(ts),
ilovetui.S.Faint.Width(10).Render(ts),
" ",
s.Bold.Render(e.Host),
s.Faint.Render(e.Path),
ilovetui.S.Bold.Render(e.Host),
ilovetui.S.Faint.Render(e.Path),
)
}
sb.WriteString(line + "\n")
+10 -12
View File
@@ -14,10 +14,10 @@ import (
"charm.land/bubbles/v2/textinput"
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/db"
"github.com/anotherhadi/spilltea/internal/icons"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/anotherhadi/spilltea/internal/ui/components/teapot"
)
@@ -88,19 +88,18 @@ type homeDelegate struct {
}
func newHomeDelegate() homeDelegate {
s := style.S
leftBorder := lipgloss.Border{Left: "│"}
return homeDelegate{
normalTitle: lipgloss.NewStyle().Foreground(s.Text).PaddingLeft(4),
normalDesc: lipgloss.NewStyle().Foreground(s.Subtle).Faint(true).PaddingLeft(4),
normalTitle: lipgloss.NewStyle().Foreground(ilovetui.S.Text).PaddingLeft(4),
normalDesc: lipgloss.NewStyle().Foreground(ilovetui.S.Subtle).Faint(true).PaddingLeft(4),
selectedTitle: lipgloss.NewStyle().
Border(leftBorder, false, false, false, true).
BorderForeground(s.Primary).
Foreground(s.Primary).Bold(true).PaddingLeft(3),
BorderForeground(ilovetui.S.Primary).
Foreground(ilovetui.S.Primary).Bold(true).PaddingLeft(3),
selectedDesc: lipgloss.NewStyle().
Border(leftBorder, false, false, false, true).
BorderForeground(s.Primary).
Foreground(s.MutedFg).PaddingLeft(3),
BorderForeground(ilovetui.S.Primary).
Foreground(ilovetui.S.Muted).PaddingLeft(3),
filterMatch: lipgloss.NewStyle().Underline(true),
}
}
@@ -304,14 +303,13 @@ func buildItems(projects []Project) []list.Item {
}
func (m Model) renderHelpLine() string {
s := style.S
k := keys.Keys.Home
fs := m.list.FilterState()
kStyle := lipgloss.NewStyle().Foreground(s.MutedFg).Inline(true)
dStyle := s.Faint.Inline(true)
kStyle := lipgloss.NewStyle().Foreground(ilovetui.S.Muted).Inline(true)
dStyle := ilovetui.S.Faint.Inline(true)
sep := s.Faint.Inline(true).Render(" • ")
sep := ilovetui.S.Faint.Inline(true).Render(" • ")
item := func(keyStr, desc string) string {
return kStyle.Render(keyStr) + " " + dStyle.Render(desc)
}
+7 -9
View File
@@ -5,29 +5,28 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/style"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/ui/components/teapot"
)
const inputPanelMaxW = 44
func (m Model) View() tea.View {
s := style.S
iw := m.innerW()
var sb strings.Builder
sb.WriteString("\n")
if m.height > teapotMinH {
frames := teapot.TeapotFrames()
frame := lipgloss.NewStyle().Foreground(s.Primary).Render(frames[m.teapotFrame])
frame := lipgloss.NewStyle().Foreground(ilovetui.S.Primary).Render(frames[m.teapotFrame])
sb.WriteString(center(iw, frame))
sb.WriteString("\n\n")
} else {
sb.WriteString("\n")
}
sb.WriteString(center(iw, lipgloss.NewStyle().Bold(true).Foreground(s.Primary).Render("SPILLTEA")))
sb.WriteString(center(iw, lipgloss.NewStyle().Bold(true).Foreground(ilovetui.S.Primary).Render("SPILLTEA")))
sb.WriteString("\n")
sb.WriteString(center(iw, s.Faint.Render("choose a project to get started")))
sb.WriteString(center(iw, ilovetui.S.Faint.Render("choose a project to get started")))
sb.WriteString("\n\n")
if m.mode == modeNaming {
@@ -50,7 +49,6 @@ func (m Model) View() tea.View {
}
func (m Model) renderNamingPanel() string {
s := style.S
iw := m.innerW()
panelW := inputPanelMaxW
@@ -63,15 +61,15 @@ func (m Model) renderNamingPanel() string {
innerW := inputPanelInnerW(iw)
inputLine := lipgloss.NewStyle().Width(innerW).Render(m.nameInput.View())
label := lipgloss.NewStyle().Foreground(s.MutedFg).Render("Project name")
label := lipgloss.NewStyle().Foreground(ilovetui.S.Muted).Render("Project name")
panel := lipgloss.NewStyle().
Border(lipgloss.RoundedBorder()).
BorderForeground(s.Primary).
BorderForeground(ilovetui.S.Primary).
Padding(1, 2).
Width(panelW).
Render(label + "\n" + inputLine)
hint := s.Faint.Render("[enter] confirm [esc] cancel")
hint := ilovetui.S.Faint.Render("[enter] confirm [esc] cancel")
var sb strings.Builder
sb.WriteString(center(iw, panel))
+3 -2
View File
@@ -7,6 +7,7 @@ import (
"strconv"
"strings"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/intercept"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/anotherhadi/spilltea/internal/util"
@@ -163,14 +164,14 @@ func (m *Model) recalcSizes() {
if bodyInner < 0 {
bodyInner = 0
}
bodyVH := style.PanelContentH(bodyH)
bodyVH := ilovetui.ContentHeight(bodyH)
m.textarea.SetWidth(bodyInner)
m.textarea.SetHeight(bodyVH)
m.bodyViewport.SetWidth(bodyInner)
m.bodyViewport.SetHeight(bodyVH)
listVH := style.PanelContentH(listH) - 1 // -1 for the pager dots row
listVH := ilovetui.ContentHeight(listH) - 1 // -1 for the pager dots row
if listVH < 0 {
listVH = 0
}
+27 -34
View File
@@ -6,6 +6,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/icons"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/anotherhadi/spilltea/internal/util"
@@ -38,17 +39,15 @@ func (m Model) View() tea.View {
}
func (m *Model) renderListPanel(w, h int) string {
s := style.S
focused := !m.editing && (!m.captureResponse || m.focusedPanel == panelRequests)
border := s.Panel
border := ilovetui.S.Panel
if focused {
border = s.PanelFocused
border = ilovetui.S.PanelFocused
}
var dots string
if len(m.queue) > 0 {
dots = s.Faint.Render(m.pager.View())
dots = ilovetui.S.Faint.Render(m.pager.View())
}
inner := lipgloss.JoinVertical(lipgloss.Left,
m.listViewport.View(),
@@ -57,32 +56,28 @@ func (m *Model) renderListPanel(w, h int) string {
title := icons.I.Request + "Requests"
if !m.interceptEnabled {
title += " " + lipgloss.NewStyle().Foreground(style.S.Error).Render("[intercept off]")
title += " " + lipgloss.NewStyle().Foreground(ilovetui.S.Error).Render("[intercept off]")
}
return style.RenderWithTitle(border, title, inner, w, h)
return ilovetui.RenderWithTitle(border, title, inner, w, h)
}
func (m *Model) renderResponseListPanel(w, h int) string {
s := style.S
focused := !m.editing && m.focusedPanel == panelResponses
border := s.Panel
border := ilovetui.S.Panel
if focused {
border = s.PanelFocused
border = ilovetui.S.PanelFocused
}
dots := s.Faint.Render(m.responsePager.View())
dots := ilovetui.S.Faint.Render(m.responsePager.View())
inner := lipgloss.JoinVertical(lipgloss.Left,
m.responseViewport.View(),
lipgloss.PlaceHorizontal(m.responseViewport.Width(), lipgloss.Center, dots),
)
return style.RenderWithTitle(border, icons.I.Response+"Responses", inner, w, h)
return ilovetui.RenderWithTitle(border, icons.I.Response+"Responses", inner, w, h)
}
func (m *Model) renderBodyPanel(h int) string {
s := style.S
var body string
if m.editing {
body = m.textarea.View()
@@ -90,13 +85,13 @@ func (m *Model) renderBodyPanel(h int) string {
body = style.ViewportView(&m.bodyViewport)
}
border := s.Panel
border := ilovetui.S.Panel
if m.editing {
border = s.PanelFocused
border = ilovetui.S.PanelFocused
}
title := icons.I.Detail + "Details"
return style.RenderWithTitle(border, title, body, m.width, h)
return ilovetui.RenderWithTitle(border, title, body, m.width, h)
}
func (m *Model) renderStatusBar() string {
@@ -105,10 +100,9 @@ func (m *Model) renderStatusBar() string {
func (m *Model) renderList() string {
if len(m.queue) == 0 {
return lipgloss.Place(m.listViewport.Width(), m.listViewport.Height(), lipgloss.Center, lipgloss.Center, style.S.Faint.Render(util.CenterLines("(。◕‿‿◕。)", "waiting for a request")))
return lipgloss.Place(m.listViewport.Width(), m.listViewport.Height(), lipgloss.Center, lipgloss.Center, ilovetui.S.Faint.Render(util.CenterLines("(。◕‿‿◕。)", "waiting for a request")))
}
s := style.S
start, end := util.PageBounds(m.pager, len(m.queue))
var sb strings.Builder
@@ -121,7 +115,7 @@ func (m *Model) renderList() string {
}
selected := globalIdx == m.cursor
selBg := s.Selection
selBg := ilovetui.S.Selection
w := m.listViewport.Width()
const fixedW = 2 + 7 + 2
@@ -134,18 +128,18 @@ func (m *Model) renderList() string {
if selected {
bg := lipgloss.NewStyle().Background(selBg)
line = lipgloss.JoinHorizontal(lipgloss.Top,
bg.Bold(true).Foreground(s.Primary).Width(2).Render(">"),
s.Method(r.Method).Background(selBg).Render(r.Method),
bg.Bold(true).Foreground(ilovetui.S.Primary).Width(2).Render(">"),
style.S.Method(r.Method).Background(selBg).Render(r.Method),
bg.Width(2).Render(""),
bg.Bold(true).Width(hostPathW).Render(r.URL.Host+path),
)
} else {
line = lipgloss.JoinHorizontal(lipgloss.Top,
" ",
s.Method(r.Method).Render(r.Method),
s.Faint.Render(" "),
s.Bold.Render(r.URL.Host),
s.Faint.Render(path),
style.S.Method(r.Method).Render(r.Method),
ilovetui.S.Faint.Render(" "),
ilovetui.S.Bold.Render(r.URL.Host),
ilovetui.S.Faint.Render(path),
)
}
sb.WriteString(line + "\n")
@@ -155,10 +149,9 @@ func (m *Model) renderList() string {
func (m *Model) renderResponseList() string {
if len(m.responseQueue) == 0 {
return lipgloss.Place(m.responseViewport.Width(), m.responseViewport.Height(), lipgloss.Center, lipgloss.Center, style.S.Faint.Render(util.CenterLines("(҂◡_◡)", "no response yet")))
return lipgloss.Place(m.responseViewport.Width(), m.responseViewport.Height(), lipgloss.Center, lipgloss.Center, ilovetui.S.Faint.Render(util.CenterLines("(҂◡_◡)", "no response yet")))
}
s := style.S
start, end := util.PageBounds(m.responsePager, len(m.responseQueue))
var sb strings.Builder
@@ -177,7 +170,7 @@ func (m *Model) renderResponseList() string {
statusStr := fmt.Sprintf("%d", code)
selected := globalIdx == m.responseCursor
selBg := s.Selection
selBg := ilovetui.S.Selection
statusSt := style.StatusStyle(code, 7)
@@ -192,7 +185,7 @@ func (m *Model) renderResponseList() string {
if selected {
bg := lipgloss.NewStyle().Background(selBg)
line = lipgloss.JoinHorizontal(lipgloss.Top,
bg.Bold(true).Foreground(s.Primary).Width(2).Render(">"),
bg.Bold(true).Foreground(ilovetui.S.Primary).Width(2).Render(">"),
statusSt.Background(selBg).Render(statusStr),
bg.Width(2).Render(""),
bg.Bold(true).Width(hostPathW).Render(f.Request.URL.Host+path),
@@ -201,9 +194,9 @@ func (m *Model) renderResponseList() string {
line = lipgloss.JoinHorizontal(lipgloss.Top,
" ",
statusSt.Render(statusStr),
s.Faint.Render(" "),
s.Bold.Render(f.Request.URL.Host),
s.Faint.Render(path),
ilovetui.S.Faint.Render(" "),
ilovetui.S.Bold.Render(f.Request.URL.Host),
ilovetui.S.Faint.Render(path),
)
}
sb.WriteString(line + "\n")
+3 -2
View File
@@ -10,6 +10,7 @@ import (
"charm.land/bubbles/v2/textinput"
"charm.land/bubbles/v2/viewport"
tea "charm.land/bubbletea/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/plugins"
"github.com/anotherhadi/spilltea/internal/style"
@@ -77,7 +78,7 @@ func (m *Model) recalcSizes() {
inner = 0
}
listVH := style.PanelContentH(listH) - 1 // -1 for the pager dots row
listVH := ilovetui.ContentHeight(listH) - 1 // -1 for the pager dots row
if listVH < 0 {
listVH = 0
}
@@ -90,7 +91,7 @@ func (m *Model) recalcSizes() {
m.filterInput.SetWidth(inner - 2)
detailContentH := style.PanelContentH(detailH)
detailContentH := ilovetui.ContentHeight(detailH)
const headerH = 2
const configFixedH = 2 // blank line + label line
textareaH := max(3, detailContentH/3)
+27 -31
View File
@@ -7,7 +7,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/glamour/v2"
"charm.land/lipgloss/v2"
"github.com/anotherhadi/spilltea/internal/config"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/icons"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
@@ -16,7 +16,7 @@ import (
func (m Model) View() tea.View {
if m.width == 0 || m.manager == nil {
return tea.NewView(lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, style.S.Faint.Render(util.CenterLines("(._.)~*.'", "no plugins loaded"))))
return tea.NewView(lipgloss.Place(m.width, m.height, lipgloss.Center, lipgloss.Center, ilovetui.S.Faint.Render(util.CenterLines("(._.)~*.'", "no plugins loaded"))))
}
listH, detailH := style.SplitH(m.height, m.renderStatusBar(), 0.4)
@@ -30,36 +30,34 @@ func (m Model) View() tea.View {
}
func (m *Model) renderListPanel(w, h int) string {
s := style.S
panelStyle := s.PanelFocused
panelStyle := ilovetui.S.PanelFocused
if m.editing {
panelStyle = s.Panel
panelStyle = ilovetui.S.Panel
}
var dots string
if len(m.filtered) > 0 {
dots = s.Faint.Render(m.pager.View())
dots = ilovetui.S.Faint.Render(m.pager.View())
}
inner := lipgloss.JoinVertical(lipgloss.Left,
m.listViewport.View(),
lipgloss.PlaceHorizontal(m.listViewport.Width(), lipgloss.Center, dots),
)
return style.RenderWithTitle(panelStyle, icons.I.Plugin+"Plugins", inner, w, h)
return ilovetui.RenderWithTitle(panelStyle, icons.I.Plugin+"Plugins", inner, w, h)
}
func (m *Model) renderDetailPanel(h int) string {
s := style.S
panelStyle := s.Panel
panelStyle := ilovetui.S.Panel
if m.editing {
panelStyle = s.PanelFocused
panelStyle = ilovetui.S.PanelFocused
}
info, ok := m.selected()
if !ok {
return style.RenderWithTitle(panelStyle, icons.I.Detail+"Detail", "", m.width, h)
return ilovetui.RenderWithTitle(panelStyle, icons.I.Detail+"Detail", "", m.width, h)
}
statusSt := lipgloss.NewStyle().Foreground(s.Error)
statusSt := lipgloss.NewStyle().Foreground(ilovetui.S.Error)
if info.Enabled {
statusSt = lipgloss.NewStyle().Foreground(s.Success)
statusSt = lipgloss.NewStyle().Foreground(ilovetui.S.Success)
}
status := "disabled"
if info.Enabled {
@@ -69,8 +67,8 @@ func (m *Model) renderDetailPanel(h int) string {
pad := lipgloss.NewStyle().Padding(0, 1)
header := pad.Render(
s.Bold.Render(info.Name) + " " + statusSt.Render(status) + "\n" +
s.Faint.Render(filepath.Base(info.FilePath)),
ilovetui.S.Bold.Render(info.Name) + " " + statusSt.Render(status) + "\n" +
ilovetui.S.Faint.Render(filepath.Base(info.FilePath)),
)
parts := []string{header, style.ViewportView(&m.detailViewport)}
@@ -79,16 +77,16 @@ func (m *Model) renderDetailPanel(h int) string {
var configLabel string
if m.editing {
escKey := keys.Keys.Global.Escape.Help().Key
configLabel = pad.Render(s.Faint.Render("editing config (" + escKey + " to save):"))
configLabel = pad.Render(ilovetui.S.Faint.Render("editing config (" + escKey + " to save):"))
} else {
editKey := keys.Keys.Plugins.EditConfig.Help().Key
configLabel = pad.Render(s.Faint.Render("config (" + editKey + " to edit):"))
configLabel = pad.Render(ilovetui.S.Faint.Render("config (" + editKey + " to edit):"))
}
parts = append(parts, "", configLabel, pad.Render(m.textarea.View()))
}
inner := lipgloss.JoinVertical(lipgloss.Left, parts...)
return style.RenderWithTitle(panelStyle, icons.I.Detail+"Detail", inner, m.width, h)
return ilovetui.RenderWithTitle(panelStyle, icons.I.Detail+"Detail", inner, m.width, h)
}
func renderPluginDescription(desc string, width int) string {
@@ -100,7 +98,7 @@ func renderPluginDescription(desc string, width int) string {
desc = strings.Join(lines, "\n")
r, err := glamour.NewTermRenderer(
glamour.WithStyles(style.GlamourStyleConfig(config.Global)),
glamour.WithStyles(ilovetui.GlamourStyleConfig()),
glamour.WithWordWrap(width),
)
if err != nil {
@@ -114,23 +112,21 @@ func renderPluginDescription(desc string, width int) string {
}
func (m *Model) renderStatusBar() string {
s := style.S
pad := lipgloss.NewStyle().Padding(0, 1)
filterKey := keys.Keys.Plugins.Filter.Help().Key
if m.filtering {
return pad.Render(s.Faint.Render(filterKey) + " " + m.filterInput.View())
return pad.Render(ilovetui.S.Faint.Render(filterKey) + " " + m.filterInput.View())
}
if m.filter != "" {
escKey := keys.Keys.Global.Escape.Help().Key
accent := lipgloss.NewStyle().Foreground(s.Primary)
filterLine := pad.Render(accent.Render(filterKey) + " " + s.Bold.Render(m.filter) + s.Faint.Render(" "+escKey+" to clear"))
accent := lipgloss.NewStyle().Foreground(ilovetui.S.Primary)
filterLine := pad.Render(accent.Render(filterKey) + " " + ilovetui.S.Bold.Render(m.filter) + ilovetui.S.Faint.Render(" "+escKey+" to clear"))
return lipgloss.JoinVertical(lipgloss.Left, filterLine, pad.Render(m.help.View(pluginsKeyMap{editing: m.editing, hasConfig: m.hasConfig(), width: m.width})))
}
return pad.Render(m.help.View(pluginsKeyMap{editing: m.editing, hasConfig: m.hasConfig(), width: m.width}))
}
func (m *Model) renderList() string {
s := style.S
if len(m.filtered) == 0 {
msg := util.CenterLines("(ง •̀_•́)ง", "no plugins", "", "spilltea --add-default-plugins")
if m.filter != "" {
@@ -139,7 +135,7 @@ func (m *Model) renderList() string {
return lipgloss.Place(
m.listViewport.Width(), m.listViewport.Height(),
lipgloss.Center, lipgloss.Center,
s.Faint.Render(msg),
ilovetui.S.Faint.Render(msg),
)
}
@@ -150,10 +146,10 @@ func (m *Model) renderList() string {
globalIdx := start + i
selected := globalIdx == m.cursor
enabledSt := lipgloss.NewStyle().Foreground(s.Error)
enabledSt := lipgloss.NewStyle().Foreground(ilovetui.S.Error)
enabledStr := "off"
if p.Enabled {
enabledSt = lipgloss.NewStyle().Foreground(s.Success)
enabledSt = lipgloss.NewStyle().Foreground(ilovetui.S.Success)
enabledStr = "on "
}
@@ -166,10 +162,10 @@ func (m *Model) renderList() string {
var line string
if selected {
bg := lipgloss.NewStyle().Background(s.Selection)
bg := lipgloss.NewStyle().Background(ilovetui.S.Selection)
line = lipgloss.JoinHorizontal(lipgloss.Top,
bg.Bold(true).Foreground(s.Primary).Width(2).Render(">"),
enabledSt.Background(s.Selection).Width(3).Render(enabledStr),
bg.Bold(true).Foreground(ilovetui.S.Primary).Width(2).Render(">"),
enabledSt.Background(ilovetui.S.Selection).Width(3).Render(enabledStr),
bg.Width(1).Render(""),
bg.Bold(true).Width(nameW).Render(p.Name),
)
@@ -178,7 +174,7 @@ func (m *Model) renderList() string {
" ",
enabledSt.Width(3).Render(enabledStr),
" ",
s.Bold.Render(p.Name),
ilovetui.S.Bold.Render(p.Name),
)
}
sb.WriteString(line + "\n")
+3 -2
View File
@@ -9,6 +9,7 @@ import (
"charm.land/bubbles/v2/textarea"
"charm.land/bubbles/v2/viewport"
tea "charm.land/bubbletea/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/db"
"github.com/anotherhadi/spilltea/internal/keys"
"github.com/anotherhadi/spilltea/internal/style"
@@ -155,7 +156,7 @@ func (m *Model) recalcSizes() {
if listInner < 0 {
listInner = 0
}
listVH := style.PanelContentH(listH) - 1 // -1 for the pager dots row
listVH := ilovetui.ContentHeight(listH) - 1 // -1 for the pager dots row
if listVH < 0 {
listVH = 0
}
@@ -175,7 +176,7 @@ func (m *Model) recalcSizes() {
if rightInner < 0 {
rightInner = 0
}
bodyVH := style.PanelContentH(bodyH)
bodyVH := ilovetui.ContentHeight(bodyH)
m.requestViewport.SetWidth(leftInner)
m.requestViewport.SetHeight(bodyVH)
+3 -2
View File
@@ -16,6 +16,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
"github.com/andybalholm/brotli"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/config"
"github.com/anotherhadi/spilltea/internal/db"
"github.com/anotherhadi/spilltea/internal/keys"
@@ -350,11 +351,11 @@ func (m *Model) refreshBody() {
m.requestViewport.SetXOffset(0)
if e.Sending {
m.responseViewport.SetContent(lipgloss.Place(m.responseViewport.Width(), m.responseViewport.Height(), lipgloss.Center, lipgloss.Center, style.S.Faint.Render(util.CenterLines("(ノ◕ヮ◕)ノ*:・゚", "sending..."))))
m.responseViewport.SetContent(lipgloss.Place(m.responseViewport.Width(), m.responseViewport.Height(), lipgloss.Center, lipgloss.Center, ilovetui.S.Faint.Render(util.CenterLines("(ノ◕ヮ◕)ノ*:・゚", "sending..."))))
} else if e.ResponseRaw != "" {
m.responseViewport.SetContent(style.HighlightHTTP(e.ResponseRaw))
} else {
m.responseViewport.SetContent(lipgloss.Place(m.responseViewport.Width(), m.responseViewport.Height(), lipgloss.Center, lipgloss.Center, style.S.Faint.Render(util.CenterLines("( •_•)>⌐■", "press send to fire"))))
m.responseViewport.SetContent(lipgloss.Place(m.responseViewport.Width(), m.responseViewport.Height(), lipgloss.Center, lipgloss.Center, ilovetui.S.Faint.Render(util.CenterLines("( •_•)>⌐■", "press send to fire"))))
}
m.responseViewport.SetYOffset(0)
m.responseViewport.SetXOffset(0)
+22 -25
View File
@@ -6,6 +6,7 @@ import (
tea "charm.land/bubbletea/v2"
"charm.land/lipgloss/v2"
ilovetui "github.com/anotherhadi/ilovetui"
"github.com/anotherhadi/spilltea/internal/icons"
"github.com/anotherhadi/spilltea/internal/style"
"github.com/anotherhadi/spilltea/internal/util"
@@ -33,45 +34,42 @@ func (m Model) View() tea.View {
}
func (m *Model) renderListPanel(w, h int) string {
s := style.S
panelStyle := s.Panel
panelStyle := ilovetui.S.Panel
if !m.editing && m.focusedPanel == panelList {
panelStyle = s.PanelFocused
panelStyle = ilovetui.S.PanelFocused
}
var dots string
if len(m.entries) > 0 {
dots = s.Faint.Render(m.pager.View())
dots = ilovetui.S.Faint.Render(m.pager.View())
}
inner := lipgloss.JoinVertical(lipgloss.Left,
m.listViewport.View(),
lipgloss.PlaceHorizontal(m.listViewport.Width(), lipgloss.Center, dots),
)
return style.RenderWithTitle(panelStyle, icons.I.Replay+"Replay", inner, w, h)
return ilovetui.RenderWithTitle(panelStyle, icons.I.Replay+"Replay", inner, w, h)
}
func (m *Model) renderRequestPanel(w, h int) string {
s := style.S
var body string
border := s.Panel
border := ilovetui.S.Panel
if m.editing {
body = m.textarea.View()
border = s.PanelFocused
border = ilovetui.S.PanelFocused
} else {
body = style.ViewportView(&m.requestViewport)
if m.focusedPanel == panelRequest {
border = s.PanelFocused
border = ilovetui.S.PanelFocused
}
}
return style.RenderWithTitle(border, icons.I.Request+"Request", body, w, h)
return ilovetui.RenderWithTitle(border, icons.I.Request+"Request", body, w, h)
}
func (m *Model) renderResponsePanel(w, h int) string {
s := style.S
border := s.Panel
border := ilovetui.S.Panel
if !m.editing && m.focusedPanel == panelResponse {
border = s.PanelFocused
border = ilovetui.S.PanelFocused
}
return style.RenderWithTitle(border, icons.I.Response+"Response", style.ViewportView(&m.responseViewport), w, h)
return ilovetui.RenderWithTitle(border, icons.I.Response+"Response", style.ViewportView(&m.responseViewport), w, h)
}
func (m *Model) renderStatusBar() string {
@@ -83,18 +81,17 @@ func (m *Model) renderList() string {
return lipgloss.Place(
m.listViewport.Width(), m.listViewport.Height(),
lipgloss.Center, lipgloss.Center,
style.S.Faint.Render(util.CenterLines("(╥﹏╥)", "send a request from History or Intercept")),
ilovetui.S.Faint.Render(util.CenterLines("(╥﹏╥)", "send a request from History or Intercept")),
)
}
s := style.S
start, end := util.PageBounds(m.pager, len(m.entries))
var sb strings.Builder
for i, e := range m.entries[start:end] {
globalIdx := start + i
selected := globalIdx == m.cursor
selBg := s.Selection
selBg := ilovetui.S.Selection
w := m.listViewport.Width()
const fixedW = 2 + 7 + 1 + 3 + 1
@@ -109,8 +106,8 @@ func (m *Model) renderList() string {
if selected {
bg := lipgloss.NewStyle().Background(selBg)
line = lipgloss.JoinHorizontal(lipgloss.Top,
bg.Bold(true).Foreground(s.Primary).Width(2).Render(">"),
s.Method(e.Method).Background(selBg).Render(e.Method),
bg.Bold(true).Foreground(ilovetui.S.Primary).Width(2).Render(">"),
style.S.Method(e.Method).Background(selBg).Render(e.Method),
bg.Width(1).Render(""),
statusSt.Background(selBg).Render(statusStr),
bg.Width(1).Render(""),
@@ -119,12 +116,12 @@ func (m *Model) renderList() string {
} else {
line = lipgloss.JoinHorizontal(lipgloss.Top,
" ",
s.Method(e.Method).Render(e.Method),
style.S.Method(e.Method).Render(e.Method),
" ",
statusSt.Render(statusStr),
" ",
s.Bold.Render(e.Host),
s.Faint.Render(e.Path),
ilovetui.S.Bold.Render(e.Host),
ilovetui.S.Faint.Render(e.Path),
)
}
sb.WriteString(line + "\n")
@@ -136,11 +133,11 @@ func entryStatus(e Entry) (string, lipgloss.Style) {
base := lipgloss.NewStyle().Bold(true).Width(3)
switch {
case e.Sending:
return "···", base.Foreground(style.S.Subtle)
return "···", base.Foreground(ilovetui.S.Subtle)
case e.Err != nil:
return "ERR", base.Foreground(style.S.Error)
return "ERR", base.Foreground(ilovetui.S.Error)
case e.StatusCode == 0:
return "---", base.Foreground(style.S.Subtle)
return "---", base.Foreground(ilovetui.S.Subtle)
}
return fmt.Sprintf("%3d", e.StatusCode), style.StatusStyle(e.StatusCode, 3)
}