fj/internal/text/text.go
sid 113505de95 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.
2026-03-23 12:42:24 -06:00

70 lines
1.6 KiB
Go

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)
}