diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs
index 838d05dd3..501ce5b22 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingAPI.cs
@@ -101,15 +101,20 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything
///
/// The key word.
/// when cancelled the current search will stop and exit (and would not reset)
+ /// Search Within a parent folder
+ /// Search Within sub folder of the parent folder
/// Sort By
/// The offset.
/// The max count.
///
- public static IEnumerable SearchAsync(string keyword, CancellationToken token, SortOption sortOption = SortOption.NAME_ASCENDING, int offset = 0, int maxCount = 100)
+ public static IEnumerable SearchAsync(string keyword,
+ CancellationToken token,
+ SortOption sortOption = SortOption.NAME_ASCENDING,
+ string parentPath = "",
+ bool recursive = false,
+ int offset = 0,
+ int maxCount = 100)
{
- if (string.IsNullOrEmpty(keyword))
- throw new ArgumentNullException(nameof(keyword));
-
if (offset < 0)
throw new ArgumentOutOfRangeException(nameof(offset));
@@ -124,6 +129,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything
keyword = keyword[1..];
}
+ if (!string.IsNullOrEmpty(parentPath))
+ {
+ keyword += $" {(recursive ? "" : "parent:")}\"{parentPath}\"";
+ }
+
EverythingApiDllImport.Everything_SetSearchW(keyword);
EverythingApiDllImport.Everything_SetOffset(offset);
EverythingApiDllImport.Everything_SetMax(maxCount);
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs
index e1486f9fb..14069f678 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/Everything/EverythingSearchManager.cs
@@ -5,7 +5,7 @@ using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search.Everything
{
- public class EverythingSearchManager : IIndexProvider
+ public class EverythingSearchManager : IIndexProvider, IContentIndexProvider, IPathEnumerable
{
private Settings Settings { get; }
@@ -15,13 +15,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.Everything
}
- public ValueTask> SearchAsync(Query query, CancellationToken token)
+ public ValueTask> SearchAsync(string search, CancellationToken token)
{
- return ValueTask.FromResult(EverythingApi.SearchAsync(query.Search, token, Settings.SortOption));
+ return ValueTask.FromResult(EverythingApi.SearchAsync(search, token, Settings.SortOption));
}
- public ValueTask> ContentSearchAsync(Query query, CancellationToken token)
+ public ValueTask> ContentSearchAsync(string search, CancellationToken token)
{
return new ValueTask>(new List());
}
+ public ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token)
+ {
+ return new ValueTask>(
+ EverythingApi.SearchAsync("", token, Settings.SortOption, path, recursive));
+ }
}
}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs
new file mode 100644
index 000000000..b2142357e
--- /dev/null
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IContentIndexProvider.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Flow.Launcher.Plugin.Explorer.Search
+{
+ public interface IContentIndexProvider
+ {
+ public ValueTask> ContentSearchAsync(string search, CancellationToken token);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IIndexProvider.cs
new file mode 100644
index 000000000..be40b6a24
--- /dev/null
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IIndexProvider.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Flow.Launcher.Plugin.Explorer.Search
+{
+ public interface IIndexProvider
+ {
+ public ValueTask> SearchAsync(string search, CancellationToken token);
+ }
+}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs
index d7f0a8ec8..eb82422f4 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/IPathEnumerable.cs
@@ -1,9 +1,12 @@
-using System.Collections.Generic;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search
{
public interface IPathEnumerable
{
- public IEnumerable Enumerate(string path, bool recursive);
+ public ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token);
}
}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
index 080621f42..93707dcf2 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs
@@ -61,11 +61,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search
if (IsFileContentSearch(query.ActionKeyword))
{
- searchResults = await Settings.IndexProvider.ContentSearchAsync(query, token);
+ searchResults = await Settings.ContentIndexProvider.ContentSearchAsync(query.Search, token);
}
else
{
- searchResults = await Settings.IndexProvider.SearchAsync(query, token);
+ searchResults = await Settings.IndexProvider.SearchAsync(query.Search, token);
}
if (ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) ||
@@ -120,12 +120,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search
var isEnvironmentVariablePath = querySearch[1..].Contains("%\\");
var locationPath = querySearch;
-
+
if (isEnvironmentVariablePath)
locationPath = EnvironmentVariables.TranslateEnvironmentVariablePath(locationPath);
// Check that actual location exists, otherwise directory search will throw directory not found exception
- if (!FilesFolders.LocationExists(FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath)))
+ if (!FilesFolders.ReturnPreviousDirectoryIfIncompleteString(locationPath).LocationExists())
return results.ToList();
var useIndexSearch = UseWindowsIndexForDirectorySearch(locationPath);
@@ -134,16 +134,24 @@ namespace Flow.Launcher.Plugin.Explorer.Search
token.ThrowIfCancellationRequested();
- // var directoryResult = await TopLevelDirectorySearchBehaviourAsync(WindowsIndexTopLevelFolderSearchAsync,
- // DirectoryInfoClassSearch,
- // useIndexSearch,
- // query,
- // locationPath,
- // token).ConfigureAwait(false);
+ IEnumerable directoryResult;
+
+ if (query.Search.Contains('>'))
+ {
+ directoryResult =
+ await Settings.PathEnumerator.EnumerateAsync(locationPath, "", false, token)
+ .ConfigureAwait(false);
+ }
+ else
+ {
+ directoryResult = DirectoryInfoSearch.TopLevelDirectorySearch(query, query.Search, token);
+ }
+
+
token.ThrowIfCancellationRequested();
- // results.UnionWith(directoryResult);
+ results.UnionWith(directoryResult.Select(searchResult => ResultManager.CreateResult(query, searchResult)));
return results.ToList();
}
@@ -153,10 +161,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search
return actionKeyword == Settings.FileContentSearchActionKeyword;
}
- private List DirectoryInfoClassSearch(Query query, string querySearch, CancellationToken token)
- {
- return DirectoryInfoSearch.TopLevelDirectorySearch(query, querySearch, token);
- }
public async Task> TopLevelDirectorySearchBehaviourAsync(
Func>> windowsIndexSearch,
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs
deleted file mode 100644
index e42d78f9a..000000000
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/IIndexProvider.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
-{
- public interface IIndexProvider
- {
- public ValueTask> SearchAsync(Query query, CancellationToken token);
- public ValueTask> ContentSearchAsync(Query query, CancellationToken token);
- }
-}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs
index 28e9c0e71..7eb9f06f3 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndex.cs
@@ -19,7 +19,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
// Reserved keywords in oleDB
private const string ReservedStringPattern = @"^[`\@\#\^,\&\/\\\$\%_;\[\]]+$";
- private static async Task> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, Query query, CancellationToken token)
+ private static async Task> ExecuteWindowsIndexSearchAsync(string indexQueryString, string connectionString, CancellationToken token)
{
var results = new List();
@@ -82,7 +82,6 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
Func createQueryHelper,
Func constructQuery,
List exclusionList,
- Query query,
CancellationToken token)
{
var regexMatch = Regex.Match(searchString, ReservedStringPattern);
@@ -93,40 +92,18 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
var constructedQuery = constructQuery(searchString);
return
- await ExecuteWindowsIndexSearchAsync(constructedQuery, createQueryHelper().ConnectionString, query, token);
+ await ExecuteWindowsIndexSearchAsync(constructedQuery, createQueryHelper().ConnectionString, token);
}
- private static List RemoveResultsInExclusionList(List results, List exclusionList, CancellationToken token)
+ private static void RemoveResultsInExclusionList(List results, IReadOnlyList exclusionList, CancellationToken token)
{
var indexExclusionListCount = exclusionList.Count;
if (indexExclusionListCount == 0)
- return results;
-
- var filteredResults = new List();
-
- for (var index = 0; index < results.Count; index++)
- {
- token.ThrowIfCancellationRequested();
-
- var excludeResult = false;
-
- for (var i = 0; i < indexExclusionListCount; i++)
- {
- token.ThrowIfCancellationRequested();
-
- if (results[index].SubTitle.StartsWith(exclusionList[i].Path, StringComparison.OrdinalIgnoreCase))
- {
- excludeResult = true;
- break;
- }
- }
-
- if (!excludeResult)
- filteredResults.Add(results[index]);
- }
-
- return filteredResults;
+ return;
+ results.RemoveAll(searchResult =>
+ exclusionList.Any(exclude => searchResult.FullPath.StartsWith(exclude.Path, StringComparison.OrdinalIgnoreCase))
+ );
}
internal static bool PathIsIndexed(string path)
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
similarity index 64%
rename from Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs
rename to Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
index 72f5e9cb1..1e64c54f6 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexManager.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Search/WindowsIndex/WindowsIndexSearchManager.cs
@@ -4,18 +4,18 @@ using System.Threading.Tasks;
namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
{
- public class WindowsIndexManager : IIndexProvider
+ public class WindowsIndexSearchManager : IIndexProvider, IContentIndexProvider, IPathEnumerable
{
private Settings Settings { get; }
private QueryConstructor QueryConstructor { get; }
- public WindowsIndexManager(Settings settings)
+ public WindowsIndexSearchManager(Settings settings)
{
Settings = settings;
QueryConstructor = new QueryConstructor(Settings);
}
- private async Task> WindowsIndexFileContentSearchAsync(Query query, string querySearchString,
+ private async Task> WindowsIndexFileContentSearchAsync(string querySearchString,
CancellationToken token)
{
if (string.IsNullOrEmpty(querySearchString))
@@ -26,13 +26,12 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
QueryConstructor.CreateQueryHelper,
QueryConstructor.QueryForFileContentSearch,
Settings.IndexSearchExcludedSubdirectoryPaths,
- query,
token).ConfigureAwait(false);
}
- private async Task> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString,
+ private async Task> WindowsIndexFilesAndFoldersSearchAsync(string querySearchString,
CancellationToken token)
{
return await WindowsIndex.WindowsIndexSearchAsync(
@@ -40,12 +39,11 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
QueryConstructor.CreateQueryHelper,
QueryConstructor.QueryForAllFilesAndFolders,
Settings.IndexSearchExcludedSubdirectoryPaths,
- query,
token).ConfigureAwait(false);
}
- private async Task> WindowsIndexTopLevelFolderSearchAsync(Query query, string path,
+ private async Task> WindowsIndexTopLevelFolderSearchAsync(string path,string search,
CancellationToken token)
{
var queryConstructor = new QueryConstructor(Settings);
@@ -55,16 +53,21 @@ namespace Flow.Launcher.Plugin.Explorer.Search.WindowsIndex
queryConstructor.CreateQueryHelper,
queryConstructor.QueryForTopLevelDirectorySearch,
Settings.IndexSearchExcludedSubdirectoryPaths,
- query,
token).ConfigureAwait(false);
}
- public ValueTask> SearchAsync(Query query, CancellationToken token)
+ public async ValueTask> SearchAsync(string search, CancellationToken token)
{
- return default;
+ return await WindowsIndexFilesAndFoldersSearchAsync(search, token);
}
- public ValueTask> ContentSearchAsync(Query query, CancellationToken token)
+ public async ValueTask> ContentSearchAsync(string search, CancellationToken token)
{
- return default;
+ return await WindowsIndexFileContentSearchAsync(search, token);
+ }
+ public async ValueTask> EnumerateAsync(string path, string search, bool recursive, CancellationToken token)
+ {
+ if(recursive)
+ return await WindowsIndexFilesAndFoldersSearchAsync(search, token).ConfigureAwait(false);
+ return await WindowsIndexTopLevelFolderSearchAsync(path, search, token);
}
}
}
\ No newline at end of file
diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
index f3ce8abc5..d9d2a788f 100644
--- a/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
+++ b/Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs
@@ -6,6 +6,7 @@ using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Text.Json.Serialization;
namespace Flow.Launcher.Plugin.Explorer
{
@@ -44,18 +45,44 @@ namespace Flow.Launcher.Plugin.Explorer
public bool WarnWindowsSearchServiceOff { get; set; } = true;
- private List _indexProviders;
+ private IReadOnlyList _indexProviders;
+ private IReadOnlyList _fileContentIndexProviders;
+ private IReadOnlyList _pathEnumerables;
public Settings()
{
+ var everythingManager = new EverythingSearchManager(this);
+ var windowsIndexManager = new WindowsIndexSearchManager(this);
+
_indexProviders = new List()
{
- new EverythingSearchManager(this),
- new WindowsIndexManager(this)
+ everythingManager,
+ windowsIndexManager
+ };
+
+ _pathEnumerables = new List()
+ {
+ everythingManager,
+ windowsIndexManager
+ };
+
+ _fileContentIndexProviders = new List
+ {
+ windowsIndexManager, everythingManager
};
}
+
public IndexSearchEngineOption IndexSearchEngine { get; set; }
+ [JsonIgnore]
public IIndexProvider IndexProvider => _indexProviders[(int)IndexSearchEngine];
+
+ public PathTraversalEngineOption PathEnumerationEngine { get; set; }
+ [JsonIgnore]
+ public IPathEnumerable PathEnumerator => _pathEnumerables[(int)PathEnumerationEngine];
+ public ContentIndexSearchEngineOption ContentSearchEngine { get; set; }
+ [JsonIgnore]
+ public IContentIndexProvider ContentIndexProvider => _fileContentIndexProviders[(int)ContentSearchEngine];
+
public enum PathTraversalEngineOption
{
Everything,
@@ -68,11 +95,17 @@ namespace Flow.Launcher.Plugin.Explorer
Everything,
WindowsIndex
}
- #region Everything Settings
-
+
+ public enum ContentIndexSearchEngineOption
+ {
+ Everything,
+ WindowsIndex
+ }
public bool LaunchHidden { get; set; } = false;
+ #region Everything Settings
+
public string EverythingInstalledPath { get; set; }
public SortOption[] SortOptions { get; set; } = Enum.GetValues();