From bab346ad2025441bd9a61d2d93d079783bef4d44 Mon Sep 17 00:00:00 2001 From: okayno14 Date: Tue, 30 Jul 2024 23:10:04 +0700 Subject: [PATCH 1/9] feat: add custom ignore dir/files --- autoload/fuzzy/files.vim | 20 +++++++++++--- autoload/ignore_tree/fd_builder.vim | 24 +++++++++++++++++ autoload/ignore_tree/find_builder.vim | 31 ++++++++++++++++++++++ autoload/ignore_tree/gci_builder.vim | 38 +++++++++++++++++++++++++++ autoload/ignore_tree/ignore_tree.vim | 18 +++++++++++++ 5 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 autoload/ignore_tree/fd_builder.vim create mode 100644 autoload/ignore_tree/find_builder.vim create mode 100644 autoload/ignore_tree/gci_builder.vim create mode 100644 autoload/ignore_tree/ignore_tree.vim diff --git a/autoload/fuzzy/files.vim b/autoload/fuzzy/files.vim index 7bc9e04..05d7cd2 100644 --- a/autoload/fuzzy/files.vim +++ b/autoload/fuzzy/files.vim @@ -2,6 +2,10 @@ vim9script import autoload 'utils/selector.vim' import autoload 'utils/devicons.vim' +import autoload 'ignore_tree/ignore_tree.vim' +import autoload 'ignore_tree/find_builder.vim' +import autoload 'ignore_tree/fd_builder.vim' +import autoload 'ignore_tree/gci_builder.vim' var last_result_len: number var cur_pattern: string @@ -17,6 +21,7 @@ var cache: dict var cmdstr: string var matched_hl_offset = 0 var devicon_char_width = devicons.GetDeviconCharWidth() +var fuzzyy_custom_ignore = {} var commands: dict var has_git = executable('git') ? v:true : v:false @@ -30,19 +35,25 @@ def InsideGitRepo(): bool endif enddef +if exists('g:fuzzyy_custom_ignore') + fuzzyy_custom_ignore = g:fuzzyy_custom_ignore +else + fuzzyy_custom_ignore = ignore_tree.MakeIgnoreTree() +endif + if executable('fd') commands = { - 'default': 'fd --type f -H -I -E .git', - 'gitignore': 'fd --type f -H -E .git', + 'default': fd_builder.Build(fuzzyy_custom_ignore), + 'gitignore': 'fd --type f -H -E .git' } else if has('win32') commands = { - 'default': 'powershell -command "gci . -r -n -File"', + 'default': gci_builder.Build(fuzzyy_custom_ignore) } else commands = { - 'default': 'find . -type f -not -path "*/.git/*"', + 'default': find_builder.Build(fuzzyy_custom_ignore) } endif # TODO bugs @@ -286,3 +297,4 @@ export def Start(windows: dict, ...args: list) files_update_tid = timer_start(400, function('FilesUpdateMenu'), {'repeat': -1}) # Profiling() enddef + diff --git a/autoload/ignore_tree/fd_builder.vim b/autoload/ignore_tree/fd_builder.vim new file mode 100644 index 0000000..298965c --- /dev/null +++ b/autoload/ignore_tree/fd_builder.vim @@ -0,0 +1,24 @@ +vim9script + +import autoload 'ignore_tree/ignore_tree.vim' + +def ParseDirList(dir_list: list): string + return reduce(dir_list, (acc, dir) => acc .. "-E " .. dir .. " ", "") +enddef + +def ParseFileList(file_list: list): string + return reduce(file_list, (acc, file) => acc .. "-E " .. file .. " ", "") +enddef + +export def Build(ignore_tree_obj: dict>): string + var dir_ignore = ignore_tree.GetDirList(ignore_tree_obj) + var dir_list_parsed = ParseDirList(dir_ignore) + + var file_ignore = ignore_tree.GetFileList(ignore_tree_obj) + var file_list_parsed = ParseFileList(file_ignore) + + var result = "fd --type f -H -I " .. dir_list_parsed .. file_list_parsed + + return result +enddef + diff --git a/autoload/ignore_tree/find_builder.vim b/autoload/ignore_tree/find_builder.vim new file mode 100644 index 0000000..1468e64 --- /dev/null +++ b/autoload/ignore_tree/find_builder.vim @@ -0,0 +1,31 @@ +vim9script + +import autoload 'ignore_tree/ignore_tree.vim' + +def ParseFileList(file_list: list): string + return reduce(file_list, (acc, file) => acc .. "-not -name " .. file .. " ", "") +enddef + +def ParseDirList(dir_list: list): string + var ParseDir = (dir): string => "*/" .. dir .. "/*" + var Append = (buf, char) => buf .. char + + var dir_list_parsed = reduce(dir_list, (acc, dir) => acc .. "-path " .. ParseDir(dir) .. " -prune -o ", "") + ->trim("-o ", 2) + ->Append(" ") + + return "\\( " .. dir_list_parsed .. "\\) " +enddef + +export def Build(ignore_tree_obj: dict>): string + var file_ignore = ignore_tree.GetFileList(ignore_tree_obj) + var file_list_parsed = ParseFileList(file_ignore) + + var dir_ignore = ignore_tree.GetDirList(ignore_tree_obj) + var dir_list_parsed = ParseDirList(dir_ignore) + + var result = "find " .. dir_list_parsed .. "-o " .. file_list_parsed .. "-type f -print " + + return result +enddef + diff --git a/autoload/ignore_tree/gci_builder.vim b/autoload/ignore_tree/gci_builder.vim new file mode 100644 index 0000000..47e6c7d --- /dev/null +++ b/autoload/ignore_tree/gci_builder.vim @@ -0,0 +1,38 @@ +vim9script + +import autoload 'ignore_tree/ignore_tree.vim' + +# GCI doc isn't clear. Get-ChildItem -Recurse -Exclude only matches exclusion on the leaf, not the parent path. +# +# Link: https://stackoverflow.com/questions/15294836/how-can-i-exclude-multiple-folders-using-get-childitem-exclude#:~:text=The%20documentation%20isn%27t%20clear%20on%20this%2C%20but%20Get%2DChildItem%20%2DRecurse%20%2DExclude%20only%20matches%20exclusion%20on%20the%20leaf%20(Split%2DPath%20%24_.FullName%20%2DLeaf)%2C%20not%20the%20parent%20path%20(Split%2DPath%20%24_.FullName%20%2DParent). +# +# That's why module builds GCI cmd and piping it into Where-filter +def BuildDirFilter(dir_list: list): string + var TransformDir = (dir) => "'" .. dir .. "\\*" .. "'" + var Append = (buf, char) => buf .. char + + return reduce(dir_list, (acc, dir) => acc .. "$_ -notlike " .. TransformDir(dir) .. " -and ", "") + -> trim(" -and ", 2) + -> Append(" ") +enddef + +def BuildFileFilter(file_list: list): string + var TransformFile = (file) => "'" .. file .. "'" + var Append = (buf, char) => buf .. char + + return reduce(file_list, (acc, file) => acc .. "$_ -notlike " .. TransformFile(file) .. " -and ", "") + -> trim(" -and ", 2) + -> Append(" ") +enddef + +def BuildFilter(dir_ignore: list, file_ignore: list): string + return "Where-Object { " .. BuildDirFilter(dir_ignore) .. "-and " .. BuildFileFilter(file_ignore) .. "} " +enddef + +export def Build(ignore_tree_obj: dict>): string + var dir_ignore = ignore_tree.GetDirList(ignore_tree_obj) + var file_ignore = ignore_tree.GetFileList(ignore_tree_obj) + var cmd = "powershell -command Get-ChildItem . -Name -File -Recurse | " .. BuildFilter(dir_ignore, file_ignore) + return cmd +enddef + diff --git a/autoload/ignore_tree/ignore_tree.vim b/autoload/ignore_tree/ignore_tree.vim new file mode 100644 index 0000000..a68bd5f --- /dev/null +++ b/autoload/ignore_tree/ignore_tree.vim @@ -0,0 +1,18 @@ +vim9script + +export def MakeIgnoreTree(): dict> + var fuzzyy_custom_ignore = { + 'dir': ['.git', '.hg', '.svn', '.rebar', '.eunit'], + 'file': ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', '*.core', '*.swn', '*.swp'] + } + return fuzzyy_custom_ignore +enddef + +export def GetDirList(ignore_tree: dict>): list + return ignore_tree.dir +enddef + +export def GetFileList(ignore_tree: dict>): list + return ignore_tree.file +enddef + From 5b6a6468f3d036911823004ca16a5f48a5be9fb7 Mon Sep 17 00:00:00 2001 From: okayno14 Date: Tue, 6 Aug 2024 00:28:08 +0700 Subject: [PATCH 2/9] add test for cmd builders --- autoload/ignore_tree/gci_builder.vim | 4 +- autoload/test/fuzzyy_test.vim | 161 +++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 autoload/test/fuzzyy_test.vim diff --git a/autoload/ignore_tree/gci_builder.vim b/autoload/ignore_tree/gci_builder.vim index 47e6c7d..b61699e 100644 --- a/autoload/ignore_tree/gci_builder.vim +++ b/autoload/ignore_tree/gci_builder.vim @@ -32,7 +32,7 @@ enddef export def Build(ignore_tree_obj: dict>): string var dir_ignore = ignore_tree.GetDirList(ignore_tree_obj) var file_ignore = ignore_tree.GetFileList(ignore_tree_obj) - var cmd = "powershell -command Get-ChildItem . -Name -File -Recurse | " .. BuildFilter(dir_ignore, file_ignore) - return cmd + var cmd = "Get-ChildItem . -Name -File -Recurse | " .. BuildFilter(dir_ignore, file_ignore) + return "powershell -command " .. '"' .. cmd .. '"' enddef diff --git a/autoload/test/fuzzyy_test.vim b/autoload/test/fuzzyy_test.vim new file mode 100644 index 0000000..1e48184 --- /dev/null +++ b/autoload/test/fuzzyy_test.vim @@ -0,0 +1,161 @@ +vim9script + +import autoload 'ignore_tree/ignore_tree.vim' +import autoload 'ignore_tree/find_builder.vim' +import autoload 'ignore_tree/fd_builder.vim' +import autoload 'ignore_tree/gci_builder.vim' + +def Setup1(): dict + var FileTMP = tempname() + var DirTMP = substitute(FileTMP, "/[^/]*$", "/", "") + var DirIgnored = ".git/" + var File = "good.txt" + var FileIgnored = "bad.beam" + + mkdir(DirTMP, 'p') + var CWDOld = getcwd() + chdir(DirTMP) + + mkdir(DirIgnored, 'p') + writefile(["foo"], DirIgnored .. "/" .. File, "") + writefile(["foo"], DirIgnored .. "/" .. FileIgnored, "") + writefile(["foo"], DirTMP .. "/" .. File, "") + writefile(["foo"], DirTMP .. "/" .. FileIgnored, "") + + var Conf = { + dir_tmp: DirTMP, + dir_ignored: DirIgnored, + file: File, + file_ignored: FileIgnored, + cwd_old: CWDOld + } + + return Conf +enddef + +def Cleanup1(conf: dict): void + chdir(conf.cwd_old) + delete(conf.dir_tmp, "rf") +enddef + +def Case1(conf: dict): void + if has("win32") || has("win64") + echo "skipped, wrong OS:windows" + return + endif + + # INIT + var CMD = find_builder.Build(ignore_tree.MakeIgnoreTree()) + + # ACT + var FileList = systemlist(CMD) + + # ASSERT + if index(FileList, "./" .. conf.file) == -1 + throw "file " .. conf.file .. " not found" + endif + + if index(FileList, "./" .. conf.file_ignored) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + if index(FileList, conf.dir_ignored .. conf.file) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + if index(FileList, conf.dir_ignored .. conf.file_ignored) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + # TERMINATE + +enddef + +def Case2(conf: dict): void + if has("win32") || has("win64") + echo "skipped, wrong OS:windows" + return + endif + + # INIT + var CMD = fd_builder.Build(ignore_tree.MakeIgnoreTree()) + + # ACT + var FileList = systemlist(CMD) + + # ASSERT + if index(FileList, conf.file) == -1 + throw "file " .. conf.file .. " not found" + endif + + if index(FileList, conf.file_ignored) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + if index(FileList, conf.dir_ignored .. conf.file) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + if index(FileList, conf.dir_ignored .. conf.file_ignored) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + # TERMINATE + +enddef + +def Case3(conf: dict): void + if !has("win32") && !has("win64") + echo "skipped, not windows" + return + endif + + # INIT + var CMD = gci_builder.Build(ignore_tree.MakeIgnoreTree()) + + # ACT + var FileList = system(CMD)->split('\n') + + # ASSERT + if index(FileList, conf.file) == -1 + throw "file " .. conf.file .. " not found" + endif + + if index(FileList, conf.file_ignored) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + if index(FileList, conf.dir_ignored .. conf.file) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + if index(FileList, conf.dir_ignored .. conf.file_ignored) != -1 + throw "file " .. conf.file_ignored .. " found" + endif + + # TERMINATE + +enddef + +def RunCaseFun(SetupFun: func(): any, CleanupFun: func(any): void, CaseName: string, CaseFun: func(any): void): void + var Conf = SetupFun() + try + CaseFun(Conf) + catch + echom "Catched exception: " .. v:exception .. " in case: " .. CaseName + endtry + CleanupFun(Conf) +enddef + +def Suite1(): void + RunCaseFun(Setup1, Cleanup1, "Case1", Case1) + RunCaseFun(Setup1, Cleanup1, "Case2", Case2) + RunCaseFun(Setup1, Cleanup1, "Case3", Case3) +enddef + +export def Start(): void + Suite1() +enddef + +Start() + From a6efe411c935957662a6dc6be4d05a566eff5c10 Mon Sep 17 00:00:00 2001 From: Donald Tang Date: Thu, 22 Aug 2024 22:42:22 +0800 Subject: [PATCH 3/9] merge all four builder into a single file --- autoload/fuzzy/files.vim | 20 ++----- autoload/ignore_tree/fd_builder.vim | 24 -------- autoload/ignore_tree/find_builder.vim | 31 ----------- autoload/ignore_tree/gci_builder.vim | 38 ------------- autoload/ignore_tree/ignore_tree.vim | 18 ------ autoload/utils/cmdbuilder.vim | 73 +++++++++++++++++++++++++ {autoload/test => test}/fuzzyy_test.vim | 0 7 files changed, 78 insertions(+), 126 deletions(-) delete mode 100644 autoload/ignore_tree/fd_builder.vim delete mode 100644 autoload/ignore_tree/find_builder.vim delete mode 100644 autoload/ignore_tree/gci_builder.vim delete mode 100644 autoload/ignore_tree/ignore_tree.vim create mode 100644 autoload/utils/cmdbuilder.vim rename {autoload/test => test}/fuzzyy_test.vim (100%) diff --git a/autoload/fuzzy/files.vim b/autoload/fuzzy/files.vim index 05d7cd2..c18d812 100644 --- a/autoload/fuzzy/files.vim +++ b/autoload/fuzzy/files.vim @@ -2,10 +2,7 @@ vim9script import autoload 'utils/selector.vim' import autoload 'utils/devicons.vim' -import autoload 'ignore_tree/ignore_tree.vim' -import autoload 'ignore_tree/find_builder.vim' -import autoload 'ignore_tree/fd_builder.vim' -import autoload 'ignore_tree/gci_builder.vim' +import autoload 'utils/cmdbuilder.vim' var last_result_len: number var cur_pattern: string @@ -21,7 +18,6 @@ var cache: dict var cmdstr: string var matched_hl_offset = 0 var devicon_char_width = devicons.GetDeviconCharWidth() -var fuzzyy_custom_ignore = {} var commands: dict var has_git = executable('git') ? v:true : v:false @@ -35,25 +31,19 @@ def InsideGitRepo(): bool endif enddef -if exists('g:fuzzyy_custom_ignore') - fuzzyy_custom_ignore = g:fuzzyy_custom_ignore -else - fuzzyy_custom_ignore = ignore_tree.MakeIgnoreTree() -endif - if executable('fd') commands = { - 'default': fd_builder.Build(fuzzyy_custom_ignore), + 'default': cmdbuilder.Build_fd(), 'gitignore': 'fd --type f -H -E .git' } else if has('win32') commands = { - 'default': gci_builder.Build(fuzzyy_custom_ignore) + 'default': cmdbuilder.Build_gci() } else commands = { - 'default': find_builder.Build(fuzzyy_custom_ignore) + 'default': cmdbuilder.Build_find() } endif # TODO bugs @@ -215,7 +205,6 @@ def FilesJobStart(path: string, cmd: string) enddef def ErrCb(channel: channel, msg: string) - # echom ['err'] enddef def ExitCb(j: job, status: number) @@ -291,6 +280,7 @@ export def Start(windows: dict, ...args: list) else cmd = cmdstr endif + echom cmd FilesJobStart(cwd, cmd) menu_wid = wids.menu timer_start(50, function('FilesUpdateMenu')) diff --git a/autoload/ignore_tree/fd_builder.vim b/autoload/ignore_tree/fd_builder.vim deleted file mode 100644 index 298965c..0000000 --- a/autoload/ignore_tree/fd_builder.vim +++ /dev/null @@ -1,24 +0,0 @@ -vim9script - -import autoload 'ignore_tree/ignore_tree.vim' - -def ParseDirList(dir_list: list): string - return reduce(dir_list, (acc, dir) => acc .. "-E " .. dir .. " ", "") -enddef - -def ParseFileList(file_list: list): string - return reduce(file_list, (acc, file) => acc .. "-E " .. file .. " ", "") -enddef - -export def Build(ignore_tree_obj: dict>): string - var dir_ignore = ignore_tree.GetDirList(ignore_tree_obj) - var dir_list_parsed = ParseDirList(dir_ignore) - - var file_ignore = ignore_tree.GetFileList(ignore_tree_obj) - var file_list_parsed = ParseFileList(file_ignore) - - var result = "fd --type f -H -I " .. dir_list_parsed .. file_list_parsed - - return result -enddef - diff --git a/autoload/ignore_tree/find_builder.vim b/autoload/ignore_tree/find_builder.vim deleted file mode 100644 index 1468e64..0000000 --- a/autoload/ignore_tree/find_builder.vim +++ /dev/null @@ -1,31 +0,0 @@ -vim9script - -import autoload 'ignore_tree/ignore_tree.vim' - -def ParseFileList(file_list: list): string - return reduce(file_list, (acc, file) => acc .. "-not -name " .. file .. " ", "") -enddef - -def ParseDirList(dir_list: list): string - var ParseDir = (dir): string => "*/" .. dir .. "/*" - var Append = (buf, char) => buf .. char - - var dir_list_parsed = reduce(dir_list, (acc, dir) => acc .. "-path " .. ParseDir(dir) .. " -prune -o ", "") - ->trim("-o ", 2) - ->Append(" ") - - return "\\( " .. dir_list_parsed .. "\\) " -enddef - -export def Build(ignore_tree_obj: dict>): string - var file_ignore = ignore_tree.GetFileList(ignore_tree_obj) - var file_list_parsed = ParseFileList(file_ignore) - - var dir_ignore = ignore_tree.GetDirList(ignore_tree_obj) - var dir_list_parsed = ParseDirList(dir_ignore) - - var result = "find " .. dir_list_parsed .. "-o " .. file_list_parsed .. "-type f -print " - - return result -enddef - diff --git a/autoload/ignore_tree/gci_builder.vim b/autoload/ignore_tree/gci_builder.vim deleted file mode 100644 index b61699e..0000000 --- a/autoload/ignore_tree/gci_builder.vim +++ /dev/null @@ -1,38 +0,0 @@ -vim9script - -import autoload 'ignore_tree/ignore_tree.vim' - -# GCI doc isn't clear. Get-ChildItem -Recurse -Exclude only matches exclusion on the leaf, not the parent path. -# -# Link: https://stackoverflow.com/questions/15294836/how-can-i-exclude-multiple-folders-using-get-childitem-exclude#:~:text=The%20documentation%20isn%27t%20clear%20on%20this%2C%20but%20Get%2DChildItem%20%2DRecurse%20%2DExclude%20only%20matches%20exclusion%20on%20the%20leaf%20(Split%2DPath%20%24_.FullName%20%2DLeaf)%2C%20not%20the%20parent%20path%20(Split%2DPath%20%24_.FullName%20%2DParent). -# -# That's why module builds GCI cmd and piping it into Where-filter -def BuildDirFilter(dir_list: list): string - var TransformDir = (dir) => "'" .. dir .. "\\*" .. "'" - var Append = (buf, char) => buf .. char - - return reduce(dir_list, (acc, dir) => acc .. "$_ -notlike " .. TransformDir(dir) .. " -and ", "") - -> trim(" -and ", 2) - -> Append(" ") -enddef - -def BuildFileFilter(file_list: list): string - var TransformFile = (file) => "'" .. file .. "'" - var Append = (buf, char) => buf .. char - - return reduce(file_list, (acc, file) => acc .. "$_ -notlike " .. TransformFile(file) .. " -and ", "") - -> trim(" -and ", 2) - -> Append(" ") -enddef - -def BuildFilter(dir_ignore: list, file_ignore: list): string - return "Where-Object { " .. BuildDirFilter(dir_ignore) .. "-and " .. BuildFileFilter(file_ignore) .. "} " -enddef - -export def Build(ignore_tree_obj: dict>): string - var dir_ignore = ignore_tree.GetDirList(ignore_tree_obj) - var file_ignore = ignore_tree.GetFileList(ignore_tree_obj) - var cmd = "Get-ChildItem . -Name -File -Recurse | " .. BuildFilter(dir_ignore, file_ignore) - return "powershell -command " .. '"' .. cmd .. '"' -enddef - diff --git a/autoload/ignore_tree/ignore_tree.vim b/autoload/ignore_tree/ignore_tree.vim deleted file mode 100644 index a68bd5f..0000000 --- a/autoload/ignore_tree/ignore_tree.vim +++ /dev/null @@ -1,18 +0,0 @@ -vim9script - -export def MakeIgnoreTree(): dict> - var fuzzyy_custom_ignore = { - 'dir': ['.git', '.hg', '.svn', '.rebar', '.eunit'], - 'file': ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', '*.core', '*.swn', '*.swp'] - } - return fuzzyy_custom_ignore -enddef - -export def GetDirList(ignore_tree: dict>): list - return ignore_tree.dir -enddef - -export def GetFileList(ignore_tree: dict>): list - return ignore_tree.file -enddef - diff --git a/autoload/utils/cmdbuilder.vim b/autoload/utils/cmdbuilder.vim new file mode 100644 index 0000000..db02e94 --- /dev/null +++ b/autoload/utils/cmdbuilder.vim @@ -0,0 +1,73 @@ +vim9script + +var file_ignore = ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', '*.core', + '*.swn', '*.swp'] +var dir_ignore = ['.git', '.hg', '.svn', '.rebar', '.eunit'] + +if exists('g:fuzzyy_files_ignore_file') + && type(g:fuzzyy_files_ignore_files) == v:t_list + file_ignore = g:fuzzyy_files_ignore_file +endif + +if exists('g:fuzzyy_files_ignore_dir') + && type(g:fuzzyy_files_ignore_files) == v:t_list + dir_ignore = g:fuzzyy_files_ignore_dir +endif + +var Append = (buf, char) => buf .. char + +export def Build_fd(): string + var dir_list_parsed = reduce(dir_ignore, + (acc, dir) => acc .. "-E " .. dir .. " ", "") + + var file_list_parsed = reduce(file_ignore, + (acc, file) => acc .. "-E " .. file .. " ", "") + + var result = "fd --type f -H -I " .. dir_list_parsed .. file_list_parsed + + return result +enddef + +export def Build_find(): string + var file_list_parsed = reduce(file_ignore, + (acc, file) => acc .. "-not -name " .. file .. " ", "") + + var ParseDir = (dir): string => "*/" .. dir .. "/*" + var dir_list_parsed = reduce(dir_ignore, (acc, dir) => acc .. "-path " + .. ParseDir(dir) .. " -prune -o ", "") + ->trim("-o ", 2) + ->Append(" ") + dir_list_parsed = "\\( " .. dir_list_parsed .. "\\) " + + var result = "find " .. dir_list_parsed .. "-o " .. file_list_parsed + .. "-type f -print " + + return result +enddef + +# GCI doc isn't clear. Get-ChildItem -Recurse -Exclude only matches exclusion +# on the leaf, not the parent path. +# +# Link: +# https://stackoverflow.com/questions/15294836/how-can-i-exclude-multiple-folders-using-get-childitem-exclude#:~:text=The%20documentation%20isn%27t%20clear%20on%20this%2C%20but%20Get%2DChildItem%20%2DRecurse%20%2DExclude%20only%20matches%20exclusion%20on%20the%20leaf%20(Split%2DPath%20%24_.FullName%20%2DLeaf)%2C%20not%20the%20parent%20path%20(Split%2DPath%20%24_.FullName%20%2DParent). +# +# That's why module builds GCI cmd and piping it into Where-filter +export def Build_gci(): string + var TransformDir = (dir) => "'" .. dir .. "\\*" .. "'" + var build_dir_filter = reduce(dir_ignore, (acc, dir) => acc + .. "$_ -notlike " .. TransformDir(dir) .. " -and ", "") + -> trim(" -and ", 2) + -> Append(" ") + + var TransformFile = (file) => "'" .. file .. "'" + var build_file_filter = reduce(file_ignore, (acc, file) => acc + .. "$_ -notlike " .. TransformFile(file) .. " -and ", "") + -> trim(" -and ", 2) + -> Append(" ") + + var build_filter = "Where-Object { " .. build_dir_filter .. "-and " + .. build_file_filter .. "} " + var cmd = "Get-ChildItem . -Name -File -Recurse | " .. build_filter + + return "powershell -command " .. '"' .. cmd .. '"' +enddef diff --git a/autoload/test/fuzzyy_test.vim b/test/fuzzyy_test.vim similarity index 100% rename from autoload/test/fuzzyy_test.vim rename to test/fuzzyy_test.vim From e6cc7f797eda7d4129193d24522e99d2eb408c57 Mon Sep 17 00:00:00 2001 From: Donald T Date: Fri, 23 Aug 2024 10:57:24 +0800 Subject: [PATCH 4/9] fix find builder not working --- autoload/utils/cmdbuilder.vim | 21 ++--- test/fuzzyy_test.vim | 161 ---------------------------------- 2 files changed, 11 insertions(+), 171 deletions(-) delete mode 100644 test/fuzzyy_test.vim diff --git a/autoload/utils/cmdbuilder.vim b/autoload/utils/cmdbuilder.vim index db02e94..df2f898 100644 --- a/autoload/utils/cmdbuilder.vim +++ b/autoload/utils/cmdbuilder.vim @@ -5,12 +5,12 @@ var file_ignore = ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', '*.core', var dir_ignore = ['.git', '.hg', '.svn', '.rebar', '.eunit'] if exists('g:fuzzyy_files_ignore_file') - && type(g:fuzzyy_files_ignore_files) == v:t_list + && type(g:fuzzyy_files_ignore_file) == v:t_list file_ignore = g:fuzzyy_files_ignore_file endif if exists('g:fuzzyy_files_ignore_dir') - && type(g:fuzzyy_files_ignore_files) == v:t_list + && type(g:fuzzyy_files_ignore_dir) == v:t_list dir_ignore = g:fuzzyy_files_ignore_dir endif @@ -33,14 +33,15 @@ export def Build_find(): string (acc, file) => acc .. "-not -name " .. file .. " ", "") var ParseDir = (dir): string => "*/" .. dir .. "/*" - var dir_list_parsed = reduce(dir_ignore, (acc, dir) => acc .. "-path " - .. ParseDir(dir) .. " -prune -o ", "") - ->trim("-o ", 2) - ->Append(" ") - dir_list_parsed = "\\( " .. dir_list_parsed .. "\\) " - - var result = "find " .. dir_list_parsed .. "-o " .. file_list_parsed - .. "-type f -print " + var dir_list_parsed = "" + if len(dir_ignore) > 0 + dir_list_parsed = reduce(dir_ignore, (acc, dir) => acc .. "-not -path " .. ParseDir(dir) .. " ", " ") + endif + var result = "find . " .. dir_list_parsed + if len(file_ignore) > 0 + result ..= reduce(file_ignore, (acc, file) => acc .. "-not -name " .. file .. " ", " ") + endif + result ..= "-type f -print " return result enddef diff --git a/test/fuzzyy_test.vim b/test/fuzzyy_test.vim deleted file mode 100644 index 1e48184..0000000 --- a/test/fuzzyy_test.vim +++ /dev/null @@ -1,161 +0,0 @@ -vim9script - -import autoload 'ignore_tree/ignore_tree.vim' -import autoload 'ignore_tree/find_builder.vim' -import autoload 'ignore_tree/fd_builder.vim' -import autoload 'ignore_tree/gci_builder.vim' - -def Setup1(): dict - var FileTMP = tempname() - var DirTMP = substitute(FileTMP, "/[^/]*$", "/", "") - var DirIgnored = ".git/" - var File = "good.txt" - var FileIgnored = "bad.beam" - - mkdir(DirTMP, 'p') - var CWDOld = getcwd() - chdir(DirTMP) - - mkdir(DirIgnored, 'p') - writefile(["foo"], DirIgnored .. "/" .. File, "") - writefile(["foo"], DirIgnored .. "/" .. FileIgnored, "") - writefile(["foo"], DirTMP .. "/" .. File, "") - writefile(["foo"], DirTMP .. "/" .. FileIgnored, "") - - var Conf = { - dir_tmp: DirTMP, - dir_ignored: DirIgnored, - file: File, - file_ignored: FileIgnored, - cwd_old: CWDOld - } - - return Conf -enddef - -def Cleanup1(conf: dict): void - chdir(conf.cwd_old) - delete(conf.dir_tmp, "rf") -enddef - -def Case1(conf: dict): void - if has("win32") || has("win64") - echo "skipped, wrong OS:windows" - return - endif - - # INIT - var CMD = find_builder.Build(ignore_tree.MakeIgnoreTree()) - - # ACT - var FileList = systemlist(CMD) - - # ASSERT - if index(FileList, "./" .. conf.file) == -1 - throw "file " .. conf.file .. " not found" - endif - - if index(FileList, "./" .. conf.file_ignored) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - if index(FileList, conf.dir_ignored .. conf.file) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - if index(FileList, conf.dir_ignored .. conf.file_ignored) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - # TERMINATE - -enddef - -def Case2(conf: dict): void - if has("win32") || has("win64") - echo "skipped, wrong OS:windows" - return - endif - - # INIT - var CMD = fd_builder.Build(ignore_tree.MakeIgnoreTree()) - - # ACT - var FileList = systemlist(CMD) - - # ASSERT - if index(FileList, conf.file) == -1 - throw "file " .. conf.file .. " not found" - endif - - if index(FileList, conf.file_ignored) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - if index(FileList, conf.dir_ignored .. conf.file) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - if index(FileList, conf.dir_ignored .. conf.file_ignored) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - # TERMINATE - -enddef - -def Case3(conf: dict): void - if !has("win32") && !has("win64") - echo "skipped, not windows" - return - endif - - # INIT - var CMD = gci_builder.Build(ignore_tree.MakeIgnoreTree()) - - # ACT - var FileList = system(CMD)->split('\n') - - # ASSERT - if index(FileList, conf.file) == -1 - throw "file " .. conf.file .. " not found" - endif - - if index(FileList, conf.file_ignored) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - if index(FileList, conf.dir_ignored .. conf.file) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - if index(FileList, conf.dir_ignored .. conf.file_ignored) != -1 - throw "file " .. conf.file_ignored .. " found" - endif - - # TERMINATE - -enddef - -def RunCaseFun(SetupFun: func(): any, CleanupFun: func(any): void, CaseName: string, CaseFun: func(any): void): void - var Conf = SetupFun() - try - CaseFun(Conf) - catch - echom "Catched exception: " .. v:exception .. " in case: " .. CaseName - endtry - CleanupFun(Conf) -enddef - -def Suite1(): void - RunCaseFun(Setup1, Cleanup1, "Case1", Case1) - RunCaseFun(Setup1, Cleanup1, "Case2", Case2) - RunCaseFun(Setup1, Cleanup1, "Case3", Case3) -enddef - -export def Start(): void - Suite1() -enddef - -Start() - From ad8ac68f52f61286dde205f6d0d19303294bbbb6 Mon Sep 17 00:00:00 2001 From: Donald T Date: Fri, 23 Aug 2024 10:57:35 +0800 Subject: [PATCH 5/9] update readme --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 02c594a..8d3aae7 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,7 @@ It ultilizes vim's native matchfuzzypos function and popup window feature. - vim > 9.0 - The maintained version is written in vim9, but it also has a vim8 branch for older vim. -- any of grep, ag or rg -- find or fd +- any of grep, ag or rg for FuzzyGrep command - [vim-devicons](https://github.com/ryanoasis/vim-devicons) (optional) ## Install @@ -106,6 +105,13 @@ let g:enable_fuzzyy_keymaps = 0 " Default to 0 let g:files_respect_gitignore = 1 +" FuzzyFiles will exclude the files/directory in these lists only work when +" g:files_respect_gitignore = 0 +" The following is the default +let g:fuzzyy_files_ignore_file = ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', + '*.core', '*.swn', '*.swp'] +var g:fuzzyy_files_ignore_dir = ['.git', '.hg', '.svn', '.rebar', '.eunit'] + " Change navigation keymaps " The following is the default let g:fuzzyy_keymaps = { @@ -132,9 +138,9 @@ let g:fuzzyy_menu_matched_hl = 'cursearch' " Default to 1 if vim-devicons is installed, 0 otherwise let g:fuzzyy_devicons = 1 -" Enable dropdown theme +" Whether enable dropdown theme " Default to 0 -let g:fuzzyy_dropdown = 1 +let g:fuzzyy_dropdown = 0 " Enable FuzzyMRUFiles command. " If enabled, the MRU list will be recorded into ~/.vim_mru_files in Unix From 16a79b1297849107e260658829f654ecb6ff55d5 Mon Sep 17 00:00:00 2001 From: Donald Tang Date: Fri, 23 Aug 2024 16:35:10 +0800 Subject: [PATCH 6/9] fix gci cmdstr not ignore folder/file correctly --- autoload/utils/cmdbuilder.vim | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/autoload/utils/cmdbuilder.vim b/autoload/utils/cmdbuilder.vim index df2f898..68aeeb2 100644 --- a/autoload/utils/cmdbuilder.vim +++ b/autoload/utils/cmdbuilder.vim @@ -54,21 +54,33 @@ enddef # # That's why module builds GCI cmd and piping it into Where-filter export def Build_gci(): string - var TransformDir = (dir) => "'" .. dir .. "\\*" .. "'" - var build_dir_filter = reduce(dir_ignore, (acc, dir) => acc - .. "$_ -notlike " .. TransformDir(dir) .. " -and ", "") + var build_dir_filter = reduce(dir_ignore, (acc, dir) => acc .. "$_ -notlike '*\\" + .. dir .. "\\*' -and $_ -notlike '" .. dir .. "\\*'" + .. " -and ", "") -> trim(" -and ", 2) -> Append(" ") - var TransformFile = (file) => "'" .. file .. "'" var build_file_filter = reduce(file_ignore, (acc, file) => acc - .. "$_ -notlike " .. TransformFile(file) .. " -and ", "") + .. "$_ -notlike '" .. file .. "' -and ", "") -> trim(" -and ", 2) -> Append(" ") - var build_filter = "Where-Object { " .. build_dir_filter .. "-and " - .. build_file_filter .. "} " - var cmd = "Get-ChildItem . -Name -File -Recurse | " .. build_filter + var build_filter = "| Where-Object { " + if len(dir_ignore) > 0 + build_filter ..= build_dir_filter + endif + if len(dir_ignore) > 0 && len(file_ignore) > 0 + build_filter ..= " -and " + endif + if len(file_ignore) > 0 + build_filter ..= build_file_filter + endif + build_filter ..= "} " + + var cmd = "Get-ChildItem . -Name -Force -File -Recurse " + if len(dir_ignore) > 0 || len(file_ignore) > 0 + cmd ..= build_filter + endif return "powershell -command " .. '"' .. cmd .. '"' enddef From 7434e23699b39743159332548a0d749cdc9614fb Mon Sep 17 00:00:00 2001 From: Donald Tang Date: Fri, 23 Aug 2024 16:41:03 +0800 Subject: [PATCH 7/9] update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d3aae7..39b33e6 100644 --- a/README.md +++ b/README.md @@ -105,8 +105,8 @@ let g:enable_fuzzyy_keymaps = 0 " Default to 0 let g:files_respect_gitignore = 1 -" FuzzyFiles will exclude the files/directory in these lists only work when -" g:files_respect_gitignore = 0 +" FuzzyFiles will exclude the files/directory in these two lists +" only work when g:files_respect_gitignore = 0 " The following is the default let g:fuzzyy_files_ignore_file = ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', '*.core', '*.swn', '*.swp'] From 66b3116770f5fb6eb6ed1670976a4a07bec374f2 Mon Sep 17 00:00:00 2001 From: Donald Tang Date: Sat, 24 Aug 2024 00:05:57 +0800 Subject: [PATCH 8/9] move option to cmdbuilder --- autoload/fuzzy/files.vim | 69 +--------------------------------- autoload/utils/cmdbuilder.vim | 70 +++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 68 deletions(-) diff --git a/autoload/fuzzy/files.vim b/autoload/fuzzy/files.vim index c18d812..9c1d76d 100644 --- a/autoload/fuzzy/files.vim +++ b/autoload/fuzzy/files.vim @@ -15,56 +15,9 @@ var jid: job var menu_wid: number var files_update_tid: number var cache: dict -var cmdstr: string var matched_hl_offset = 0 var devicon_char_width = devicons.GetDeviconCharWidth() -var commands: dict -var has_git = executable('git') ? v:true : v:false - -def InsideGitRepo(): bool - if has_git - return stridx(system('git rev-parse --is-inside-work-tree'), 'true') == 0 - else - echom 'fuzzyy: git is not installed' - return v:false - endif -enddef - -if executable('fd') - commands = { - 'default': cmdbuilder.Build_fd(), - 'gitignore': 'fd --type f -H -E .git' - } -else - if has('win32') - commands = { - 'default': cmdbuilder.Build_gci() - } - else - commands = { - 'default': cmdbuilder.Build_find() - } - endif - # TODO bugs - if has_git && InsideGitRepo() - commands.gitignore = 'git ls-files --cached --other --exclude-standard --full-name .' - else - commands.gitignore = v:null - endif -endif - -if has_git - commands.only_git_files = 'git ls-files' -endif - -def GetOrDefault(name: string, default: any): any - if exists(name) - return eval(name) - endif - return default -enddef - var enable_devicons = exists('g:fuzzyy_devicons') && exists('g:WebDevIconsGetFileTypeSymbol') ? g:fuzzyy_devicons : exists('g:WebDevIconsGetFileTypeSymbol') if enable_devicons @@ -72,26 +25,7 @@ if enable_devicons matched_hl_offset = devicons.GetDeviconWidth() + 1 endif -# options -var respect_gitignore = GetOrDefault('g:files_respect_gitignore', 0) -var only_git_files = GetOrDefault('g:files_only_git_files', 0) - -def InitConfig() - cmdstr = '' - if only_git_files - && commands.only_git_files != v:null - && InsideGitRepo() - cmdstr = commands.only_git_files - elseif respect_gitignore - && commands.gitignore != v:null - && InsideGitRepo() - cmdstr = commands.gitignore - else - cmdstr = commands.default - endif -enddef - -InitConfig() +var cmdstr = cmdbuilder.Build() def ProcessResult(list_raw: list, ...args: list): list var limit = -1 @@ -280,7 +214,6 @@ export def Start(windows: dict, ...args: list) else cmd = cmdstr endif - echom cmd FilesJobStart(cwd, cmd) menu_wid = wids.menu timer_start(50, function('FilesUpdateMenu')) diff --git a/autoload/utils/cmdbuilder.vim b/autoload/utils/cmdbuilder.vim index 68aeeb2..5a6c18a 100644 --- a/autoload/utils/cmdbuilder.vim +++ b/autoload/utils/cmdbuilder.vim @@ -4,6 +4,15 @@ var file_ignore = ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', '*.core', '*.swn', '*.swp'] var dir_ignore = ['.git', '.hg', '.svn', '.rebar', '.eunit'] +var respect_gitignore = 0 +var only_git_files = 0 +if exists('g:files_respect_gitignore') + respect_gitignore = g:files_respect_gitignore +endif +if exists('g:files_only_git_files') + only_git_files = g:files_only_git_files +endif + if exists('g:fuzzyy_files_ignore_file') && type(g:fuzzyy_files_ignore_file) == v:t_list file_ignore = g:fuzzyy_files_ignore_file @@ -16,7 +25,21 @@ endif var Append = (buf, char) => buf .. char +var has_git = executable('git') ? v:true : v:false + +def InsideGitRepo(): bool + if has_git + return stridx(system('git rev-parse --is-inside-work-tree'), 'true') == 0 + else + echom 'fuzzyy: git is not installed' + return v:false + endif +enddef + export def Build_fd(): string + if respect_gitignore + return 'fd --type f -H -E .git' + endif var dir_list_parsed = reduce(dir_ignore, (acc, dir) => acc .. "-E " .. dir .. " ", "") @@ -84,3 +107,50 @@ export def Build_gci(): string return "powershell -command " .. '"' .. cmd .. '"' enddef + +export def Build_git_ls_files(): string +enddef + +def RespectGitignore(): string + var cmdstr = '' + if executable('fd') + cmdstr = Build_fd() + elseif has_git && InsideGitRepo() + cmdstr = 'git ls-files --cached --other --exclude-standard --full-name .' + endif + return cmdstr +enddef + +def OnlyGitFile(): string + var cmdstr = '' + if has_git && InsideGitRepo() + cmdstr = 'git ls-files' + endif + return cmdstr +enddef + +export def Build(): string + var cmdstr = '' + if only_git_files + cmdstr = OnlyGitFile() + if cmdstr != '' + return cmdstr + endif + endif + if respect_gitignore + cmdstr = RespectGitignore() + if cmdstr != '' + return cmdstr + endif + endif + if executable('fd') #fd is cross-platform + cmdstr = Build_fd() + else + if has('win32') + cmdstr = Build_gci() + else + cmdstr = Build_find() + endif + endif + return cmdstr +enddef From e15aca5286198a33c2e98c1e682e1a3228bf8e58 Mon Sep 17 00:00:00 2001 From: Donald T Date: Sat, 24 Aug 2024 12:17:13 +0800 Subject: [PATCH 9/9] improve code structure --- autoload/utils/cmdbuilder.vim | 41 +++++++++++++---------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/autoload/utils/cmdbuilder.vim b/autoload/utils/cmdbuilder.vim index 5a6c18a..d0274ce 100644 --- a/autoload/utils/cmdbuilder.vim +++ b/autoload/utils/cmdbuilder.vim @@ -1,29 +1,20 @@ vim9script -var file_ignore = ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', '*.core', - '*.swn', '*.swp'] -var dir_ignore = ['.git', '.hg', '.svn', '.rebar', '.eunit'] - -var respect_gitignore = 0 -var only_git_files = 0 -if exists('g:files_respect_gitignore') - respect_gitignore = g:files_respect_gitignore -endif -if exists('g:files_only_git_files') - only_git_files = g:files_only_git_files -endif - -if exists('g:fuzzyy_files_ignore_file') - && type(g:fuzzyy_files_ignore_file) == v:t_list - file_ignore = g:fuzzyy_files_ignore_file -endif - -if exists('g:fuzzyy_files_ignore_dir') - && type(g:fuzzyy_files_ignore_dir) == v:t_list - dir_ignore = g:fuzzyy_files_ignore_dir -endif - -var Append = (buf, char) => buf .. char +var file_ignore_default = ['*.beam', '*.so', '*.exe', '*.dll', '*.dump', + '*.core', '*.swn', '*.swp'] +var dir_ignore_default = ['.git', '.hg', '.svn', '.rebar', '.eunit'] + +# OPTIONS +var respect_gitignore = exists('g:files_respect_gitignore') ? + g:files_respect_gitignore : 0 +var only_git_files = exists('g:files_only_git_files') ? + g:files_only_git_files : 0 +var file_ignore = exists('g:fuzzyy_files_ignore_file') + && type(g:fuzzyy_files_ignore_file) == v:t_list ? + g:fuzzyy_files_ignore_file : file_ignore_default +var dir_ignore = exists('g:fuzzyy_files_ignore_dir') + && type(g:fuzzyy_files_ignore_dir) == v:t_list ? + g:fuzzyy_files_ignore_dir : dir_ignore_default var has_git = executable('git') ? v:true : v:false @@ -81,12 +72,10 @@ export def Build_gci(): string .. dir .. "\\*' -and $_ -notlike '" .. dir .. "\\*'" .. " -and ", "") -> trim(" -and ", 2) - -> Append(" ") var build_file_filter = reduce(file_ignore, (acc, file) => acc .. "$_ -notlike '" .. file .. "' -and ", "") -> trim(" -and ", 2) - -> Append(" ") var build_filter = "| Where-Object { " if len(dir_ignore) > 0