Skip to content
This repository has been archived by the owner on May 23, 2022. It is now read-only.

#5 string helpers #12

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@

# Dependency directories
vendor

# IDE Files
.idea/
220 changes: 219 additions & 1 deletion str/str.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package str

import "unicode"
import (
"regexp"
"strings"
"unicode"
)

func UpperFirst(input string) string {
if len(input) == 0 {
Expand All @@ -19,3 +23,217 @@ func InSlice(input interface{}, expects ...interface{}) bool {
}
return false
}

// Return the remainder of a string after the first occurrence of a given value.
func After(subject string, search string) string {
if len(search) == 0 {
return subject
}
results := strings.SplitN(subject, search, 2)
return results[len(results)-1]
}

// Return the remainder of a string after the last occurrence of a given value.
func AfterLast(subject string, search string) string {
if len(search) == 0 {
return subject
}
position := strings.LastIndex(subject, search)

if position == -1 {
return subject
}

return subject[position+len(search):]
}

// Get the portion of a string before the first occurrence of a given value.
func Before(subject string, search string) string {
if len(search) == 0 {
return subject
}
position := strings.Index(subject, search)

if position == -1 {
return subject
}

return subject[:position]
}

func BeforeLast(subject string, search string) string {
if len(search) == 0 {
return subject
}
position := strings.LastIndex(subject, search)

if position == -1 {
return subject
}

return subject[:position]
}

func Between(subject string, from string, to string) string {
if len(from) == 0 || len(to) == 0 {
return subject
}

return BeforeLast(After(subject, from), to)
}

func Contains(haystack string, needle string) bool {
if len(needle) == 0 {
return false
}

return strings.Contains(haystack, needle)
}

func ContainsFromSlice(haystack string, needles []string) bool {
if len(needles) == 0 {
return false
}

for _, needle := range needles {
if Contains(haystack, needle){
return true
}
}

return false
}

func ContainsAllFromSlice(haystack string, needles []string) bool {
if len(needles) == 0 {
return false
}

for _, needle := range needles {
if !Contains(haystack, needle){
return false
}
}

return true
}

func EndsWith(haystack string, needle string) bool {
if len(needle) == 0 {
return false
}

return strings.HasSuffix(haystack, needle)
}

func StartsWith(haystack string, needle string) bool {
if len(needle) == 0 {
return false
}

return strings.HasPrefix(haystack, needle)
}

func Lower(value string) string {
return strings.ToLower(value)
}

func Upper(value string) string {
return strings.ToUpper(value)
}

func Finish(value string, cap string) string {
quoted := regexp.QuoteMeta(cap)

re := regexp.MustCompile("(?:"+ quoted +")+$")
return re.ReplaceAllString(value, "") + cap
}

func Start(value string, prefix string) string {
quoted := regexp.QuoteMeta(prefix)

re := regexp.MustCompile("^(?:"+ quoted +")+")
return prefix + re.ReplaceAllString(value, "")
}

//
//func Title(value string) string {
// // TODO
// return ""
//}
//
// func Kebab(vale string) string {
// // TODO
// return ""
// }
//
// func Length(value string) int {
// // TODO
// return 0
// }
//
// func LimitCharacters(value string, limit int, end string) string{
// // TODO
// return ""
// }
//
// func LimitWords(value string, limit int, end string) string{
// // TODO
// return ""
// }
//
// func PadBoth(value string, length int, pad string) string {
// // TODO
// return ""
// }
//
// func PadLeft(value string, length int, pad string) string {
// // TODO
// return ""
// }
//
// func PadRight(value string, length int, pad string) string {
// // TODO
// return ""
// }
//
// func ReplaceArray(search string, replace []string, subject string) string {
// // TODO
// return ""
// }
//
// func ReplaceFirst(search string, replace string, subject string) string {
// // TODO
// return ""
// }
//
// func ReplaceLast(search string, replace string, subject string) string {
// // TODO
// return ""
// }
//
// func Slug(value string) string {
// // TODO
// return ""
// }
//
// func SlugWithDelimiter(value string, delimiter string) string {
// // TODO
// return ""
// }
//
// func Snake(value string) string {
// // TODO
// return ""
// }
//
// func Studly(value string) string {
// // TODO
// return ""
// }
//
// func UcFirst(value string) string {
// // TODO
// return ""
// }
//
156 changes: 156 additions & 0 deletions test/str_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,159 @@ func Test_in_slice_with_multiple_one_matched_parameters(t *testing.T) {
func Test_in_slice_with_integer(t *testing.T) {
require.True(t, str.InSlice(1, 0, 1))
}

func Test_After(t *testing.T) {
// TODO: What if nothing is found?
require.Equal(t, "", str.After("", ""))
require.Equal(t, "", str.After("", "han"))
require.Equal(t, "hannah", str.After("hannah", ""))
require.Equal(t, "nah", str.After("hannah", "han"))
require.Equal(t, "nah", str.After("hannah", "n"))
require.Equal(t, "nah", str.After("eee hannah", "han"))
require.Equal(t, "nah", str.After("ééé hannah", "han"))
require.Equal(t, "hannah", str.After("hannah", "xxxx"))
require.Equal(t, "nah", str.After("han0nah", "0"))
require.Equal(t, "nah", str.After("han2nah", "2"))
}

func Test_AfterLast(t *testing.T) {
// TODO: What if nothing is found?
require.Equal(t, "", str.After("", ""))
require.Equal(t, "", str.After("", "han"))
require.Equal(t, "hannah", str.After("hannah", ""))
require.Equal(t, "tte", str.AfterLast("yvette", "yve"))
require.Equal(t, "e", str.AfterLast("yvette", "t"))
require.Equal(t, "e", str.AfterLast("ééé yvette", "t"))
require.Equal(t, "", str.AfterLast("yvette", "tte"))
require.Equal(t, "yvette", str.AfterLast("yvette", "xxxx"))
require.Equal(t, "te", str.AfterLast("yv0et0te", "0"))
require.Equal(t, "te", str.AfterLast("yv0et0te", "0"))
require.Equal(t, "te", str.AfterLast("yv2et2te", "2"))
require.Equal(t, "foo", str.AfterLast("----foo", "---"))
}

func Test_Before(t *testing.T) {
require.Equal(t, "hannah", str.Before("hannah", ""))
require.Equal(t, "han", str.Before("hannah", "nah"))
require.Equal(t, "ha", str.Before("hannah", "n"))
require.Equal(t, "ééé ", str.Before("ééé hannah", "han"))
require.Equal(t, "hannah", str.Before("hannah", "xxxx"))
require.Equal(t, "han", str.Before("han0nah", "0"))
require.Equal(t, "han", str.Before("han0nah", "0"))
require.Equal(t, "han", str.Before("han2nah", "2"))
}

func Test_BeforeLast(t *testing.T) {
require.Equal(t, "yve", str.BeforeLast("yvette", "tte"))
require.Equal(t, "yvet", str.BeforeLast("yvette", "t"))
require.Equal(t, "ééé ", str.BeforeLast("ééé yvette", "yve"))
require.Equal(t, "", str.BeforeLast("yvette", "yve"))
require.Equal(t, "yvette", str.BeforeLast("yvette", "xxxx"))
require.Equal(t, "yvette", str.BeforeLast("yvette", ""))
require.Equal(t, "yv0et", str.BeforeLast("yv0et0te", "0"))
require.Equal(t, "yv0et", str.BeforeLast("yv0et0te", "0"))
require.Equal(t, "yv2et", str.BeforeLast("yv2et2te", "2"))
}

func Test_Between(t *testing.T) {
require.Equal(t, "abc", str.Between("abc", "", "c"))
require.Equal(t, "abc", str.Between("abc", "a", ""))
require.Equal(t, "abc", str.Between("abc", "", ""))
require.Equal(t, "b", str.Between("abc", "a", "c"))
require.Equal(t, "b", str.Between("dddabc", "a", "c"))
require.Equal(t, "b", str.Between("abcddd", "a", "c"))
require.Equal(t, "b", str.Between("dddabcddd", "a", "c"))
require.Equal(t, "nn", str.Between("hannah", "ha", "ah"))
require.Equal(t, "a]ab[b", str.Between("[a]ab[b]", "[", "]"))
require.Equal(t, "foo", str.Between("foofoobar", "foo", "bar"))
require.Equal(t, "bar", str.Between("foobarbar", "foo", "bar"))
}

func Test_Contains(t *testing.T) {
require.True(t, str.Contains("taylor", "ylo"))
require.True(t, str.Contains("taylor", "taylor"))
require.False(t, str.Contains("taylor", "xxx"))
require.False(t, str.Contains("taylor", ""))
require.False(t, str.Contains("", ""))
}

func Test_ContainsFromSlice(t *testing.T) {
require.True(t, str.ContainsFromSlice("taylor", []string{"ylo"}))
require.True(t, str.ContainsFromSlice("taylor", []string{"xxx", "ylo"}))
require.False(t, str.ContainsFromSlice("taylor", []string{"xxx"}))
require.False(t, str.ContainsFromSlice("taylor", []string{}))
require.False(t, str.ContainsFromSlice("taylor", []string{""}))
}

func Test_ContainsAllFromSlice(t *testing.T) {
require.True(t, str.ContainsAllFromSlice("This is my name", []string{"This", "is"}))
require.True(t, str.ContainsAllFromSlice("This is my name", []string{"my", "ame"}))
require.True(t, str.ContainsAllFromSlice("taylor", []string{"tay", "ylo"}))
require.False(t, str.ContainsAllFromSlice("taylor", []string{"xxx", "ylo"}))
require.False(t, str.ContainsAllFromSlice("taylor", []string{"xxx", "tay"}))
require.False(t, str.ContainsAllFromSlice("This is my name", []string{"are", "name"}))
require.False(t, str.ContainsAllFromSlice("taylor", []string{}))
require.False(t, str.ContainsAllFromSlice("taylor", []string{"", ""}))
}

func Test_EndsWith(t *testing.T) {
require.True(t, str.EndsWith("This is my name", "name"))
require.True(t, str.EndsWith("This is my name", "e"))
require.True(t, str.EndsWith("jason", "on"))
require.True(t, str.EndsWith("7", "7"))
require.True(t, str.EndsWith("a7", "7"))
require.False(t, str.EndsWith("jason", "no"))
require.False(t, str.EndsWith("jason", ""))
require.False(t, str.EndsWith("", ""))
// Test for multibyte string support
require.True(t, str.EndsWith("Jönköping", "öping"))
require.True(t, str.EndsWith("Malmö", "mö"))
require.True(t, str.EndsWith("Malmö", "mö"))
require.False(t, str.EndsWith("Jönköping", "oping"))
require.False(t, str.EndsWith("Malmö", "mo"))
require.True(t, str.EndsWith("你好", "好"))
require.False(t, str.EndsWith("你好", "你"))
require.False(t, str.EndsWith("你好", "a"))
}

func Test_StartsWith(t *testing.T) {
require.True(t, str.StartsWith("jason", "jas"))
require.True(t, str.StartsWith("jason", "jason"))
require.True(t, str.StartsWith("7a", "7"))
require.True(t, str.StartsWith("7", "7"))
require.False(t, str.StartsWith("jason", "J"))
require.False(t, str.StartsWith("jason", ""))
require.False(t, str.StartsWith("", ""))
// Test for multibyte string support
require.True(t, str.StartsWith("Jönköping", "Jö"))
require.True(t, str.StartsWith("Malmö", "Malmö"))
require.True(t, str.StartsWith("你好", "你"))
require.False(t, str.StartsWith("Jönköping", "Jonko"))
require.False(t, str.StartsWith("Malmö", "Malmo"))
require.False(t, str.StartsWith("你好", "好"))
require.False(t, str.StartsWith("你好", "a"))
}

func Test_Lower(t *testing.T) {
require.Equal(t, "foo bar baz", str.Lower("FOO BAR BAZ"))
require.Equal(t, "foo bar baz", str.Lower("fOo Bar bAz"))
}

func Test_Upper(t *testing.T) {
require.Equal(t, "FOO BAR BAZ", str.Upper("foo bar baz"))
require.Equal(t, "FOO BAR BAZ", str.Upper("fOo Bar bAZ"))
}

func Test_Finish(t *testing.T) {
require.Equal(t, "abbc", str.Finish("ab", "bc"))
require.Equal(t, "abbc", str.Finish("abbcbc", "bc"))
require.Equal(t, "abcbbc", str.Finish("abcbbcbc", "bc"))
require.Equal(t, "this/string/", str.Finish("this/string", "/"))
require.Equal(t, "this/string/", str.Finish("this/string/", "/"))
}

func Test_Start(t *testing.T) {
require.Equal(t, "/test/string", str.Start("test/string", "/"))
require.Equal(t, "/test/string", str.Start("/test/string", "/"))
require.Equal(t, "/test/string", str.Start("//test/string", "/"))
}