From 1920bf48f73c881ef5c394364b3abe00f3027ced Mon Sep 17 00:00:00 2001 From: diamondburned Date: Thu, 31 Oct 2024 13:57:45 -0700 Subject: [PATCH] Style longDescription better --- cmd/nix-search/main.go | 85 ++++++++++++++++++++++++---------------- cmd/nix-search/styler.go | 44 +++++++++++++++++++++ flake.nix | 2 +- go.mod | 2 +- 4 files changed, 97 insertions(+), 36 deletions(-) create mode 100644 cmd/nix-search/styler.go diff --git a/cmd/nix-search/main.go b/cmd/nix-search/main.go index 2c77dad..a72da8d 100644 --- a/cmd/nix-search/main.go +++ b/cmd/nix-search/main.go @@ -10,7 +10,9 @@ import ( "os" "os/exec" "os/signal" + "regexp" "strings" + "sync" "github.com/hashicorp/go-hclog" "github.com/mattn/go-isatty" @@ -245,58 +247,73 @@ func mainAction(c *cli.Context) error { fmt.Fprint(out, "\n") fmt.Fprint(out, wrap(pkg.Description, " "), "\n") + + if pkg.LongDescription != "" && pkg.Description != pkg.LongDescription { + fmt.Fprint(out, styleLongDescription(styler, pkg.LongDescription), "\n") + } } return ctx.Err() } -type textStyler bool - -const styledText textStyler = true +var ( + reFencedCodeBlock = regexp.MustCompile(`(?ms)\x60\x60\x60+\s*(.*?)\s*\x60\x60\x60+`) + reInlineHyperlink = regexp.MustCompile(`(?m)\[(.*?)\]\n*\((http.*?)\)`) + reInlineCode = regexp.MustCompile(`(?m)\x60\x60?(.*?)\x60\x60?`) +) -func (s textStyler) strikethrough(text string) string { - if !s { - return text - } - return "\x1b[9m" + text + "\x1b[29m" -} +// TODO: consider using goldmark? +func styleLongDescription(styler textStyler, text string) string { + linkReplace := styler.bold("$1") + styler.with(dontEndStyle).dim(" ($2)") + codeReplace := styler.bold("$1") + styler.with(dontEndStyle).dim("") + + for _, f := range []func(string) string{ + func(text string) string { + var sb strings.Builder + sb.Grow(len(text)) + + var start int + for _, is := range reFencedCodeBlock.FindAllStringSubmatchIndex(text, -1) { + sb.WriteString(text[start:is[0]]) + start = is[1] + for _, codeLine := range strings.Split(text[is[2]:is[3]], "\n") { + sb.WriteString("\t") + sb.WriteString(codeLine) + sb.WriteString("\n") + } + } + sb.WriteString(text[start:]) -func (s textStyler) dim(text string) string { - if !s { - return text + return sb.String() + }, + func(text string) string { return reInlineHyperlink.ReplaceAllString(text, linkReplace) }, + func(text string) string { return reInlineCode.ReplaceAllString(text, codeReplace) }, + func(text string) string { return wrap(text, " ") }, + styler.dim, + } { + text = f(text) } - return "\x1b[2m" + text + "\x1b[22m" -} -func (s textStyler) bold(text string) string { - if !s { - return text - } - return "\x1b[1m" + text + "\x1b[22m" + return text } func wrap(text, indent string) string { - width := termWidth() - if width == 0 { + width := min(termWidth(), 80) + if width < 1 { return indent + text } - if width > 80 { - width = 80 - } d := new(doc.Package).Parser().Parse(text) pr := &comment.Printer{ - TextPrefix: indent, - TextWidth: width, + TextCodePrefix: indent + indent, + TextPrefix: indent, + TextWidth: width, } + return string(pr.Text(d)) } -var width = -1 - -func termWidth() int { - if width == -1 { - width, _, _ = term.GetSize(int(os.Stdout.Fd())) - } - return width -} +var termWidth = sync.OnceValue(func() int { + termWidth, _, _ := term.GetSize(int(os.Stdout.Fd())) + return termWidth +}) diff --git a/cmd/nix-search/styler.go b/cmd/nix-search/styler.go new file mode 100644 index 0000000..cb4cbd9 --- /dev/null +++ b/cmd/nix-search/styler.go @@ -0,0 +1,44 @@ +package main + +import "strings" + +type textStyler uint8 + +const ( + styledText textStyler = 1 << iota + dontEndStyle +) + +func (s textStyler) strikethrough(text string) string { + return s.styleTextBlock(text, "\x1b[9m", "\x1b[29m") +} + +func (s textStyler) dim(text string) string { + return s.styleTextBlock(text, "\x1b[2m", "\x1b[22m") +} + +func (s textStyler) bold(text string) string { + return s.styleTextBlock(text, "\x1b[1m", "\x1b[22m") +} + +func (s textStyler) underline(text string) string { + return s.styleTextBlock(text, "\x1b[4m", "\x1b[24m") +} + +func (s textStyler) with(o textStyler) textStyler { + return s | o +} + +func (s textStyler) styleTextBlock(text string, prefix, suffix string) string { + if s&1 == 0 { + return text + } + if s&dontEndStyle != 0 { + suffix = "" + } + lines := strings.Split(text, "\n") + for i, line := range lines { + lines[i] = prefix + line + suffix + } + return strings.Join(lines, "\n") +} diff --git a/flake.nix b/flake.nix index 870b8ae..bc218ae 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ { devShells.default = pkgs.mkShell { packages = with pkgs; [ - go + go_1_21 gopls gotools sqlc diff --git a/go.mod b/go.mod index d73c28d..77d2a79 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module libdb.so/nix-search -go 1.20 +go 1.21 require ( github.com/alecthomas/assert/v2 v2.2.2