Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
42c0e48081
|
+71
-8
@@ -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
|
||||
@@ -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()
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
@@ -636,7 +636,7 @@ pre.rouge .gs {
|
||||
<div class="details">
|
||||
<span id="author" class="author">Brent Saner</span><br>
|
||||
<span id="email" class="email"><a href="mailto:bts@square-r00t.net">bts@square-r00t.net</a></span><br>
|
||||
<span id="revdate">Last rendered 2026-06-22 18:51:24 -0400</span>
|
||||
<span id="revdate">Last rendered 2026-07-06 16:21:08 -0400</span>
|
||||
</div>
|
||||
<div id="toc" class="toc2">
|
||||
<div id="toctitle">Table of Contents</div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<span id="author" class="author">Brent Saner</span>
|
||||
<span id="email" class="email"><bts@square-r00t.net></span>
|
||||
<span id="revdate">Last rendered 2026-06-22 18:51:29 -0400</span>
|
||||
<span id="revdate">Last rendered 2026-07-06 16:21:13 -0400</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user