diff --git a/src/SharpIDE.Application/Features/Search/SearchResult.cs b/src/SharpIDE.Application/Features/Search/SearchResult.cs new file mode 100644 index 0000000..9d75f35 --- /dev/null +++ b/src/SharpIDE.Application/Features/Search/SearchResult.cs @@ -0,0 +1,10 @@ +using SharpIDE.Application.Features.SolutionDiscovery; + +namespace SharpIDE.Application.Features.Search; + +public class SearchResult +{ + public required SharpIdeFile File { get; set; } + public required int LineNumber { get; set; } + public required string LineText { get; set; } +} diff --git a/src/SharpIDE.Application/Features/Search/SearchService.cs b/src/SharpIDE.Application/Features/Search/SearchService.cs index 66f15df..179ca10 100644 --- a/src/SharpIDE.Application/Features/Search/SearchService.cs +++ b/src/SharpIDE.Application/Features/Search/SearchService.cs @@ -1,4 +1,5 @@ using System.Collections.Concurrent; +using System.Diagnostics; using System.IO.MemoryMappedFiles; using SharpIDE.Application.Features.SolutionDiscovery.VsPersistence; @@ -6,24 +7,34 @@ namespace SharpIDE.Application.Features.Search; public static class SearchService { - public static async Task FindInFiles(SharpIdeSolutionModel solutionModel, string searchTerm) + public static async Task> FindInFiles(SharpIdeSolutionModel solutionModel, string searchTerm) { if (searchTerm.Length < 4) { - return; + return []; } + + var timer = Stopwatch.StartNew(); var files = solutionModel.AllFiles; - ConcurrentBag results = []; + ConcurrentBag results = []; await Parallel.ForEachAsync(files, async (file, ct) => { await foreach (var (index, line) in File.ReadLinesAsync(file.Path, ct).Index().WithCancellation(ct)) { if (line.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) { - results.Add($"{file.Path} (Line {index + 1}): {line.Trim()}"); + results.Add(new SearchResult + { + File = file, + LineNumber = index + 1, + LineText = line.Trim() + }); } } } ); + timer.Stop(); + Console.WriteLine($"Search completed in {timer.ElapsedMilliseconds} ms. Found {results.Count} results."); + return results.ToList(); } } diff --git a/src/SharpIDE.Godot/Features/Search/SearchResultComponent.cs b/src/SharpIDE.Godot/Features/Search/SearchResultComponent.cs new file mode 100644 index 0000000..d2def30 --- /dev/null +++ b/src/SharpIDE.Godot/Features/Search/SearchResultComponent.cs @@ -0,0 +1,29 @@ +using Godot; +using SharpIDE.Application.Features.Search; + +namespace SharpIDE.Godot.Features.Search; + +public partial class SearchResultComponent : MarginContainer +{ + private Label _matchingLineLabel = null!; + private Label _fileNameLabel = null!; + private Label _lineNumberLabel = null!; + + public SearchResult Result { get; set; } = null!; + + public override void _Ready() + { + _matchingLineLabel = GetNode