-
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
4 changed files
with
349 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
package semver | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
var ( | ||
semverRegex = regexp.MustCompile(`^v?(\d+)\.(\d+)\.(\d+)(?:-([\w\.\-]+))?(?:\+([\w\.\-]+))?$`) | ||
) | ||
|
||
type Version struct { | ||
Major int | ||
Minor int | ||
Patch int | ||
PreRelease string | ||
BuildMetadata string | ||
} | ||
|
||
func Parse(version string) (*Version, error) { | ||
matches := semverRegex.FindStringSubmatch(version) | ||
if matches == nil { | ||
return nil, errors.New("invalid semantic version") | ||
} | ||
|
||
major, _ := strconv.Atoi(matches[1]) | ||
minor, _ := strconv.Atoi(matches[2]) | ||
patch, _ := strconv.Atoi(matches[3]) | ||
|
||
return &Version{ | ||
Major: major, | ||
Minor: minor, | ||
Patch: patch, | ||
PreRelease: matches[4], | ||
BuildMetadata: matches[5], | ||
}, nil | ||
} | ||
|
||
func (v *Version) String() string { | ||
ver := fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Patch) | ||
if v.PreRelease != "" { | ||
ver += "-" + v.PreRelease | ||
} | ||
if v.BuildMetadata != "" { | ||
ver += "+" + v.BuildMetadata | ||
} | ||
return ver | ||
} | ||
|
||
func (v *Version) Compare(other *Version) int { | ||
if v.Major != other.Major { | ||
return compareInt(v.Major, other.Major) | ||
} | ||
if v.Minor != other.Minor { | ||
return compareInt(v.Minor, other.Minor) | ||
} | ||
if v.Patch != other.Patch { | ||
return compareInt(v.Patch, other.Patch) | ||
} | ||
return comparePreRelease(v.PreRelease, other.PreRelease) | ||
} | ||
|
||
func compareInt(a, b int) int { | ||
if a < b { | ||
return -1 | ||
} | ||
if a > b { | ||
return 1 | ||
} | ||
return 0 | ||
} | ||
|
||
func comparePreRelease(a, b string) int { | ||
if a == b { | ||
return 0 | ||
} | ||
if a == "" { | ||
return 1 | ||
} | ||
if b == "" { | ||
return -1 | ||
} | ||
return strings.Compare(a, b) | ||
} | ||
|
||
type Constraint struct { | ||
Operator string | ||
Version *Version | ||
} | ||
|
||
func ParseConstraint(constraint string) (*Constraint, error) { | ||
parts := strings.Fields(constraint) | ||
if len(parts) != 2 { | ||
return nil, errors.New("invalid constraint format") | ||
} | ||
|
||
version, err := Parse(parts[1]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return &Constraint{ | ||
Operator: parts[0], | ||
Version: version, | ||
}, nil | ||
} | ||
|
||
func (c *Constraint) Matches(v *Version) bool { | ||
switch c.Operator { | ||
case "=": | ||
return v.Compare(c.Version) == 0 | ||
case "!=": | ||
return v.Compare(c.Version) != 0 | ||
case "<": | ||
return v.Compare(c.Version) < 0 | ||
case "<=": | ||
return v.Compare(c.Version) <= 0 | ||
case ">": | ||
return v.Compare(c.Version) > 0 | ||
case ">=": | ||
return v.Compare(c.Version) >= 0 | ||
default: | ||
return false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package semver | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestParse(t *testing.T) { | ||
version, err := Parse("1.2.3-alpha+001") | ||
if err != nil { | ||
t.Fatalf("expected no error, got %v", err) | ||
} | ||
if version.Major != 1 || version.Minor != 2 || version.Patch != 3 || version.PreRelease != "alpha" || version.BuildMetadata != "001" { | ||
t.Fatalf("parsed version incorrect: %v", version) | ||
} | ||
} | ||
|
||
func TestString(t *testing.T) { | ||
version, _ := Parse("1.2.3-alpha+001") | ||
if version.String() != "v1.2.3-alpha+001" { | ||
t.Fatalf("expected version string 'v1.2.3-alpha+001', got %s", version.String()) | ||
} | ||
} | ||
|
||
func TestCompare(t *testing.T) { | ||
v1, _ := Parse("1.2.3") | ||
v2, _ := Parse("2.0.0") | ||
if v1.Compare(v2) >= 0 { | ||
t.Fatalf("expected v1 < v2") | ||
} | ||
} | ||
|
||
func TestConstraint(t *testing.T) { | ||
constraint, err := ParseConstraint(">= 1.2.3") | ||
if err != nil { | ||
t.Fatalf("expected no error, got %v", err) | ||
} | ||
version, _ := Parse("1.2.3") | ||
if !constraint.Matches(version) { | ||
t.Fatalf("expected version to match constraint") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,71 +1,71 @@ | ||
package table | ||
|
||
import ( | ||
"fmt" | ||
"fmt" | ||
) | ||
|
||
// Beispiel-Datenstrukturen | ||
type Person struct { | ||
Name string | ||
Age int | ||
Email string | ||
Name string | ||
Age int | ||
Email string | ||
} | ||
|
||
type Product struct { | ||
ID int | ||
Name string | ||
Price float64 | ||
ID int | ||
Name string | ||
Price float64 | ||
} | ||
|
||
// Beispiel: ASCII-Tabelle ohne Rotation | ||
func ExampleRenderASCII_noRotation() { | ||
people := []Person{ | ||
{Name: "John", Age: 42, Email: "john@example.com"}, | ||
{Name: "Jane", Age: 32, Email: "jane@example.com"}, | ||
} | ||
people := []Person{ | ||
{Name: "John", Age: 42, Email: "john@example.com"}, | ||
{Name: "Jane", Age: 32, Email: "jane@example.com"}, | ||
} | ||
|
||
asciiTable, _ := RenderASCII(people, TableOption{Rotate: false}) | ||
fmt.Println(asciiTable) | ||
// Output: | ||
// +------+-----+------------------+ | ||
// | Name | Age | Email | | ||
// +------+-----+------------------+ | ||
// | John | 42 | john@example.com | | ||
// | Jane | 32 | jane@example.com | | ||
// +------+-----+------------------+ | ||
asciiTable, _ := RenderASCII(people, TableOption{Rotate: false}) | ||
fmt.Println(asciiTable) | ||
// Output: | ||
// +------+-----+------------------+ | ||
// | Name | Age | Email | | ||
// +------+-----+------------------+ | ||
// | John | 42 | john@example.com | | ||
// | Jane | 32 | jane@example.com | | ||
// +------+-----+------------------+ | ||
} | ||
|
||
// Beispiel: ASCII-Tabelle mit Rotation | ||
func ExampleRenderASCII_withRotation() { | ||
people := []Person{ | ||
{Name: "John", Age: 42, Email: "john@example.com"}, | ||
{Name: "Jane", Age: 32, Email: "jane@example.com"}, | ||
} | ||
people := []Person{ | ||
{Name: "John", Age: 42, Email: "john@example.com"}, | ||
{Name: "Jane", Age: 32, Email: "jane@example.com"}, | ||
} | ||
|
||
rotatedASCIITable, _ := RenderASCII(people, TableOption{Rotate: true}) | ||
fmt.Println(rotatedASCIITable) | ||
// Output: | ||
// +-------+------------------+------------------+ | ||
// | | Row 1 | Row 2 | | ||
// +-------+------------------+------------------+ | ||
// | Name | John | Jane | | ||
// | Age | 42 | 32 | | ||
// | Email | john@example.com | jane@example.com | | ||
// +-------+------------------+------------------+ | ||
rotatedASCIITable, _ := RenderASCII(people, TableOption{Rotate: true}) | ||
fmt.Println(rotatedASCIITable) | ||
// Output: | ||
// +-------+------------------+------------------+ | ||
// | | Row 1 | Row 2 | | ||
// +-------+------------------+------------------+ | ||
// | Name | John | Jane | | ||
// | Age | 42 | 32 | | ||
// | Email | john@example.com | jane@example.com | | ||
// +-------+------------------+------------------+ | ||
} | ||
|
||
// Beispiel: Markdown-Tabelle ohne Rotation | ||
func ExampleRenderMarkdown_noRotation() { | ||
people := []Person{ | ||
{Name: "John", Age: 42, Email: "john@example.com"}, | ||
{Name: "Jane", Age: 32, Email: "jane@example.com"}, | ||
} | ||
people := []Person{ | ||
{Name: "John", Age: 42, Email: "john@example.com"}, | ||
{Name: "Jane", Age: 32, Email: "jane@example.com"}, | ||
} | ||
|
||
markdownTable, _ := RenderMarkdown(people, TableOption{Rotate: false}) | ||
fmt.Println(markdownTable) | ||
// Output: | ||
// | Name | Age | Email | | ||
// |------|-----|------------------| | ||
// | John | 42 | john@example.com | | ||
// | Jane | 32 | jane@example.com | | ||
markdownTable, _ := RenderMarkdown(people, TableOption{Rotate: false}) | ||
fmt.Println(markdownTable) | ||
// Output: | ||
// | Name | Age | Email | | ||
// |------|-----|------------------| | ||
// | John | 42 | john@example.com | | ||
// | Jane | 32 | jane@example.com | | ||
} |
Oops, something went wrong.