Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Gs-itisitcat committed May 22, 2024
2 parents b37c7c2 + d23a7e4 commit e53f574
Show file tree
Hide file tree
Showing 13 changed files with 284 additions and 284 deletions.
14 changes: 5 additions & 9 deletions local-repository-listing/ListLocalReposCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ You can use glob patterns.
/// <param name="fuzzyFinderArgs">Arguments to pass to the fuzzy finder process.</param>
/// <returns>The result of the command execution.</returns>
[RootCommand]
public int Lepol(
public async ValueTask<int> Lepol(
[Option(0, ArgumentDescription)] string arg = "",
[Option("r", RootDescription)] string root = "",
[Option("l", ListOnlyDescription)] bool listOnly = false,
Expand All @@ -52,15 +52,11 @@ public int Lepol(
? new NonRecursiveRepositorySearcher(rootDirectories, excludePaths ?? [], excludeNames ?? [])
: new RecursiveRepositorySearcher(rootDirectories, excludePaths ?? [], excludeNames ?? []);

ISearchResultProcessor processor = listOnly
? new ConsoleOutputProcessor(arg)
: new FZFProcessor(arg, fuzzyFinderArgs ?? []);
IResultLister listable = listOnly
? new ConsoleOutputLister(searcher, arg)
: new FZFLister(searcher, arg, fuzzyFinderArgs ?? []);


// Pass the cancellation token source of search cancellation token to the fuzzy finder process
// to cancel the search when the fuzzy finder process is terminated.
var cts = new CancellationTokenSource();
Context.CancellationToken.Register(cts.Cancel);
return processor.ProcessSearchResult(searcher.Search(cts.Token), cts);
return await listable.ExecuteListing(Context.CancellationToken);
}
}
58 changes: 58 additions & 0 deletions local-repository-listing/ResultLister/ConsoleOutputLister.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using LocalRepositoryListing.Searcher;
using R3;
namespace LocalRepositoryListing.ResultProcessor;

/// <summary>
/// Initializes a new instance of the <see cref="ConsoleOutputLister"/> class with the specified search pattern.
/// </summary>
/// <param name="searcher">The <see cref="ISearcher"/> object representing the searcher.</param>
/// <param name="searchPattern">The search pattern to match against the full names of the directories.</param>
public class ConsoleOutputLister(ISearcher searcher, string searchPattern) : IResultLister
{
/// <summary>
/// The search pattern to match against the full names of the directories.
/// </summary>
private readonly string _searchPattern = searchPattern;
private readonly ISearcher _searcher = searcher;

public async ValueTask<int> ExecuteListing(CancellationToken cancellationToken)
{
using var searchSubscription = _searcher.SearchResults.Subscribe(d =>
{
var fullName = d.FullName.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);

if (string.IsNullOrEmpty(fullName) || (!string.IsNullOrEmpty(_searchPattern) && !fullName.Contains(_searchPattern)))
{
return;
}

Console.WriteLine(fullName);
});

cancellationToken.Register(searchSubscription.Dispose);

try
{
var searchTask = _searcher.Search(cancellationToken);

while (
!cancellationToken.IsCancellationRequested
&& !searchTask.IsCompleted
&& !searchTask.IsFaulted
&& !searchTask.IsCanceled
)
{
await Task.Delay(100, cancellationToken);
}
}
catch (OperationCanceledException)
{
searchSubscription.Dispose();
Console.Error.WriteLine("Search was cancelled.");
return 1;
}
searchSubscription.Dispose();

return 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
namespace LocalRepositoryListing.ResultProcessor;
using LocalRepositoryListing.Searcher;

public class FZFProcessor(string? searchPattern, string[] args) : FuzzyFinderProcessorBase(arguments: [
namespace LocalRepositoryListing.ResultProcessor;

/// <summary>
/// Represents the processor for the FZF fuzzy finder.
/// </summary>
/// <seealso cref="FuzzyFinderListerBase" />
/// <seealso cref="IResultLister" />
public class FZFLister(ISearcher searcher, string? searchPattern, string[] args) : FuzzyFinderListerBase(searcher, arguments: [
"--ansi",
"--header",
"\"Select a git repository\"",
Expand All @@ -18,7 +25,7 @@ public class FZFProcessor(string? searchPattern, string[] args) : FuzzyFinderPro
"--query",
$"{(string.IsNullOrWhiteSpace(searchPattern) ? "\"\"" : searchPattern)}",
..args
])
]), IResultLister
{
private static readonly string _fuzzyFinderName = "fzf";
public override string FuzzyFinderName => _fuzzyFinderName;
Expand Down
72 changes: 72 additions & 0 deletions local-repository-listing/ResultLister/FuzzyFinderListerBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.Collections.ObjectModel;
using System.Diagnostics;
using LocalRepositoryListing.Searcher;
using R3;

namespace LocalRepositoryListing.ResultProcessor;

/// <summary>
/// Represents the base class for a fuzzy finder process.
/// </summary>
public abstract class FuzzyFinderListerBase : IResultLister
{
/// <summary>
/// Gets the name of the fuzzy finder.
/// </summary>
public abstract string FuzzyFinderName { get; }

/// <summary>
/// Gets the arguments for the processor.
/// </summary>
public ReadOnlyCollection<string> Arguments => _arguments.AsReadOnly();
private readonly string[] _arguments = [];

private readonly ProcessStartInfo _processStartInfo;
private readonly ISearcher _searcher;

/// <summary>
/// Initializes a new instance of the <see cref="FuzzyFinderListerBase"/> class.
/// </summary>
/// <param name="searcher">The <see cref="ISearcher"/> object representing the searcher.</param>
/// <param name="arguments">The arguments for the processor.</param>
public FuzzyFinderListerBase(ISearcher searcher, string[] arguments)
{
_arguments = arguments;
_processStartInfo = new ProcessStartInfo(FuzzyFinderName)
{
// UseShellExecute is set to false to start the child process without using a shell
UseShellExecute = false,
RedirectStandardInput = true,
// For Non-ASCII characters
StandardInputEncoding = System.Text.Encoding.UTF8,
Arguments = string.Join(" ", arguments),
};

_searcher = searcher;
}

public ValueTask<int> ExecuteListing(CancellationToken cancellationToken)
{
using var process = Process.Start(_processStartInfo);
if (process == null)
{
Console.Error.WriteLine($"Failed to start {FuzzyFinderName}");
return ValueTask.FromResult(1);
}

using var input = TextWriter.Synchronized(process.StandardInput);
if (input == null)
{
Console.Error.WriteLine($"Failed to get StandardInput of {FuzzyFinderName}");
return ValueTask.FromResult(1);
}

using var searchSubscription = _searcher.SearchResults.Subscribe(d => input.WriteLine(d.FullName.Replace(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)));

_ = _searcher.Search(cancellationToken);

process.WaitForExit();

return ValueTask.FromResult(process.ExitCode);
}
}
11 changes: 11 additions & 0 deletions local-repository-listing/ResultLister/IResultLister.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace LocalRepositoryListing.ResultProcessor;

public interface IResultLister
{
/// <summary>
/// Executes the listing operation.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A <see cref="ValueTask{TResult}"/> representing the asynchronous operation, yielding the result of the listing operation.</returns>
public ValueTask<int> ExecuteListing(CancellationToken cancellationToken);
}
60 changes: 0 additions & 60 deletions local-repository-listing/ResultProcessor/ConsoleOutputProcessor.cs

This file was deleted.

This file was deleted.

12 changes: 0 additions & 12 deletions local-repository-listing/ResultProcessor/ISearchResultProcessor.cs

This file was deleted.

Loading

0 comments on commit e53f574

Please sign in to comment.