to

package module
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 21, 2024 License: Apache-2.0 Imports: 17 Imported by: 10

Documentation

Overview

Package to contains a number of converters that take any number of types and return something transformed from them. It also contains a more granular approach to fmt.Stringer.

Index

Examples

Constants

This section is empty.

Variables

View Source
var EscThese = " \r\t\n|&;()<>![]"

EscThese is set to the default UNIX shell characters which require escaping to be used safely on the terminal. It can be changed to suit the needs of different host shell environments.

Functions

func Bytes

func Bytes(in any) []byte

Bytes converts whatever is passed into a []byte slice. Logs and returns nil if it cannot convert. Supports the following types: string, []byte, []rune, io.Reader.

Example (Bork)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	it := to.Bytes(42)
	if it == nil {
		fmt.Println("yes, it is nil")
	}
	fmt.Printf("%v %T", it, it)
}
Output:

yes, it is nil
[] []uint8
Example (Bytes)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%T", to.Bytes([]byte(`foo`)))
}
Output:

[]uint8
Example (Reader)
package main

import (
	"fmt"
	"strings"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%T", to.Bytes(strings.NewReader(`foo`)))
}
Output:

[]uint8
Example (Runes)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%T", to.Bytes([]rune(`foo`)))
}
Output:

[]uint8
Example (String)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%T", to.Bytes(`foo`))
}
Output:

[]uint8

func CrunchSpace

func CrunchSpace(in string) string

CrunchSpace crunches all unicode.IsSpace into a single space. It does not trim. See TrimCrunchSpace.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%q\n", to.CrunchSpace(`here    is some`))
	fmt.Printf("%q\n", to.CrunchSpace(`   here is some`))
	fmt.Printf("%q\n", to.CrunchSpace(`here is some   `))
	fmt.Printf("%q\n", to.CrunchSpace("here is\nsome"))
	fmt.Printf("%q\n", to.CrunchSpace("here is\rsome"))
	fmt.Printf("%q\n", to.CrunchSpace("here is\r\n some"))

}
Output:

"here is some"
" here is some"
"here is some "
"here is some"
"here is some"
"here is some"

func CrunchSpaceVisible

func CrunchSpaceVisible(in string) string

CrunchSpaceVisible crunches all unicode.IsSpace into a single space and filters out anything that is not unicode.IsPrint. It does not trim. See TrimCrunchSpaceVisible. Note that this requires three passes through the string in order to resolve any white space that might have been separated by escape and other characters.

func Dedented

func Dedented(in string) string

Dedented discards any initial blank lines with nothing but whitespace in them and then detects the number and type of whitespace characters at the beginning of the first line to the first non-whitespace rune and then subsequently removes that number of runes from every following line treating empty lines as if they had only n number of spaces. Note that if any line does not have n number of initial spaces it the initial runes will still be removed. It is, therefore, up to the content creator to ensure that all lines have the same space indentation.

func Esc

func Esc(s string) string

Esc returns a shell-escaped version of the string s. The returned value is a string that can safely be used as one token in a shell command line.

func EscAll

func EscAll(args []string) []string

EscAll calls Esc on all passed strings.

func EscReturns

func EscReturns[T string | []byte | []rune](in T) string

EscReturns changes any actual carriage returns or line returns into their backslashed equivalents and returns a string. This is different than Sprintf("%q") since that escapes several other things.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println(to.EscReturns("some\rthing\n"))
}
Output:

some\rthing\n

func FuncName

func FuncName(i any) string

FuncName makes a best effort attempt to return the string name of the passed function. Anonymous functions are named "funcN" where N is the order of appearance within the current scope. Note that this function will panic if not passed a function.

Example
package main

import (
	"github.com/rwxrob/bonzai/fn"
	"github.com/rwxrob/bonzai/fn/each"

	"github.com/rwxrob/bonzai/to"
)

func Foo() {}

func main() {
	f1 := func() {}
	f2 := func() {}

	// Foo is defined outside of the ExampleFuncName

	each.Println(fn.Map([]any{f1, f2, Foo, to.Lines}, to.FuncName))

}
Output:

func1
func2
Foo
Lines

