Add CompletePath method

CompletePath takes an existing path and returns possible filesystem
completions based on that path.
This commit is contained in:
Galen Abell 2019-07-30 15:10:57 -04:00 committed by Drew DeVault
parent b73fcaae32
commit c4b57aaad8

View file

@ -1,12 +1,17 @@
package commands package commands
import ( import (
"fmt"
"io" "io"
"os"
"os/exec" "os/exec"
"path/filepath"
"strings"
"time" "time"
"git.sr.ht/~sircmpwn/aerc/widgets" "git.sr.ht/~sircmpwn/aerc/widgets"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"github.com/mitchellh/go-homedir"
) )
// QuickTerm is an ephemeral terminal for running a single command and quiting. // QuickTerm is an ephemeral terminal for running a single command and quiting.
@ -54,3 +59,89 @@ func QuickTerm(aerc *widgets.Aerc, args []string, stdin io.Reader) (*widgets.Ter
return term, nil return term, nil
} }
// CompletePath provides filesystem completions given a starting path.
func CompletePath(path string) []string {
if path == "" {
// default to cwd
cwd, err := os.Getwd()
if err != nil {
return nil
}
path = cwd
}
path, err := homedir.Expand(path)
if err != nil {
return nil
}
// strip trailing slashes, etc.
path = filepath.Clean(path)
if _, err := os.Stat(path); os.IsNotExist(err) {
// if the path doesn't exist, it is likely due to it being a partial path
// in this case, we want to return possible matches (ie /hom* should match
// /home)
matches, err := filepath.Glob(fmt.Sprintf("%s*", path))
if err != nil {
return nil
}
for i, m := range matches {
if isDir(m) {
matches[i] = m + "/"
}
}
return matches
}
files := listDir(path, false)
for i, f := range files {
f = filepath.Join(path, f)
if isDir(f) {
f += "/"
}
files[i] = f
}
return files
}
func isDir(path string) bool {
info, err := os.Stat(path)
if err != nil {
return false
}
return info.IsDir()
}
// return all filenames in a directory, optionally including hidden files
func listDir(path string, hidden bool) []string {
f, err := os.Open(path)
if err != nil {
return []string{}
}
files, err := f.Readdirnames(-1) // read all dir names
if err != nil {
return []string{}
}
if hidden {
return files
}
var filtered []string
for _, g := range files {
if !strings.HasPrefix(g, ".") {
filtered = append(filtered, g)
}
}
return filtered
}