support local file path auto completer for lls / lcd command

This commit is contained in:
tickstep
2025-03-19 21:31:00 +08:00
parent e669063be9
commit d7b4d0c846
4 changed files with 126 additions and 46 deletions
+2 -2
View File
@@ -68,7 +68,7 @@ func CmdLocalPwd() cli.Command {
lwd := config.Config.LocalWorkdir
if lwd == "" {
// 默认为用户主页目录
lwd = getLocalHomeDir()
lwd = GetLocalHomeDir()
config.Config.LocalWorkdir = lwd
}
if runtime.GOOS == "windows" {
@@ -84,7 +84,7 @@ func CmdLocalPwd() cli.Command {
}
func RunChangeLocalDirectory(targetPath string) {
targetPath = localPathJoin(targetPath)
targetPath = LocalPathJoin(targetPath)
// 获取目标路径文件信息
localFileInfo, er := os.Stat(targetPath)
+1 -1
View File
@@ -113,7 +113,7 @@ func CmdLocalLs() cli.Command {
func RunLocalLs(targetPath string,
showAllFile bool,
orderBy aliyunpan.FileOrderBy, orderDirection aliyunpan.FileOrderDirection) {
targetPath = localPathJoin(targetPath)
targetPath = LocalPathJoin(targetPath)
// 获取目标路径文件信息
localFileInfo, er := os.Stat(targetPath)
+5 -5
View File
@@ -9,8 +9,8 @@ import (
"strings"
)
// getLocalHomeDir 获取本地用户主目录
func getLocalHomeDir() string {
// GetLocalHomeDir 获取本地用户主目录
func GetLocalHomeDir() string {
// 默认为用户主页目录
if hd, e := os.UserHomeDir(); e == nil {
return hd
@@ -18,8 +18,8 @@ func getLocalHomeDir() string {
return ""
}
// localPathJoin 拼接本地路径
func localPathJoin(p string) string {
// LocalPathJoin 拼接本地路径
func LocalPathJoin(p string) string {
p = path.Clean(strings.ReplaceAll(p, "\\", "/"))
if filepath.IsAbs(p) {
return p
@@ -30,7 +30,7 @@ func localPathJoin(p string) string {
}
wd := config.Config.LocalWorkdir
if wd == "" {
wd = getLocalHomeDir()
wd = GetLocalHomeDir()
}
return path.Join(wd, p)
}
+118 -38
View File
@@ -29,6 +29,7 @@ import (
"github.com/tickstep/aliyunpan/internal/global"
"github.com/tickstep/aliyunpan/internal/panupdate"
"github.com/tickstep/aliyunpan/internal/utils"
"github.com/tickstep/aliyunpan/library/homedir"
"github.com/tickstep/library-go/converter"
"github.com/tickstep/library-go/logger"
"github.com/urfave/cli"
@@ -231,10 +232,15 @@ func main() {
// 检测输入的命令是否支持tab补全路径
if cmdutil.ContainsString(acceptCompleteFilePanCommands, thisCmd.FullName()) {
// 云盘文件路径的补全
return panFilePathCompleter(line, lineArgs, numArgs, closed)
if thisCmd.FullName() == "ls" || thisCmd.FullName() == "cd" {
// 树状结构,需要补全文件夹路径
return panFilePathCompleter(line, lineArgs, numArgs, closed, true)
} else {
return panFilePathCompleter(line, lineArgs, numArgs, closed, false)
}
} else if cmdutil.ContainsString(acceptCompleteFileLocalCommands, thisCmd.FullName()) {
// 本地文件路径的补全
return localFilePathCompleter(line, lineArgs, numArgs, closed)
return localFilePathCompleter(line, lineArgs, numArgs, closed, true)
}
return
})
@@ -657,9 +663,17 @@ func main() {
}
// panFilePathCompleter 云盘文件路径Tab补全处理器
func panFilePathCompleter(line string, lineArgs []string, numArgs int, closed bool) (s []string) {
func panFilePathCompleter(line string, lineArgs []string, numArgs int, closed bool, onlyNeedFolder bool) (s []string) {
return filePathCompleterProcessor(line, lineArgs, numArgs, closed, onlyNeedFolder, getPanFileListByTargetPath)
}
// localFilePathCompleter 本地文件路径Tab补全处理器
func localFilePathCompleter(line string, lineArgs []string, numArgs int, closed bool, onlyNeedFolder bool) (s []string) {
return filePathCompleterProcessor(line, lineArgs, numArgs, closed, onlyNeedFolder, getLocalFileListByTargetPath)
}
func filePathCompleterProcessor(line string, lineArgs []string, numArgs int, closed bool, onlyNeedFolder bool, fileListFunc getFileListByTargetPath) (s []string) {
var (
activeUser = config.Config.ActiveUser()
runeFunc = unicode.IsSpace
cmdRuneFunc = func(r rune) bool {
switch r {
@@ -671,10 +685,6 @@ func panFilePathCompleter(line string, lineArgs []string, numArgs int, closed bo
targetPath string
)
if activeUser == nil {
return
}
if !closed {
targetPath = lineArgs[numArgs-1]
escaper.EscapeStringsByRuneFunc(lineArgs[:numArgs-1], runeFunc) // 转义
@@ -690,39 +700,21 @@ func panFilePathCompleter(line string, lineArgs []string, numArgs int, closed bo
s = append(s, line+"/")
return
}
var (
targetDir string
isAbs = path.IsAbs(targetPath)
isDir = strings.LastIndex(targetPath, "/") == len(targetPath)-1
)
if isAbs {
targetDir = path.Dir(targetPath)
} else {
wd := "/"
if activeUser.IsFileDriveActive() {
wd = activeUser.Workdir
} else if activeUser.IsResourceDriveActive() {
wd = activeUser.ResourceWorkdir
} else if activeUser.IsAlbumDriveActive() {
wd = activeUser.AlbumWorkdir
}
targetDir = path.Join(wd, targetPath)
if !isDir {
targetDir = path.Dir(targetDir)
if strings.HasPrefix(targetPath, "~") {
if p, e := homedir.Expand(targetPath); e == nil {
targetPath = p
}
}
// tab键补全路径
files, err := activeUser.CacheFilesDirectoriesList(targetDir)
if err != nil {
return
}
targetDir, files := fileListFunc(targetPath)
for _, file := range files {
if file == nil {
continue
}
if onlyNeedFolder && !file.IsFolder {
// 过滤文件,只需要文件夹
continue
}
var (
appendLine string
@@ -745,7 +737,7 @@ func panFilePathCompleter(line string, lineArgs []string, numArgs int, closed bo
goto handle
handle:
if file.IsFolder() {
if file.IsFolder {
s = append(s, appendLine+"/")
continue
}
@@ -760,7 +752,95 @@ func panFilePathCompleter(line string, lineArgs []string, numArgs int, closed bo
return
}
// localFilePathCompleter 本地文件路径Tab补全处理器
func localFilePathCompleter(line string, lineArgs []string, numArgs int, closed bool) (s []string) {
return nil
type fileEntity struct {
FileName string
Path string
IsFolder bool
}
type getFileListByTargetPath func(targetPath string) (string, []*fileEntity)
// getPanFileListByTargetPath 通过路径获取云盘文件列表
func getPanFileListByTargetPath(targetPath string) (string, []*fileEntity) {
var (
activeUser = config.Config.ActiveUser()
targetDir string
isAbs = path.IsAbs(targetPath)
isDir = strings.LastIndex(targetPath, "/") == len(targetPath)-1
r = []*fileEntity{}
)
if activeUser == nil {
return targetDir, r
}
if isAbs {
targetDir = path.Dir(targetPath)
} else {
wd := "/"
if activeUser.IsFileDriveActive() {
wd = activeUser.Workdir
} else if activeUser.IsResourceDriveActive() {
wd = activeUser.ResourceWorkdir
} else if activeUser.IsAlbumDriveActive() {
wd = activeUser.AlbumWorkdir
}
targetDir = path.Join(wd, targetPath)
if !isDir {
targetDir = path.Dir(targetDir)
}
}
files, err := activeUser.CacheFilesDirectoriesList(targetDir)
if err != nil {
return targetDir, r
}
for _, file := range files {
if file == nil {
continue
}
r = append(r, &fileEntity{
FileName: file.FileName,
Path: file.Path,
IsFolder: file.IsFolder(),
})
}
return targetDir, r
}
// getLocalFileListByTargetPath 通过路径获取本地文件列表
func getLocalFileListByTargetPath(targetPath string) (string, []*fileEntity) {
var (
targetDir string
isAbs = filepath.IsAbs(targetPath)
isDir = strings.LastIndex(targetPath, "/") == len(targetPath)-1
r = []*fileEntity{}
)
if isAbs {
targetDir = path.Dir(targetPath)
} else {
targetDir = command_local.LocalPathJoin(targetPath)
if !isDir {
targetDir = path.Dir(targetDir)
}
}
fileEntryList, err := os.ReadDir(targetDir)
if err != nil {
return targetDir, r
}
for _, file := range fileEntryList {
if file == nil {
continue
}
if strings.HasPrefix(file.Name(), ".") {
continue
}
r = append(r, &fileEntity{
FileName: file.Name(),
Path: path.Join(targetDir, file.Name()),
IsFolder: file.IsDir(),
})
}
return targetDir, r
}