Skip to content

Commit

Permalink
create a package-scoped instance
Browse files Browse the repository at this point in the history
refactoring
  • Loading branch information
alessio committed Jan 22, 2024
1 parent 0f3ef74 commit faaadb9
Show file tree
Hide file tree
Showing 7 changed files with 354 additions and 116 deletions.
18 changes: 9 additions & 9 deletions cmd/pathctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"os"
"strings"

"al.essio.dev/pkg/tools/dirlist"
"al.essio.dev/pkg/tools/internal/version"
"al.essio.dev/pkg/tools/pathlist"
)

const (
Expand All @@ -27,7 +27,7 @@ var (
envVar string
)

var cmdHandlers map[string]func(d pathlist.List)
var cmdHandlers map[string]func(d dirlist.List)

func init() {
flag.BoolVar(&helpMode, "help", false, "display this help and exit.")
Expand All @@ -39,22 +39,22 @@ func init() {
flag.Usage = usage
flag.CommandLine.SetOutput(os.Stderr)

cmdHandlers = func() map[string]func(pathlist.List) {
hAppend := func(d pathlist.List) {
cmdHandlers = func() map[string]func(dirlist.List) {
hAppend := func(d dirlist.List) {
if dropMode {
d.Drop(flag.Arg(1))
}
d.Append(flag.Arg(1))
}
hDrop := func(d pathlist.List) { d.Drop(flag.Arg(1)) }
hPrepend := func(d pathlist.List) {
hDrop := func(d dirlist.List) { d.Drop(flag.Arg(1)) }
hPrepend := func(d dirlist.List) {
if dropMode {
d.Drop(flag.Arg(1))
}
d.Prepend(flag.Arg(1))
}

return map[string]func(pathlist.List){
return map[string]func(dirlist.List){
"append": hAppend,
"drop": hDrop,
"prepend": hPrepend,
Expand All @@ -75,7 +75,7 @@ func main() {

handleHelpAndVersionModes()

dirs := pathlist.New()
dirs := dirlist.New()
dirs.LoadEnv(envVar)

if flag.NArg() < 1 {
Expand All @@ -91,7 +91,7 @@ func main() {
}
}

func printPathList(d pathlist.List) {
func printPathList(d dirlist.List) {
var sb = strings.Builder{}
sb.Reset()

Expand Down
43 changes: 43 additions & 0 deletions dirlist/dirlist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package dirlist

var (
dList List
)

func init() {
dList = New()
}

func Reset() { dList.Reset() }

func Contains(p string) bool {
return dList.Contains(quoteAndClean(p))
}

func Load(s string) {
dList.Load(s)
}

func LoadEnv(s string) {
dList.LoadEnv(s)
}

func Prepend(p string) {
dList.Prepend(p)
}

func Append(p string) {
dList.Append(p)
}

func Drop(p string) {
dList.Drop(p)
}

func Slice() []string {
return dList.Slice()
}

func String() string {
return dList.String()
}
97 changes: 97 additions & 0 deletions dirlist/dirlist_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package dirlist

import (
"fmt"
"testing"

"github.com/stretchr/testify/require"
)

func TestAppend(t *testing.T) {
Reset()
require.Equal(t, "", String())
for _, p := range []string{"/var", "/var", "/bin", "/bin/", "/bin///"} {
Append(p)
}

require.Equal(t, "/var:/bin", String())
Prepend("/bin///")
require.Equal(t, "/var:/bin", String())
}

func TestContains(t *testing.T) {
Reset()
Load("/opt/local/bin:/usr/local/bin:/sbin:/bin:/var:/bin")
require.False(t, Contains("/ur/local/sbin"))
require.False(t, Contains("/ur/local////sbin/"))
require.True(t, Contains("/sbin"))
require.True(t, Contains("///sbin//"))

}

func TestDrop(t *testing.T) {
Reset()
Load("/opt/local/bin:/usr/local/bin:/sbin:/bin:/var:/bin")
require.Equal(t, Slice(), []string{"/opt/local/bin", "/usr/local/bin", "/sbin", "/bin", "/var"})
Drop("/opt/local/bin")
Drop("/opt/local/bin")
Drop("/opt/local/bin")
Drop("/usr/local/bin")
Drop("/var")
require.NotEqual(t, "", String())
Drop("/sbin")
Drop("/bin")
require.False(t, Contains("/bin"))
require.Equal(t, "", String())

Reset()
require.NotPanics(t, func() { Drop("") })
}

func TestLoadEnv(t *testing.T) {
tests := []struct {
name string
val string
want string
}{
{"empty", "", ""},
}
for i, tt := range tests {
tt2 := tt
t.Run(tt2.name, func(t *testing.T) {
envvar := fmt.Sprintf("%s_%d_VAR", t.Name(), i)
Reset()
t.Setenv(envvar, tt.val)
LoadEnv(envvar)
require.Equal(t, tt2.want, String())
})
}
}

func TestPrepend(t *testing.T) {
Reset()
require.Equal(t, "", String())
for _, p := range []string{"/var", "/var", "/bin", "/bin/", "/bin///"} {
Append(p)
}

require.Equal(t, "/var:/bin", String())
Prepend("/bin///")
require.Equal(t, "/var:/bin", String())
}

func TestSlice(t *testing.T) {
Reset()
require.Equal(t, 0, len(Slice()))
Prepend("/usr/bin")
Append("/bin")
require.Equal(t, []string{"/usr/bin", "/bin"}, Slice())
}

func TestString(t *testing.T) {
Reset()
require.Equal(t, "", String())
Prepend("/usr/bin")
Append("/bin")
require.Equal(t, "/usr/bin:/bin", String())
}
77 changes: 47 additions & 30 deletions pathlist/list.go → dirlist/list.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Package pathlist implements functions to manipulate PATH-like
// Package dirlist implements functions to manipulate PATH-like
// environment variables.
package pathlist
package dirlist

import (
"fmt"
"os"
"path/filepath"
"slices"
Expand All @@ -22,7 +23,7 @@ type List interface {
Contains(string) bool

// Nil returns true if the list is emppty.
Nil() bool
// Nil() bool

// Load reads the list of directories from a string.
Load(string)
Expand Down Expand Up @@ -62,16 +63,16 @@ func New() List {
}

func (d *dirList) Contains(p string) bool {
return slices.Contains(d.lst, p)
return slices.Contains(d.lst, quoteAndClean(p))
}

func (d *dirList) Reset() {
d.init()
}

func (d *dirList) Nil() bool {
return d.lst == nil || len(d.lst) == 0
}
// func (d *dirList) Nil() bool {
// return d.l == nil || len(d.l) == 0
// }

func (d *dirList) Load(s string) {
d.src = s
Expand All @@ -82,26 +83,25 @@ func (d *dirList) LoadEnv(s string) {
d.Load(os.Getenv(s))
}

func (d *dirList) Slice() []string {
if d.Nil() {
return []string{}
func (d *dirList) Slice() (dst []string) {
if len(d.lst) == 0 {
return
}

dst := make([]string, len(d.lst))
n := copy(dst, d.lst)
if n != len(d.lst) {
panic("couldn't copy the list")
dst = make([]string, len(d.lst))
if n := copy(dst, d.lst); n == len(d.lst) {
return dst
}

return dst
panic("couldn't copy the list")
}

func (d *dirList) String() string {
if !d.Nil() {
return strings.Join(d.lst, string(filepath.ListSeparator))
if len(d.lst) == 0 {
return ""
}

return ""
return strings.Join(d.lst, string(filepath.ListSeparator))
}

func (d *dirList) load() {
Expand All @@ -110,7 +110,7 @@ func (d *dirList) load() {

func (d *dirList) Append(path string) {
p := quoteAndClean(path)
if d.Nil() {
if len(d.lst) == 0 {
d.lst = []string{p}
return
}
Expand All @@ -121,9 +121,10 @@ func (d *dirList) Append(path string) {
}

func (d *dirList) Drop(path string) {
if d.Nil() {
if len(d.lst) == 0 {
return
}

p := quoteAndClean(path)

if idx := slices.Index(d.lst, p); idx != -1 {
Expand All @@ -133,7 +134,7 @@ func (d *dirList) Drop(path string) {

func (d *dirList) Prepend(path string) {
p := quoteAndClean(path)
if d.Nil() {
if len(d.lst) == 0 {
d.lst = []string{p}
return
}
Expand All @@ -149,12 +150,16 @@ func (d *dirList) init() {
}

func (d *dirList) cleanPathVar() []string {
if d.src == "" {
return cleanPathVar(d.src)
}

func cleanPathVar(src string) []string {
if src == "" {
return nil
}

pthSlice := filepath.SplitList(d.src)
if pthSlice == nil {
pthSlice := filepath.SplitList(src)
if len(pthSlice) == 0 {
return nil
}

Expand All @@ -163,8 +168,13 @@ func (d *dirList) cleanPathVar() []string {

func (d *dirList) clone(o *dirList) *dirList {
o.src = d.src
o.lst = make([]string, len(d.lst))
copy(o.lst, d.lst)

n := len(d.lst)
o.lst = make([]string, n)

if m := copy(o.lst, d.lst); n != m {
panic(fmt.Sprintf("copy: expected %d items, got %d", n, m))
}

return o
}
Expand All @@ -190,12 +200,19 @@ func removeDups(col []string, applyFn func(string) (string, bool)) []string {
}

var filterEmptyStrings = func(s string) (string, bool) {
clean := filepath.Clean(s)
if clean != "" {
return clean, true
if strings.TrimSpace(s) == "" {
return s, false
}

return clean, false
// I removed the following because filepath.Clean()
// never returns "".
//
// clean := filepath.Clean(s)
// if clean == "" {
// return clean, false
// }

return filepath.Clean(s), true
}

func quoteAndClean(s string) string {
Expand Down
Loading

0 comments on commit faaadb9

Please sign in to comment.