Documentation
¶
Overview ¶
Package strings provides string helpers: split, contains, indent/dedent, truncate, and blank checks.
Index ¶
- func AppendCSV(dst []string, raw string) []string
- func Closest(target string, candidates []string) string
- func CompactLines(s, sep string) string
- func CompareFold(a, b string) int
- func CompareNatural(a, b string) int
- func ContainsAll(s string, substrings ...string) bool
- func ContainsAny(s string, substrings ...string) bool
- func CountAny(s, chars string) int
- func Dedent(s string) string
- func EnsureTrailingNewline(s string) string
- func EqualNatural(a, b string) bool
- func Indent(s, prefix string) string
- func IsBlank(s string) bool
- func IsDigits(s string) bool
- func IsGitCommit(s string) bool
- func IsHex(s string) bool
- func IsHexChar(c rune) bool
- func IsSHA256(s string) bool
- func LessNatural(a, b string) bool
- func PadCenter(s string, width int) string
- func PadLeft(s string, width int) string
- func PadRight(s string, width int) string
- func SplitAny(s, chars string) []string
- func SplitBy(s, sep string) []string
- func SplitCSV(s string) []string
- func SplitLines(s string) []string
- func SplitLinesRaw(s string) []string
- func Truncate(s string, n int, marker string) string
- func TruncateLeft(s string, n int, marker string) string
- func TruncateMiddle(s string, n int, marker string) string
- func TruncateRight(s string, n int, marker string) string
- func Unwrap(s, prefix, suffix string) (string, bool)
Examples ¶
- AppendCSV
- Closest
- CompactLines
- CompareFold
- CompareNatural
- ContainsAll
- ContainsAny
- CountAny
- Dedent
- EnsureTrailingNewline
- EqualNatural
- Indent
- IsBlank
- IsDigits
- IsGitCommit
- IsHex
- IsHexChar
- IsSHA256
- LessNatural
- PadCenter
- PadLeft
- PadRight
- SplitAny
- SplitBy
- SplitCSV
- SplitLines
- SplitLinesRaw
- Truncate
- TruncateLeft
- TruncateMiddle
- TruncateRight
- Unwrap
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AppendCSV ¶
AppendCSV splits `raw` on commas, trims whitespace, drops empty values, and appends the remaining values to `dst`.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.AppendCSV([]string{"x"}, " a, b ,, c "))
}
Output: ["x" "a" "b" "c"]
func Closest ¶
Closest returns the candidate nearest to `target`, suitable for a "did you mean?" suggestion. Distance is the Damerau-Levenshtein (optimal string alignment) edit distance, so an adjacent transposition like "verfiy" counts as one edit, not two - the common typo plain Levenshtein over-penalizes. It returns "" when the nearest candidate is further than a third of `target`'s length in edits, so an unrelated word is never suggested. An empty `target` carries no signal and suggests nothing. Ties resolve to the first candidate.
Closest("verfiy", []string{"verify", "deep"}) // "verify"
Closest("xyzzy", []string{"verify", "deep"}) // ""
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.Closest("verfiy", []string{"verify", "deep"}))
fmt.Printf("%q\n", xstrings.Closest("xyzzy", []string{"verify", "deep"}))
}
Output: "verify" ""
func CompactLines ¶
CompactLines trims lines, drops blank lines, removes duplicate lines while preserving first-seen order, and joins the remaining lines with `sep`.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.CompactLines(" foo \n\nbar\nfoo\n", ", "))
}
Output: foo, bar
func CompareFold ¶
CompareFold compares `a` and `b` case-insensitively, using the same simple case-folding as strings.EqualFold, and returns -1, 0, or 1 following the cmp.Compare convention. `CompareFold(a, b) == 0` iff `strings.EqualFold(a, b)`.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.CompareFold("Go", "go"))
fmt.Println(xstrings.CompareFold("abc", "ABD"))
fmt.Println(xstrings.CompareFold("B", "a"))
}
Output: 0 -1 1
func CompareNatural ¶
CompareNatural orders `a` and `b` the way a human reads them, treating each run of digits as a single decimal number so "x2" sorts before "x10". It returns -1, 0, or +1 and allocates nothing, handling numbers of any length without overflow.
Example ¶
package main
import (
"fmt"
"slices"
xstrings "github.com/gechr/x/strings"
)
func main() {
versions := []string{"v10", "v2", "v1"}
slices.SortFunc(versions, xstrings.CompareNatural)
fmt.Println(versions)
}
Output: [v1 v2 v10]
func ContainsAll ¶
ContainsAll reports whether `s` contains all of the given `substrings`.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.ContainsAll("hello world", "hello", "world"))
fmt.Println(xstrings.ContainsAll("hello world", "hello", "moon"))
}
Output: true false
func ContainsAny ¶
ContainsAny reports whether `s` contains any of the given `substrings`.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.ContainsAny("hello world", "moon", "world"))
fmt.Println(xstrings.ContainsAny("hello world", "moon", "sun"))
}
Output: true false
func CountAny ¶
CountAny returns the number of Unicode code points in `s` that are contained in `chars`, following the cutset convention of strings.IndexAny.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.CountAny("hello world", "lo"))
}
Output: 5
func Dedent ¶
Dedent strips the longest common leading-whitespace prefix from non-empty lines. Whitespace-only lines are normalized to empty (Python textwrap.dedent).
Dedent(" foo\n bar\n baz") // "foo\n bar\nbaz"
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.Dedent(" foo\n bar\n baz"))
}
Output: foo bar baz
func EnsureTrailingNewline ¶
EnsureTrailingNewline trims any trailing newlines from `s` and appends exactly one, so the result always ends in a single "\n". An empty string becomes "\n".
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.EnsureTrailingNewline("hello\n\n"))
fmt.Printf("%q\n", xstrings.EnsureTrailingNewline("hello"))
}
Output: "hello\n" "hello\n"
func EqualNatural ¶
EqualNatural reports whether `a` and `b` compare equal in natural order, as decided by CompareNatural. This can differ from `a == b`, since a numeric run followed by more to compare matches regardless of leading zeros (for example "a00b00" and "a0b00").
Example ¶
Leading zeros are ignored when more text follows the numeric run.
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.EqualNatural("a00b00", "a0b00"))
fmt.Println(xstrings.EqualNatural("a1", "a2"))
}
Output: true false
func Indent ¶
Indent prefixes every non-blank line of `s` with `prefix`. Blank and whitespace-only lines are normalized to empty.
Indent("foo\nbar", " ") // " foo\n bar"
Indent("foo\n\nbar", "> ") // "> foo\n\n> bar"
Indent("foo\n \nbar", "> ") // "> foo\n\n> bar"
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.Indent("foo\nbar", "> "))
}
Output: > foo > bar
func IsBlank ¶
IsBlank reports whether `s` is empty or consists only of whitespace.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.IsBlank(" \t\n"))
fmt.Println(xstrings.IsBlank("x"))
}
Output: true false
func IsDigits ¶
IsDigits reports whether `s` is non-empty and consists entirely of ASCII digits (0-9). An empty string is not digits.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.IsDigits("12345"))
fmt.Println(xstrings.IsDigits("12a45"))
fmt.Println(xstrings.IsDigits(""))
}
Output: true false false
func IsGitCommit ¶
IsGitCommit reports whether `s` is 40 hexadecimal digits (a Git commit hash).
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.IsGitCommit("3b18e512dba79e4c8300dd08aeb37f8e728b8dad"))
fmt.Println(xstrings.IsGitCommit("deadbeef"))
}
Output: true false
func IsHex ¶
IsHex reports whether `s` is non-empty and consists entirely of hexadecimal digits. An empty string is not hex.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.IsHex("deadBEEF42"))
fmt.Println(xstrings.IsHex("xyz"))
}
Output: true false
func IsHexChar ¶
IsHexChar reports whether `c` is a valid hexadecimal digit (0-9, a-f, A-F).
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.IsHexChar('f'))
fmt.Println(xstrings.IsHexChar('F'))
fmt.Println(xstrings.IsHexChar('9'))
fmt.Println(xstrings.IsHexChar('g'))
}
Output: true true true false
func IsSHA256 ¶
IsSHA256 reports whether `s` is 64 hexadecimal digits (a SHA-256 digest).
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(
xstrings.IsSHA256("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"),
)
fmt.Println(xstrings.IsSHA256("deadbeef"))
}
Output: true false
func LessNatural ¶
LessNatural reports whether `a` sorts before `b` in natural order, as decided by CompareNatural. It reads cleanly at call sites that want a boolean rather than a three-way result, such as sort predicates and conditionals.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.LessNatural("v2", "v10"))
fmt.Println(xstrings.LessNatural("v10", "v2"))
}
Output: true false
func PadCenter ¶
PadCenter pads `s` with spaces on both sides to `width` runes, centring it. An odd rune of padding goes on the right. Strings already `width` runes or longer are returned unchanged.
PadCenter("hi", 5) // " hi "
Example ¶
PadCenter places the odd rune of padding on the right.
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.PadCenter("hi", 5))
}
Output: " hi "
func PadLeft ¶
PadLeft pads `s` with spaces on the left to `width` runes, right-aligning it. Strings already `width` runes or longer are returned unchanged. Width is counted in runes; for display-width-aware handling of ANSI text use the github.com/gechr/x/ansi package.
PadLeft("hi", 5) // " hi"
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.PadLeft("hi", 5))
}
Output: " hi"
func PadRight ¶
PadRight pads `s` with spaces on the right to `width` runes, left-aligning it. Strings already `width` runes or longer are returned unchanged.
PadRight("hi", 5) // "hi "
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.PadRight("hi", 5))
}
Output: "hi "
func SplitAny ¶
SplitAny splits `s` around each occurrence of any Unicode code point in `chars`, following the cutset convention of strings.IndexAny. Empty segments between adjacent separators are preserved, matching strings.Split semantics. If `chars` is empty, SplitAny returns a single-element slice containing `s`.
Example ¶
Empty segments between adjacent separators are preserved.
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.SplitAny("a,b;;c", ",;"))
}
Output: ["a" "b" "" "c"]
func SplitBy ¶
SplitBy splits `s` by `sep`, trims whitespace from each part, and drops empty values.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.SplitBy(" a | b || c ", "|"))
}
Output: ["a" "b" "c"]
func SplitCSV ¶
SplitCSV splits `s` on commas, trims whitespace, and drops empty values.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.SplitCSV(" a, b ,, c "))
}
Output: ["a" "b" "c"]
func SplitLines ¶
SplitLines splits `s` into non-empty trimmed lines.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.SplitLines("foo\n\n bar \n"))
}
Output: ["foo" "bar"]
func SplitLinesRaw ¶
SplitLinesRaw splits `s` into lines losslessly, normalizing CRLF to LF: every line is kept verbatim - empty lines and the trailing empty element included - so the result joins back with `"\n"` without losing content or line numbers.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Printf("%q\n", xstrings.SplitLinesRaw("foo\r\nbar\n"))
}
Output: ["foo" "bar" ""]
func Truncate ¶
Truncate is an alias for TruncateRight, the most common form: it keeps the head and trims the tail.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.Truncate("hello world", 8, "…"))
}
Output: hello w…
func TruncateLeft ¶
TruncateLeft shortens `s` to at most `n` runes (including `marker`) by removing characters from the left, prepending `marker` when truncation occurs. The tail is kept.
TruncateLeft("hello world", 8, "…") // "…o world"
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.TruncateLeft("hello world", 8, "…"))
}
Output: …o world
func TruncateMiddle ¶
TruncateMiddle shortens `s` to at most `n` runes (including `marker`) by removing characters from the middle, inserting `marker` between the kept head and tail so both ends stay visible. This suits hashes and paths, where the start and end are the recognisable parts.
TruncateMiddle("0123456789abcdef", 7, "…") // "012…def"
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.TruncateMiddle("0123456789abcdef", 7, "…"))
}
Output: 012…def
func TruncateRight ¶
TruncateRight shortens `s` to at most `n` runes (including `marker`) by removing characters from the right, appending `marker` when truncation occurs. The head is kept. For display-width-aware truncation of ANSI text use github.com/gechr/x/ansi.Truncate.
TruncateRight("hello world", 8, "…") // "hello w…"
TruncateRight("hi", 8, "…") // "hi"
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.TruncateRight("hello world", 8, "…"))
fmt.Println(xstrings.TruncateRight("hi", 8, "…"))
}
Output: hello w… hi
func Unwrap ¶
Unwrap returns `s` with the leading `prefix` and trailing `suffix` removed and reports whether both were present. Unlike a strings.TrimPrefix + strings.TrimSuffix chain, nothing is removed unless `s` starts with `prefix` AND ends with `suffix`, so a one-sided match is returned unchanged.
Example ¶
package main
import (
"fmt"
xstrings "github.com/gechr/x/strings"
)
func main() {
fmt.Println(xstrings.Unwrap(`"quoted"`, `"`, `"`))
fmt.Println(xstrings.Unwrap(`"one-sided`, `"`, `"`))
}
Output: quoted true "one-sided false
Types ¶
This section is empty.