package completer import ( "context" "path" "path/filepath" "strings" "github.com/databricks/cli/libs/filer" "github.com/spf13/cobra" ) type completer struct { ctx context.Context // The filer to use for completing remote or local paths. filer filer.Filer // CompletePath will only return directories when onlyDirs is true. onlyDirs bool // Prefix to prepend to completions. prefix string // Whether the path is local or remote. If the path is local we use the `filepath` // package for path manipulation. Otherwise we use the `path` package. isLocalPath bool } // General completer that takes a filer to complete remote paths when TAB-ing through a path. func New(ctx context.Context, filer filer.Filer, onlyDirs bool) *completer { return &completer{ctx: ctx, filer: filer, onlyDirs: onlyDirs, prefix: "", isLocalPath: true} } func (c *completer) SetPrefix(p string) { c.prefix = p } func (c *completer) SetIsLocalPath(i bool) { c.isLocalPath = i } func (c *completer) CompletePath(p string) ([]string, cobra.ShellCompDirective, error) { trailingSeparator := "/" joinFunc := path.Join // Use filepath functions if we are in a local path. if c.isLocalPath { joinFunc = filepath.Join trailingSeparator = string(filepath.Separator) } // If the user is TAB-ing their way through a path and the // path ends in a trailing slash, we should list nested directories. // If the path is incomplete, however, then we should list adjacent // directories. dirPath := p if !strings.HasSuffix(p, trailingSeparator) { dirPath = path.Dir(p) } entries, err := c.filer.ReadDir(c.ctx, dirPath) if err != nil { return nil, cobra.ShellCompDirectiveError, err } completions := []string{} for _, entry := range entries { if c.onlyDirs && !entry.IsDir() { continue } // Join directory path and entry name completion := joinFunc(dirPath, entry.Name()) // Prepend prefix if it has been set if c.prefix != "" { completion = joinFunc(c.prefix, completion) } // Add trailing separator for directories. if entry.IsDir() { completion += trailingSeparator } completions = append(completions, completion) } // If the path is local, we add the dbfs:/ prefix suggestion as an option if c.isLocalPath { completions = append(completions, "dbfs:/") } return completions, cobra.ShellCompDirectiveNoSpace, err }