Files
nib-v1/cmd/ls.go
T
lerko 949ccaca59 feat: add browse-at-scale — date ranges, load more, month navigator
CLI: --month YYYY-MM, --from/--to date range, --limit override
API: from/to query params for date range filtering
Web: load more button for pagination, month nav (◂/▸) in stream view
2026-05-14 14:03:45 -04:00

172 lines
3.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package cmd
import (
"fmt"
"strings"
"time"
"github.com/lerko/nib/internal/db"
"github.com/lerko/nib/internal/display"
"github.com/spf13/cobra"
)
var (
lsTag string
lsDate string
lsMonth string
lsFrom string
lsTo string
lsLimit int
lsAll bool
)
var lsCmd = &cobra.Command{
Use: "ls",
Short: "list entities in stream order",
RunE: runLs,
}
func init() {
lsCmd.Flags().StringVar(&lsTag, "tag", "", "filter by tag")
lsCmd.Flags().StringVar(&lsDate, "date", "", "filter by date (YYYY-MM-DD)")
lsCmd.Flags().StringVar(&lsMonth, "month", "", "filter by month (YYYY-MM)")
lsCmd.Flags().StringVar(&lsFrom, "from", "", "start date (YYYY-MM-DD)")
lsCmd.Flags().StringVar(&lsTo, "to", "", "end date (YYYY-MM-DD)")
lsCmd.Flags().IntVar(&lsLimit, "limit", 0, "max entities to show (default 50)")
lsCmd.Flags().BoolVar(&lsAll, "all", false, "include deleted entities")
}
func runLs(_ *cobra.Command, _ []string) error {
store, err := openStore()
if err != nil {
return err
}
defer store.Close()
p := db.DefaultListParams()
p.IncludeDeleted = lsAll
if lsTag != "" {
p.Tag = &lsTag
}
if lsLimit > 0 {
p.Limit = lsLimit
}
hasDateFilter := false
if lsDate != "" {
p.Date = &lsDate
hasDateFilter = true
}
if lsMonth != "" {
t, err := time.Parse("2006-01", lsMonth)
if err != nil {
return fmt.Errorf("bad --month format, use YYYY-MM")
}
from := t.Format("2006-01-02")
to := t.AddDate(0, 1, -1).Format("2006-01-02")
p.From = &from
p.To = &to
hasDateFilter = true
}
if lsFrom != "" {
if _, err := time.Parse("2006-01-02", lsFrom); err != nil {
return fmt.Errorf("bad --from format, use YYYY-MM-DD")
}
p.From = &lsFrom
hasDateFilter = true
}
if lsTo != "" {
if _, err := time.Parse("2006-01-02", lsTo); err != nil {
return fmt.Errorf("bad --to format, use YYYY-MM-DD")
}
p.To = &lsTo
hasDateFilter = true
}
if !hasDateFilter {
since := time.Now().UTC().Add(-48 * time.Hour)
p.Since = &since
}
entities, err := store.List(p)
if err != nil {
return err
}
if len(entities) == 0 {
return nil
}
groups := groupByDate(entities)
for _, g := range groups {
fmt.Printf("── %s ──\n", g.label)
for _, e := range g.entities {
printEntity(e)
}
fmt.Println()
}
return nil
}
type dateGroup struct {
label string
entities []*db.Entity
}
func groupByDate(entities []*db.Entity) []dateGroup {
var groups []dateGroup
var current *dateGroup
for _, e := range entities {
label := formatDateLabel(e.CreatedAt)
if current == nil || current.label != label {
if current != nil {
groups = append(groups, *current)
}
current = &dateGroup{label: label}
}
current.entities = append(current.entities, e)
}
if current != nil {
groups = append(groups, *current)
}
return groups
}
func formatDateLabel(t time.Time) string {
return strings.ToLower(t.Format("Jan 2"))
}
func printEntity(e *db.Entity) {
glyph := display.DisplayGlyph(e.Glyph, e.CardType)
shortID := display.FormatID(e.ID)
var line strings.Builder
fmt.Fprintf(&line, "%s %-40s", glyph, e.Body)
if e.TimeAnchor != nil {
fmt.Fprintf(&line, " @%-5s", *e.TimeAnchor)
} else {
line.WriteString(" ")
}
var tagStr string
for _, tag := range e.Tags {
tagStr += " #" + tag
}
if tagStr != "" {
fmt.Fprintf(&line, " %-16s", strings.TrimSpace(tagStr))
} else {
line.WriteString(" ")
}
fmt.Fprintf(&line, " %s", shortID)
if e.UseCount > 0 {
fmt.Fprintf(&line, " (%d×)", e.UseCount)
}
fmt.Println(line.String())
}