Compare commits

..
2 Commits
Author SHA1 Message Date
brent saner f002766c74 v1.17.3
ADDED:
* slicesx.First
* slicesx.FirstIndex
* slicesx.Remove
* slicesx.RemoveAll
* slicesx.RemoveReverse
2026-09-03 16:25:31 -04:00
brent saner 67bd30907e v1.17.2
ADDED:
* iox/fsx:
** FsPaths
** HasType
** IsType
2026-08-08 00:30:44 -04:00
5 changed files with 380 additions and 218 deletions
+16
View File
@@ -6,6 +6,8 @@ import (
"path/filepath" "path/filepath"
) )
// TODO: FilterFsPaths
/* /*
FsPaths returns all paths in [io/fs.FS] `fsys`. FsPaths returns all paths in [io/fs.FS] `fsys`.
@@ -82,6 +84,8 @@ func getEntries(fsys fs.FS, t fs.FileMode, inclFiles bool, maxDepth int, relPath
var idx int var idx int
var p string var p string
var k string
var v fs.DirEntry
var e []fs.DirEntry var e []fs.DirEntry
var subs map[string]fs.DirEntry = make(map[string]fs.DirEntry) var subs map[string]fs.DirEntry = make(map[string]fs.DirEntry)
@@ -89,12 +93,24 @@ func getEntries(fsys fs.FS, t fs.FileMode, inclFiles bool, maxDepth int, relPath
return return
} }
fsPaths = make(map[string]fs.DirEntry)
for idx = range e { for idx = range e {
p = filepath.Join(relPath, e[idx].Name()) p = filepath.Join(relPath, e[idx].Name())
if e[idx].IsDir() { if e[idx].IsDir() {
if subs, err = getEntries(fsys, t, inclFiles, maxDepth, p); err != nil { if subs, err = getEntries(fsys, t, inclFiles, maxDepth, p); err != nil {
return return
} }
for k, v = range subs {
fsPaths[k] = v
}
}
if t != 0 {
if HasType(t, e[idx].Type()) {
fsPaths[p] = e[idx]
}
} else if inclFiles && e[idx].Type() == 0 {
fsPaths[p] = e[idx]
} }
} }
+3
View File
@@ -1,4 +1,7 @@
/* /*
Package slicesx aims to extend functionality of the stdlib [slices] module. Package slicesx aims to extend functionality of the stdlib [slices] module.
Most are convenience functions that aid in readability (sometimes at a VERY negligible performance hit),
but others can be quite useful (e.g. [Remove], [RemoveAll], [RemoveReverse]) that will save on significant boilerplate.
*/ */
package slicesx package slicesx
+146 -1
View File
@@ -1,10 +1,51 @@
package slicesx package slicesx
import (
`slices`
)
/*
First returns the first item/element in slice s.
e will be the nil/zero value of the slice element type
if the slice length is 0 (including if s == nil).
*/
func First[S ~[]E, E any](s S) (e E) {
if len(s) == 0 {
return
}
e = s[0]
return
}
/*
FirstIndex returns the index of the first element in slice s.
While at first glance this may seem useless, it may have some usecases as instead of causing panics:
* If s is empty, idx will be -1.
* If s is nil, idx will be -2.
* Otherwise idx will ALWAYS be 0.
*/_
func FirstIndex[S ~[]E, E any](s S) (idx int) {
if s == nil {
idx = -2
} else if len(s) == 0 {
idx = -1
}
return
}
/* /*
Last returns the last item/element in slice s. Last returns the last item/element in slice s.
e will be the nil/zero value of the slice element type e will be the nil/zero value of the slice element type
if the slice length is 0. if the slice length is 0 (including if s == nil).
*/ */
func Last[S ~[]E, E any](s S) (e E) { func Last[S ~[]E, E any](s S) (e E) {
@@ -41,3 +82,107 @@ func LastIndex[S ~[]E, E any](s S) (idx int) {
return return
} }
/*
Remove removes any values of value elem from slice s up to max number of elems.
If maxRemove is negative (< 0), start from the end instead.
This simply wraps [RemoveReverse]:
removed = slicesx.RemoveReverse(s, elem, uint(-maxRemove))
If maxRemove is exactly 0, remove ALL instances of elem.
If s is nil, removed will be nil as well.
Note that s will remain untouched, and removed will be a new slice.
*/
func Remove[S ~[]E, E comparable](s S, elem E, maxRemove int) (removed S) {
var idx int
if s == nil {
return
}
if len(s) == 0 {
removed = []E{}
return
}
removed = make(S, 0, len(s))
defer func() {
if removed != nil {
removed = slices.Clip(removed)
}
}()
if maxRemove < 0 {
removed = RemoveReverse(s, elem, uint(-maxRemove))
return
} else if maxRemove == 0 {
maxRemove = len(s)
}
for idx = range s {
if s[idx] == elem && maxRemove > 0 {
maxRemove--
continue
}
removed = append(removed, s[idx])
}
return
}
/*
RemoveAll is simply a convenience wrapper around [Remove], e.g.:
removed = slicesx.Remove(s, elem, 0)
*/
func RemoveAll[S ~[]E, E comparable](s S, elem E) (removed S) { return Remove(s, elem, 0) }
/*
RemoveReverse removes any values of value elem from slice s up to max number of elems in reverse order
(i.e. starting from the END of s).
If maxRemove is exactly 0, remove all instances of elem (via [RemoveAll]), i.e.:
removed = slicesx.RemoveAll(s, elem)
// or, more directly:
removed = slicesx.Remove(s, elem, 0)
If s is nil, removed will be nil as well.
Note that s will remain untouched, and removed will be a new slice.
*/
func RemoveReverse[S ~[]E, E comparable](s S, elem E, maxRemove uint) (removed S) {
var idx int
if s == nil {
return
}
if len(s) == 0 {
removed = []E{}
return
}
if maxRemove == 0 {
removed = RemoveAll(s, elem)
return
}
removed = make(S, 0, len(s))
for idx = len(s) - 1; idx >= 0; idx-- {
if s[idx] == elem && maxRemove > 0 {
maxRemove--
continue
}
removed = append(removed, s[idx])
}
removed = slices.Clip(removed)
slices.Reverse(removed)
return
}
+1 -1
View File
@@ -636,7 +636,7 @@ pre.rouge .gs {
<div class="details"> <div class="details">
<span id="author" class="author">Brent Saner</span><br> <span id="author" class="author">Brent Saner</span><br>
<span id="email" class="email"><a href="mailto:bts@square-r00t.net">bts@square-r00t.net</a></span><br> <span id="email" class="email"><a href="mailto:bts@square-r00t.net">bts@square-r00t.net</a></span><br>
<span id="revdate">Last rendered 2026-08-08 00:13:35 -0400</span> <span id="revdate">Last rendered 2026-09-03 16:25:31 -0400</span>
</div> </div>
<div id="toc" class="toc2"> <div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div> <div id="toctitle">Table of Contents</div>
+214 -216
View File
File diff suppressed because it is too large Load Diff