Skip to content

Commit ad36f89

Browse files
authored
Merge pull request #449 from Flow-Launcher/ExplorerPathActionkeyword
Add specific keyword for path explore in explorer plugin
2 parents 6868544 + c842a4c commit ad36f89

File tree

15 files changed

+307
-158
lines changed

15 files changed

+307
-158
lines changed

Flow.Launcher.Core/Plugin/PluginManager.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ public static List<Result> GetContextMenusForPlugin(Result result)
252252

253253
public static bool ActionKeywordRegistered(string actionKeyword)
254254
{
255+
// this method is only checking for action keywords (defined as not '*') registration
256+
// hence the actionKeyword != Query.GlobalPluginWildcardSign logic
255257
return actionKeyword != Query.GlobalPluginWildcardSign
256258
&& NonGlobalPlugins.ContainsKey(actionKeyword);
257259
}
@@ -276,7 +278,7 @@ public static void AddActionKeyword(string id, string newActionKeyword)
276278
}
277279

278280
/// <summary>
279-
/// used to add action keyword for multiple action keyword plugin
281+
/// used to remove action keyword for multiple action keyword plugin
280282
/// e.g. web search
281283
/// </summary>
282284
public static void RemoveActionKeyword(string id, string oldActionkeyword)

Flow.Launcher.Infrastructure/UserSettings/PluginSettings.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ public void UpdatePluginSettings(List<PluginMetadata> metadatas)
1616
{
1717
var settings = Plugins[metadata.ID];
1818

19-
// TODO: Remove. This is one off for 1.2.0 release.
20-
// Introduced a new action keyword in Explorer, so need to update plugin setting in the UserData folder.
21-
// This kind of plugin meta update should be handled by a dedicated method trigger by version bump.
19+
// TODO: Remove. This is backwards compatibility for 1.8.0 release.
20+
// Introduced two new action keywords in Explorer, so need to update plugin setting in the UserData folder.
2221
if (metadata.ID == "572be03c74c642baae319fc283e561a8" && metadata.ActionKeywords.Count != settings.ActionKeywords.Count)
23-
settings.ActionKeywords = metadata.ActionKeywords;
22+
{
23+
settings.ActionKeywords.Add(Query.GlobalPluginWildcardSign); // for index search
24+
settings.ActionKeywords.Add(Query.GlobalPluginWildcardSign); // for path search
25+
}
2426

2527
if (string.IsNullOrEmpty(settings.Version))
2628
settings.Version = metadata.Version;

Flow.Launcher/ViewModel/MainViewModel.cs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -547,26 +547,9 @@ async Task QueryTask(PluginPair plugin)
547547

548548
private void RemoveOldQueryResults(Query query)
549549
{
550-
string lastKeyword = _lastQuery.ActionKeyword;
551-
552-
string keyword = query.ActionKeyword;
553-
if (string.IsNullOrEmpty(lastKeyword))
554-
{
555-
if (!string.IsNullOrEmpty(keyword))
556-
{
557-
Results.KeepResultsFor(PluginManager.NonGlobalPlugins[keyword].Metadata);
558-
}
559-
}
560-
else
550+
if (_lastQuery.ActionKeyword != query.ActionKeyword)
561551
{
562-
if (string.IsNullOrEmpty(keyword))
563-
{
564-
Results.KeepResultsExcept(PluginManager.NonGlobalPlugins[lastKeyword].Metadata);
565-
}
566-
else if (lastKeyword != keyword)
567-
{
568-
Results.KeepResultsFor(PluginManager.NonGlobalPlugins[keyword].Metadata);
569-
}
552+
Results.Clear();
570553
}
571554
}
572555

Plugins/Flow.Launcher.Plugin.Explorer/Languages/en.xaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@
1919
<system:String x:Key="plugin_explorer_quickaccesslinks_header">Quick Access Links</system:String>
2020
<system:String x:Key="plugin_explorer_indexsearchexcludedpaths_header">Index Search Excluded Paths</system:String>
2121
<system:String x:Key="plugin_explorer_manageindexoptions">Indexing Options</system:String>
22-
<system:String x:Key="plugin_explorer_actionkeywordview_search">Search Activation:</system:String>
22+
<system:String x:Key="plugin_explorer_actionkeywordview_search">Search:</system:String>
23+
<system:String x:Key="plugin_explorer_actionkeywordview_pathsearch">Path Search:</system:String>
2324
<system:String x:Key="plugin_explorer_actionkeywordview_filecontentsearch">File Content Search:</system:String>
25+
<system:String x:Key="plugin_explorer_actionkeywordview_indexsearch">Index Search:</system:String>
26+
<system:String x:Key="plugin_explorer_actionkeyword_current">Current Action Keyword:</system:String>
27+
<system:String x:Key="plugin_explorer_actionkeyword_done">Done</system:String>
28+
<system:String x:Key="plugin_explorer_actionkeyword_enabled">Enabled</system:String>
29+
<system:String x:Key="plugin_explorer_actionkeyword_enabled_tooltip">When disabled Flow will not execute this search option, and will additionally revert back to '*' to free up the action keyword</system:String>
2430

2531
<!--Plugin Infos-->
2632
<system:String x:Key="plugin_explorer_plugin_name">Explorer</system:String>

Plugins/Flow.Launcher.Plugin.Explorer/Languages/zh-cn.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
<system:String x:Key="plugin_explorer_indexsearchexcludedpaths_header">索引搜索排除的路径</system:String>
2121
<system:String x:Key="plugin_explorer_manageindexoptions">索引选项</system:String>
2222
<system:String x:Key="plugin_explorer_actionkeywordview_search">搜索激活:</system:String>
23+
<system:String x:Key="plugin_explorer_actionkeywordview_pathsearch">路径搜索激活:</system:String>
2324
<system:String x:Key="plugin_explorer_actionkeywordview_filecontentsearch">文件内容搜索:</system:String>
2425

2526
<!--Plugin Infos-->

Plugins/Flow.Launcher.Plugin.Explorer/Main.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public Control CreateSettingPanel()
2828
return new ExplorerSettings(viewModel);
2929
}
3030

31-
public async Task InitAsync(PluginInitContext context)
31+
public Task InitAsync(PluginInitContext context)
3232
{
3333
Context = context;
3434

@@ -47,6 +47,8 @@ public async Task InitAsync(PluginInitContext context)
4747
contextMenu = new ContextMenu(Context, Settings, viewModel);
4848
searchManager = new SearchManager(Settings, Context);
4949
ResultManager.Init(Context);
50+
51+
return Task.CompletedTask;
5052
}
5153

5254
public List<Result> LoadContextMenus(Result selectedResult)

Plugins/Flow.Launcher.Plugin.Explorer/Search/EnvironmentVariables.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ public static class EnvironmentVariables
1010
{
1111
internal static bool IsEnvironmentVariableSearch(string search)
1212
{
13-
return LoadEnvironmentStringPaths().Count > 0
14-
&& search.StartsWith("%")
13+
return search.StartsWith("%")
1514
&& search != "%%"
16-
&& !search.Contains("\\");
15+
&& !search.Contains("\\") &&
16+
LoadEnvironmentStringPaths().Count > 0;
1717
}
1818

1919
internal static Dictionary<string, string> LoadEnvironmentStringPaths()

Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ private class PathEqualityComparator : IEqualityComparer<Result>
2626
{
2727
private static PathEqualityComparator instance;
2828
public static PathEqualityComparator Instance => instance ??= new PathEqualityComparator();
29+
2930
public bool Equals(Result x, Result y)
3031
{
3132
return x.SubTitle == y.SubTitle;
@@ -39,21 +40,61 @@ public int GetHashCode(Result obj)
3940

4041
internal async Task<List<Result>> SearchAsync(Query query, CancellationToken token)
4142
{
42-
var results = new HashSet<Result>(PathEqualityComparator.Instance);
43-
4443
var querySearch = query.Search;
4544

4645
if (IsFileContentSearch(query.ActionKeyword))
4746
return await WindowsIndexFileContentSearchAsync(query, querySearch, token).ConfigureAwait(false);
4847

48+
var result = new HashSet<Result>(PathEqualityComparator.Instance);
49+
50+
if (ActionKeywordMatch(query, Settings.ActionKeyword.PathSearchActionKeyword) ||
51+
ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword))
52+
{
53+
result.UnionWith(await PathSearchAsync(query, token).ConfigureAwait(false));
54+
}
55+
56+
if ((ActionKeywordMatch(query, Settings.ActionKeyword.IndexSearchActionKeyword) ||
57+
ActionKeywordMatch(query, Settings.ActionKeyword.SearchActionKeyword)) &&
58+
querySearch.Length > 0 &&
59+
!querySearch.IsLocationPathString())
60+
{
61+
result.UnionWith(await WindowsIndexFilesAndFoldersSearchAsync(query, querySearch, token)
62+
.ConfigureAwait(false));
63+
}
64+
65+
return result.ToList();
66+
}
67+
68+
private bool ActionKeywordMatch(Query query, Settings.ActionKeyword allowedActionKeyword)
69+
{
70+
var keyword = query.ActionKeyword.Length == 0 ? Query.GlobalPluginWildcardSign : query.ActionKeyword;
71+
72+
return allowedActionKeyword switch
73+
{
74+
Settings.ActionKeyword.SearchActionKeyword => settings.EnableSearchActionKeyword &&
75+
keyword == settings.SearchActionKeyword,
76+
Settings.ActionKeyword.PathSearchActionKeyword => settings.EnabledPathSearchKeyword &&
77+
keyword == settings.PathSearchActionKeyword,
78+
Settings.ActionKeyword.FileContentSearchActionKeyword => keyword ==
79+
settings.FileContentSearchActionKeyword,
80+
Settings.ActionKeyword.IndexSearchActionKeyword => settings.EnabledIndexOnlySearchKeyword &&
81+
keyword == settings.IndexSearchActionKeyword
82+
};
83+
}
84+
85+
public async Task<List<Result>> PathSearchAsync(Query query, CancellationToken token = default)
86+
{
87+
var querySearch = query.Search;
88+
4989
// This allows the user to type the assigned action keyword and only see the list of quick folder links
5090
if (string.IsNullOrEmpty(query.Search))
5191
return QuickAccess.AccessLinkListAll(query, settings.QuickAccessLinks);
5292

93+
var results = new HashSet<Result>(PathEqualityComparator.Instance);
94+
5395
var quickaccessLinks = QuickAccess.AccessLinkListMatched(query, settings.QuickAccessLinks);
5496

55-
if (quickaccessLinks.Count > 0)
56-
results.UnionWith(quickaccessLinks);
97+
results.UnionWith(quickaccessLinks);
5798

5899
var isEnvironmentVariable = EnvironmentVariables.IsEnvironmentVariableSearch(querySearch);
59100

@@ -63,13 +104,6 @@ internal async Task<List<Result>> SearchAsync(Query query, CancellationToken tok
63104
// Query is a location path with a full environment variable, eg. %appdata%\somefolder\
64105
var isEnvironmentVariablePath = querySearch[1..].Contains("%\\");
65106

66-
if (!querySearch.IsLocationPathString() && !isEnvironmentVariablePath)
67-
{
68-
results.UnionWith(await WindowsIndexFilesAndFoldersSearchAsync(query, querySearch, token).ConfigureAwait(false));
69-
70-
return results.ToList();
71-
}
72-
73107
var locationPath = querySearch;
74108

75109
if (isEnvironmentVariablePath)
@@ -99,19 +133,20 @@ internal async Task<List<Result>> SearchAsync(Query query, CancellationToken tok
99133
return results.ToList();
100134
}
101135

102-
private async Task<List<Result>> WindowsIndexFileContentSearchAsync(Query query, string querySearchString, CancellationToken token)
136+
private async Task<List<Result>> WindowsIndexFileContentSearchAsync(Query query, string querySearchString,
137+
CancellationToken token)
103138
{
104139
var queryConstructor = new QueryConstructor(settings);
105140

106141
if (string.IsNullOrEmpty(querySearchString))
107142
return new List<Result>();
108143

109144
return await IndexSearch.WindowsIndexSearchAsync(querySearchString,
110-
queryConstructor.CreateQueryHelper().ConnectionString,
111-
queryConstructor.QueryForFileContentSearch,
112-
settings.IndexSearchExcludedSubdirectoryPaths,
113-
query,
114-
token).ConfigureAwait(false);
145+
queryConstructor.CreateQueryHelper().ConnectionString,
146+
queryConstructor.QueryForFileContentSearch,
147+
settings.IndexSearchExcludedSubdirectoryPaths,
148+
query,
149+
token).ConfigureAwait(false);
115150
}
116151

117152
public bool IsFileContentSearch(string actionKeyword)
@@ -138,28 +173,30 @@ public async Task<List<Result>> TopLevelDirectorySearchBehaviourAsync(
138173
return await windowsIndexSearch(query, querySearchString, token);
139174
}
140175

141-
private async Task<List<Result>> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString, CancellationToken token)
176+
private async Task<List<Result>> WindowsIndexFilesAndFoldersSearchAsync(Query query, string querySearchString,
177+
CancellationToken token)
142178
{
143179
var queryConstructor = new QueryConstructor(settings);
144180

145181
return await IndexSearch.WindowsIndexSearchAsync(querySearchString,
146-
queryConstructor.CreateQueryHelper().ConnectionString,
147-
queryConstructor.QueryForAllFilesAndFolders,
148-
settings.IndexSearchExcludedSubdirectoryPaths,
149-
query,
150-
token).ConfigureAwait(false);
182+
queryConstructor.CreateQueryHelper().ConnectionString,
183+
queryConstructor.QueryForAllFilesAndFolders,
184+
settings.IndexSearchExcludedSubdirectoryPaths,
185+
query,
186+
token).ConfigureAwait(false);
151187
}
152188

153-
private async Task<List<Result>> WindowsIndexTopLevelFolderSearchAsync(Query query, string path, CancellationToken token)
189+
private async Task<List<Result>> WindowsIndexTopLevelFolderSearchAsync(Query query, string path,
190+
CancellationToken token)
154191
{
155192
var queryConstructor = new QueryConstructor(settings);
156193

157194
return await IndexSearch.WindowsIndexSearchAsync(path,
158-
queryConstructor.CreateQueryHelper().ConnectionString,
159-
queryConstructor.QueryForTopLevelDirectorySearch,
160-
settings.IndexSearchExcludedSubdirectoryPaths,
161-
query,
162-
token).ConfigureAwait(false);
195+
queryConstructor.CreateQueryHelper().ConnectionString,
196+
queryConstructor.QueryForTopLevelDirectorySearch,
197+
settings.IndexSearchExcludedSubdirectoryPaths,
198+
query,
199+
token).ConfigureAwait(false);
163200
}
164201

165202
private bool UseWindowsIndexForDirectorySearch(string locationPath)
@@ -170,11 +207,11 @@ private bool UseWindowsIndexForDirectorySearch(string locationPath)
170207
return false;
171208

172209
if (settings.IndexSearchExcludedSubdirectoryPaths
173-
.Any(x => FilesFolders.ReturnPreviousDirectoryIfIncompleteString(pathToDirectory)
174-
.StartsWith(x.Path, StringComparison.OrdinalIgnoreCase)))
210+
.Any(x => FilesFolders.ReturnPreviousDirectoryIfIncompleteString(pathToDirectory)
211+
.StartsWith(x.Path, StringComparison.OrdinalIgnoreCase)))
175212
return false;
176213

177214
return IndexSearch.PathIsIndexed(pathToDirectory);
178215
}
179216
}
180-
}
217+
}

Plugins/Flow.Launcher.Plugin.Explorer/Settings.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using Flow.Launcher.Plugin.Explorer.Search;
22
using Flow.Launcher.Plugin.Explorer.Search.QuickAccessLinks;
3+
using Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption;
4+
using System;
35
using System.Collections.Generic;
6+
using System.IO;
47

58
namespace Flow.Launcher.Plugin.Explorer
69
{
@@ -18,7 +21,57 @@ public class Settings
1821
public List<AccessLink> IndexSearchExcludedSubdirectoryPaths { get; set; } = new List<AccessLink>();
1922

2023
public string SearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign;
24+
public bool EnableSearchActionKeyword { get; set; } = true;
2125

2226
public string FileContentSearchActionKeyword { get; set; } = Constants.DefaultContentSearchActionKeyword;
27+
28+
public string PathSearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign;
29+
30+
public bool EnabledPathSearchKeyword { get; set; }
31+
32+
public string IndexSearchActionKeyword { get; set; } = Query.GlobalPluginWildcardSign;
33+
34+
public bool EnabledIndexOnlySearchKeyword { get; set; }
35+
36+
internal enum ActionKeyword
37+
{
38+
SearchActionKeyword,
39+
PathSearchActionKeyword,
40+
FileContentSearchActionKeyword,
41+
IndexSearchActionKeyword
42+
}
43+
44+
internal string GetActionKeyword(ActionKeyword actionKeyword) => actionKeyword switch
45+
{
46+
ActionKeyword.SearchActionKeyword => SearchActionKeyword,
47+
ActionKeyword.PathSearchActionKeyword => PathSearchActionKeyword,
48+
ActionKeyword.FileContentSearchActionKeyword => FileContentSearchActionKeyword,
49+
ActionKeyword.IndexSearchActionKeyword => IndexSearchActionKeyword
50+
};
51+
52+
internal void SetActionKeyword(ActionKeyword actionKeyword, string keyword) => _ = actionKeyword switch
53+
{
54+
ActionKeyword.SearchActionKeyword => SearchActionKeyword = keyword,
55+
ActionKeyword.PathSearchActionKeyword => PathSearchActionKeyword = keyword,
56+
ActionKeyword.FileContentSearchActionKeyword => FileContentSearchActionKeyword = keyword,
57+
ActionKeyword.IndexSearchActionKeyword => IndexSearchActionKeyword = keyword,
58+
_ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "Unexpected property")
59+
};
60+
61+
internal bool? GetActionKeywordEnable(ActionKeyword actionKeyword) => actionKeyword switch
62+
{
63+
ActionKeyword.SearchActionKeyword => EnableSearchActionKeyword,
64+
ActionKeyword.PathSearchActionKeyword => EnabledPathSearchKeyword,
65+
ActionKeyword.IndexSearchActionKeyword => EnabledIndexOnlySearchKeyword,
66+
_ => null
67+
};
68+
69+
internal void SetActionKeywordEnable(ActionKeyword actionKeyword, bool enable) => _ = actionKeyword switch
70+
{
71+
ActionKeyword.SearchActionKeyword => EnableSearchActionKeyword = enable,
72+
ActionKeyword.PathSearchActionKeyword => EnabledPathSearchKeyword = enable,
73+
ActionKeyword.IndexSearchActionKeyword => EnabledIndexOnlySearchKeyword = enable,
74+
_ => throw new ArgumentOutOfRangeException(nameof(actionKeyword), actionKeyword, "Unexpected property")
75+
};
2376
}
2477
}

Plugins/Flow.Launcher.Plugin.Explorer/ViewModels/SettingsViewModel.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,15 @@ internal void OpenWindowsIndexingOptions()
4141
Process.Start(psi);
4242
}
4343

44-
internal void UpdateActionKeyword(string newActionKeyword, string oldActionKeyword)
44+
internal void UpdateActionKeyword(Settings.ActionKeyword modifiedActionKeyword, string newActionKeyword, string oldActionKeyword)
4545
{
4646
PluginManager.ReplaceActionKeyword(Context.CurrentPluginMetadata.ID, oldActionKeyword, newActionKeyword);
47-
48-
if (Settings.FileContentSearchActionKeyword == oldActionKeyword)
49-
Settings.FileContentSearchActionKeyword = newActionKeyword;
50-
51-
if (Settings.SearchActionKeyword == oldActionKeyword)
52-
Settings.SearchActionKeyword = newActionKeyword;
5347
}
5448

55-
internal bool IsActionKeywordAlreadyAssigned(string newActionKeyword) => PluginManager.ActionKeywordRegistered(newActionKeyword);
49+
internal bool IsActionKeywordAlreadyAssigned(string newActionKeyword)
50+
{
51+
return PluginManager.ActionKeywordRegistered(newActionKeyword);
52+
}
5653

5754
internal bool IsNewActionKeywordGlobal(string newActionKeyword) => newActionKeyword == Query.GlobalPluginWildcardSign;
5855
}

0 commit comments

Comments
 (0)