diff --git a/README.md b/README.md index 3695c3f..c147c7d 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,12 @@ properties, as follows: foreground: #aabbcc; foreground: 123; foreground: adaptive(,); + foreground: complete(,,); + foreground: adaptive(,); + foreground: adaptive(complete(,,),complete(,,)); ``` -- Padding, margin etc which can take multiple values at once: +- Padding, margin, align etc which can take multiple values at once: ``` margin: 10 diff --git a/convert.go b/convert.go index 2f7f47d..a31933c 100644 --- a/convert.go +++ b/convert.go @@ -135,6 +135,13 @@ func printValue(buf *strings.Builder, v reflect.Value) { buf.WriteString(string(c)) case lipgloss.AdaptiveColor: fmt.Fprintf(buf, "adaptive(%s,%s)", c.Light, c.Dark) + case lipgloss.CompleteColor: + fmt.Fprintf(buf, "complete(%s,%s,%s)", c.TrueColor, c.ANSI256, c.ANSI) + case lipgloss.CompleteAdaptiveColor: + fmt.Fprintf(buf, "adaptive(complete(%s,%s,%s),complete(%s,%s,%s))", + c.Light.TrueColor, c.Light.ANSI256, c.Light.ANSI, + c.Dark.TrueColor, c.Dark.ANSI256, c.Dark.ANSI, + ) default: r, g, b, _ := tc.RGBA() fmt.Fprintf(buf, "#%02x%02x%02x", r, g, b) @@ -166,6 +173,7 @@ func isDefault(v reflect.Value) bool { } var ignoredMethods = map[string]bool{ + "GetAlign": true, "GetBorder": true, "GetMargin": true, "GetPadding": true, @@ -336,22 +344,54 @@ var rePos = regexp.MustCompile(`^\s*(top|bottom|center|left|right|1|1\.0|0\.5|\. type colortype struct{} +func getColors(rematch [][]byte, cvals []string) error { + for i := 0; i < len(cvals); i++ { + val := strings.TrimSpace(string(rematch[i+1])) + if !reColor.MatchString(val) { + return fmt.Errorf("color not recognized: %q", val) + } + cvals[i] = val + } + return nil +} + func (colortype) parse(input []byte, first int) (pos int, val reflect.Value, err error) { pos = first // possible syntaxes: // - adaptive(X, Y) + // - complete(X, Y, Z) + // - adaptive(complete(A,B,C), complete(D,E,F)) // - one word, either "none", just a number or a RGB value if r := reAdaptive.FindSubmatch(input[pos:]); r != nil { pos += len(r[0]) - firstValue := strings.TrimSpace(string(r[1])) - if !reColor.MatchString(firstValue) { - return pos, val, fmt.Errorf("color not recognized: %q", firstValue) + var cvals [2]string + if err := getColors(r, cvals[:]); err != nil { + return pos, val, err } - secondValue := strings.TrimSpace(string(r[2])) - if !reColor.MatchString(secondValue) { - return pos, val, fmt.Errorf("color not recognized: %q", secondValue) + c := lipgloss.AdaptiveColor{Light: cvals[0], Dark: cvals[1]} + val = reflect.ValueOf(c) + return pos, val, nil + } + if r := reComplete.FindSubmatch(input[pos:]); r != nil { + pos += len(r[0]) + var cvals [3]string + if err := getColors(r, cvals[:]); err != nil { + return pos, val, err + } + c := lipgloss.CompleteColor{TrueColor: cvals[0], ANSI256: cvals[1], ANSI: cvals[2]} + val = reflect.ValueOf(c) + return pos, val, nil + } + if r := reCompleteAdaptive.FindSubmatch(input[pos:]); r != nil { + pos += len(r[0]) + var cvals [6]string + if err := getColors(r, cvals[:]); err != nil { + return pos, val, err + } + c := lipgloss.CompleteAdaptiveColor{ + Light: lipgloss.CompleteColor{TrueColor: cvals[0], ANSI256: cvals[1], ANSI: cvals[2]}, + Dark: lipgloss.CompleteColor{TrueColor: cvals[3], ANSI256: cvals[4], ANSI: cvals[5]}, } - c := lipgloss.AdaptiveColor{Light: firstValue, Dark: secondValue} val = reflect.ValueOf(c) return pos, val, nil } @@ -378,6 +418,15 @@ var reColor = regexp.MustCompile(`^\s*(\d+|#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6})(?:\s var reColorOrNone = regexp.MustCompile(`^\s*(none|\d+|#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6})(?:\s+|$)`) var reAdaptive = regexp.MustCompile(`^\s*(?:adaptive\s*\(([^,]*),([^,]*)\))(?:\s+|$)`) +var reComplete = regexp.MustCompile(`^\s*(?:complete\s*\(([^,]*),([^,]*),([^,]*)\))(?:\s+|$)`) + +var reCompleteAdaptive = regexp.MustCompile(`^\s*(?:` + + `adaptive\s*\(\s*` + + `complete\s*\(([^,]*),([^,]*),([^,]*)\)` + + `\s*,\s*` + + `complete\s*\(([^,]*),([^,]*),([^,]*)\)` + + `\))(?:\s+|$)`) + type bordertype struct{} func (bordertype) parse(input []byte, first int) (pos int, val reflect.Value, err error) { diff --git a/convert_test.go b/convert_test.go index 8dd434f..74713be 100644 --- a/convert_test.go +++ b/convert_test.go @@ -31,13 +31,18 @@ func TestImport(t *testing.T) { {emptyStyle, `bold: aa`, ``, `in "bold: aa": no value found`}, {emptyStyle, `bold: true extra`, ``, `in "bold: true extra": excess values at end: ...extra`}, {emptyStyle.Foreground(lipgloss.Color("11")), `foreground: unset`, ``, ``}, - {emptyStyle, `align: top`, ``, ``}, - {emptyStyle, `align: xx`, ``, `in "align: xx": no value found`}, - {emptyStyle, `align: bottom`, `align: 1;`, ``}, - {emptyStyle, `align: center`, `align: 0.5;`, ``}, + {emptyStyle, `align-horizontal: left`, ``, ``}, {emptyStyle, `align: left`, ``, ``}, - {emptyStyle, `align: right`, `align: 1;`, ``}, - {emptyStyle, `align: 1.0`, `align: 1;`, ``}, + {emptyStyle, `align: xx`, ``, `in "align: xx": no value found`}, + {emptyStyle, `align: center`, `align-horizontal: 0.5;`, ``}, + {emptyStyle, `align: right`, `align-horizontal: 1;`, ``}, + {emptyStyle, `align: 1.0`, `align-horizontal: 1;`, ``}, + {emptyStyle, `align-horizontal: right`, `align-horizontal: 1;`, ``}, + {emptyStyle, `align-vertical: top`, ``, ``}, + {emptyStyle, `align-vertical: center`, `align-vertical: 0.5;`, ``}, + {emptyStyle, `align-vertical: bottom`, `align-vertical: 1;`, ``}, + {emptyStyle, `align: bottom right`, `align-horizontal: 1; +align-vertical: 1;`, ``}, {emptyStyle.Foreground(lipgloss.Color("11")), `foreground: none`, ``, ``}, {emptyStyle.Foreground(lipgloss.Color("11")), `clear`, ``, ``}, {emptyStyle.Foreground(lipgloss.Color("11")), `background: 12; clear`, ``, ``}, @@ -46,8 +51,12 @@ func TestImport(t *testing.T) { {emptyStyle, `foreground: #123456`, `foreground: #123456;`, ``}, {emptyStyle, `foreground: #axxa`, ``, `in "foreground: #axxa": color not recognized`}, {emptyStyle, `foreground: adaptive(1,2)`, `foreground: adaptive(1,2);`, ``}, + {emptyStyle, `foreground: complete(#111, 22, 3)`, `foreground: complete(#111,22,3);`, ``}, + {emptyStyle, `foreground: adaptive(complete(#111, 22, 3), complete(#444,55,6))`, `foreground: adaptive(complete(#111,22,3),complete(#444,55,6));`, ``}, {emptyStyle, `foreground: adaptive(a,b)`, ``, `in "foreground: adaptive(a,b)": color not recognized: "a"`}, {emptyStyle, `foreground: adaptive(1,b)`, ``, `in "foreground: adaptive(1,b)": color not recognized: "b"`}, + {emptyStyle, `foreground: complete(1,1,b)`, ``, `in "foreground: complete(1,1,b)": color not recognized: "b"`}, + {emptyStyle, `foreground: adaptive(complete(1,1,b),complete(2,2,b))`, ``, `in "foreground: adaptive(complete(1,1,b),complete(2,2,b))": color not recognized: "b"`}, {emptyStyle, `margin: 10`, `margin-bottom: 10; margin-left: 10; margin-right: 10; @@ -151,7 +160,7 @@ func TestExport(t *testing.T) { Width(22) t.Run("shortened", func(t *testing.T) { - exp := `align: 0.5; + exp := `align-horizontal: 0.5; background: adaptive(#7D56F4,#112233); bold: true; border-style: border("─","─","│","│","╭","╮","╯","╰"); @@ -178,7 +187,8 @@ width: 22;` }) t.Run("full", func(t *testing.T) { - exp := `align: 0.5; + exp := `align-horizontal: 0.5; +align-vertical: 0; background: adaptive(#7D56F4,#112233); blink: false; bold: true; diff --git a/go.mod b/go.mod index 7af21e2..9b0fedb 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/knz/lipgloss-convert go 1.13 require ( - github.com/charmbracelet/lipgloss v0.5.0 + github.com/charmbracelet/lipgloss v0.6.0 github.com/kr/pretty v0.3.0 github.com/pmezard/go-difflib v1.0.0 ) diff --git a/go.sum b/go.sum index 58956f2..1cd8493 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= +github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= +github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=