lockbox

password manager
Log | Files | Refs | README | LICENSE

commit f442abbe0c07611ec5d5c0ed2c82f8b5e68bc438
parent e80b71e1c96504b4ec04200547b035d6a838834e
Author: Sean Enck <sean@ttypty.com>
Date:   Mon,  2 Jun 2025 22:03:21 -0400

textwrap -> output, utils almost split up

Diffstat:
Minternal/app/help/core.go | 4++--
Minternal/config/toml.go | 4++--
Ainternal/output/text.go | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainternal/output/text_test.go | 26++++++++++++++++++++++++++
Minternal/util/reflect.go | 19+++++++++++++++++++
Minternal/util/reflect_test.go | 7+++++++
Dinternal/util/text.go | 80-------------------------------------------------------------------------------
Dinternal/util/text_test.go | 33---------------------------------
8 files changed, 117 insertions(+), 117 deletions(-)

diff --git a/internal/app/help/core.go b/internal/app/help/core.go @@ -13,7 +13,7 @@ import ( "git.sr.ht/~enckse/lockbox/internal/app/commands" "git.sr.ht/~enckse/lockbox/internal/backend" "git.sr.ht/~enckse/lockbox/internal/config" - "git.sr.ht/~enckse/lockbox/internal/util" + "git.sr.ht/~enckse/lockbox/internal/output" ) const ( @@ -161,7 +161,7 @@ func processDoc(header, file string, doc Documentation) (string, error) { if err := t.Execute(&buf, doc); err != nil { return "", err } - return fmt.Sprintf("%s\n%s", header, util.TextWrap(0, buf.String())), nil + return fmt.Sprintf("%s\n%s", header, output.TextWrap(0, buf.String())), nil } func setDocFlag(f string) string { diff --git a/internal/config/toml.go b/internal/config/toml.go @@ -11,7 +11,7 @@ import ( "strings" "git.sr.ht/~enckse/lockbox/internal/config/store" - "git.sr.ht/~enckse/lockbox/internal/util" + "git.sr.ht/~enckse/lockbox/internal/output" "github.com/BurntSushi/toml" ) @@ -106,7 +106,7 @@ func generateDetailText(data printer) (string, error) { if len(value) == 0 { value = unset } - description := strings.TrimSpace(util.TextWrap(2, env.description)) + description := strings.TrimSpace(output.TextWrap(2, env.description)) requirement := "optional/default" r := strings.TrimSpace(env.requirement) if r != "" { diff --git a/internal/output/text.go b/internal/output/text.go @@ -0,0 +1,61 @@ +package output + +import ( + "bytes" + "fmt" + "strings" +) + +// TextWrap performs simple block text word wrapping +func TextWrap(indent uint, in string) string { + var sections []string + var cur []string + for _, line := range strings.Split(strings.TrimSpace(in), "\n") { + trimmed := strings.TrimSpace(line) + if trimmed == "" { + if len(cur) > 0 { + sections = append(sections, strings.Join(cur, " ")) + cur = []string{} + } + continue + } + cur = append(cur, line) + } + if len(cur) > 0 { + sections = append(sections, strings.Join(cur, " ")) + } + var out bytes.Buffer + indenting := "" + var cnt uint + for cnt < indent { + indenting = fmt.Sprintf("%s ", indenting) + cnt++ + } + indenture := int(80 - indent) + for _, s := range sections { + for _, line := range strings.Split(wrap(s, indenture), "\n") { + fmt.Fprintf(&out, "%s%s\n", indenting, line) + } + fmt.Fprint(&out, "\n") + } + return out.String() +} + +func wrap(in string, maxLength int) string { + var lines []string + var cur []string + for _, p := range strings.Split(in, " ") { + state := strings.Join(cur, " ") + l := len(p) + if len(state)+l >= maxLength { + lines = append(lines, strings.Join(cur, " ")) + cur = []string{p} + } else { + cur = append(cur, p) + } + } + if len(cur) > 0 { + lines = append(lines, strings.Join(cur, " ")) + } + return strings.Join(lines, "\n") +} diff --git a/internal/output/text_test.go b/internal/output/text_test.go @@ -0,0 +1,26 @@ +package output_test + +import ( + "testing" + + "git.sr.ht/~enckse/lockbox/internal/output" +) + +func TestWrap(t *testing.T) { + w := output.TextWrap(0, "") + if w != "" { + t.Errorf("invalid wrap: %s", w) + } + w = output.TextWrap(0, "abc\n\nabc\nxyz\n") + if w != "abc\n\nabc xyz\n\n" { + t.Errorf("invalid wrap: %s", w) + } + w = output.TextWrap(0, "abc\n\nabc\nxyz\n\nx") + if w != "abc\n\nabc xyz\n\nx\n\n" { + t.Errorf("invalid wrap: %s", w) + } + w = output.TextWrap(5, "abc\n\nabc\nxyz\n\nx") + if w != " abc\n\n abc xyz\n\n x\n\n" { + t.Errorf("invalid wrap: %s", w) + } +} diff --git a/internal/util/reflect.go b/internal/util/reflect.go @@ -5,6 +5,20 @@ import ( "fmt" "reflect" "sort" + "strings" +) + +type ( + // Position is the start/end of a word in a greater set + Position struct { + Start int + End int + } + // Word is the text and position in a greater position + Word struct { + Text string + Position Position + } ) // ListFields will get the values of strings on an "all string" struct @@ -30,3 +44,8 @@ func readNested(v reflect.Type, root string) []string { } return fields } + +// TextPositionFields is the displayable set of templated fields +func TextPositionFields() string { + return strings.Join(readNested(reflect.TypeOf(Word{}), ""), ", ") +} diff --git a/internal/util/reflect_test.go b/internal/util/reflect_test.go @@ -18,3 +18,10 @@ func TestListFields(t *testing.T) { t.Errorf("invalid fields: %v", fields) } } + +func TestTextFields(t *testing.T) { + v := util.TextPositionFields() + if v != "Text, Position.Start, Position.End" { + t.Errorf("unexpected fields: %s", v) + } +} diff --git a/internal/util/text.go b/internal/util/text.go @@ -1,80 +0,0 @@ -package util - -import ( - "bytes" - "fmt" - "reflect" - "strings" -) - -type ( - // Position is the start/end of a word in a greater set - Position struct { - Start int - End int - } - // Word is the text and position in a greater position - Word struct { - Text string - Position Position - } -) - -// TextWrap performs simple block text word wrapping -func TextWrap(indent uint, in string) string { - var sections []string - var cur []string - for _, line := range strings.Split(strings.TrimSpace(in), "\n") { - trimmed := strings.TrimSpace(line) - if trimmed == "" { - if len(cur) > 0 { - sections = append(sections, strings.Join(cur, " ")) - cur = []string{} - } - continue - } - cur = append(cur, line) - } - if len(cur) > 0 { - sections = append(sections, strings.Join(cur, " ")) - } - var out bytes.Buffer - indenting := "" - var cnt uint - for cnt < indent { - indenting = fmt.Sprintf("%s ", indenting) - cnt++ - } - indenture := int(80 - indent) - for _, s := range sections { - for _, line := range strings.Split(wrap(s, indenture), "\n") { - fmt.Fprintf(&out, "%s%s\n", indenting, line) - } - fmt.Fprint(&out, "\n") - } - return out.String() -} - -func wrap(in string, maxLength int) string { - var lines []string - var cur []string - for _, p := range strings.Split(in, " ") { - state := strings.Join(cur, " ") - l := len(p) - if len(state)+l >= maxLength { - lines = append(lines, strings.Join(cur, " ")) - cur = []string{p} - } else { - cur = append(cur, p) - } - } - if len(cur) > 0 { - lines = append(lines, strings.Join(cur, " ")) - } - return strings.Join(lines, "\n") -} - -// TextPositionFields is the displayable set of templated fields -func TextPositionFields() string { - return strings.Join(readNested(reflect.TypeOf(Word{}), ""), ", ") -} diff --git a/internal/util/text_test.go b/internal/util/text_test.go @@ -1,33 +0,0 @@ -package util_test - -import ( - "testing" - - "git.sr.ht/~enckse/lockbox/internal/util" -) - -func TestWrap(t *testing.T) { - w := util.TextWrap(0, "") - if w != "" { - t.Errorf("invalid wrap: %s", w) - } - w = util.TextWrap(0, "abc\n\nabc\nxyz\n") - if w != "abc\n\nabc xyz\n\n" { - t.Errorf("invalid wrap: %s", w) - } - w = util.TextWrap(0, "abc\n\nabc\nxyz\n\nx") - if w != "abc\n\nabc xyz\n\nx\n\n" { - t.Errorf("invalid wrap: %s", w) - } - w = util.TextWrap(5, "abc\n\nabc\nxyz\n\nx") - if w != " abc\n\n abc xyz\n\n x\n\n" { - t.Errorf("invalid wrap: %s", w) - } -} - -func TestTextFields(t *testing.T) { - v := util.TextPositionFields() - if v != "Text, Position.Start, Position.End" { - t.Errorf("unexpected fields: %s", v) - } -}