func HTTPS

func HTTPS(url string) string

HTTPS simply adds the prefix "https://" if not found. Useful for allowing non-prefixed URLs and later converting them.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println(to.HTTPS(`https://rwx.gg`))
	fmt.Println(to.HTTPS(`rwx.gg`))
}
Output:

https://rwx.gg
https://rwx.gg

func Human

func Human(a any) string

Human returns a human-friendly string version of the item, specifically:

  • single-quoted runes
  • double-quoted strings
  • numbers as numbers
  • function names are looked up
  • slices joined with "," and wrapped in []

Anything else is rendered as its fmt.Sprintf("%v",it) form.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

type FooStruct struct{}

func (f FooStruct) String() string { return "FOO" }

type HumanFoo struct{}

func (f HumanFoo) Human() string { return "a friendly foo" }

func FooFunc(a any) {}

func main() {
	fmt.Println(to.Human('r'))                    // not number
	fmt.Println(to.Human("string💢good"))          // unescaped
	fmt.Println(to.Human(new(FooStruct)))         // has String()
	fmt.Println(to.Human(new(HumanFoo)))          // has Human()
	fmt.Println(to.Human([]rune{'r', 's', 'm'}))  // commas
	fmt.Println(to.Human([]string{"foo", "bar"})) // also commas
	fmt.Println(to.Human(func() {}))              // func1
	fmt.Println(to.Human(FooFunc))                // FooFunc
}
Output:

'r'
"string💢good"
FOO
a friendly foo
['r','s','m']
["foo","bar"]
func1
FooFunc

func IndentWrapped

func IndentWrapped(indent, width int, in string) string

IndentWrapped adds the specified number of spaces to the beginning of every line ensuring that the wrapping is preserved to the specified width. See Wrapped and Indented.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	description := `
		The y2j command converts YAML (including references and
		anchors) to compressed JSON (with a single training newline) using
		the popular Go yaml.v3 package and its special <yaml:",inline"> tag.
		Because of this only YAML maps are supported as a base type (no
		arrays). An array can easily be done as the value of a map key.

		`

	fmt.Println("Indented:\n" + to.IndentWrapped(7, 60, description))

}
Output:

Indented:
       The y2j command converts YAML (including references
       and anchors) to compressed JSON (with a single
       training newline) using the popular Go yaml.v3
       package and its special <yaml:",inline"> tag. Because
       of this only YAML maps are supported as a base type
       (no arrays). An array can easily be done as the value
       of a map key.

func Indentation

func Indentation[T Text](in T) int

Indentation returns the number of whitespace runes (in bytes) between beginning of the passed string and the first non-whitespace rune.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println(to.Indentation("    some"))
	fmt.Println(to.Indentation("  some"))
	fmt.Println(to.Indentation("some"))
	fmt.Println(to.Indentation(" 💚ome"))
}
Output:

4
2
0
1

func Indented

func Indented(indent int, in string) string

Indented returns a string with each line indented by the specified number of spaces. Carriage returns are stripped (if found) as a side-effect. Per pkg/text/template rules, the string input argument is last so that this function can be used as-is within template pipe constructs:

{{ .Some | indent 4 }}
Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println("Indented:\n" + to.Indented(4, "some\nthing"))
}
Output:

Indented:
    some
    thing

func Lines

func Lines(in any) []string

Lines transforms the input into a string and then divides that string up into lines (\r?\n) suitable for functional map operations.

Example
package main

import (
	"github.com/rwxrob/bonzai/fn/each"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	buf := `
some

thing 
here

mkay
`
	each.Print(to.Lines(buf))
}
Output:

something heremkay

func LinesChopped added in v0.5.0

func LinesChopped(offset int, in string) string

LinesChopped returns the string with lines chopped from the bottom (positive offset) or the top (negative offset).

Example (FromBottom)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println(to.LinesChopped(2, "one\ntwo\nthree\nfour"))
}
Output:

one
two
Example (FromTop)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println(to.LinesChopped(-2, "one\ntwo\nthree\nfour"))
}
Output:

three
four

func MergedMaps

func MergedMaps[K comparable, V any](maps ...map[K]V) map[K]V

