mirror of
https://github.com/haven1433/HexManiacAdvance.git
synced 2026-05-20 04:08:04 -05:00
Add 'matchExactCase' parameter for ViewPort.Find
This commit is contained in:
parent
cde4328bc0
commit
a278d91f9f
|
|
@ -24,8 +24,10 @@ namespace HavenSoft.HexManiac.Core.Models {
|
|||
private static readonly int CapitalE = PCSString.PCS.IndexOf("E");
|
||||
private static readonly int LowerE = PCSString.PCS.IndexOf("e");
|
||||
private readonly byte match1, match2;
|
||||
public static ISearchByte Create(byte value) {
|
||||
if (value == CapitalE || value == CapitalEWithAccent || value == LowerE || value == LowerEWithAccent) {
|
||||
public static ISearchByte Create(byte value, bool matchExactCase) {
|
||||
if (matchExactCase) {
|
||||
return new ExactMatchSearchByte(value);
|
||||
} else if (value == CapitalE || value == CapitalEWithAccent || value == LowerE || value == LowerEWithAccent) {
|
||||
return MatchESearchByte.Instance;
|
||||
} else {
|
||||
return new PCSSearchByte(value);
|
||||
|
|
@ -51,5 +53,11 @@ namespace HavenSoft.HexManiac.Core.Models {
|
|||
private MatchESearchByte() { }
|
||||
public bool Match(byte value) => value == CapitalE || value == CapitalEWithAccent || value == LowerE || value == LowerEWithAccent;
|
||||
}
|
||||
|
||||
private class ExactMatchSearchByte : ISearchByte {
|
||||
private byte value;
|
||||
public ExactMatchSearchByte(byte value) => this.value = value;
|
||||
public bool Match(byte value) => value == this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
|
||||
public void ExpandSelection(int x, int y) => ForEach(child => child.ExpandSelection(x, y));
|
||||
|
||||
public IReadOnlyList<(int start, int end)> Find(string search) => new (int, int)[0];
|
||||
public IReadOnlyList<(int start, int end)> Find(string search, bool matchExactCase = false) => new (int, int)[0];
|
||||
|
||||
public void FindAllSources(int x, int y) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
|
||||
public void ExpandSelection(int x, int y) { }
|
||||
|
||||
public IReadOnlyList<(int start, int end)> Find(string search) => throw new NotImplementedException();
|
||||
public IReadOnlyList<(int start, int end)> Find(string search, bool matchExactCase = false) => throw new NotImplementedException();
|
||||
|
||||
public void FindAllSources(int x, int y) { }
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
bool IsSelected(Point point);
|
||||
bool IsTable(Point point);
|
||||
|
||||
IReadOnlyList<(int start, int end)> Find(string search);
|
||||
IReadOnlyList<(int start, int end)> Find(string search, bool matchExactCase = false);
|
||||
IChildViewPort CreateChildView(int startAddress, int endAddress);
|
||||
void FollowLink(int x, int y);
|
||||
void ExpandSelection(int x, int y);
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
public IChildViewPort CreateChildView(int startAddress, int endAddress) => throw new NotImplementedException();
|
||||
|
||||
// if asked to search the search results... just don't
|
||||
public IReadOnlyList<(int, int)> Find(string search) => new (int, int)[0];
|
||||
public IReadOnlyList<(int, int)> Find(string search, bool matchExactCase = false) => new (int, int)[0];
|
||||
|
||||
public bool UseCustomHeaders {
|
||||
get => children.FirstOrDefault()?.UseCustomHeaders ?? false;
|
||||
|
|
|
|||
|
|
@ -1458,14 +1458,15 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
|
||||
#region Find
|
||||
|
||||
public IReadOnlyList<(int start, int end)> Find(string rawSearch) {
|
||||
public IReadOnlyList<(int start, int end)> Find(string rawSearch, bool matchExactCase = false) {
|
||||
var results = new List<(int start, int end)>();
|
||||
var cleanedSearchString = rawSearch.ToUpper();
|
||||
var cleanedSearchString = rawSearch;
|
||||
if (!matchExactCase) cleanedSearchString = rawSearch.ToUpper();
|
||||
var searchBytes = new List<ISearchByte>();
|
||||
|
||||
// it might be a string with no quotes, we should check for matches for that.
|
||||
if (cleanedSearchString.Length > 3 && !cleanedSearchString.Contains(StringDelimeter) && !cleanedSearchString.All(AllHexCharacters.Contains)) {
|
||||
results.AddRange(FindUnquotedText(cleanedSearchString, searchBytes));
|
||||
results.AddRange(FindUnquotedText(cleanedSearchString, searchBytes, matchExactCase));
|
||||
}
|
||||
|
||||
// it might be a matched-word
|
||||
|
|
@ -1548,14 +1549,14 @@ namespace HavenSoft.HexManiac.Core.ViewModels {
|
|||
}
|
||||
}
|
||||
|
||||
private IEnumerable<(int start, int end)> FindUnquotedText(string cleanedSearchString, List<ISearchByte> searchBytes) {
|
||||
private IEnumerable<(int start, int end)> FindUnquotedText(string cleanedSearchString, List<ISearchByte> searchBytes, bool matchExactCase) {
|
||||
var pcsBytes = PCSString.Convert(cleanedSearchString);
|
||||
pcsBytes.RemoveAt(pcsBytes.Count - 1); // remove the 0xFF that was added, since we're searching for a string segment instead of a whole string.
|
||||
|
||||
// only search for the string if every character in the search string is allowed
|
||||
if (pcsBytes.Count != cleanedSearchString.Length) yield break;
|
||||
|
||||
searchBytes.AddRange(pcsBytes.Select(PCSSearchByte.Create));
|
||||
searchBytes.AddRange(pcsBytes.Select(b => PCSSearchByte.Create(b, matchExactCase)));
|
||||
var textResults = Model.Search(searchBytes).ToList();
|
||||
Model.ConsiderResultsAsTextRuns(history.CurrentChange, textResults);
|
||||
foreach (var result in textResults) {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
public class FindTests {
|
||||
private static Func<int, int, ChildViewPort> CreateCreateChildView(Func<IViewPort> tab) => (start, end) => new ChildViewPort(tab(), InstantDispatch.Instance, BaseViewModelTestClass.Singletons);
|
||||
private static ViewPort NewViewPort(IDataModel model) => new ViewPort("test.gba", model, InstantDispatch.Instance, BaseViewModelTestClass.Singletons);
|
||||
private static Func<string, bool, (int, int)[]> DefaultFind(params (int, int)[] results) => (text, matchExactCase) => results;
|
||||
|
||||
[Fact]
|
||||
public void FindCanFindSingle() {
|
||||
|
|
@ -45,7 +46,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
var tab = new StubViewPort();
|
||||
var editor = new EditorViewModel(new StubFileSystem()) { tab };
|
||||
|
||||
tab.Find = str => new (int, int)[0];
|
||||
tab.Find = DefaultFind();
|
||||
editor.Find.Execute("something");
|
||||
|
||||
Assert.True(editor.ShowError);
|
||||
|
|
@ -58,7 +59,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
var editor = new EditorViewModel(new StubFileSystem()) { tab };
|
||||
string gotoArg = string.Empty;
|
||||
|
||||
tab.Find = str => new[] { (0x54, 0x54) };
|
||||
tab.Find = DefaultFind((0x54, 0x54));
|
||||
tab.Goto = new StubCommand { CanExecute = arg => true, Execute = arg => gotoArg = (string)arg };
|
||||
editor.Find.Execute("something");
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
var editor = new EditorViewModel(new StubFileSystem()) { tab };
|
||||
var count = 0;
|
||||
|
||||
tab.Find = str => new[] { (0x54, 0x54), (0x154, 0x154) };
|
||||
tab.Find = DefaultFind((0x54, 0x54), (0x154, 0x154));
|
||||
tab.Model = new BasicModel(new byte[0x200]);
|
||||
tab.CreateChildView = (int startAddress, int endAddress) => {
|
||||
var child = new ChildViewPort(tab, InstantDispatch.Instance, BaseViewModelTestClass.Singletons);
|
||||
|
|
@ -92,7 +93,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
int gotoCount = 0;
|
||||
StubViewPort tab = null;
|
||||
tab = new StubViewPort {
|
||||
Find = str => new[] { (0x54, 0x54), (0x154, 0x154) },
|
||||
Find = DefaultFind((0x54, 0x54), (0x154, 0x154)),
|
||||
Model = new BasicModel(new byte[0x200]),
|
||||
Goto = new StubCommand { CanExecute = arg => true, Execute = arg => gotoCount++ },
|
||||
CreateChildView = (start, end) => new ChildViewPort(tab, InstantDispatch.Instance, BaseViewModelTestClass.Singletons),
|
||||
|
|
@ -114,7 +115,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
public void EditorFindNextDoesNotSwitchTabs() {
|
||||
StubViewPort tab1 = null;
|
||||
tab1 = new StubViewPort {
|
||||
Find = query => new[] { (0x60, 0x60) },
|
||||
Find = DefaultFind((0x60, 0x60)),
|
||||
Goto = new StubCommand(),
|
||||
Model = new BasicModel(new byte[0x200]),
|
||||
CreateChildView = CreateCreateChildView(() => tab1),
|
||||
|
|
@ -124,7 +125,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
};
|
||||
StubViewPort tab2 = null;
|
||||
tab2 = new StubViewPort {
|
||||
Find = query => new[] { (0x50, 0x50), (0x70, 0x70) },
|
||||
Find = DefaultFind((0x50, 0x50), (0x70, 0x70)),
|
||||
Goto = new StubCommand(),
|
||||
Model = new BasicModel(new byte[0x200]),
|
||||
CreateChildView = CreateCreateChildView(() => tab2),
|
||||
|
|
@ -152,7 +153,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
public void FindResultsHasHeadersAndGaps() {
|
||||
StubViewPort tab = null;
|
||||
tab = new StubViewPort {
|
||||
Find = query => new[] { (0x50, 0x50), (0x70, 0x70) },
|
||||
Find = DefaultFind((0x50, 0x50), (0x70, 0x70)),
|
||||
Goto = new StubCommand(),
|
||||
Model = new BasicModel(new byte[0x200]),
|
||||
CreateChildView = CreateCreateChildView(() => tab),
|
||||
|
|
@ -173,7 +174,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
public void FindClosesAfterRun() {
|
||||
StubViewPort tab = null;
|
||||
tab = new StubViewPort {
|
||||
Find = query => new[] { (0x50, 0x50), (0x70, 0x70) },
|
||||
Find = DefaultFind((0x50, 0x50), (0x70, 0x70)),
|
||||
Goto = new StubCommand(),
|
||||
Model = new BasicModel(new byte[0x200]),
|
||||
CreateChildView = CreateCreateChildView(() => tab),
|
||||
|
|
@ -234,7 +235,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
var tab1 = new StubTabContent();
|
||||
var editor = new EditorViewModel(new StubFileSystem()) { tab0, tab1 };
|
||||
|
||||
tab0.Find = query => new[] { (0x50, 0x50) };
|
||||
tab0.Find = DefaultFind((0x50, 0x50));
|
||||
editor.Find.Execute("search");
|
||||
|
||||
Assert.Equal(0, editor.SelectedIndex);
|
||||
|
|
@ -253,7 +254,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
var editor = new EditorViewModel(new StubFileSystem());
|
||||
StubViewPort tab = null;
|
||||
tab = new StubViewPort {
|
||||
Find = query => new[] { (0x50, 0x50) },
|
||||
Find = DefaultFind((0x50, 0x50)),
|
||||
Goto = new StubCommand(),
|
||||
CreateChildView = CreateCreateChildView(() => tab),
|
||||
Headers = new ObservableCollection<string> { "00", "01", "02", "03" },
|
||||
|
|
@ -273,7 +274,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
var editor = new EditorViewModel(new StubFileSystem());
|
||||
StubViewPort tab = null;
|
||||
tab = new StubViewPort {
|
||||
Find = query => new[] { (0x50, 0x50), (0x70, 0x70) },
|
||||
Find = DefaultFind((0x50, 0x50), (0x70, 0x70)),
|
||||
Goto = new StubCommand(),
|
||||
Model = new BasicModel(new byte[0x200]),
|
||||
CreateChildView = CreateCreateChildView(() => tab),
|
||||
|
|
@ -404,7 +405,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
[Fact]
|
||||
public void SameModelDoesNotGetSearchedMultipleTimes() {
|
||||
int findCalls = 0;
|
||||
IReadOnlyList<(int, int)> Find(string input) {
|
||||
IReadOnlyList<(int, int)> Find(string input, bool matchExactCase = false) {
|
||||
findCalls += 1;
|
||||
return new List<(int, int)>();
|
||||
}
|
||||
|
|
@ -422,7 +423,7 @@ namespace HavenSoft.HexManiac.Tests {
|
|||
[Fact]
|
||||
public void DifferentModelsAllGetSearched() {
|
||||
int findCalls = 0;
|
||||
IReadOnlyList<(int, int)> Find(string input) {
|
||||
IReadOnlyList<(int, int)> Find(string input, bool matchExactCase = false) {
|
||||
findCalls += 1;
|
||||
return new List<(int, int)>();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user