Factor out functional (fn), sets, loops

This commit is contained in:
rwxrob 2022-02-25 21:46:36 -05:00
parent 7e9b0cf872
commit 193727dc0f
No known key found for this signature in database
GPG Key ID: 2B9111F33082AE77
17 changed files with 289 additions and 22 deletions

6
cmd.go
View File

@ -8,7 +8,7 @@ import (
"os"
"github.com/rwxrob/bonzai/comp"
"github.com/rwxrob/bonzai/filter"
"github.com/rwxrob/bonzai/loop"
)
// Cmd is a struct the easier to use and read when creating
@ -79,10 +79,10 @@ func (x *Cmd) Run() {
if cmd.Completer == nil {
list := comp.Standard(cmd, args...)
filter.Println(list)
loop.Println(list)
Exit()
}
filter.Println(cmd.Completer(cmd, args...))
loop.Println(cmd.Completer(cmd, args...))
Exit()
}

View File

@ -9,7 +9,8 @@ import (
"github.com/rwxrob/bonzai"
"github.com/rwxrob/bonzai/check"
"github.com/rwxrob/bonzai/comp"
"github.com/rwxrob/bonzai/filter"
"github.com/rwxrob/bonzai/filt"
"github.com/rwxrob/bonzai/maps"
)
// Help provides help documentation for the caller allowing the specific
@ -47,7 +48,7 @@ func helpCompleter(x comp.Command, args ...string) []string {
if !check.IsNil(caller) {
other := caller.GetOther()
if other != nil {
list = append(list, filter.Keys(other)...)
list = append(list, maps.Keys(other)...)
}
}
@ -55,5 +56,5 @@ func helpCompleter(x comp.Command, args ...string) []string {
return list
}
return filter.HasPrefix(list, args[0])
return filt.HasPrefix(list, args[0])
}

View File

@ -4,7 +4,10 @@
package comp
import (
"github.com/rwxrob/bonzai/filter"
"strings"
"github.com/rwxrob/bonzai/filt"
"github.com/rwxrob/bonzai/maps"
"github.com/rwxrob/bonzai/util"
)
@ -12,15 +15,23 @@ import (
// passed. If nothing is passed assumes the current working directory.
func File(x Command, args ...string) []string {
match := ""
dir := "."
dir := ""
if len(args) > 0 {
match = args[0]
// FIXME if there is an unescaped "/" at all, truncate the directory
// and keep the rest to add on later for match
if strings.HasSuffix(args[0], "/") {
dir = args[0]
match = ""
} else {
match = args[0]
}
}
list := []string{}
list = append(list, util.Files(dir)...)
list = filter.HasPrefix(list, match)
list = append(list, maps.Prefix(util.Files(dir), dir)...)
list = filt.HasPrefix(list, match)
list = maps.CleanPaths(list)
return list
}

View File

@ -4,7 +4,8 @@
package comp
import (
"github.com/rwxrob/bonzai/filter"
"github.com/rwxrob/bonzai/filt"
"github.com/rwxrob/bonzai/set"
)
// Standard completion is resolved as follows:
@ -36,11 +37,11 @@ func Standard(x Command, args ...string) []string {
list := []string{}
list = append(list, x.GetCommands()...)
list = append(list, x.GetParams()...)
list = filter.Minus(list, x.GetHidden())
list = set.Minus(list, x.GetHidden())
if len(args) == 0 {
return list
}
return filter.HasPrefix(list, args[0])
return filt.HasPrefix(list, args[0])
}

View File

@ -8,7 +8,7 @@ import (
"github.com/rwxrob/bonzai"
"github.com/rwxrob/bonzai/comp"
"github.com/rwxrob/bonzai/filter"
"github.com/rwxrob/bonzai/filt"
)
func ExampleStandard() {
@ -39,7 +39,7 @@ func ExampleStandard() {
if len(args) == 0 {
return list
}
return filter.HasPrefix(list, args[0])
return filt.HasPrefix(list, args[0])
}
fmt.Println(comp.Standard(foo, `t`))

View File

@ -1,4 +1,4 @@
package filter
package filt
import (
"strings"

View File

@ -1,19 +1,19 @@
// Copyright 2022 Robert S. Muhlestein.
// SPDX-License-Identifier: Apache-2.0
package filter_test
package filt_test
import (
"fmt"
"github.com/rwxrob/bonzai/filter"
"github.com/rwxrob/bonzai/filt"
)
func ExampleHasPrefix() {
set := []string{
"one", "two", "three", "four", "five", "six", "seven",
}
fmt.Println(filter.HasPrefix(set, "t"))
fmt.Println(filt.HasPrefix(set, "t"))
// Output:
// [two three]
}

16
fn/fn.go Normal file
View File

@ -0,0 +1,16 @@
// Copyright 2022 Robert S. Muhlestein.
// SPDX-License-Identifier: Apache-2.0
package fn
// Map executes an operator function provided on each item in the
// slice returning a new slice. If error handling is needed it should be
// handled within an enclosure within the function. This keeps
// signatures simple and functional.
func Map[I any, O any](slice []I, f func(in I) O) []O {
list := []O{}
for _, i := range slice {
list = append(list, f(i))
}
return list
}

65
fn/fn_test.go Normal file
View File

@ -0,0 +1,65 @@
// Copyright 2022 Robert S. Muhlestein.
// SPDX-License-Identifier: Apache-2.0
package fn_test
import (
"fmt"
"github.com/rwxrob/bonzai/fn"
)
func ExampleHasPrefix() {
set := []string{
"one", "two", "three", "four", "five", "six", "seven",
}
fmt.Println(fn.HasPrefix(set, "t"))
// Output:
// [two three]
}
func ExamplePrintln() {
set := []string{"doe", "ray", "mi"}
filter.Println(set)
bools := []bool{false, true, true}
filter.Println(bools)
// Output:
// doe
// ray
// mi
// false
// true
// true
}
func ExampleKeys() {
m1 := map[string]int{"two": 2, "three": 3, "one": 1}
m2 := map[string]string{"two": "two", "three": "three", "one": "one"}
fmt.Println(filter.Keys(m1))
fmt.Println(filter.Keys(m2))
// Output:
// [one three two]
// [one three two]
}
func ExamplePrefix() {
fmt.Println(filter.Prefix([]string{"foo", "bar"}, "my"))
// Output:
// [myfoo mybar]
}
func ExampleCleanPaths() {
paths := []string{
``,
`.`,
`./`,
`./thing`,
`/sub/../../thing`,
}
filter.Println(filter.CleanPaths(paths))
// Output:
// .
// .
// .
// /thing
}

27
generic/generic.go Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2022 Robert S. Muhlestein.
// SPDX-License-Identifier: Apache-2.0
package generic
// Number combines the primitives generally considered numbers by JSON
// and other high-level structure data representations.
type Number interface {
int | int64 | int32 | int16 | int8 |
uint64 | uint32 | uint16 | uint8 |
float64 | float32
}
// Text combines byte slice and string.
type Text interface {
[]byte | string
}
// Sharable are the types that have representations in JSON, YAML, TOML
// and other high-level structured data representations.
type Sharable interface {
int | int64 | int32 | int16 | int8 |
uint64 | uint32 | uint16 | uint8 |
float64 | float32 |
[]byte | string |
bool
}

22
loop/loop.go Normal file
View File

@ -0,0 +1,22 @@
/*
Package loop shamelessly attempts to bring the better parts of Lisp loops to Go specifically in order to enable rapid, and clean applications development --- particularly when replacing shell scripts with Go.
*/
package loop
import "fmt"
// Do executes the given function for each item in the slice. If any
// error is encountered processing stops and error returned.
func Do[T any](set []T, p func(i T) error) error {
for _, i := range set {
if err := p(i); err != nil {
return err
}
}
return nil
}
// Println prints ever element of the set.
func Println[T any](set []T) {
Do(set, func(i T) error { fmt.Println(i); return nil })
}

17
loop/loop_test.go Normal file
View File

@ -0,0 +1,17 @@
package loop_test
import "github.com/rwxrob/bonzai/loop"
func ExamplePrintln() {
set := []string{"doe", "ray", "mi"}
loop.Println(set)
bools := []bool{false, true, true}
loop.Println(bools)
// Output:
// doe
// ray
// mi
// false
// true
// true
}

28
maps/maps.go Normal file
View File

@ -0,0 +1,28 @@
package maps
import (
"path/filepath"
"sort"
"github.com/rwxrob/bonzai/fn"
)
// Prefix returns a new slice with prefix added to each string.
func Prefix(in []string, pre string) []string {
return fn.Map(in, func(i string) string { return pre + i })
}
// Keys returns the keys in lexicographically sorted order.
func Keys[T any](m map[string]T) []string {
keys := []string{}
for k, _ := range m {
keys = append(keys, k)
sort.Strings(keys)
}
return keys
}
// CleanPaths runs filepath.Clean on each item in the slice and returns.
func CleanPaths(paths []string) []string {
return fn.Map(paths, func(i string) string { return filepath.Clean(i) })
}

39
maps/maps_test.go Normal file
View File

@ -0,0 +1,39 @@
package maps_test
import (
"fmt"
"github.com/rwxrob/bonzai/maps"
)
func ExampleKeys() {
m1 := map[string]int{"two": 2, "three": 3, "one": 1}
m2 := map[string]string{"two": "two", "three": "three", "one": "one"}
fmt.Println(maps.Keys(m1))
fmt.Println(maps.Keys(m2))
// Output:
// [one three two]
// [one three two]
}
func ExamplePrefix() {
fmt.Println(maps.Prefix([]string{"foo", "bar"}, "my"))
// Output:
// [myfoo mybar]
}
func ExampleCleanPaths() {
paths := []string{
``,
`.`,
`./`,
`./thing`,
`/sub/../../thing`,
}
filter.Println(filter.CleanPaths(paths))
// Output:
// .
// .
// .
// /thing
}

24
set/set.go Normal file
View File

@ -0,0 +1,24 @@
package set
type Text interface {
string | []byte
}
// Minus performs a set "minus" operation by returning a new set with
// the elements of the second set removed from it.
func Minus[T Text, M Text](set []T, min []M) []T {
m := []T{}
for _, i := range set {
var seen bool
for _, n := range min {
if string(n) == string(i) {
seen = true
break
}
}
if !seen {
m = append(m, i)
}
}
return m
}

16
set/set_test.go Normal file
View File

@ -0,0 +1,16 @@
package set_test
import (
"fmt"
"github.com/rwxrob/bonzai/set"
)
func ExampleMinus() {
s := []string{
"one", "two", "three", "four", "five", "six", "seven",
}
fmt.Println(set.Minus(s, []string{"two", "four", "six"}))
// Output:
// [one three five seven]
}

View File

@ -3,7 +3,7 @@ package util
import (
"os"
"github.com/rwxrob/bonzai/filter"
"github.com/rwxrob/bonzai/filt"
)
// Files returns a slice of strings matching the names of the files
@ -26,5 +26,5 @@ func Files(dir string) []string {
}
func FilesWith(dir, pre string) []string {
return filter.HasPrefix(Files(dir), pre)
return filt.HasPrefix(Files(dir), pre)
}