feat: Join() reclaimed for strings — ErrorJoin for errors
core.Join("/", "deploy", "to", "homelab") → "deploy/to/homelab"
core.Join(".", "cmd", "deploy", "description") → "cmd.deploy.description"
Join builds via Concat — same hook point for security/validation.
errors.Join wrapper renamed to ErrorJoin.
JoinPath now delegates to Join("/", ...).
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
2fab391cc9
commit
f1d6c2a174
6 changed files with 22 additions and 13 deletions
|
|
@ -184,7 +184,7 @@ func (c *Core) Command(args ...any) any {
|
|||
// Build parent chain — "deploy/to/homelab" creates "deploy" and "deploy/to" if missing
|
||||
parts := Split(path, "/")
|
||||
for i := len(parts) - 1; i > 0; i-- {
|
||||
parentPath := StringJoin(parts[:i], "/")
|
||||
parentPath := JoinPath(parts[:i]...)
|
||||
if _, exists := c.commands.commands[parentPath]; !exists {
|
||||
c.commands.commands[parentPath] = &Command{
|
||||
name: parts[i-1],
|
||||
|
|
|
|||
|
|
@ -138,9 +138,10 @@ func NewError(text string) error {
|
|||
return errors.New(text)
|
||||
}
|
||||
|
||||
// Join combines multiple errors into one.
|
||||
// Wrapper around errors.Join for convenience.
|
||||
func Join(errs ...error) error {
|
||||
// ErrorJoin combines multiple errors into one.
|
||||
//
|
||||
// core.ErrorJoin(err1, err2, err3)
|
||||
func ErrorJoin(errs ...error) error {
|
||||
return errors.Join(errs...)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -60,11 +60,19 @@ func SplitN(s, sep string, n int) []string {
|
|||
return strings.SplitN(s, sep, n)
|
||||
}
|
||||
|
||||
// StringJoin joins segments with separator.
|
||||
// Join joins parts with a separator, building via Concat.
|
||||
//
|
||||
// core.StringJoin([]string{"a", "b", "c"}, "/") // "a/b/c"
|
||||
func StringJoin(elems []string, sep string) string {
|
||||
return strings.Join(elems, sep)
|
||||
// core.Join("/", "deploy", "to", "homelab") // "deploy/to/homelab"
|
||||
// core.Join(".", "cmd", "deploy", "description") // "cmd.deploy.description"
|
||||
func Join(sep string, parts ...string) string {
|
||||
if len(parts) == 0 {
|
||||
return ""
|
||||
}
|
||||
result := parts[0]
|
||||
for _, p := range parts[1:] {
|
||||
result = Concat(result, sep, p)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Replace replaces all occurrences of old with new in s.
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ func Print(w io.Writer, format string, args ...any) {
|
|||
//
|
||||
// core.JoinPath("deploy", "to", "homelab") // → "deploy/to/homelab"
|
||||
func JoinPath(segments ...string) string {
|
||||
return StringJoin(segments, "/")
|
||||
return Join("/", segments...)
|
||||
}
|
||||
|
||||
// IsFlag returns true if the argument starts with a dash.
|
||||
|
|
|
|||
|
|
@ -187,10 +187,10 @@ func TestNewError_Good(t *testing.T) {
|
|||
assert.Equal(t, "simple error", err.Error())
|
||||
}
|
||||
|
||||
func TestJoin_Good(t *testing.T) {
|
||||
func TestErrorJoin_Good(t *testing.T) {
|
||||
e1 := errors.New("first")
|
||||
e2 := errors.New("second")
|
||||
joined := Join(e1, e2)
|
||||
joined := ErrorJoin(e1, e2)
|
||||
assert.ErrorIs(t, joined, e1)
|
||||
assert.ErrorIs(t, joined, e2)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ func TestSplitN_Good(t *testing.T) {
|
|||
assert.Equal(t, []string{"key", "value=extra"}, SplitN("key=value=extra", "=", 2))
|
||||
}
|
||||
|
||||
func TestStringJoin_Good(t *testing.T) {
|
||||
assert.Equal(t, "a/b/c", StringJoin([]string{"a", "b", "c"}, "/"))
|
||||
func TestJoin_Good(t *testing.T) {
|
||||
assert.Equal(t, "a/b/c", Join("/", "a", "b", "c"))
|
||||
}
|
||||
|
||||
func TestReplace_Good(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue