mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-04-11 00:02:28 -04:00
core: add slices, paths, exec utils
This commit is contained in:
8
core/internal/utils/exec.go
Normal file
8
core/internal/utils/exec.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package utils
|
||||
|
||||
import "os/exec"
|
||||
|
||||
func CommandExists(cmd string) bool {
|
||||
_, err := exec.LookPath(cmd)
|
||||
return err == nil
|
||||
}
|
||||
52
core/internal/utils/paths.go
Normal file
52
core/internal/utils/paths.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ExpandPath(path string) (string, error) {
|
||||
expanded := os.ExpandEnv(path)
|
||||
expanded = filepath.Clean(expanded)
|
||||
|
||||
if strings.HasPrefix(expanded, "~") {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
expanded = filepath.Join(home, expanded[1:])
|
||||
}
|
||||
|
||||
return expanded, nil
|
||||
}
|
||||
|
||||
func XDGConfigHome() string {
|
||||
if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" {
|
||||
return configHome
|
||||
}
|
||||
if home, err := os.UserHomeDir(); err == nil {
|
||||
return filepath.Join(home, ".config")
|
||||
}
|
||||
return filepath.Join(os.TempDir(), ".config")
|
||||
}
|
||||
|
||||
func XDGCacheHome() string {
|
||||
if cacheHome := os.Getenv("XDG_CACHE_HOME"); cacheHome != "" {
|
||||
return cacheHome
|
||||
}
|
||||
if home, err := os.UserHomeDir(); err == nil {
|
||||
return filepath.Join(home, ".cache")
|
||||
}
|
||||
return filepath.Join(os.TempDir(), ".cache")
|
||||
}
|
||||
|
||||
func XDGDataHome() string {
|
||||
if dataHome := os.Getenv("XDG_DATA_HOME"); dataHome != "" {
|
||||
return dataHome
|
||||
}
|
||||
if home, err := os.UserHomeDir(); err == nil {
|
||||
return filepath.Join(home, ".local", "share")
|
||||
}
|
||||
return filepath.Join(os.TempDir(), ".local", "share")
|
||||
}
|
||||
106
core/internal/utils/paths_test.go
Normal file
106
core/internal/utils/paths_test.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExpandPathTilde(t *testing.T) {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Skip("no home directory")
|
||||
}
|
||||
result, err := ExpandPath("~/test")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
expected := filepath.Join(home, "test")
|
||||
if result != expected {
|
||||
t.Errorf("expected %s, got %s", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandPathEnvVar(t *testing.T) {
|
||||
t.Setenv("TEST_PATH_VAR", "/custom/path")
|
||||
result, err := ExpandPath("$TEST_PATH_VAR/subdir")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result != "/custom/path/subdir" {
|
||||
t.Errorf("expected /custom/path/subdir, got %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandPathAbsolute(t *testing.T) {
|
||||
result, err := ExpandPath("/absolute/path")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if result != "/absolute/path" {
|
||||
t.Errorf("expected /absolute/path, got %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestXDGConfigHomeDefault(t *testing.T) {
|
||||
t.Setenv("XDG_CONFIG_HOME", "")
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Skip("no home directory")
|
||||
}
|
||||
result := XDGConfigHome()
|
||||
expected := filepath.Join(home, ".config")
|
||||
if result != expected {
|
||||
t.Errorf("expected %s, got %s", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestXDGConfigHomeCustom(t *testing.T) {
|
||||
t.Setenv("XDG_CONFIG_HOME", "/custom/config")
|
||||
result := XDGConfigHome()
|
||||
if result != "/custom/config" {
|
||||
t.Errorf("expected /custom/config, got %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestXDGCacheHomeDefault(t *testing.T) {
|
||||
t.Setenv("XDG_CACHE_HOME", "")
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Skip("no home directory")
|
||||
}
|
||||
result := XDGCacheHome()
|
||||
expected := filepath.Join(home, ".cache")
|
||||
if result != expected {
|
||||
t.Errorf("expected %s, got %s", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestXDGCacheHomeCustom(t *testing.T) {
|
||||
t.Setenv("XDG_CACHE_HOME", "/custom/cache")
|
||||
result := XDGCacheHome()
|
||||
if result != "/custom/cache" {
|
||||
t.Errorf("expected /custom/cache, got %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestXDGDataHomeDefault(t *testing.T) {
|
||||
t.Setenv("XDG_DATA_HOME", "")
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
t.Skip("no home directory")
|
||||
}
|
||||
result := XDGDataHome()
|
||||
expected := filepath.Join(home, ".local", "share")
|
||||
if result != expected {
|
||||
t.Errorf("expected %s, got %s", expected, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestXDGDataHomeCustom(t *testing.T) {
|
||||
t.Setenv("XDG_DATA_HOME", "/custom/data")
|
||||
result := XDGDataHome()
|
||||
if result != "/custom/data" {
|
||||
t.Errorf("expected /custom/data, got %s", result)
|
||||
}
|
||||
}
|
||||
56
core/internal/utils/slices.go
Normal file
56
core/internal/utils/slices.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package utils
|
||||
|
||||
func Filter[T any](items []T, predicate func(T) bool) []T {
|
||||
var result []T
|
||||
for _, item := range items {
|
||||
if predicate(item) {
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func Find[T any](items []T, predicate func(T) bool) (T, bool) {
|
||||
for _, item := range items {
|
||||
if predicate(item) {
|
||||
return item, true
|
||||
}
|
||||
}
|
||||
var zero T
|
||||
return zero, false
|
||||
}
|
||||
|
||||
func Map[T, U any](items []T, transform func(T) U) []U {
|
||||
result := make([]U, len(items))
|
||||
for i, item := range items {
|
||||
result[i] = transform(item)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func Contains[T comparable](items []T, target T) bool {
|
||||
for _, item := range items {
|
||||
if item == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Any[T any](items []T, predicate func(T) bool) bool {
|
||||
for _, item := range items {
|
||||
if predicate(item) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func All[T any](items []T, predicate func(T) bool) bool {
|
||||
for _, item := range items {
|
||||
if !predicate(item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
72
core/internal/utils/slices_test.go
Normal file
72
core/internal/utils/slices_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
evens := Filter(nums, func(n int) bool { return n%2 == 0 })
|
||||
if len(evens) != 2 || evens[0] != 2 || evens[1] != 4 {
|
||||
t.Errorf("expected [2, 4], got %v", evens)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterEmpty(t *testing.T) {
|
||||
result := Filter([]int{1, 2, 3}, func(n int) bool { return n > 10 })
|
||||
if len(result) != 0 {
|
||||
t.Errorf("expected empty slice, got %v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFind(t *testing.T) {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
val, found := Find(nums, func(n int) bool { return n == 3 })
|
||||
if !found || val != 3 {
|
||||
t.Errorf("expected 3, got %v (found=%v)", val, found)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindNotFound(t *testing.T) {
|
||||
nums := []int{1, 2, 3}
|
||||
val, found := Find(nums, func(n int) bool { return n == 99 })
|
||||
if found || val != 0 {
|
||||
t.Errorf("expected zero value not found, got %v (found=%v)", val, found)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
nums := []int{1, 2, 3}
|
||||
doubled := Map(nums, func(n int) int { return n * 2 })
|
||||
if len(doubled) != 3 || doubled[0] != 2 || doubled[1] != 4 || doubled[2] != 6 {
|
||||
t.Errorf("expected [2, 4, 6], got %v", doubled)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapTypeConversion(t *testing.T) {
|
||||
nums := []int{1, 2, 3}
|
||||
strs := Map(nums, func(n int) string { return string(rune('a' + n - 1)) })
|
||||
if strs[0] != "a" || strs[1] != "b" || strs[2] != "c" {
|
||||
t.Errorf("expected [a, b, c], got %v", strs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
nums := []int{1, 2, 3}
|
||||
if !Contains(nums, 2) {
|
||||
t.Error("expected to contain 2")
|
||||
}
|
||||
if Contains(nums, 99) {
|
||||
t.Error("expected not to contain 99")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAny(t *testing.T) {
|
||||
nums := []int{1, 2, 3, 4, 5}
|
||||
if !Any(nums, func(n int) bool { return n > 4 }) {
|
||||
t.Error("expected any > 4")
|
||||
}
|
||||
if Any(nums, func(n int) bool { return n > 10 }) {
|
||||
t.Error("expected none > 10")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user