From 18c3e46ac6bca121777ffab32d02556b780180c6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 16 Sep 2022 08:56:07 +0530 Subject: [PATCH] When completing on patterns exclude directories that only contain files that dont match --- kitty_tests/completion.py | 2 +- tools/completion/files.go | 44 +++++++++++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/kitty_tests/completion.py b/kitty_tests/completion.py index 4f6c6f7a2..ce4f2a7a7 100644 --- a/kitty_tests/completion.py +++ b/kitty_tests/completion.py @@ -99,7 +99,7 @@ def completion(self: TestCompletion, tdir: str): add('kitty @ goto-layout ', has_words('tall', 'fat')) add('kitty @ goto-layout spli', all_words('splits')) add('kitty @ goto-layout f f', all_words()) - add('kitty @ set-window-logo ', all_words('exe-not2.jpeg', 'sub/', 'bin/')) + add('kitty @ set-window-logo ', all_words('exe-not2.jpeg', 'sub/')) add('kitty @ set-window-logo e', all_words('exe-not2.jpeg')) add('kitty @ set-window-logo e e', all_words()) diff --git a/tools/completion/files.go b/tools/completion/files.go index 0d63f0dd6..934f13380 100644 --- a/tools/completion/files.go +++ b/tools/completion/files.go @@ -121,19 +121,51 @@ func complete_executables_in_path(prefix string, paths ...string) []string { return ans } +func is_dir_or_symlink_to_dir(entry os.DirEntry, path string) bool { + if entry.IsDir() { + return true + } + if entry.Type()&os.ModeSymlink == os.ModeSymlink { + p, err := filepath.EvalSymlinks(path) + if err == nil { + s, err := os.Stat(p) + if err == nil && s.IsDir() { + return true + } + } + } + return false +} + func complete_by_fnmatch(prefix string, patterns []string) []string { ans := make([]string, 0, 1024) + + matches := func(name string) bool { + for _, pat := range patterns { + matched, err := filepath.Match(pat, name) + if err == nil && matched { + return true + } + } + return false + } + complete_files(prefix, func(entry *FileEntry) { if entry.is_dir && !entry.is_empty_dir { - ans = append(ans, entry.completion_candidate) + entries, err := os.ReadDir(entry.abspath) + if err == nil { + for _, e := range entries { + if matches(e.Name()) || is_dir_or_symlink_to_dir(e, filepath.Join(entry.abspath, e.Name())) { + ans = append(ans, entry.completion_candidate) + return + } + } + } return } q := strings.ToLower(entry.name) - for _, pat := range patterns { - matched, err := filepath.Match(pat, q) - if err == nil && matched { - ans = append(ans, entry.completion_candidate) - } + if matches(q) { + ans = append(ans, entry.completion_candidate) } }) return ans