feat: v0.3.0d — add PR checks, iostreams, aliases, and broad enhancements
Add PR checks command, iostreams/text packages for colored table output, top-level run/workflow aliases matching gh CLI structure. Enhance actions, issues, PRs, releases, repos, labels, milestones, and wiki commands with improved flags, JSON output, and error handling.
This commit is contained in:
parent
7c0dcc8696
commit
113505de95
29 changed files with 3131 additions and 542 deletions
70
internal/text/text.go
Normal file
70
internal/text/text.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package text
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Pluralize returns "1 issue" or "2 issues" depending on count.
|
||||
// It applies a simple "s" suffix rule.
|
||||
func Pluralize(count int, singular string) string {
|
||||
if count == 1 {
|
||||
return fmt.Sprintf("%d %s", count, singular)
|
||||
}
|
||||
return fmt.Sprintf("%d %ss", count, singular)
|
||||
}
|
||||
|
||||
// FuzzyAgo returns a human-friendly relative time string like "just now",
|
||||
// "2 minutes ago", "3 hours ago", etc.
|
||||
func FuzzyAgo(t time.Time) string {
|
||||
d := time.Since(t)
|
||||
|
||||
if d < time.Minute {
|
||||
return "just now"
|
||||
}
|
||||
|
||||
minutes := int(math.Floor(d.Minutes()))
|
||||
if minutes < 60 {
|
||||
return fmt.Sprintf("%s ago", Pluralize(minutes, "minute"))
|
||||
}
|
||||
|
||||
hours := int(math.Floor(d.Hours()))
|
||||
if hours < 24 {
|
||||
return fmt.Sprintf("%s ago", Pluralize(hours, "hour"))
|
||||
}
|
||||
|
||||
days := hours / 24
|
||||
if days < 30 {
|
||||
return fmt.Sprintf("%s ago", Pluralize(days, "day"))
|
||||
}
|
||||
|
||||
months := days / 30
|
||||
if months < 12 {
|
||||
return fmt.Sprintf("%s ago", Pluralize(months, "month"))
|
||||
}
|
||||
|
||||
years := months / 12
|
||||
return fmt.Sprintf("%s ago", Pluralize(years, "year"))
|
||||
}
|
||||
|
||||
// Truncate shortens text to maxWidth, replacing the end with "..." if it exceeds
|
||||
// the limit. If maxWidth is less than or equal to 3, the result is just "...".
|
||||
func Truncate(text string, maxWidth int) string {
|
||||
if len(text) <= maxWidth {
|
||||
return text
|
||||
}
|
||||
if maxWidth <= 3 {
|
||||
return "..."[:maxWidth]
|
||||
}
|
||||
return text[:maxWidth-3] + "..."
|
||||
}
|
||||
|
||||
// FormatDate returns a human-friendly relative time for TTY output, or an
|
||||
// RFC3339 timestamp for piped output.
|
||||
func FormatDate(t time.Time, isTTY bool) string {
|
||||
if isTTY {
|
||||
return FuzzyAgo(t)
|
||||
}
|
||||
return t.Format(time.RFC3339)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue