Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bytes and indent #18

Merged
merged 4 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ jobs:
fi
- name: Release Notes Capture
run: |
sed -n '/^## [0-9]/{:loop n; /^## [0-9]/q; p; b loop}' Changes.md > release-notes.md
sed -n '/^## v[0-9]/{:loop n; /^## v[0-9]/q; p; b loop}' Changes.md > release-notes.md
echo "Release Notes Will be..."
echo "========================"
cat release-notes.md
- name: Create Release
run: gh release create -t "v$RELEASE_VERSION" "v$RELEASE_VERSION" --draft --notes-file=release-notes.md
- name: Finalize Release
run: gh release edit "v$RELEASE_VERSION" --draft=false
6 changes: 6 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## WIP TBD

* Adding `bytes.ContainsOnly`, `bytes.FromRange`, `bytes.Reverse`, `bytes.Indent`.
* Adding `strings.Indent`.
* Corrected documentation for `deferred.Error` which gave incorrect guidance on how to use it.

## v0.7.0 2024-06-13

* :boom: Breaking Change :boom:: Now requires Go 1.20.
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ There are a lot of common operations simply missing from the Golang builtin
library. This makes up for that deficiency. Here's a summary of some of the
provided tools:

## Byte Slice Operations

There are a lot of common byte slice operations that are missing from the
built-in standard library:

* `ContainsOnly(b, chars)`
* `FromRange(a, z)`
* `Reverse(b)`
* `Indent(b, indent)`

## Deferred Handling

Handling deferred functions is a bit of a pain. This provides a way to handle
Expand Down Expand Up @@ -153,5 +163,6 @@ built-in `strings` package:
* `Reverse(s)`
* `Increment(s)`
* `IncrementWithSets(s, sets)`
* `Indent(s, indent)`

The latter two operations might warrant their own library, but I put them here for now.
64 changes: 64 additions & 0 deletions bytes/content.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package bytes

import "bytes"

// ContainsOnly returns true fi the given byte slice only contains the given
// letters.
func ContainsOnly(b []byte, chars []rune) bool {
idx := make(map[rune]struct{}, len(chars))
for _, c := range chars {
idx[c] = struct{}{}
}
return bytes.IndexFunc(b, func(c rune) bool {
_, expectedChar := idx[c]
return !expectedChar
}) == -1
}

// FromRange returns a byte slice containing all the characters between two given
// bytes (inclusive).
func FromRange(a, z byte) []byte {
reverse := false
if a > z {
reverse = true
a, z = z, a
}

out := make([]byte, z-a+1)
for i := a; i <= z; i++ {
out[i-a] = i
}

if reverse {
return Reverse(out)
}

return out
}

// Reverse returns the byte slice reversed. That is, passing the byte slice
// []byte("Reversing text.") will result in this function returning
// []byte(".txet gnisreveR").
func Reverse(in []byte) []byte {
out := make([]byte, len(in))
for i := 0; i < len(in); i++ {
out[i] = in[len(in)-i-1]
}
return out
}

// Indent returns a new byte slice with each line in the input byte slice
// indented by the given byte slice.
func Indent(b, indent []byte) []byte {
startIndent := indent
if b[0] == '\n' {
startIndent = []byte{}
}
newB := bytes.ReplaceAll(b, []byte("\n"), []byte("\n"+string(indent)))
if len(startIndent) > 0 {
newB = append(newB, startIndent...)
copy(newB[len(startIndent):], newB)
copy(newB, startIndent)
}
return bytes.TrimRight(newB, " ")
}
40 changes: 40 additions & 0 deletions bytes/content_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package bytes_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/zostay/go-std/bytes"
)

func TestContainsOnly(t *testing.T) {
t.Parallel()

assert.True(t, bytes.ContainsOnly([]byte("abc"), []rune("abc")))
assert.True(t, bytes.ContainsOnly([]byte("a"), []rune("abc")))
assert.True(t, bytes.ContainsOnly([]byte("aaaaaabbbbbbccccc"), []rune("cba")))
assert.False(t, bytes.ContainsOnly([]byte("a b c"), []rune("abc")))
}

func TestFromRange(t *testing.T) {
t.Parallel()

assert.Equal(t, []byte("abcd"), bytes.FromRange('a', 'd'))
assert.Equal(t, []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), bytes.FromRange('A', 'Z'))
assert.Equal(t, []byte("0123456789"), bytes.FromRange('0', '9'))
assert.Equal(t, []byte("zyxwvutsrqponmlkjihgfedcba"), bytes.FromRange('z', 'a'))
}

func TestReverse(t *testing.T) {
t.Parallel()

assert.Equal(t, []byte(".txet gnisreveR"), bytes.Reverse([]byte("Reversing text.")))
}

func TestIndent(t *testing.T) {
t.Parallel()

assert.Equal(t, []byte("\n a\n b\n c\n"), bytes.Indent([]byte("\na\nb\nc\n"), []byte(" ")))
assert.Equal(t, []byte(" a\n b\n c"), bytes.Indent([]byte("a\nb\nc"), []byte(" ")))
}
2 changes: 2 additions & 0 deletions bytes/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package bytes provides additional tools for working with byte slices.
package bytes
2 changes: 1 addition & 1 deletion deferred/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import "errors"
// if err != nil {
// return
// }
// defer deferred.Error(&err, r.Close())
// defer func() { deferred.Error(&err, r.Close()) }()
//
// // process file
// return
Expand Down
11 changes: 11 additions & 0 deletions strings/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,14 @@ var defaultIncs = []IncrementSet{
func Increment(input string) string {
return IncrementWithSets(input, defaultIncs...)
}

// Indent returns the string with each line indented by the given string.
func Indent(s, indent string) string {
startIndent := indent
if s[0] == '\n' {
startIndent = ""
}
return strings.TrimRight(
startIndent+strings.ReplaceAll(s, "\n", "\n"+indent),
" ")
}
7 changes: 7 additions & 0 deletions strings/content_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,10 @@ func TestIncrement(t *testing.T) {
assert.Equal(t, "ID:AAA000", strings.IncrementWithSets("ID:ZZ999", licPlate...))
assert.Equal(t, "ID:AAAA000", strings.IncrementWithSets("ID:ZZZ999", licPlate...))
}

func TestIndent(t *testing.T) {
t.Parallel()

assert.Equal(t, "\n a\n b\n c\n", strings.Indent("\na\nb\nc\n", " "))
assert.Equal(t, " a\n b\n c", strings.Indent("a\nb\nc", " "))
}