commit 4837130a3e1358de58b2ce3e8c8a24497b2ca89a
parent 354c1cca7947cf0743f718f5ec9b26ec068f695e
Author: dwrz <dwrz@dwrz.net>
Date: Sat, 20 May 2023 19:16:14 +0000
Refactor wisdom
Diffstat:
3 files changed, 67 insertions(+), 32 deletions(-)
diff --git a/cmd/wisdom/wisdom.go b/cmd/wisdom/wisdom.go
@@ -6,13 +6,10 @@ import (
"path/filepath"
"code.dwrz.net/src/pkg/log"
+ "code.dwrz.net/src/pkg/terminal"
"code.dwrz.net/src/pkg/wisdom"
)
-var (
- wrap = flag.Int("w", 72, "word wrap; disabled if negative")
-)
-
func main() {
var l = log.New(os.Stderr)
@@ -23,10 +20,20 @@ func main() {
l.Error.Fatalf("failed to get user config dir: %v", err)
}
+ terminal, err := terminal.New(os.Stdin.Fd())
+ if err != nil {
+ l.Error.Fatalf("failed to create terminal: %v", err)
+ }
+
+ size, err := terminal.Size()
+ if err != nil {
+ l.Error.Fatalf("failed to get terminal size: %v", err)
+ }
+
w, err := wisdom.New(wisdom.Parameters{
Log: l,
Path: filepath.Join(dir, "wisdom"),
- Wrap: *wrap,
+ Size: size,
})
if err := w.Command(flag.CommandLine.Args()); err != nil {
diff --git a/pkg/wisdom/quote/quote.go b/pkg/wisdom/quote/quote.go
@@ -2,8 +2,6 @@ package quote
import (
"strings"
-
- "code.dwrz.net/src/pkg/text"
)
type Quote struct {
@@ -14,26 +12,26 @@ type Quote struct {
Text string `json:"text"`
}
-func (q *Quote) Render(width int) string {
+func (q *Quote) Render() string {
var str strings.Builder
- str.WriteString(text.Wrap(q.Text, width))
+ str.WriteString(q.Text)
if q.Author != "" || q.Source != "" {
str.WriteString("\n\n")
}
if q.Author != "" {
- str.WriteString(text.Wrap(q.Author, width))
+ str.WriteString(q.Author)
}
if q.Author != "" && q.Source != "" {
str.WriteString(", ")
}
if q.Source != "" {
- str.WriteString(text.Wrap(q.Source, width))
+ str.WriteString(q.Source)
}
if q.Comment != "" {
str.WriteString("\n\n")
- str.WriteString(text.Wrap(q.Comment, width))
+ str.WriteString(q.Comment)
}
if len(q.Tags) > 0 {
str.WriteString("\nTags: ")
@@ -41,7 +39,7 @@ func (q *Quote) Render(width int) string {
for tag := range q.Tags {
tags += tag + " "
}
- str.WriteString(text.Wrap(tags, width))
+ str.WriteString(tags)
}
return str.String()
diff --git a/pkg/wisdom/wisdom.go b/pkg/wisdom/wisdom.go
@@ -9,13 +9,14 @@ import (
"os/exec"
"path/filepath"
"strings"
- "text/tabwriter"
"unicode"
"github.com/google/uuid"
+ "github.com/mattn/go-runewidth"
"code.dwrz.net/src/pkg/log"
"code.dwrz.net/src/pkg/store"
+ "code.dwrz.net/src/pkg/terminal"
"code.dwrz.net/src/pkg/text"
"code.dwrz.net/src/pkg/wisdom/quote"
)
@@ -25,13 +26,13 @@ const coll = "data"
type Parameters struct {
Log *log.Logger
Path string
- Wrap int
+ Size *terminal.Size
}
type Wisdom struct {
log *log.Logger
store *store.Store
- wrap int
+ size *terminal.Size
}
func New(p Parameters) (*Wisdom, error) {
@@ -50,7 +51,7 @@ func New(p Parameters) (*Wisdom, error) {
return &Wisdom{
log: p.Log,
store: store,
- wrap: p.Wrap,
+ size: p.Size,
}, nil
}
@@ -69,7 +70,7 @@ func (w *Wisdom) Command(args []string) error {
)
}
- fmt.Println(q.Render(w.wrap))
+ fmt.Println(q.Render())
return nil
}
@@ -258,8 +259,8 @@ func (w *Wisdom) list() error {
return fmt.Errorf("failed to load quotes: %v", err)
}
- tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', 0)
- fmt.Fprintln(tw, "Id\tText\tAuthor\tSource\t")
+ var output strings.Builder
+ output.WriteString("id,author,source,text\n")
for _, d := range docs {
var q = "e.Quote{}
@@ -271,20 +272,49 @@ func (w *Wisdom) list() error {
continue
}
- var t = q.Text
- if w.wrap > 0 {
- t = text.Truncate(q.Text, w.wrap-1) + "…"
+ var (
+ line strings.Builder
+ // Account for the final newline.
+ space = int(w.size.Columns)
+ )
+ // Id
+ line.WriteString(text.Truncate(d.Id, space))
+ space -= runewidth.StringWidth(d.Id)
+ line.WriteByte(',')
+ space -= 1
+
+ // Author
+ line.WriteString(text.Truncate(q.Author, space))
+ space -= runewidth.StringWidth(q.Author)
+ line.WriteByte(',')
+ space -= 1
+
+ // Source
+ line.WriteString(text.Truncate(q.Source, space))
+ space -= runewidth.StringWidth(q.Source)
+ line.WriteByte(',')
+ space -= 1
+
+ // Text
+ t := strings.ReplaceAll(q.Text, "\n", " ")
+ switch {
+ case space < 1:
+ // Don't output text.
+ case len(t) > space:
+ line.WriteString(text.Truncate(
+ t,
+ space-runewidth.RuneWidth('…'),
+ ))
+ line.WriteRune('…')
+ default:
+ line.WriteString(t)
}
+ line.WriteByte('\n')
- fmt.Fprintf(
- tw, "%s\t%s\t%s\t%s\t\n",
- d.Id,
- strings.ReplaceAll(t, "\n", " "),
- q.Author,
- q.Source,
- )
+ output.WriteString(line.String())
}
- tw.Flush()
+
+ fmt.Println(output.String())
return nil
}
@@ -318,7 +348,7 @@ func (w *Wisdom) show(args []string) error {
)
}
- fmt.Println(q.Render(w.wrap))
+ fmt.Println(q.Render())
}
return nil