diff --git a/src/Commands/CompareRevisions.cs b/src/Commands/CompareRevisions.cs
index 7b4a496de..fe7430bc6 100644
--- a/src/Commands/CompareRevisions.cs
+++ b/src/Commands/CompareRevisions.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
+using SourceGit.ViewModels;
namespace SourceGit.Commands
{
@@ -39,7 +40,8 @@ public CompareRevisions(string repo, string start, string end, string path)
foreach (var line in lines)
ParseLine(line);
- _changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
+ _changes.Sort((l, r) => string.Compare(l.Path, r.Path,
+ Preferences.Instance.GetPreferredListComparisonType()));
return _changes;
}
diff --git a/src/Commands/QueryLocalChanges.cs b/src/Commands/QueryLocalChanges.cs
index 788ed6172..f9af4f07c 100644
--- a/src/Commands/QueryLocalChanges.cs
+++ b/src/Commands/QueryLocalChanges.cs
@@ -159,6 +159,8 @@ public QueryLocalChanges(string repo, bool includeUntracked = true)
outs.Add(change);
}
+ outs.Sort((l, r) => string.Compare(l.Path, r.Path,
+ ViewModels.Preferences.Instance.GetPreferredListComparisonType()));
return outs;
}
}
diff --git a/src/Models/Commit.cs b/src/Models/Commit.cs
index ced7597ec..79c346bfc 100644
--- a/src/Models/Commit.cs
+++ b/src/Models/Commit.cs
@@ -113,7 +113,8 @@ public void ParseDecorators(string data)
if (l.Type != r.Type)
return (int)l.Type - (int)r.Type;
else
- return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
+ return string.Compare(l.Name, r.Name,
+ ViewModels.Preferences.Instance.GetPreferredListComparisonType());
});
}
}
diff --git a/src/Models/NumericSort.cs b/src/Models/NumericSort.cs
index ed5002e62..8ba485571 100644
--- a/src/Models/NumericSort.cs
+++ b/src/Models/NumericSort.cs
@@ -1,4 +1,6 @@
-namespace SourceGit.Models
+using System;
+
+namespace SourceGit.Models
{
public static class NumericSort
{
@@ -10,58 +12,51 @@ public static int Compare(string s1, string s2)
int marker1 = 0;
int marker2 = 0;
- char[] tmp1 = new char[len1];
- char[] tmp2 = new char[len2];
+ char[] tmp = new char[Math.Max(len1, len2)];
while (marker1 < len1 && marker2 < len2)
{
char c1 = s1[marker1];
char c2 = s2[marker2];
- int loc1 = 0;
- int loc2 = 0;
bool isDigit1 = char.IsDigit(c1);
bool isDigit2 = char.IsDigit(c2);
if (isDigit1 != isDigit2)
return c1.CompareTo(c2);
- do
- {
- tmp1[loc1] = c1;
- loc1++;
- marker1++;
+ int subLen1 = GetCoherentSubstringLength(s1, len1, marker1, isDigit1, ref tmp);
+ int subLen2 = GetCoherentSubstringLength(s2, len2, marker2, isDigit2, ref tmp);
- if (marker1 < len1)
- c1 = s1[marker1];
- else
- break;
- } while (char.IsDigit(c1) == isDigit1);
+ string sub1 = s1.Substring(marker1, subLen1);
+ string sub2 = s2.Substring(marker2, subLen2);
- do
- {
- tmp2[loc2] = c2;
- loc2++;
- marker2++;
+ marker1 += subLen1;
+ marker2 += subLen2;
- if (marker2 < len2)
- c2 = s2[marker2];
- else
- break;
- } while (char.IsDigit(c2) == isDigit2);
-
- string sub1 = new string(tmp1, 0, loc1);
- string sub2 = new string(tmp2, 0, loc2);
int result;
if (isDigit1)
- result = loc1 == loc2 ? string.CompareOrdinal(sub1, sub2) : loc1 - loc2;
+ {
+ // NOTE: We don't strip leading zeroes before comparing substring digits/lengths - should we?
+ result = (subLen1 == subLen2) ? string.CompareOrdinal(sub1, sub2) : (subLen1 - subLen2);
+ }
else
- result = string.CompareOrdinal(sub1, sub2);
-
+ {
+ result = string.Compare(sub1, sub2,
+ ViewModels.Preferences.Instance.GetPreferredListComparisonType());
+ }
if (result != 0)
return result;
}
return len1 - len2;
}
+
+ private static int GetCoherentSubstringLength(string s, int len, int start, bool isDigit, ref char[] tmp)
+ {
+ int num = 1;
+ while (start + num < len && char.IsDigit(s[start + num]) == isDigit)
+ num++;
+ return num;
+ }
}
}
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index afdff5da7..d534fbf47 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -491,6 +491,7 @@
Use monospace font only in text editor
Theme
Theme Overrides
+ Use case-insensitive sorting in lists
Use fixed tab width in titlebar
Use native window frame
DIFF/MERGE TOOL
diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs
index e41e046ef..84172343c 100644
--- a/src/ViewModels/Preferences.cs
+++ b/src/ViewModels/Preferences.cs
@@ -89,6 +89,20 @@ public bool OnlyUseMonoFontInEditor
}
}
+ public bool UseCaseInsensitiveSortingInLists
+ {
+ get => _useCaseInsensitiveSortingInLists;
+ set
+ {
+ if (SetProperty(ref _useCaseInsensitiveSortingInLists, value) && !_isLoading)
+ {
+ var launcher = App.GetLauncher();
+ if (launcher.ActivePage.Data is ViewModels.Repository repo)
+ repo.RefreshAll();
+ }
+ }
+ }
+
public bool UseSystemWindowFrame
{
get => Native.OS.UseSystemWindowFrame;
@@ -432,6 +446,12 @@ public Workspace GetActiveWorkspace()
return first;
}
+ public StringComparison GetPreferredListComparisonType()
+ {
+ return Preferences.Instance.UseCaseInsensitiveSortingInLists ?
+ StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
+ }
+
public void AddNode(RepositoryNode node, RepositoryNode to, bool save)
{
var collection = to == null ? RepositoryNodes : to.SubNodes;
@@ -449,7 +469,7 @@ public void SortNodes(List collection)
if (l.IsRepository != r.IsRepository)
return l.IsRepository ? 1 : -1;
- return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
+ return string.Compare(l.Name, r.Name, GetPreferredListComparisonType());
});
}
@@ -669,6 +689,7 @@ private bool RemoveInvalidRepositoriesRecursive(List collection)
private string _defaultFontFamily = string.Empty;
private string _monospaceFontFamily = string.Empty;
private bool _onlyUseMonoFontInEditor = true;
+ private bool _useCaseInsensitiveSortingInLists = false;
private double _defaultFontSize = 13;
private double _editorFontSize = 13;
private int _editorTabWidth = 4;
diff --git a/src/ViewModels/StashesPage.cs b/src/ViewModels/StashesPage.cs
index dec8ea6bf..99bcce094 100644
--- a/src/ViewModels/StashesPage.cs
+++ b/src/ViewModels/StashesPage.cs
@@ -71,7 +71,8 @@ public Models.Stash SelectedStash
changes.Add(c);
if (needSort)
- changes.Sort((l, r) => string.Compare(l.Path, r.Path, StringComparison.Ordinal));
+ changes.Sort((l, r) => string.Compare(l.Path, r.Path,
+ Preferences.Instance.GetPreferredListComparisonType()));
}
Dispatcher.UIThread.Invoke(() =>
diff --git a/src/ViewModels/WorkingCopy.cs b/src/ViewModels/WorkingCopy.cs
index b7dee5c9c..09ebc6f63 100644
--- a/src/ViewModels/WorkingCopy.cs
+++ b/src/ViewModels/WorkingCopy.cs
@@ -1778,16 +1778,11 @@ private bool IsChanged(List old, List cur)
if (old.Count != cur.Count)
return true;
- var oldMap = new Dictionary();
- foreach (var c in old)
- oldMap.Add(c.Path, c);
-
- foreach (var c in cur)
+ for (int idx = 0; idx < old.Count; idx++)
{
- if (!oldMap.TryGetValue(c.Path, out var o))
- return true;
-
- if (o.Index != c.Index || o.WorkTree != c.WorkTree)
+ var o = old[idx];
+ var c = cur[idx];
+ if (o.Path != c.Path || o.Index != c.Index || o.WorkTree != c.WorkTree)
return true;
}
diff --git a/src/Views/Preferences.axaml b/src/Views/Preferences.axaml
index beb228b65..45b6253d4 100644
--- a/src/Views/Preferences.axaml
+++ b/src/Views/Preferences.axaml
@@ -153,7 +153,7 @@
-
+
+
+
- {
- if (l.IsFolder == r.IsFolder)
- return string.Compare(l.Name, r.Name, StringComparison.Ordinal);
- return l.IsFolder ? -1 : 1;
- });
+ SortNodes(_tree);
var topTree = new List();
MakeRows(topTree, _tree, 0);
@@ -341,12 +336,7 @@ private void OnRowsSelectionChanged(object sender, SelectionChangedEventArgs _)
foreach (var obj in objects)
node.Children.Add(new ViewModels.RevisionFileTreeNode() { Backend = obj });
- node.Children.Sort((l, r) =>
- {
- if (l.IsFolder == r.IsFolder)
- return Models.NumericSort.Compare(l.Name, r.Name);
- return l.IsFolder ? -1 : 1;
- });
+ SortNodes(node.Children);
return node.Children;
}
@@ -365,6 +355,16 @@ private void MakeRows(List rows, List nodes)
+ {
+ nodes.Sort((l, r) =>
+ {
+ if (l.IsFolder == r.IsFolder)
+ return Models.NumericSort.Compare(l.Name, r.Name);
+ return l.IsFolder ? -1 : 1;
+ });
+ }
+
private List _tree = [];
private AvaloniaList _rows = [];
private bool _disableSelectionChangingEvent = false;