Skip to content

Commit dc735a5

Browse files
authored
feat(search): show filename first + icons (#105)
1 parent e651360 commit dc735a5

4 files changed

Lines changed: 96 additions & 68 deletions

File tree

go.mod

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
module github.com/dlvhdr/diffnav
22

3-
go 1.24.2
4-
5-
toolchain go1.24.11
3+
go 1.25.8
64

75
require (
86
charm.land/bubbles/v2 v2.0.0-rc.1
97
charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251216153312-819e2e89c62e
10-
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251205162909-7869489d8971
8+
charm.land/lipgloss/v2 v2.0.1
9+
charm.land/log/v2 v2.0.0
1110
github.com/atotto/clipboard v0.1.4
1211
github.com/bluekeyes/go-gitdiff v0.8.1
1312
github.com/charmbracelet/fang v0.4.4
1413
github.com/charmbracelet/log v0.4.2
1514
github.com/charmbracelet/x/ansi v0.11.6
1615
github.com/lrstanley/bubblezone/v2 v2.0.0-alpha.3
16+
github.com/lrstanley/go-nf v0.0.0-20260301073247-b319fa3edf0e
1717
github.com/muesli/reflow v0.3.0
1818
github.com/muesli/termenv v0.16.0
1919
github.com/spf13/cobra v1.10.2
@@ -22,17 +22,16 @@ require (
2222

2323
require (
2424
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
25-
github.com/charmbracelet/colorprofile v0.4.1 // indirect
25+
github.com/charmbracelet/colorprofile v0.4.2 // indirect
2626
github.com/charmbracelet/lipgloss v1.1.0 // indirect
2727
github.com/charmbracelet/ultraviolet v0.0.0-20251212194010-b927aa605560 // indirect
2828
github.com/charmbracelet/x/cellbuf v0.0.15 // indirect
2929
github.com/charmbracelet/x/exp/charmtone v0.0.0-20250603201427-c31516f43444 // indirect
3030
github.com/charmbracelet/x/term v0.2.2 // indirect
3131
github.com/charmbracelet/x/termios v0.1.1 // indirect
3232
github.com/charmbracelet/x/windows v0.2.2 // indirect
33-
github.com/clipperhouse/displaywidth v0.9.0 // indirect
34-
github.com/clipperhouse/stringish v0.1.1 // indirect
35-
github.com/clipperhouse/uax29/v2 v2.5.0 // indirect
33+
github.com/clipperhouse/displaywidth v0.11.0 // indirect
34+
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
3635
github.com/go-logfmt/logfmt v0.6.1 // indirect
3736
github.com/inconshreveable/mousetrap v1.1.0 // indirect
3837
github.com/lucasb-eyer/go-colorful v1.3.0 // indirect
@@ -48,7 +47,7 @@ require (
4847
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
4948
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
5049
golang.org/x/sync v0.19.0 // indirect
51-
golang.org/x/sys v0.40.0 // indirect
50+
golang.org/x/sys v0.42.0 // indirect
5251
golang.org/x/text v0.24.0 // indirect
5352
)
5453

go.sum

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251216153312-819e2e89c62e h1:tXwTmgGpwZT7ParKF5xbEQBVjM2e1uKhKi/GpfU3mYQ=
22
charm.land/bubbletea/v2 v2.0.0-rc.2.0.20251216153312-819e2e89c62e/go.mod h1:pDM18flq3Z4njKZPA3zCvyVSSIJbMcoqlE82BdGUtL8=
3-
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251205162909-7869489d8971 h1:xZFcNsJMiIDbFtWRyDmkKNk1sjojfaom4Zoe0cyH/8c=
4-
charm.land/lipgloss/v2 v2.0.0-beta.3.0.20251205162909-7869489d8971/go.mod h1:i61Y3FmdbcBNSKa+pKB3DaE4uVQmBLMs/xlvRyHcXAE=
3+
charm.land/lipgloss/v2 v2.0.1 h1:6Xzrn49+Py1Um5q/wZG1gWgER2+7dUyZ9XMEufqPSys=
4+
charm.land/lipgloss/v2 v2.0.1/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM=
5+
charm.land/log/v2 v2.0.0 h1:SY3Cey7ipx86/MBXQHwsguOT6X1exT94mmJRdzTNs+s=
6+
charm.land/log/v2 v2.0.0/go.mod h1:c3cZSRqm20qUVVAR1WmS/7ab8bgha3C6G7DjPcaVZz0=
57
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
68
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
79
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
810
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
9-
github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY=
10-
github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E=
11+
github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o=
12+
github.com/aymanbagabas/go-udiff v0.4.1/go.mod h1:0L9PGwj20lrtmEMeyw4WKJ/TMyDtvAoK9bf2u/mNo3w=
1113
github.com/bluekeyes/go-gitdiff v0.8.1 h1:lL1GofKMywO17c0lgQmJYcKek5+s8X6tXVNOLxy4smI=
1214
github.com/bluekeyes/go-gitdiff v0.8.1/go.mod h1:WWAk1Mc6EgWarCrPFO+xeYlujPu98VuLW3Tu+B/85AE=
13-
github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk=
14-
github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk=
15+
github.com/charmbracelet/colorprofile v0.4.2 h1:BdSNuMjRbotnxHSfxy+PCSa4xAmz7szw70ktAtWRYrY=
16+
github.com/charmbracelet/colorprofile v0.4.2/go.mod h1:0rTi81QpwDElInthtrQ6Ni7cG0sDtwAd4C4le060fT8=
1517
github.com/charmbracelet/fang v0.4.4 h1:G4qKxF6or/eTPgmAolwPuRNyuci3hTUGGX1rj1YkHJY=
1618
github.com/charmbracelet/fang v0.4.4/go.mod h1:P5/DNb9DddQ0Z0dbc0P3ol4/ix5Po7Ofr2KMBfAqoCo=
1719
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
@@ -34,12 +36,10 @@ github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8
3436
github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo=
3537
github.com/charmbracelet/x/windows v0.2.2 h1:IofanmuvaxnKHuV04sC0eBy/smG6kIKrWG2/jYn2GuM=
3638
github.com/charmbracelet/x/windows v0.2.2/go.mod h1:/8XtdKZzedat74NQFn0NGlGL4soHB0YQZrETF96h75k=
37-
github.com/clipperhouse/displaywidth v0.9.0 h1:Qb4KOhYwRiN3viMv1v/3cTBlz3AcAZX3+y9OLhMtAtA=
38-
github.com/clipperhouse/displaywidth v0.9.0/go.mod h1:aCAAqTlh4GIVkhQnJpbL0T/WfcrJXHcj8C0yjYcjOZA=
39-
github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
40-
github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
41-
github.com/clipperhouse/uax29/v2 v2.5.0 h1:x7T0T4eTHDONxFJsL94uKNKPHrclyFI0lm7+w94cO8U=
42-
github.com/clipperhouse/uax29/v2 v2.5.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
39+
github.com/clipperhouse/displaywidth v0.11.0 h1:lBc6kY44VFw+TDx4I8opi/EtL9m20WSEFgwIwO+UVM8=
40+
github.com/clipperhouse/displaywidth v0.11.0/go.mod h1:bkrFNkf81G8HyVqmKGxsPufD3JhNl3dSqnGhOoSD/o0=
41+
github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk=
42+
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
4343
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
4444
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4545
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -53,6 +53,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
5353
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
5454
github.com/lrstanley/bubblezone/v2 v2.0.0-alpha.3 h1:hFH0W7GQO1tCu9p0ljSxxr0PLWjrp/9NgHXEMWoCL70=
5555
github.com/lrstanley/bubblezone/v2 v2.0.0-alpha.3/go.mod h1:O2jUHrhH1gDH/VhsqNIv35PN8+7zyAQqZ16rQPpCJxU=
56+
github.com/lrstanley/go-nf v0.0.0-20260301073247-b319fa3edf0e h1:xBf4TxIi9coll8yHG71reJQOXK4MNvGXhY1HcxCHlOw=
57+
github.com/lrstanley/go-nf v0.0.0-20260301073247-b319fa3edf0e/go.mod h1:MW7vmvMkwop4wD5DgTS5dzykKwN/r+3OWcxfzAANOrw=
5658
github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag=
5759
github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
5860
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -96,8 +98,8 @@ golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHi
9698
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
9799
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
98100
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
99-
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
100-
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
101+
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
102+
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
101103
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
102104
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
103105
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

pkg/ui/tui.go

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"os"
66
"os/exec"
7+
"path"
78
"strings"
89
"time"
910

@@ -13,8 +14,8 @@ import (
1314
"charm.land/bubbles/v2/viewport"
1415
tea "charm.land/bubbletea/v2"
1516
"charm.land/lipgloss/v2"
17+
"charm.land/log/v2"
1618
"github.com/bluekeyes/go-gitdiff/gitdiff"
17-
"github.com/charmbracelet/log"
1819
zone "github.com/lrstanley/bubblezone/v2"
1920

2021
"github.com/dlvhdr/diffnav/pkg/config"
@@ -25,6 +26,8 @@ import (
2526
"github.com/dlvhdr/diffnav/pkg/ui/panes/filetree"
2627
"github.com/dlvhdr/diffnav/pkg/ui/panes/help"
2728
"github.com/dlvhdr/diffnav/pkg/utils"
29+
"github.com/lrstanley/go-nf/glyphs/md"
30+
"github.com/lrstanley/go-nf/glyphs/neo"
2831
)
2932

3033
const (
@@ -510,41 +513,18 @@ func (m mainModel) fetchFileTree() tea.Msg {
510513
return fileTreeMsg{files: files, preamble: preamble, branch: branch}
511514
}
512515

513-
func relativeTime(t time.Time) string {
514-
d := time.Since(t)
515-
switch {
516-
case d < time.Minute:
517-
return "now"
518-
case d < time.Hour:
519-
m := int(d.Minutes())
520-
return fmt.Sprintf("%dm", m)
521-
case d < 24*time.Hour:
522-
h := int(d.Hours())
523-
return fmt.Sprintf("%dh", h)
524-
case d < 30*24*time.Hour:
525-
days := int(d.Hours() / 24)
526-
return fmt.Sprintf("%dD", days)
527-
case d < 365*24*time.Hour:
528-
months := int(d.Hours() / 24 / 30)
529-
return fmt.Sprintf("%dM", months)
530-
default:
531-
years := int(d.Hours() / 24 / 365)
532-
return fmt.Sprintf("%dY", years)
533-
}
534-
}
535-
536516
// resolveBranch finds branches pointing at the preamble commit.
537517
func resolveBranch(preamble string) string {
538518
// Check for decoration in commit line: "commit abc123 (HEAD -> branch)"
539-
for _, line := range strings.Split(preamble, "\n") {
519+
for line := range strings.SplitSeq(preamble, "\n") {
540520
trimmed := strings.TrimSpace(line)
541521
if strings.HasPrefix(trimmed, "commit ") {
542522
if idx := strings.Index(trimmed, " ("); idx > 0 {
543523
refs := trimmed[idx+2:]
544524
if end := strings.Index(refs, ")"); end > 0 {
545525
refs = refs[:end]
546526
}
547-
for _, ref := range strings.Split(refs, ",") {
527+
for ref := range strings.SplitSeq(refs, ",") {
548528
ref = strings.TrimSpace(ref)
549529
if strings.HasPrefix(ref, "HEAD -> ") {
550530
return strings.TrimPrefix(ref, "HEAD -> ")
@@ -563,7 +543,7 @@ func resolveBranch(preamble string) string {
563543
if err != nil {
564544
return ""
565545
}
566-
for _, l := range strings.Split(strings.TrimSpace(string(out)), "\n") {
546+
for l := range strings.SplitSeq(strings.TrimSpace(string(out)), "\n") {
567547
b := strings.TrimLeft(l, " *+")
568548
if b != "" {
569549
return b
@@ -586,7 +566,7 @@ func (m mainModel) parseCommitMeta() commitMeta {
586566
if m.preamble == "" {
587567
return meta
588568
}
589-
for _, line := range strings.Split(m.preamble, "\n") {
569+
for line := range strings.SplitSeq(m.preamble, "\n") {
590570
trimmed := strings.TrimSpace(line)
591571
if strings.HasPrefix(trimmed, "commit ") && meta.hash == "" {
592572
h := strings.TrimPrefix(trimmed, "commit ")
@@ -637,7 +617,7 @@ func (m mainModel) commitSubject() string {
637617
if m.preamble == "" {
638618
return ""
639619
}
640-
for _, line := range strings.Split(m.preamble, "\n") {
620+
for line := range strings.SplitSeq(m.preamble, "\n") {
641621
trimmed := strings.TrimSpace(line)
642622
if trimmed == "" {
643623
continue
@@ -676,18 +656,26 @@ func (m mainModel) viewHeader() string {
676656
var infoParts []string
677657
infoParts = append(infoParts, hashStyle.Render(meta.hash))
678658
if meta.date != "" {
679-
infoParts = append(infoParts, dateStyle.Render(meta.date))
659+
if m.iconStyle != filenode.IconsASCII && m.iconStyle != filenode.IconsUnicode {
660+
infoParts = append(infoParts, dateStyle.Render(string(md.ClockOutline) + " " + meta.date))
661+
} else {
662+
infoParts = append(infoParts, dateStyle.Render(meta.date))
663+
}
680664
}
681665
if meta.author != "" {
666+
if m.iconStyle != filenode.IconsASCII && m.iconStyle != filenode.IconsUnicode {
667+
infoParts = append(infoParts, authorStyle.Render(string(md.AccountCircleOutline) + " " + meta.author))
668+
} else {
682669
infoParts = append(infoParts, authorStyle.Render(meta.author))
670+
}
683671
}
684-
headerParts = headerParts + sep + strings.Join(infoParts, " ")
672+
headerParts = headerParts + sep + strings.Join(infoParts, sep)
685673

686674
// Branch ref.
687675
if m.commitBranch != "" {
688676
branchLabel := "[" + m.commitBranch + "]"
689677
if m.iconStyle != filenode.IconsASCII && m.iconStyle != filenode.IconsUnicode {
690-
branchLabel = "\ue0a0 " + m.commitBranch
678+
branchLabel = string(md.SourceBranch) + " " + m.commitBranch
691679
}
692680
headerParts = headerParts + sep + refStyle.Render(branchLabel)
693681
}
@@ -733,7 +721,7 @@ func (m *mainModel) messageView() string {
733721
var out []string
734722

735723
// Render preamble lines.
736-
for _, line := range strings.Split(m.preamble, "\n") {
724+
for line := range strings.SplitSeq(m.preamble, "\n") {
737725
switch {
738726
case strings.HasPrefix(line, "commit "):
739727
out = append(out, dim.Render("commit ")+yellow.Render(strings.TrimPrefix(line, "commit ")))
@@ -755,10 +743,7 @@ func (m *mainModel) messageView() string {
755743
func (m *mainModel) updateMessageVp() {
756744
s := overlayStyle()
757745
maxWidth := min(m.width*3/4, 80)
758-
maxHeight := m.height/2 - s.GetVerticalFrameSize()
759-
if maxHeight < 5 {
760-
maxHeight = 5
761-
}
746+
maxHeight := max(m.height/2 - s.GetVerticalFrameSize(), 5)
762747
content := lipgloss.NewStyle().Width(maxWidth).Render(m.messageView())
763748
m.messageVp.SetWidth(maxWidth)
764749
m.messageVp.SetHeight(maxHeight)
@@ -786,7 +771,7 @@ func (m mainModel) renderScrollbar() string {
786771
thumb := lipgloss.NewStyle().Foreground(lipgloss.Blue)
787772

788773
var sb strings.Builder
789-
for i := 0; i < trackHeight; i++ {
774+
for i := range trackHeight {
790775
if i > 0 {
791776
sb.WriteByte('\n')
792777
}
@@ -801,17 +786,33 @@ func (m mainModel) renderScrollbar() string {
801786

802787
func (m mainModel) resultsView() string {
803788
sb := strings.Builder{}
789+
baseStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("#F7F7F7"))
790+
dirStyle := lipgloss.NewStyle().Bold(false).Foreground(lipgloss.Color("#B8B8B8"))
804791
for i, f := range m.filtered {
805-
fName := utils.TruncateString(" "+f, m.config.UI.SearchTreeWidth-2)
792+
icon := neo.ByPath(f)
793+
if icon == nil {
794+
icon = neo.ByFileExtension("txt")
795+
}
796+
base := utils.RemoveReset(lipgloss.NewStyle().
797+
Foreground(icon.Color(true)).
798+
Render(icon.Glyph().String()) + " " + baseStyle.Render(path.Base(f)))
799+
dir := utils.TruncateString(
800+
dirStyle.Render(path.Dir(f)),
801+
m.config.UI.SearchTreeWidth-2-lipgloss.Width(base),
802+
)
803+
if path.Dir(f) == "." {
804+
dir = ""
805+
}
806806
if i == m.resultsCursor {
807-
sb.WriteString(
808-
lipgloss.NewStyle().
809-
Background(lipgloss.Color("#1b1b33")).
810-
Bold(true).
811-
Render(fName) +
812-
"\n",
807+
bg := lipgloss.NewStyle().Background(lipgloss.Color("#1b1b33"))
808+
fName := lipgloss.NewStyle().Bold(true).Render(bg.Render(base)) + bg.Render(" ") + bg.Render(dir)
809+
sb.WriteString(bg.
810+
Width(m.config.UI.SearchTreeWidth).
811+
Render(fName) +
812+
"\n",
813813
)
814814
} else {
815+
fName := base + " " + dir
815816
sb.WriteString(fName + "\n")
816817
}
817818
}

pkg/ui/utils.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package ui
22

33
import (
4+
"fmt"
45
"path/filepath"
56
"slices"
67
"strings"
8+
"time"
79

810
"github.com/bluekeyes/go-gitdiff/gitdiff"
911

@@ -41,3 +43,27 @@ func sortFiles(files []*gitdiff.File) {
4143
return strings.Compare(strings.ToLower(nameA), strings.ToLower(nameB))
4244
})
4345
}
46+
47+
func relativeTime(t time.Time) string {
48+
d := time.Since(t)
49+
switch {
50+
case d < time.Minute:
51+
return "now"
52+
case d < time.Hour:
53+
m := int(d.Minutes())
54+
return fmt.Sprintf("%dm", m)
55+
case d < 24*time.Hour:
56+
h := int(d.Hours())
57+
return fmt.Sprintf("%dh", h)
58+
case d < 30*24*time.Hour:
59+
days := int(d.Hours() / 24)
60+
return fmt.Sprintf("%dd", days)
61+
case d < 365*24*time.Hour:
62+
months := int(d.Hours() / 24 / 30)
63+
return fmt.Sprintf("%dmo", months)
64+
default:
65+
years := int(d.Hours() / 24 / 365)
66+
return fmt.Sprintf("%dy", years)
67+
}
68+
}
69+

0 commit comments

Comments
 (0)