MergedMaps combines the maps with "last wins" priority. Always returns a new map of the given type, even if empty.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	m1 := map[string]any{"foo": 1, "bar": 2}
	m2 := map[string]any{"FOO": 1, "BAR": 2}
	m3 := map[string]any{"foo": 10}
	fmt.Println(to.MergedMaps(m1, m2, m3))
}
Output:

map[BAR:2 FOO:1 bar:2 foo:10]

func PrefixTrimmed added in v0.4.0

func PrefixTrimmed(pre, in string) string

PrefixTrimmed returns a string where every line has the passed prefix removed if found at the absolute beginning of the line. Carriage returns (if any) are dropped.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println(to.PrefixTrimmed("P ", "P some\nP thing"))
}
Output:

some
thing

func Prefixed

func Prefixed(pre, in string) string

Prefixed returns a string where every line is prefixed. Carriage returns (if any) are dropped.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println(to.Prefixed("P ", "some\nthing"))
}
Output:

P some
P thing

func RuneCount

func RuneCount[T string | []byte | []rune](in T) int

RuneCount returns the actual number of runes of the string only counting the unicode.IsGraphic runes. All others are ignored. This is critical when calculating line lengths for terminal output where the string contains escape characters. Note that some runes will occupy two columns instead of one depending on the terminal. This includes omitting any ASCI terminal escape sequences.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	// scan.Trace++
	fmt.Println(to.RuneCount("\033some\033"))
	fmt.Println(to.RuneCount("some"))
	fmt.Println(to.RuneCount("\033[32msome\033[0m"))
}
Output:

4
4
4

func StopWatch

func StopWatch(dur time.Duration) string

StopWatch converts a duration into a string that one would expect to see on a stopwatch.

func String

func String(in any) string

String first looks for string, []byte, []rune, and io.Reader types and if matched returns a string with their content and the string type.

String converts whatever remains to that types fmt.Sprintf("%v") string version (but avoids calling it if possible). Be sure you use things with consistent string representations. Keep in mind that this is extremely high level for rapid tooling and prototyping.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/rwxrob/bonzai/to"
)

type stringer struct{}

func (s stringer) String() string { return "stringer" }

func main() {
	r := strings.NewReader(`reader`)
	stuff := []any{
		"some",
		[]byte{'t', 'h', 'i', 'n', 'g'},
		1, 2.234,
		stringer{},
		r,
	}
	for _, s := range stuff {
		fmt.Printf("%q ", to.String(s))
	}
}
Output:

"some" "thing" "1" "2.234" "stringer" "reader"

func TrimCrunchSpace

func TrimCrunchSpace(in string) string

TrimCrunchSpace is same as CrunchSpace but trims initial and trailing space.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%q\n", to.TrimCrunchSpace(`here    is some`))
	fmt.Printf("%q\n", to.TrimCrunchSpace(`   here is some`))
	fmt.Printf("%q\n", to.TrimCrunchSpace(`here is some   `))
	fmt.Printf("%q\n", to.TrimCrunchSpace("here is\nsome"))
	fmt.Printf("%q\n", to.TrimCrunchSpace("here is\rsome"))
	fmt.Printf("%q\n", to.TrimCrunchSpace("here is\r\n some"))

}
Output:

"here is some"
"here is some"
"here is some"
"here is some"
"here is some"
"here is some"

func TrimCrunchSpaceVisible

func TrimCrunchSpaceVisible(in string) string

TrimCrunchSpaceVisible is same as CrunchSpaceVisible but trims initial and trailing space.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%q\n", to.TrimCrunchSpaceVisible(" here  \033  is\nsome "))
	fmt.Printf("%q\n", to.TrimCrunchSpaceVisible(" here  \033  is \nsome "))

}
Output:

"here is some"
"here is some"

func TrimVisible

func TrimVisible(in string) string

TrimVisible removes anything but unicode.IsPrint and then trims. It does not crunch spaces, however.

func Type added in v0.2.0

func Type[T any](from string, this T) T

