mirror of
https://github.com/charmbracelet/glow
synced 2024-12-12 13:12:32 +00:00
fce3edf7db
* feat!: cleanup Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * more cleanup Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: more cleanup Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com> * fix: more cleanup --------- Signed-off-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
84 lines
2.7 KiB
Go
84 lines
2.7 KiB
Go
package ui
|
|
|
|
import (
|
|
"math"
|
|
"time"
|
|
"unicode"
|
|
|
|
"github.com/charmbracelet/log"
|
|
"github.com/dustin/go-humanize"
|
|
"golang.org/x/text/runes"
|
|
"golang.org/x/text/transform"
|
|
"golang.org/x/text/unicode/norm"
|
|
)
|
|
|
|
type markdown struct {
|
|
// Full path of a local markdown file. Only relevant to local documents and
|
|
// those that have been stashed in this session.
|
|
localPath string
|
|
|
|
// Value we filter against. This exists so that we can maintain positions
|
|
// of filtered items if notes are edited while a filter is active. This
|
|
// field is ephemeral, and should only be referenced during filtering.
|
|
filterValue string
|
|
|
|
Body string
|
|
Note string
|
|
Modtime time.Time
|
|
}
|
|
|
|
// Generate the value we're doing to filter against.
|
|
func (m *markdown) buildFilterValue() {
|
|
note, err := normalize(m.Note)
|
|
if err != nil {
|
|
log.Error("error normalizing", "note", m.Note, "error", err)
|
|
m.filterValue = m.Note
|
|
}
|
|
|
|
m.filterValue = note
|
|
}
|
|
|
|
func (m markdown) relativeTime() string {
|
|
return relativeTime(m.Modtime)
|
|
}
|
|
|
|
// Normalize text to aid in the filtering process. In particular, we remove
|
|
// diacritics, "ö" becomes "o". Note that Mn is the unicode key for nonspacing
|
|
// marks.
|
|
func normalize(in string) (string, error) {
|
|
t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC)
|
|
out, _, err := transform.String(t, in)
|
|
return out, err
|
|
}
|
|
|
|
// Return the time in a human-readable format relative to the current time.
|
|
func relativeTime(then time.Time) string {
|
|
now := time.Now()
|
|
if ago := now.Sub(then); ago < time.Minute {
|
|
return "just now"
|
|
} else if ago < humanize.Week {
|
|
return humanize.CustomRelTime(then, now, "ago", "from now", magnitudes)
|
|
}
|
|
return then.Format("02 Jan 2006 15:04 MST")
|
|
}
|
|
|
|
// Magnitudes for relative time.
|
|
var magnitudes = []humanize.RelTimeMagnitude{
|
|
{D: time.Second, Format: "now", DivBy: time.Second},
|
|
{D: 2 * time.Second, Format: "1 second %s", DivBy: 1},
|
|
{D: time.Minute, Format: "%d seconds %s", DivBy: time.Second},
|
|
{D: 2 * time.Minute, Format: "1 minute %s", DivBy: 1},
|
|
{D: time.Hour, Format: "%d minutes %s", DivBy: time.Minute},
|
|
{D: 2 * time.Hour, Format: "1 hour %s", DivBy: 1},
|
|
{D: humanize.Day, Format: "%d hours %s", DivBy: time.Hour},
|
|
{D: 2 * humanize.Day, Format: "1 day %s", DivBy: 1},
|
|
{D: humanize.Week, Format: "%d days %s", DivBy: humanize.Day},
|
|
{D: 2 * humanize.Week, Format: "1 week %s", DivBy: 1},
|
|
{D: humanize.Month, Format: "%d weeks %s", DivBy: humanize.Week},
|
|
{D: 2 * humanize.Month, Format: "1 month %s", DivBy: 1},
|
|
{D: humanize.Year, Format: "%d months %s", DivBy: humanize.Month},
|
|
{D: 18 * humanize.Month, Format: "1 year %s", DivBy: 1},
|
|
{D: 2 * humanize.Year, Format: "2 years %s", DivBy: 1},
|
|
{D: humanize.LongTime, Format: "%d years %s", DivBy: humanize.Year},
|
|
{D: math.MaxInt64, Format: "a long while %s", DivBy: 1},
|
|
}
|