Skip to content

Commit

Permalink
Merge pull request #17 from m00ndark/m00ndark/frequent-quick-launch-f…
Browse files Browse the repository at this point in the history
…iles

Added option to show frequently used quick launch files at the top of the context menu
  • Loading branch information
Mattias Wijkström authored Jan 20, 2023
2 parents 8b3cce6 + e1d50f7 commit 52582b5
Show file tree
Hide file tree
Showing 13 changed files with 387 additions and 119 deletions.
65 changes: 45 additions & 20 deletions src/GitBranchView/Controls/FolderEntry.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using GitBranchView.Forms;
using GitBranchView.Model;
using ToolComponents.Core.Extensions;
using ToolComponents.Core.Logging;
using IOPath = System.IO.Path;

namespace GitBranchView.Controls
{
Expand Down Expand Up @@ -57,8 +56,8 @@ private void SetHighlightColor()
{
HighlightColor = Root.Filters
.Where(filter => filter.Type == FilterType.Highlight)
.Where(filter => filter.Target.HasFlag(FilterTargets.Path) && Regex.IsMatch(Path.RelativeTo(Root), filter.Filter)
|| filter.Target.HasFlag(FilterTargets.Branch) && Regex.IsMatch(Branch, filter.Filter))
.Where(filter => filter.Target.HasFlag(FilterTargets.Path) && filter.CachedFilterRegex.IsMatch(Path.RelativeTo(Root))
|| filter.Target.HasFlag(FilterTargets.Branch) && filter.CachedFilterRegex.IsMatch(Branch))
.Select(filter => (Color?) filter.Color)
.FirstOrDefault();
}
Expand Down Expand Up @@ -132,26 +131,45 @@ private void UpdateSize()

public void ResetContextMenu()
{
// executing this on non-UI thread if possible, since it's a bit heavy
List<IGrouping<string, string>> groupedQuickLaunchPaths = !string.IsNullOrWhiteSpace(Settings.Default.QuickLaunchFilesFilter)
? Directory.EnumerateFiles(Path, "*", SearchOption.AllDirectories)
.Where(filePath => Settings.Default.CachedQuickLaunchFilesFilterRegex.IsMatch(filePath.RelativeTo(Path)))
.GroupBy(filePath => Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.ByExtension
? IOPath.GetExtension(filePath)
: Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.ByPath
? IOPath.GetDirectoryName(filePath)?.RelativeTo(Path) ?? string.Empty
: string.Empty)
.ToList()
: null;

contextMenuStrip.InvokeIfRequired(() =>
{
contextMenuStrip.Items.DisposeItems();
contextMenuStrip.Items.Clear();

if (!string.IsNullOrWhiteSpace(Settings.Default.QuickLaunchFilesFilter))
if (groupedQuickLaunchPaths != null)
{
try
{
List<IGrouping<string, string>> groupedQuickLaunchPaths = Directory.EnumerateFiles(Path, "*", SearchOption.AllDirectories)
.Where(filePath => Regex.IsMatch(filePath.RelativeTo(Path), Settings.Default.QuickLaunchFilesFilter, RegexOptions.IgnoreCase))
.GroupBy(filePath => Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.ByExtension
? System.IO.Path.GetExtension(filePath)
: Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.ByPath
? System.IO.Path.GetDirectoryName(filePath)?.RelativeTo(Path) ?? string.Empty
: string.Empty)
.ToList();

if (groupedQuickLaunchPaths.Any())
{
if (Settings.Default.ShowFrequentQuickLaunchFiles
&& Settings.Default.RepositoryLinkBehavior != RepositoryLinkBehavior.LaunchSelectedQuickLaunchFile
&& QuickLaunchHistory.Default.TryGet(Path, out List<QuickLaunchItem> quickLaunchItems)
&& quickLaunchItems.Any())
{
foreach (string quickLaunchPath in quickLaunchItems
.OrderByDescending(item => item.LaunchCount)
.Take(Settings.Default.FrequentQuickLaunchFilesCount)
.Select(item => item.FilePath))
{
contextMenuStrip.Items.Add<ToolStripMenuItem>(quickLaunchPath.RelativeTo(Path), QuickLaunchPathMenuItem_Click, quickLaunchPath);
}

contextMenuStrip.AddItem<ToolStripSeparator>();
}

Settings.Default.SelectedQuickLaunchFiles.TryGetValue(Path.ToLower(), out string selectedQuickLaunchPath);

foreach (IGrouping<string, string> quickLaunchPaths in groupedQuickLaunchPaths)
Expand All @@ -170,7 +188,7 @@ public void ResetContextMenu()
foreach (string quickLaunchPath in quickLaunchPaths.Take(MAX_QUICK_LAUNCH_ITEMS))
{
string menuItemText = groupedQuickLaunchPaths.Count > 1 && Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.ByPath
? System.IO.Path.GetFileName(quickLaunchPath)
? IOPath.GetFileName(quickLaunchPath)
: quickLaunchPath.RelativeTo(Path);

ToolStripMenuItem item = menuItems.Add<ToolStripMenuItem>(menuItemText, QuickLaunchPathMenuItem_Click, quickLaunchPath);
Expand All @@ -185,8 +203,9 @@ public void ResetContextMenu()
int itemCount = quickLaunchPaths.Count();
if (itemCount > MAX_QUICK_LAUNCH_ITEMS)
{
contextMenuStrip.AddItem<ToolStripMenuItem>(
$"-- Found {itemCount} matching quick launch files, limiting to first {MAX_QUICK_LAUNCH_ITEMS} --").Enabled = false;
contextMenuStrip
.AddItem<ToolStripMenuItem>($"-- Found {itemCount} matching quick launch files, limiting to first {MAX_QUICK_LAUNCH_ITEMS} --")
.Enabled = false;
}
}

Expand Down Expand Up @@ -375,16 +394,22 @@ await Task.Run(() =>
}
}

private static void ExecuteQuickLaunchFile(ToolStripItem item)
private void ExecuteQuickLaunchFile(ToolStripItem item)
{
string quickLaunchPath = item.GetTagValue<string>();

if (quickLaunchPath == null)
return;

try
{
using (Process.Start(quickLaunchPath)) { }
{
using (Process.Start(quickLaunchPath)) { }
bool changed = QuickLaunchHistory.Default.Add(Path, quickLaunchPath);

if (changed)
{
Task.Run(ResetContextMenu);
}
}
catch (Exception ex)
{
Expand Down
11 changes: 7 additions & 4 deletions src/GitBranchView/Controls/RootEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,13 @@ public void HighlightChanged()

public void ResetContextMenus()
{
foreach (FolderEntry folderEntry in flowLayoutPanel.Controls.OfType<FolderEntry>())
{
folderEntry.ResetContextMenu();
}
Task.Run(() =>
{
foreach (FolderEntry folderEntry in flowLayoutPanel.Controls.OfType<FolderEntry>())
{
folderEntry.ResetContextMenu();
}
});
}
}
}
7 changes: 5 additions & 2 deletions src/GitBranchView/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ public static bool ShouldInclude(this Root root, string path, string branch)
{
return root.Filters
.Where(filter => filter.Type == FilterType.Include || filter.Type == FilterType.Exclude)
.Aggregate(true, (include, filter) => filter.Target.HasFlag(FilterTargets.Path) && Regex.IsMatch(path.RelativeTo(root), filter.Filter)
|| filter.Target.HasFlag(FilterTargets.Branch) && Regex.IsMatch(branch, filter.Filter) ? filter.Type == FilterType.Include : include);
.Aggregate(true, (include, filter) => filter.Target.HasFlag(FilterTargets.Path) && filter.CachedFilterRegex.IsMatch(path.RelativeTo(root))
|| filter.Target.HasFlag(FilterTargets.Branch) && filter.CachedFilterRegex.IsMatch(branch) ? filter.Type == FilterType.Include : include);
}

public static IEnumerable<string> ScanFolder(this string path)
Expand All @@ -105,6 +105,9 @@ public static IEnumerable<string> ScanFolder(this string path)

public static bool IsValidRegex(this string pattern, bool allowEmpty = false)
{
if (allowEmpty && pattern == string.Empty)
return true;

if (string.IsNullOrWhiteSpace(pattern))
return false;

Expand Down
6 changes: 4 additions & 2 deletions src/GitBranchView/Forms/CloneForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace GitBranchView.Forms
public partial class CloneForm : Form
{
private const string REPOSITORY_URL_PATTERN = @"^[^:]+://(?:([^/]+)/)*(.+)\.git$";

private static readonly Regex _repositoryUrlRegex = REPOSITORY_URL_PATTERN.GetCachedRegex(RegexOptions.IgnoreCase);
private bool _isTerminating;

public event EventHandler ClonedSuccessfully;
Expand Down Expand Up @@ -69,7 +71,7 @@ private void TextBoxRepositoryUrl_TextChanged(object sender, EventArgs e)
if (!string.IsNullOrWhiteSpace(textBoxFolderName.Text))
return;

Match match = Regex.Match(textBoxRepositoryUrl.Text, REPOSITORY_URL_PATTERN, RegexOptions.IgnoreCase);
Match match = _repositoryUrlRegex.Match(textBoxRepositoryUrl.Text);

if (!match.Success)
return;
Expand Down Expand Up @@ -115,7 +117,7 @@ private bool InputIsValid()
return false;
}

if (!Regex.IsMatch(textBoxRepositoryUrl.Text, REPOSITORY_URL_PATTERN, RegexOptions.IgnoreCase))
if (!_repositoryUrlRegex.IsMatch(textBoxRepositoryUrl.Text))
{
Program.ShowError("Repository URL is not a valid git URL!");
return false;
Expand Down
7 changes: 4 additions & 3 deletions src/GitBranchView/Forms/OutputForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ public void AddLine(string line)
return;

line = line.StartsWith("\u001b[K") ? line.Substring(3) : line;
string initialText = Regex.Match(line, @"^([^\d]*)").Value;
string similarLine = Regex
.Matches(textBoxDetails.Text, @"^(.*)\r{1}$", RegexOptions.Multiline)
string initialText = @"^([^\d]*)".GetCachedRegex().Match(line).Value;
string similarLine = @"^(.*)\r{1}$"
.GetCachedRegex(RegexOptions.Multiline)
.Matches(textBoxDetails.Text)
.Cast<Match>()
.Select(match => match.Groups[1].Value)
.LastOrDefault(x => x.StartsWith(initialText));
Expand Down
55 changes: 49 additions & 6 deletions src/GitBranchView/Forms/SettingsForm.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions src/GitBranchView/Forms/SettingsForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ private void RadioButtonQuickLaunchFilesGroupByPath_CheckedChanged(object sender
_quickLaunchFilesChanged = true;
}

private void CheckBoxQuickLaunchFilesShowFrequent_CheckedChanged(object sender, EventArgs e)
{
_quickLaunchFilesChanged = true;
EnableControls();
}

private void NumericUpDownQuickLaunchFilesFrequentCount_ValueChanged(object sender, EventArgs e)
{
_quickLaunchFilesChanged = true;
}

private void RadioButtonGitRepositoryLinkExecuteCustomCommand_CheckedChanged(object sender, EventArgs e)
{
_repositoryLinkBehaviorChanged = true;
Expand Down Expand Up @@ -450,6 +461,7 @@ private void MoveFilterEntry(Root root, FilterEntry filterEntry, int adjustment)

private void EnableControls(bool enable = true)
{
numericUpDownQuickLaunchFilesFrequentCount.Enabled = enable && checkBoxQuickLaunchFilesShowFrequent.Checked;
labelCustomCommandName.Enabled = enable && radioButtonGitRepositoryLinkLaunchSelectedQuickLaunchFile.Checked;
textBoxCustomCommandName.Enabled = enable && radioButtonGitRepositoryLinkLaunchSelectedQuickLaunchFile.Checked;
}
Expand Down Expand Up @@ -480,6 +492,8 @@ private void LoadSettings()
radioButtonQuickLaunchFilesDoNotGroup.Checked = Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.None;
radioButtonQuickLaunchFilesGroupByExtension.Checked = Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.ByExtension;
radioButtonQuickLaunchFilesGroupByPath.Checked = Settings.Default.QuickLaunchFilesGrouping == QuickLaunchFilesGrouping.ByPath;
checkBoxQuickLaunchFilesShowFrequent.Checked = Settings.Default.ShowFrequentQuickLaunchFiles;
numericUpDownQuickLaunchFilesFrequentCount.Value = Settings.Default.FrequentQuickLaunchFilesCount;
radioButtonGitRepositoryLinkExecuteCustomCommand.Checked = Settings.Default.RepositoryLinkBehavior == RepositoryLinkBehavior.ExecuteCustomCommand;
radioButtonGitRepositoryLinkLaunchSelectedQuickLaunchFile.Checked = Settings.Default.RepositoryLinkBehavior == RepositoryLinkBehavior.LaunchSelectedQuickLaunchFile;
checkBoxCloseOnLostFocus.Checked = Settings.Default.CloseOnLostFocus;
Expand Down Expand Up @@ -528,6 +542,8 @@ private void SaveSettings()
: radioButtonQuickLaunchFilesGroupByPath.Checked
? QuickLaunchFilesGrouping.ByPath
: QuickLaunchFilesGrouping.None;
Settings.Default.ShowFrequentQuickLaunchFiles = checkBoxQuickLaunchFilesShowFrequent.Checked;
Settings.Default.FrequentQuickLaunchFilesCount = (int)numericUpDownQuickLaunchFilesFrequentCount.Value;
Settings.Default.RepositoryLinkBehavior = radioButtonGitRepositoryLinkLaunchSelectedQuickLaunchFile.Checked
? RepositoryLinkBehavior.LaunchSelectedQuickLaunchFile
: RepositoryLinkBehavior.ExecuteCustomCommand;
Expand Down
Loading

0 comments on commit 52582b5

Please sign in to comment.