diff --git a/stringsx/funcs.go b/stringsx/funcs.go index e1b0184..b430fae 100644 --- a/stringsx/funcs.go +++ b/stringsx/funcs.go @@ -1,13 +1,13 @@ package stringsx import ( - `bytes` - `errors` - `fmt` - `io` - `slices` - `strings` - `unicode` + "bytes" + "errors" + "fmt" + "io" + "slices" + "strings" + "unicode" ) /* @@ -17,6 +17,7 @@ It is more strict than [HasBoundary] (which only requires that s has sym at the beginning OR the end.) Examples: + HasBookend("|foo|", "|") → true HasBookend("|foo", "|") → false HasBookend("foo|", "|") → false @@ -38,6 +39,7 @@ func HasBookend(s, sym string) (bounded bool) { HasBoundary returns true if string s starts OR ends with symbol sym. Examples: + HasBoundary("|foo|", "|") → true HasBoundary("|foo", "|") → true HasBoundary("foo|", "|") → true @@ -51,9 +53,9 @@ If sym is empty, HasBoundary will *always* return true. If you instead require string s to be *enclosed* by sym, see [HasBookend]. */ func HasBoundary(s, sym string) (bounded bool) { - + bounded = strings.HasPrefix(s, sym) || strings.HasSuffix(s, sym) - + return } @@ -453,6 +455,37 @@ func Redact(s, maskStr string, leading, trailing uint, newlines bool) (redacted return } +/* +RemoveWhitespace removes all leading, trailing, and INNER whitespace +from unicode string `s`. + +This is done by allocating a strings.Builder with len(s). +This may consume more memory than needed if s is mostly whitespace; +in that case, it is better to use [StripWhitespace]. +*/ +func RemoveWhitespace(s string) (removed string) { + + // https://stackoverflow.com/questions/32081808/strip-all-whitespace-from-a-string/32081891#32081891 + + var c rune + var sb strings.Builder + + if s == "" { + return + } + + sb.Grow(len(s)) + for _, c = range s { + if !unicode.IsSpace(c) { + sb.WriteRune(c) + } + } + + removed = sb.String() + + return +} + // Reverse reverses string s. (It's absolutely insane that this isn't in stdlib.) func Reverse(s string) (revS string) { @@ -465,6 +498,35 @@ func Reverse(s string) (revS string) { return } +/* +StripWhitespace removes all leading, trailing, and INNER whitespace +from unicode string `s`. + +This is done by mapping each rune in `s`. +This may use far more allocations than necessary if `s` is mostly NON-whitespace; +in that case, it is better to use [RemoveWhitespace]. +*/ +func StripWhitespace(s string) (stripped string) { + + // https://stackoverflow.com/questions/32081808/strip-all-whitespace-from-a-string/32081891#32081891 + + if s == "" { + return + } + + stripped = strings.Map( + func(c rune) rune { + if unicode.IsSpace(c) { + return -1 + } + return c + }, + s, + ) + + return +} + /* TrimLines is like [strings.TrimSpace] but operates on *each line* of s. It is *NIX-newline (`\n`) vs. Windows-newline (`\r\n`) agnostic. @@ -500,7 +562,8 @@ func TrimLines(s string, left, right bool) (trimmed string) { } else if right { sl = TrimSpaceRight(sl) } - sb.WriteString(sl + nl) + sb.WriteString(sl) + sb.WriteString(nl) } trimmed = sb.String() diff --git a/stringsx/func_asciiinvaliderror.go b/stringsx/funcs_asciiinvaliderror.go similarity index 100% rename from stringsx/func_asciiinvaliderror.go rename to stringsx/funcs_asciiinvaliderror.go diff --git a/tplx/internal/todo/example_recursive_parse.go b/tplx/internal/todo/example_recursive_parse.go new file mode 100644 index 0000000..1963013 --- /dev/null +++ b/tplx/internal/todo/example_recursive_parse.go @@ -0,0 +1,99 @@ +package main + +import ( + "embed" + "io" + "io/fs" + // "fmt" + "log" + // "os" + // "path/filepath" + "text/template" + // "github.com/davecgh/go-spew/spew" +) + +var ( + //go:embed "tplfiles" + tplfiles embed.FS + + tpl *template.Template = template.New("") + + tw *TplWalker = new(TplWalker) +) + +type ( + TplWalker struct { + tpl *template.Template + fs fs.FS + } +) + +func (t *TplWalker) walkFunc(fpath string, d fs.DirEntry, inErr error) (err error) { + + var b []byte + var f fs.File + + if inErr != nil { + err = inErr + return + } + + if d.IsDir() { + return + } + + if f, err = t.fs.Open(fpath); err != nil { + return + } + defer func() { + var ok bool + var c io.Closer + if f != nil { + if c, ok = f.(io.Closer); ok { + if err = c.Close(); err != nil { + return + } + } + } + }() + + if b, err = io.ReadAll(f); err != nil { + return + } + + if _, err = t.tpl.New(fpath).Parse(string(b)); err != nil { + return + } + + return +} + +func (t *TplWalker) Walk() (err error) { + + if err = fs.WalkDir(t.fs, ".", t.walkFunc); err != nil { + return + } + + return +} + +func init() { + var err error + + tw.tpl = tpl + tw.fs = tplfiles + + if err = tw.Walk(); err != nil { + log.Panicln(err) + } +} + +func main() { + var idx int + var sub *template.Template + + log.Printf("Root template name is %q", tpl.Name()) + for idx, sub = range tpl.Templates() { + log.Printf("Sub template %d: %q", idx, sub.Name()) + } +} diff --git a/tplx/sprigx/README.html b/tplx/sprigx/README.html index e605c8c..8884289 100644 --- a/tplx/sprigx/README.html +++ b/tplx/sprigx/README.html @@ -636,7 +636,7 @@ pre.rouge .gs {
Brent Saner
bts@square-r00t.net
-Last rendered 2026-06-22 18:51:24 -0400 +Last rendered 2026-07-06 16:21:08 -0400
Table of Contents
diff --git a/tplx/sprigx/README.md b/tplx/sprigx/README.md index 73145f0..499285a 100644 --- a/tplx/sprigx/README.md +++ b/tplx/sprigx/README.md @@ -6,7 +6,7 @@ Brent Saner -Last rendered 2026-06-22 18:51:29 -0400 +Last rendered 2026-07-06 16:21:13 -0400