kitty/tools/utils/misc.go
2023-03-27 07:53:54 +05:30

167 lines
3.1 KiB
Go

// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package utils
import (
"fmt"
"regexp"
"sort"
"golang.org/x/exp/constraints"
"golang.org/x/exp/slices"
)
var _ = fmt.Print
func Reverse[T any](s []T) []T {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}
func Reversed[T any](s []T) []T {
ans := make([]T, len(s))
for i, x := range s {
ans[len(s)-1-i] = x
}
return ans
}
func Remove[T comparable](s []T, q T) []T {
idx := slices.Index(s, q)
if idx > -1 {
return slices.Delete(s, idx, idx+1)
}
return s
}
func RemoveAll[T comparable](s []T, q T) []T {
ans := s
for {
idx := slices.Index(ans, q)
if idx < 0 {
break
}
ans = slices.Delete(ans, idx, idx+1)
}
return ans
}
func Filter[T any](s []T, f func(x T) bool) []T {
ans := make([]T, 0, len(s))
for _, x := range s {
if f(x) {
ans = append(ans, x)
}
}
return ans
}
func Map[T any, O any](f func(x T) O, s []T) []O {
ans := make([]O, 0, len(s))
for _, x := range s {
ans = append(ans, f(x))
}
return ans
}
func Repeat[T any](x T, n int) []T {
ans := make([]T, n)
for i := 0; i < n; i++ {
ans[i] = x
}
return ans
}
func Sort[T any](s []T, less func(a, b T) bool) []T {
sort.Slice(s, func(i, j int) bool { return less(s[i], s[j]) })
return s
}
func StableSort[T any](s []T, less func(a, b T) bool) []T {
sort.SliceStable(s, func(i, j int) bool { return less(s[i], s[j]) })
return s
}
func sort_with_key[T any, C constraints.Ordered](impl func(any, func(int, int) bool), s []T, key func(a T) C) []T {
temp := make([]struct {
key C
val T
}, len(s))
for i, x := range s {
temp[i].val, temp[i].key = x, key(x)
}
impl(temp, func(i, j int) bool {
return temp[i].key < temp[j].key
})
for i, x := range temp {
s[i] = x.val
}
return s
}
func SortWithKey[T any, C constraints.Ordered](s []T, key func(a T) C) []T {
return sort_with_key(sort.Slice, s, key)
}
func StableSortWithKey[T any, C constraints.Ordered](s []T, key func(a T) C) []T {
return sort_with_key(sort.SliceStable, s, key)
}
func Max[T constraints.Ordered](a T, items ...T) (ans T) {
ans = a
for _, q := range items {
if q > ans {
ans = q
}
}
return ans
}
func Min[T constraints.Ordered](a T, items ...T) (ans T) {
ans = a
for _, q := range items {
if q < ans {
ans = q
}
}
return ans
}
func Memset[T any](dest []T, pattern ...T) []T {
if len(pattern) == 0 {
var zero T
switch any(zero).(type) {
case byte: // special case this as the compiler can generate efficient code for memset of a byte slice to zero
bd := any(dest).([]byte)
for i := range bd {
bd[i] = 0
}
default:
for i := range dest {
dest[i] = zero
}
}
return dest
}
bp := copy(dest, pattern)
for bp < len(dest) {
copy(dest[bp:], dest[:bp])
bp *= 2
}
return dest
}
var ControlCodesPat = (&Once[*regexp.Regexp]{Run: func() *regexp.Regexp {
return regexp.MustCompile("[\x00-\x09\x0b-\x1f\x7f\u0080-\u009f]")
}}).Get
func SanitizeControlCodes(raw string, replace_with ...string) string {
r := ""
if len(replace_with) > 0 {
r = replace_with[0]
}
return ControlCodesPat().ReplaceAllLiteralString(raw, r)
}