diff options
-rw-r--r-- | commands/testdata/Foobar | 0 | ||||
-rw-r--r-- | commands/util.go | 60 | ||||
-rw-r--r-- | commands/util_test.go | 39 |
3 files changed, 77 insertions, 22 deletions
diff --git a/commands/testdata/Foobar b/commands/testdata/Foobar new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/commands/testdata/Foobar diff --git a/commands/util.go b/commands/util.go index 8c1e497d..fb1532fc 100644 --- a/commands/util.go +++ b/commands/util.go @@ -76,10 +76,16 @@ func QuickTerm(args []string, stdin io.Reader, silent bool) (*app.Terminal, erro // CompletePath provides filesystem completions given a starting path. func CompletePath(path string, onlyDirs bool) []string { + return completePath(path, onlyDirs, app.SelectedAccountUiConfig().FuzzyComplete) +} + +func completePath(path string, onlyDirs bool, fuzzyComplete bool) []string { if path == ".." || strings.HasSuffix(path, "/..") { return []string{path + "/"} } - if path == "~" || strings.HasPrefix(path, "~/") { + if path == "~" { + path = xdg.HomeDir() + "/" + } else if strings.HasPrefix(path, "~/") { path = xdg.HomeDir() + strings.TrimPrefix(path, "~") } includeHidden := path == "." @@ -87,25 +93,40 @@ func CompletePath(path string, onlyDirs bool) []string { includeHidden = strings.HasPrefix(path[i+1:], ".") } - matches, err := filepath.Glob(path + "*") - if err != nil || matches == nil { - return nil + const currentDir = "." + dir, search := filepath.Split(path) + // for `file` case dir will be `` which does not work in listDir + if dir == "" { + dir = currentDir } - results := make([]string, 0, len(matches)) - - for _, m := range matches { - if isDir(m) { + entries := listDir(dir, includeHidden) + filteredEntries := make([]string, 0, len(entries)) + for _, m := range entries { + testM := m + if dir != currentDir { + testM = dir + m + } + if isDir(testM) { m += "/" } else if onlyDirs { continue } - if strings.HasPrefix(filepath.Base(m), ".") && !includeHidden { - continue - } - results = append(results, opt.QuoteArg(xdg.TildeHome(m))) + filteredEntries = append(filteredEntries, m) } + results := filterList( + filteredEntries, + search, + func(s string) string { + if dir != currentDir { + s = dir + s + } + return opt.QuoteArg(xdg.TildeHome(s)) + }, + fuzzyComplete, + ) + sort.Strings(results) return results @@ -244,13 +265,24 @@ func QuoteSpace(s string) string { // An optional post processing function can be passed to prepend, append or // quote each value. func FilterList( - valid []string, search string, postProc func(string) string, + valid []string, + search string, + postProc func(string) string, +) []string { + return filterList(valid, search, postProc, app.SelectedAccountUiConfig().FuzzyComplete) +} + +func filterList( + valid []string, + search string, + postProc func(string) string, + fuzzyComplete bool, ) []string { if postProc == nil { postProc = opt.QuoteArg } out := make([]string, 0, len(valid)) - if app.SelectedAccountUiConfig().FuzzyComplete { + if fuzzyComplete { for _, v := range fuzzy.RankFindFold(search, valid) { out = append(out, postProc(v.Target)) } diff --git a/commands/util_test.go b/commands/util_test.go index 16b072d2..90b2123c 100644 --- a/commands/util_test.go +++ b/commands/util_test.go @@ -1,10 +1,9 @@ -package commands_test +package commands import ( "os" "testing" - "git.sr.ht/~rjarry/aerc/commands" "github.com/stretchr/testify/assert" ) @@ -13,13 +12,14 @@ func TestCompletePath(t *testing.T) { defer os.Chdir("..") vectors := []struct { - arg string - onlyDirs bool - expected []string + arg string + onlyDirs bool + fuzzyComplete bool + expected []string }{ { arg: "", - expected: []string{"baz/", "foo.ini", "foo/"}, + expected: []string{"Foobar", "baz/", "foo.ini", "foo/"}, }, { arg: "", @@ -32,7 +32,11 @@ func TestCompletePath(t *testing.T) { }, { arg: "fo", - expected: []string{"foo.ini", "foo/"}, + expected: []string{"Foobar", "foo.ini", "foo/"}, + }, + { + arg: "Fo", + expected: []string{"Foobar"}, }, { arg: "..", @@ -45,6 +49,7 @@ func TestCompletePath(t *testing.T) { { arg: "../testdata/", expected: []string{ + "../testdata/Foobar", "../testdata/baz/", "../testdata/foo.ini", "../testdata/foo/", @@ -55,10 +60,28 @@ func TestCompletePath(t *testing.T) { onlyDirs: true, expected: []string{"../testdata/foo/"}, }, + { + arg: "oo", + expected: []string{}, + }, + { + arg: "oo", + fuzzyComplete: true, + expected: []string{"Foobar", "foo.ini", "foo/"}, + }, + { + arg: "../testdata/oo", + expected: []string{}, + }, + { + arg: "../testdata/oo", + fuzzyComplete: true, + expected: []string{"../testdata/Foobar", "../testdata/foo.ini", "../testdata/foo/"}, + }, } for _, vec := range vectors { t.Run(vec.arg, func(t *testing.T) { - res := commands.CompletePath(vec.arg, vec.onlyDirs) + res := completePath(vec.arg, vec.onlyDirs, vec.fuzzyComplete) assert.Equal(t, vec.expected, res) }) } |