Add TopLevelDirecotry search using DirectoryInfo

This commit is contained in:
Jeremy Wu 2020-05-24 20:14:36 +10:00
parent d839ecab26
commit 6badecb877
5 changed files with 191 additions and 22 deletions

View file

@ -2,6 +2,7 @@ using Flow.Launcher.Plugin;
using Flow.Launcher.Plugin.Explorer;
using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex;
using Flow.Launcher.Plugin.SharedCommands;
using NUnit.Framework;
using System;
using System.Collections.Generic;
@ -16,7 +17,7 @@ namespace Flow.Launcher.Test.Plugins
return new List<Result>();
}
private List<Result> MethodDirectoryInfoClassSearchReturnsTwoResults(string dummyString)
private List<Result> MethodDirectoryInfoClassSearchReturnsTwoResults(Query dummyQuery, string dummyString)
{
return new List<Result>
{
@ -111,7 +112,8 @@ namespace Flow.Launcher.Test.Plugins
MethodWindowsIndexSearchReturnsZeroResults,
MethodDirectoryInfoClassSearchReturnsTwoResults,
MethodIndexExistsReturnsFalse,
"path string not used");
new Query(),
"string not used");
// Then
Assert.IsTrue(results.Count == 2,
@ -130,7 +132,8 @@ namespace Flow.Launcher.Test.Plugins
MethodWindowsIndexSearchReturnsZeroResults,
MethodDirectoryInfoClassSearchReturnsTwoResults,
MethodIndexExistsReturnsTrue,
"path string not used");
new Query(),
"string not used");
// Then
Assert.IsTrue(results.Count == 0,
@ -149,9 +152,7 @@ namespace Flow.Launcher.Test.Plugins
public void WhenGivenQuerySearchString_ThenShouldIndicateIfItIsLocationString(string querySearchString, bool expectedResult)
{
// When, Given
var searchManager = new SearchManager(new Settings(), new PluginInitContext());
var result = searchManager.IsLocationPathString(querySearchString);
var result = FilesFolders.IsLocationPathString(querySearchString);
//Then
Assert.IsTrue(result == expectedResult,

View file

@ -1,4 +1,4 @@
using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Infrastructure.Storage;
using Flow.Launcher.Plugin.Explorer.Search;
using Flow.Launcher.Plugin.Explorer.ViewModels;
using Flow.Launcher.Plugin.Explorer.Views;
@ -42,8 +42,6 @@ namespace Flow.Launcher.Plugin.Explorer
return results;
return new SearchManager(_settings, Context).Search(query);
return new SearchManager(_settings, Context).Search(query.Search);
}
public void Save()

View file

@ -0,0 +1,114 @@
using Flow.Launcher.Infrastructure;
using Flow.Launcher.Plugin.SharedCommands;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
namespace Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo
{
public class DirectoryInfoSearch
{
private PluginInitContext _context;
private Settings _settings;
public DirectoryInfoSearch(Settings settings, PluginInitContext context)
{
_context = context;
_settings = settings;
}
public List<Result> TopLevelDirectorySearch(Query query, string search)
{
var results = new List<Result>();
//var hasSpecial = search.IndexOfAny(_specialSearchChars) >= 0;
string incompleteName = "";
//if (hasSpecial || !Directory.Exists(search + "\\"))
if (!FilesFolders.LocationExists(search + "\\"))
{
// if folder doesn't exist, we want to take the last part and use it afterwards to help the user
// find the right folder.
int index = search.LastIndexOf('\\');
if (index > 0 && index < (search.Length - 1))
{
incompleteName = search.Substring(index + 1).ToLower();
search = search.Substring(0, index + 1);
if (!FilesFolders.LocationExists(search))
{
return results;
}
}
else
{
return results;
}
}
else
{
// folder exist, add \ at the end of doesn't exist
if (!search.EndsWith("\\"))
{
search += "\\";
}
}
results.Add(new ResultManager().CreateOpenCurrentFolderResult(incompleteName, search));
var searchOption = SearchOption.TopDirectoryOnly;
incompleteName += "*";
//// give the ability to search all folder when starting with >
//if (incompleteName.StartsWith(">"))
//{
// searchOption = SearchOption.AllDirectories;
// // match everything before and after search term using supported wildcard '*', ie. *searchterm*
// incompleteName = "*" + incompleteName.Substring(1);
//}
var folderList = new List<Result>();
var fileList = new List<Result>();
var folderSubtitleString = Constants.DefaultFolderSubtitleString;
try
{
// search folder and add results
var directoryInfo = new System.IO.DirectoryInfo(search);
var fileSystemInfos = directoryInfo.GetFileSystemInfos(incompleteName, searchOption);
foreach (var fileSystemInfo in fileSystemInfos)
{
if ((fileSystemInfo.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden) continue;
if (fileSystemInfo is System.IO.DirectoryInfo)
{
if (searchOption == SearchOption.AllDirectories)
folderSubtitleString = fileSystemInfo.FullName;
folderList.Add(new ResultManager().CreateFolderResult(fileSystemInfo.Name, folderSubtitleString, fileSystemInfo.FullName, query));
}
else
{
fileList.Add(new ResultManager().CreateFileResult(fileSystemInfo.FullName, query));
}
}
}
catch (Exception e)
{
if (e is UnauthorizedAccessException || e is ArgumentException)
{
results.Add(new Result { Title = e.Message, Score = 501 });
return results;
}
throw;
}
// Intial ordering, this order can be updated later by UpdateResultView.MainViewModel based on history of user selection.
return results.Concat(folderList.OrderBy(x => x.Title)).Concat(fileList.OrderBy(x => x.Title)).ToList(); //<===== MOVE ORDERING OUT
}
}
}

View file

@ -2,6 +2,8 @@
using Flow.Launcher.Plugin.SharedCommands;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
@ -42,6 +44,55 @@ namespace Flow.Launcher.Plugin.Explorer.Search
ContextData = new SearchResult { Type = ResultType.Folder, FullPath = path }
};
}
public Result CreateOpenCurrentFolderResult(string incompleteName, string search)
{
var firstResult = "Open current directory";
if (incompleteName.Length > 0)
firstResult = "Open " + search;
var folderName = search.TrimEnd('\\').Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None).Last();
return new Result
{
Title = firstResult,
SubTitle = $"Use > to search files and subfolders within {folderName}, " +
$"* to search for file extensions in {folderName} or both >* to combine the search",
IcoPath = search,
Score = 500,
Action = c =>
{
FilesFolders.OpenPath(search);
return true;
}
};
}
public Result CreateFileResult(string filePath, Query query)
{
var result = new Result
{
Title = Path.GetFileName(filePath),
SubTitle = filePath,
IcoPath = filePath,
TitleHighlightData = StringMatcher.FuzzySearch(query.Search, Path.GetFileName(filePath)).MatchData,
Action = c =>
{
try
{
FilesFolders.OpenPath(filePath);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Could not start " + filePath);
}
return true;
},
ContextData = new SearchResult { Type = ResultType.File, FullPath = filePath }
};
return result;
}
}
public class SearchResult

View file

@ -1,4 +1,6 @@
using Flow.Launcher.Plugin.Explorer.Search.DirectoryInfo;
using Flow.Launcher.Plugin.Explorer.Search.WindowsIndex;
using Flow.Launcher.Plugin.SharedCommands;
using System;
using System.Collections.Generic;
@ -18,7 +20,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
searcher = new IndexSearcher(_context);
}
public List<Result> Search(string querySearchString)
internal List<Result> Search(Query query)
{
var querySearch = query.Search;
@ -34,33 +36,36 @@ namespace Flow.Launcher.Plugin.Explorer.Search
querySearch = EnvironmentVariables.TranslateEnvironmentVariablePath(querySearch);
}
if (FilesFolders.IsLocationPathString(querySearch))
{
return TopLevelFolderSearchBehaviour(WindowsIndexTopLevelFolderSearch,
DirectoryInfoClassSearch,
WindowsIndexExists,
querySearchString);
query,
querySearch);
}
return WindowsIndexFilesAndFoldersSearch(querySearchString);
return WindowsIndexFilesAndFoldersSearch(querySearch);
}
private List<Result> DirectoryInfoClassSearch(string arg)
private List<Result> DirectoryInfoClassSearch(Query query, string querySearch)
{
throw new NotImplementedException();
}
var directoryInfoSearch = new DirectoryInfoSearch(_settings, _context);
///<summary>
return directoryInfoSearch.TopLevelDirectorySearch(query, querySearch);
}
public List<Result> TopLevelFolderSearchBehaviour(
Func<string, List<Result>> windowsIndexSearch,
Func<string, List<Result>> directoryInfoClassSearch,
Func<Query, string, List<Result>> directoryInfoClassSearch,
Func<string, bool> indexExists,
string path)
Query query,
string querySearchString)
{
var results = windowsIndexSearch(path);
var results = windowsIndexSearch(querySearchString);
if (results.Count == 0 && !indexExists(path))
return directoryInfoClassSearch(path);
if (results.Count == 0 && !indexExists(querySearchString))
return directoryInfoClassSearch(query, querySearchString);
return results;
}
@ -73,7 +78,7 @@ namespace Flow.Launcher.Plugin.Explorer.Search
queryConstructor.CreateQueryHelper().ConnectionString,
queryConstructor.QueryForAllFilesAndFolders);
}
private List<Result> WindowsIndexTopLevelFolderSearch(string path)
{
var queryConstructor = new QueryConstructor(_settings);