Type attempts to convert a string [from] into the type of the provided [this] fallback value. It uses the type of [this] to determine the conversion logic and returns the converted value if successful. If conversion fails, it returns [this] as a fallback.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Println("true, false", to.Type("true", false))
	fmt.Println("false, false", to.Type("false", false))
	fmt.Println("false, true", to.Type("false", true))
	fmt.Println(`"", true`, to.Type("", true))
	fmt.Println(`"", false`, to.Type("", false))

	fmt.Println("1, 0", to.Type("1", 0))
	fmt.Println("14, 0", to.Type("14", 0))
	fmt.Println("-14, 0", to.Type("-14", 0))
	fmt.Println(`"", 0`, to.Type("", 0))

	fmt.Println("1, 0.0", to.Type("1", 0.0))
	fmt.Println("14, 0.0", to.Type("14", 0.0))
	fmt.Println("-14, 0.0", to.Type("-14", 0.0))
	fmt.Println(`"", 0.0`, to.Type("", 0.0))

	fmt.Println("hello, hello", to.Type("hello", "default"))

}
Output:

true, false true
false, false false
false, true false
"", true false
"", false false
1, 0 1
14, 0 14
-14, 0 -14
"", 0 0
1, 0.0 1
14, 0.0 14
-14, 0.0 -14
"", 0.0 0
hello, hello hello

func UnEscReturns

func UnEscReturns[T string | []byte | []rune](in T) string

UnEscReturns changes any escaped carriage returns or line returns into their actual values.

Example
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	fmt.Printf("%q\n", to.UnEscReturns(`some\rthing\n`))
}
Output:

"some\rthing\n"

func Visible

func Visible(in string) string

Visible filters out any rune that is not unicode.IsPrint().

func Words

func Words(it string) string

Words will return the string will all contiguous runs of unicode.IsSpace runes converted into a single space. All leading and trailing white space will also be trimmed.

func Wrapped

func Wrapped(width int, it string) (string, int)

Wrapped returns a word wrapped string at the given boundary width (in bytes) and the count of words contained in the string. All white space is compressed to a single space. Any width less than 1 will simply trim and crunch white space returning essentially the same string and the word count. If the width is less than any given word at the start of a line than it will be the only word on the line even if the word length exceeds the width. No attempt at word-hyphenation is made. Note that white space is defined as unicode.IsSpace and does not include control characters. Anything that is not unicode.IsSpace or unicode.IsGraphic will be ignored in the column count. Any terminal escapes that begin with \033[ will also be kept automatically out of calculations. See Unescaped.

Example

wrapped, count = to.Wrapped("There I was not knowing what to do about this exceedingly long line and knowing that certain people would shun me for injecting\nreturns wherever I wanted.", 40)

package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	wrapped, count := to.Wrapped(3, "some thing")
	fmt.Printf("%q %v\n", wrapped, count)

}
Output:

"some\nthing" 2
Example (Escapes)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	in := `Here is a ` + "\033[34m" + `blue` + "\033[0m" + ` thing `
	out, count := to.Wrapped(16, in)
	fmt.Println(count)
	fmt.Printf("%q", out)
}
Output:

5
"Here is a \x1b[34mblue\x1b[0m\nthing"
Example (Long)
package main

import (
	"fmt"

	"github.com/rwxrob/bonzai/to"
)

func main() {
	in := `
		The config command allows configuration of the current command in
		YAML and JSON (since all JSON is valid YAML). All changes to
		configuration values are done via the <edit> command since
		configurations may be complex and deeply nested in some cases.
		Querying configuration data, however, can be easily accomplished
		with the <query> command that uses jq-like selection syntax.`

	out, count := to.Wrapped(80, in)
	fmt.Println(count)
	fmt.Printf("%q", out)

}
Output:

58
"The config command allows configuration of the current command in YAML and JSON\n(since all JSON is valid YAML). All changes to configuration values are done via\nthe <edit> command since configurations may be complex and deeply nested in some\ncases. Querying configuration data, however, can be easily accomplished with the\n<query> command that uses jq-like selection syntax."

Types

type HumanFriend

type HumanFriend interface {
	Human() string
}

HumanFriend implementations have a human readable form that is even friendlier than fmt.Stringer.

type Text

type Text interface{ string | []rune }

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL