mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Merge pull request #1479 from VictoriousRaptor/SearchProgramsInPATH
[Program Plugin] Search programs in PATH
This commit is contained in:
commit
f8b009ed75
6 changed files with 129 additions and 112 deletions
|
|
@ -16,10 +16,14 @@
|
|||
<system:String x:Key="flowlauncher_plugin_program_suffixes">File Type</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_reindex">Reindex</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_indexing">Indexing</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_start">Index Start Menu</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_source">Index Sources</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_option">Options</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_start">Start Menu</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_start_tooltip">When enabled, Flow will load programs from the start menu</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_registry">Index Registry</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_registry">Registry</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_registry_tooltip">When enabled, Flow will load programs from the registry</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_PATH">PATH</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_index_PATH_tooltip">When enabled, Flow will load programs from the PATH environment variable</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_enable_hidelnkpath">Hide app path</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_enable_hidelnkpath_tooltip">For executable files such as UWP or lnk, hide the file path from being visible</system:String>
|
||||
<system:String x:Key="flowlauncher_plugin_program_enable_description">Search in Program Description</system:String>
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ namespace Flow.Launcher.Plugin.Program
|
|||
|
||||
var b = Task.Run(() =>
|
||||
{
|
||||
Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|Win32Program index cost", IndexUwpPrograms);
|
||||
Stopwatch.Normal("|Flow.Launcher.Plugin.Program.Main|UWPPRogram index cost", IndexUwpPrograms);
|
||||
});
|
||||
|
||||
if (cacheEmpty)
|
||||
|
|
|
|||
|
|
@ -11,10 +11,7 @@ using Flow.Launcher.Infrastructure;
|
|||
using Flow.Launcher.Plugin.Program.Logger;
|
||||
using Flow.Launcher.Plugin.SharedCommands;
|
||||
using Flow.Launcher.Plugin.SharedModels;
|
||||
using Flow.Launcher.Infrastructure.Logger;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
using Stopwatch = Flow.Launcher.Infrastructure.Stopwatch;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Channels;
|
||||
|
|
@ -279,6 +276,14 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
program.Valid = false;
|
||||
return program;
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
ProgramLogger.LogException($"|Win32|LnkProgram|{path}" +
|
||||
"|An unexpected error occurred in the calling method LnkProgram", e);
|
||||
|
||||
program.Valid = false;
|
||||
return program;
|
||||
}
|
||||
#if !DEBUG //Only do a catch all in production. This is so make developer aware of any unhandled exception and add the exception handling in.
|
||||
catch (Exception e)
|
||||
{
|
||||
|
|
@ -352,14 +357,14 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<string> ProgramPaths(string directory, string[] suffixes)
|
||||
private static IEnumerable<string> ProgramPaths(string directory, string[] suffixes, bool recursive = true)
|
||||
{
|
||||
if (!Directory.Exists(directory))
|
||||
return Enumerable.Empty<string>();
|
||||
|
||||
return Directory.EnumerateFiles(directory, "*", new EnumerationOptions
|
||||
{
|
||||
IgnoreInaccessible = true, RecurseSubdirectories = true
|
||||
IgnoreInaccessible = true, RecurseSubdirectories = recursive
|
||||
}).Where(x => suffixes.Contains(Extension(x)));
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +400,6 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
|
||||
private static IEnumerable<Win32> StartMenuPrograms(string[] suffixes)
|
||||
{
|
||||
var disabledProgramsList = Main._settings.DisabledProgramSources;
|
||||
|
||||
var directory1 = Environment.GetFolderPath(Environment.SpecialFolder.Programs);
|
||||
var directory2 = Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms);
|
||||
|
|
@ -414,6 +418,29 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
return programs;
|
||||
}
|
||||
|
||||
private static IEnumerable<Win32> PATHPrograms(string[] suffixes)
|
||||
{
|
||||
var pathEnv = Environment.GetEnvironmentVariable("Path");
|
||||
if (String.IsNullOrEmpty(pathEnv))
|
||||
{
|
||||
return Array.Empty<Win32>();
|
||||
}
|
||||
|
||||
var paths = pathEnv.Split(";", StringSplitOptions.RemoveEmptyEntries).DistinctBy(p => p.ToLowerInvariant());
|
||||
|
||||
var toFilter = paths.AsParallel().SelectMany(p => ProgramPaths(p, suffixes, recursive: false));
|
||||
|
||||
var programs = ExceptDisabledSource(toFilter.Distinct())
|
||||
.Select(x => Extension(x) switch
|
||||
{
|
||||
ShortcutExtension => LnkProgram(x),
|
||||
UrlExtension => UrlProgram(x),
|
||||
ExeExtension => ExeProgram(x),
|
||||
_ => Win32Program(x)
|
||||
});
|
||||
return programs;
|
||||
}
|
||||
|
||||
private static IEnumerable<Win32> AppPathsPrograms(string[] suffixes)
|
||||
{
|
||||
// https://msdn.microsoft.com/en-us/library/windows/desktop/ee872121
|
||||
|
|
@ -566,6 +593,12 @@ namespace Flow.Launcher.Plugin.Program.Programs
|
|||
autoIndexPrograms = autoIndexPrograms.Concat(startMenu);
|
||||
}
|
||||
|
||||
if (settings.EnablePATHSource)
|
||||
{
|
||||
var path = PATHPrograms(settings.GetSuffixes());
|
||||
autoIndexPrograms = autoIndexPrograms.Concat(path);
|
||||
}
|
||||
|
||||
autoIndexPrograms = ProgramsHasher(autoIndexPrograms);
|
||||
|
||||
return programs.Concat(autoIndexPrograms).Where(x => x.Valid).Distinct().ToArray();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using PropertyChanged;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace Flow.Launcher.Plugin.Program
|
||||
|
|
@ -13,7 +14,7 @@ namespace Flow.Launcher.Plugin.Program
|
|||
public List<ProgramSource> ProgramSources { get; set; } = new List<ProgramSource>();
|
||||
public List<DisabledProgramSource> DisabledProgramSources { get; set; } = new List<DisabledProgramSource>();
|
||||
|
||||
[Obsolete, JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
[Obsolete("Should use GetSuffixes() instead."), JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
||||
public string[] ProgramSuffixes { get; set; } = null;
|
||||
public string[] CustomSuffixes { get; set; } = Array.Empty<string>(); // Custom suffixes only
|
||||
public string[] CustomProtocols { get; set; } = Array.Empty<string>();
|
||||
|
|
@ -111,6 +112,8 @@ namespace Flow.Launcher.Plugin.Program
|
|||
public bool EnableDescription { get; set; } = false;
|
||||
public bool HideAppsPath { get; set; } = true;
|
||||
public bool EnableRegistrySource { get; set; } = true;
|
||||
public bool EnablePATHSource { get; set; } = true;
|
||||
|
||||
public string CustomizedExplorer { get; set; } = Explorer;
|
||||
public string CustomizedArgs { get; set; } = ExplorerArgs;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,58 +10,88 @@
|
|||
mc:Ignorable="d">
|
||||
<Grid Margin="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="170" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="60" />
|
||||
</Grid.RowDefinitions>
|
||||
<DockPanel
|
||||
Margin="70,10,0,8"
|
||||
HorizontalAlignment="Stretch"
|
||||
LastChildFill="True">
|
||||
<TextBlock
|
||||
MinWidth="120"
|
||||
Margin="0,5,10,0"
|
||||
Text="{DynamicResource flowlauncher_plugin_program_index_source}" />
|
||||
<WrapPanel
|
||||
Width="Auto"
|
||||
Margin="0,0,14,0"
|
||||
HorizontalAlignment="Right"
|
||||
DockPanel.Dock="Right">
|
||||
<CheckBox
|
||||
Name="StartMenuEnabled"
|
||||
Margin="12,0,12,0"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_index_start}"
|
||||
IsChecked="{Binding EnableStartMenuSource}"
|
||||
ToolTip="{DynamicResource flowlauncher_plugin_program_index_start_tooltip}" />
|
||||
<CheckBox
|
||||
Name="RegistryEnabled"
|
||||
Margin="12,0,12,0"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_index_registry}"
|
||||
IsChecked="{Binding EnableRegistrySource}"
|
||||
ToolTip="{DynamicResource flowlauncher_plugin_program_index_registry_tooltip}" />
|
||||
|
||||
<CheckBox
|
||||
Name="PATHEnabled"
|
||||
Margin="12,0,12,0"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_index_PATH}"
|
||||
IsChecked="{Binding EnablePATHSource}"
|
||||
ToolTip="{DynamicResource flowlauncher_plugin_program_index_PATH_tooltip}" />
|
||||
</WrapPanel>
|
||||
</DockPanel>
|
||||
|
||||
<StackPanel
|
||||
Grid.Row="0"
|
||||
Grid.Row="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
Orientation="Vertical">
|
||||
<StackPanel Width="Auto" Orientation="Vertical">
|
||||
<StackPanel Width="Auto" Orientation="Horizontal">
|
||||
<CheckBox
|
||||
Name="StartMenuEnabled"
|
||||
Width="220"
|
||||
Margin="70,8,10,8"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_index_start}"
|
||||
IsChecked="{Binding EnableStartMenuSource}"
|
||||
ToolTip="{DynamicResource flowlauncher_plugin_program_index_start_tooltip}" />
|
||||
<CheckBox
|
||||
Name="RegistryEnabled"
|
||||
Margin="70,8,10,8"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_index_registry}"
|
||||
IsChecked="{Binding EnableRegistrySource}"
|
||||
ToolTip="{DynamicResource flowlauncher_plugin_program_index_registry_tooltip}" />
|
||||
</StackPanel>
|
||||
|
||||
<Separator
|
||||
Height="1"
|
||||
BorderBrush="{DynamicResource Color03B}"
|
||||
BorderThickness="1" />
|
||||
<StackPanel Width="Auto" Orientation="Horizontal">
|
||||
<Separator
|
||||
Height="1"
|
||||
BorderBrush="{DynamicResource Color03B}"
|
||||
BorderThickness="1" />
|
||||
<DockPanel
|
||||
Margin="70,10,0,8"
|
||||
HorizontalAlignment="Stretch"
|
||||
LastChildFill="True">
|
||||
<TextBlock
|
||||
MinWidth="120"
|
||||
Margin="0,5,10,0"
|
||||
Text="{DynamicResource flowlauncher_plugin_program_index_option}" />
|
||||
<WrapPanel
|
||||
Width="Auto"
|
||||
Margin="0,0,14,0"
|
||||
HorizontalAlignment="Right"
|
||||
DockPanel.Dock="Right">
|
||||
<CheckBox
|
||||
Name="HideLnkEnabled"
|
||||
Width="220"
|
||||
Margin="70,8,10,8"
|
||||
Margin="12,0,12,0"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath}"
|
||||
IsChecked="{Binding HideAppsPath}"
|
||||
ToolTip="{DynamicResource flowlauncher_plugin_program_enable_hidelnkpath_tooltip}" />
|
||||
<CheckBox
|
||||
Name="DescriptionEnabled"
|
||||
Margin="70,8,10,8"
|
||||
Margin="12,0,12,0"
|
||||
Content="{DynamicResource flowlauncher_plugin_program_enable_description}"
|
||||
IsChecked="{Binding EnableDescription}"
|
||||
ToolTip="{DynamicResource flowlauncher_plugin_program_enable_description_tooltip}" />
|
||||
</StackPanel>
|
||||
<Separator
|
||||
Height="1"
|
||||
BorderBrush="{DynamicResource Color03B}"
|
||||
BorderThickness="1" />
|
||||
</StackPanel>
|
||||
</WrapPanel>
|
||||
</DockPanel>
|
||||
<Separator
|
||||
Height="1"
|
||||
BorderBrush="{DynamicResource Color03B}"
|
||||
BorderThickness="1" />
|
||||
<StackPanel
|
||||
Width="Auto"
|
||||
Margin="10,6,0,0"
|
||||
Margin="60,6,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
|
|
@ -107,8 +137,8 @@
|
|||
</StackPanel>
|
||||
<ListView
|
||||
x:Name="programSourceView"
|
||||
Grid.Row="1"
|
||||
Margin="20,0,20,0"
|
||||
Grid.Row="2"
|
||||
Margin="70,0,20,0"
|
||||
AllowDrop="True"
|
||||
BorderBrush="DarkGray"
|
||||
BorderThickness="1"
|
||||
|
|
@ -147,7 +177,7 @@
|
|||
</ListView.View>
|
||||
</ListView>
|
||||
<DockPanel
|
||||
Grid.Row="2"
|
||||
Grid.Row="3"
|
||||
Grid.RowSpan="1"
|
||||
Margin="0,0,20,10">
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
|
|
@ -173,66 +203,3 @@
|
|||
</DockPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -66,6 +66,16 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
}
|
||||
}
|
||||
|
||||
public bool EnablePATHSource
|
||||
{
|
||||
get => _settings.EnablePATHSource;
|
||||
set
|
||||
{
|
||||
_settings.EnablePATHSource = value;
|
||||
ReIndexing();
|
||||
}
|
||||
}
|
||||
|
||||
public string CustomizedExplorerPath
|
||||
{
|
||||
get => _settings.CustomizedExplorer;
|
||||
|
|
@ -360,4 +370,4 @@ namespace Flow.Launcher.Plugin.Program.Views
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue