diff --git a/src/Spectre.IO.Testing/FakeDirectoryContent.cs b/src/Spectre.IO.Testing/FakeDirectoryContent.cs index 46e381d..40e46db 100644 --- a/src/Spectre.IO.Testing/FakeDirectoryContent.cs +++ b/src/Spectre.IO.Testing/FakeDirectoryContent.cs @@ -13,7 +13,7 @@ internal sealed class FakeDirectoryContent public IReadOnlyDictionary Files => _files; - public FakeDirectoryContent(FakeDirectory owner, PathComparer comparer) + public FakeDirectoryContent(FakeDirectory owner, IPathComparer comparer) { Owner = owner; _directories = new Dictionary(comparer); diff --git a/src/Spectre.IO.Testing/FakeFileSystem.cs b/src/Spectre.IO.Testing/FakeFileSystem.cs index a70c6d3..14eb87e 100644 --- a/src/Spectre.IO.Testing/FakeFileSystem.cs +++ b/src/Spectre.IO.Testing/FakeFileSystem.cs @@ -11,6 +11,10 @@ public sealed class FakeFileSystem : IFileSystem private readonly FakeFileProvider _fileProvider; private readonly FakeDirectoryProvider _directoryProvider; private readonly IEnvironment _environment; + private readonly IPathComparer _comparer; + + /// + public IPathComparer Comparer => _comparer; /// public IFileProvider File => _fileProvider; @@ -28,7 +32,8 @@ public FakeFileSystem(IEnvironment environment) _fileProvider = new FakeFileProvider(tree); _directoryProvider = new FakeDirectoryProvider(tree); - _environment = environment; + _environment = environment ?? throw new ArgumentNullException(nameof(environment)); + _comparer = new PathComparer(_environment.Platform.IsUnix()); } /// diff --git a/src/Spectre.IO.Testing/FakeFileSystemTree.cs b/src/Spectre.IO.Testing/FakeFileSystemTree.cs index e029e7f..33429c5 100644 --- a/src/Spectre.IO.Testing/FakeFileSystemTree.cs +++ b/src/Spectre.IO.Testing/FakeFileSystemTree.cs @@ -10,7 +10,7 @@ internal sealed class FakeFileSystemTree { private readonly FakeDirectory _root; - public PathComparer Comparer { get; } + public IPathComparer Comparer { get; } public FakeFileSystemTree(IEnvironment environment) { diff --git a/src/Spectre.IO/DirectoryPathCollection.cs b/src/Spectre.IO/DirectoryPathCollection.cs index f845acd..df78d52 100644 --- a/src/Spectre.IO/DirectoryPathCollection.cs +++ b/src/Spectre.IO/DirectoryPathCollection.cs @@ -19,13 +19,13 @@ public sealed class DirectoryPathCollection : IEnumerable /// The number of directories in the collection. public int Count => _paths.Count; - internal PathComparer Comparer { get; } + internal IPathComparer Comparer { get; } /// /// Initializes a new instance of the class. /// public DirectoryPathCollection() - : this(PathComparer.Default) + : this(Enumerable.Empty(), null) { } @@ -33,7 +33,7 @@ public DirectoryPathCollection() /// Initializes a new instance of the class. /// /// The comparer. - public DirectoryPathCollection(PathComparer comparer) + public DirectoryPathCollection(IPathComparer comparer) : this(Enumerable.Empty(), comparer) { } @@ -43,7 +43,7 @@ public DirectoryPathCollection(PathComparer comparer) /// /// The paths. public DirectoryPathCollection(IEnumerable paths) - : this(paths, PathComparer.Default) + : this(paths, null) { } @@ -52,10 +52,11 @@ public DirectoryPathCollection(IEnumerable paths) /// /// The paths. /// The comparer. - /// is null. - public DirectoryPathCollection(IEnumerable paths, PathComparer comparer) + public DirectoryPathCollection(IEnumerable paths, IPathComparer? comparer = null) { - Comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); + ArgumentNullException.ThrowIfNull(paths); + + Comparer = comparer ?? PathComparer.Default; _paths = new HashSet(paths, comparer); } diff --git a/src/Spectre.IO/Extensions/DirectoryPathExtensions.cs b/src/Spectre.IO/Extensions/DirectoryPathExtensions.cs index 558f401..b00d074 100644 --- a/src/Spectre.IO/Extensions/DirectoryPathExtensions.cs +++ b/src/Spectre.IO/Extensions/DirectoryPathExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Spectre.IO; @@ -34,4 +35,15 @@ public static DirectoryPath ExpandEnvironmentVariables(this DirectoryPath path, var result = environment.ExpandEnvironmentVariables(path.FullPath); return new DirectoryPath(result); } + + /// + /// Converts an to a . + /// + /// The paths to add to the collection. + /// The comparer to use. If null, the default one is used. + /// A new . + public static DirectoryPathCollection ToPathCollection(this IEnumerable source, IPathComparer? comparer = null) + { + return new DirectoryPathCollection(source, comparer); + } } \ No newline at end of file diff --git a/src/Spectre.IO/Extensions/FilePathExtensions.cs b/src/Spectre.IO/Extensions/FilePathExtensions.cs index 7ed2d9c..3c77e57 100644 --- a/src/Spectre.IO/Extensions/FilePathExtensions.cs +++ b/src/Spectre.IO/Extensions/FilePathExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Spectre.IO; @@ -34,4 +35,15 @@ public static FilePath ExpandEnvironmentVariables(this FilePath path, IEnvironme var result = environment.ExpandEnvironmentVariables(path.FullPath); return new FilePath(result); } + + /// + /// Converts an to a . + /// + /// The paths to add to the collection. + /// The comparer to use. If null, the default one is used. + /// A new . + public static FilePathCollection ToPathCollection(this IEnumerable source, IPathComparer? comparer = null) + { + return new FilePathCollection(source, comparer); + } } \ No newline at end of file diff --git a/src/Spectre.IO/Extensions/PathExtensions.cs b/src/Spectre.IO/Extensions/PathExtensions.cs new file mode 100644 index 0000000..a46f906 --- /dev/null +++ b/src/Spectre.IO/Extensions/PathExtensions.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace Spectre.IO; + +/// +/// Contains extensions for . +/// +public static class PathExtensions +{ + /// + /// Converts an to a . + /// + /// The paths to add to the collection. + /// The comparer to use. If null, the default one is used. + /// A new . + public static PathCollection ToPathCollection(this IEnumerable source, IPathComparer? comparer = null) + { + return new PathCollection(source, comparer); + } +} \ No newline at end of file diff --git a/src/Spectre.IO/FilePathCollection.cs b/src/Spectre.IO/FilePathCollection.cs index 3a400f6..0c4fadb 100644 --- a/src/Spectre.IO/FilePathCollection.cs +++ b/src/Spectre.IO/FilePathCollection.cs @@ -19,13 +19,13 @@ public sealed class FilePathCollection : IEnumerable /// The number of files in the collection. public int Count => _paths.Count; - internal PathComparer Comparer { get; } + internal IPathComparer Comparer { get; } /// /// Initializes a new instance of the class. /// public FilePathCollection() - : this(PathComparer.Default) + : this(Enumerable.Empty(), null) { } @@ -33,7 +33,7 @@ public FilePathCollection() /// Initializes a new instance of the class. /// /// The comparer. - public FilePathCollection(PathComparer comparer) + public FilePathCollection(IPathComparer comparer) : this(Enumerable.Empty(), comparer) { } @@ -43,7 +43,7 @@ public FilePathCollection(PathComparer comparer) /// /// The paths. public FilePathCollection(IEnumerable paths) - : this(paths, PathComparer.Default) + : this(paths, null) { } @@ -53,10 +53,12 @@ public FilePathCollection(IEnumerable paths) /// The paths. /// The comparer. /// is null. - public FilePathCollection(IEnumerable paths, PathComparer comparer) + public FilePathCollection(IEnumerable paths, IPathComparer? comparer = null) { - Comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); - _paths = new HashSet(paths, comparer); + ArgumentNullException.ThrowIfNull(paths); + + Comparer = comparer ?? PathComparer.Default; + _paths = new HashSet(paths, Comparer); } /// diff --git a/src/Spectre.IO/FileSystem.cs b/src/Spectre.IO/FileSystem.cs index d1784aa..01dde23 100644 --- a/src/Spectre.IO/FileSystem.cs +++ b/src/Spectre.IO/FileSystem.cs @@ -1,4 +1,6 @@ -namespace Spectre.IO; +using System; + +namespace Spectre.IO; /// /// A physical file system implementation. @@ -10,6 +12,9 @@ public sealed class FileSystem : IFileSystem /// public static FileSystem Shared { get; } = new(); + /// + public IPathComparer Comparer { get; } + /// public IFileProvider File { get; } @@ -19,8 +24,10 @@ public sealed class FileSystem : IFileSystem /// /// Initializes a new instance of the class. /// - public FileSystem() + /// The path comparer to use. + public FileSystem(IPathComparer? comparer = null) { + Comparer = comparer ?? PathComparer.Default; File = new FileProvider(); Directory = new DirectoryProvider(); } diff --git a/src/Spectre.IO/Globber.cs b/src/Spectre.IO/Globber.cs index 4f436eb..3e54f1e 100644 --- a/src/Spectre.IO/Globber.cs +++ b/src/Spectre.IO/Globber.cs @@ -10,6 +10,7 @@ namespace Spectre.IO; /// public sealed class Globber : IGlobber { + private readonly IPathComparer _comparer; private readonly GlobParser _parser; private readonly GlobVisitor _visitor; @@ -25,16 +26,10 @@ public sealed class Globber : IGlobber /// The environment. public Globber(IFileSystem fileSystem, IEnvironment environment) { - if (fileSystem == null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - - if (environment is null) - { - throw new ArgumentNullException(nameof(environment)); - } + ArgumentNullException.ThrowIfNull(fileSystem); + ArgumentNullException.ThrowIfNull(environment); + _comparer = fileSystem.Comparer; _parser = new GlobParser(environment); _visitor = new GlobVisitor(fileSystem, environment); } @@ -42,25 +37,21 @@ public Globber(IFileSystem fileSystem, IEnvironment environment) /// public IEnumerable Match(string pattern, GlobberSettings settings) { - if (pattern == null) - { - throw new ArgumentNullException(nameof(pattern)); - } + ArgumentNullException.ThrowIfNull(settings); + ArgumentNullException.ThrowIfNull(pattern); if (string.IsNullOrWhiteSpace(pattern)) { return Enumerable.Empty(); } - // Make sure we got some settings. - settings ??= new GlobberSettings(); - // Parse the pattern into an AST. - var root = _parser.Parse(pattern, settings.Comparer ?? PathComparer.Default); + var comparer = settings.Comparer ?? _comparer; + var root = _parser.Parse(pattern, comparer); // Visit all nodes in the parsed patterns and filter the result. return _visitor.Walk(root, settings) .Select(x => x.Path) - .Distinct(settings.Comparer ?? PathComparer.Default); + .Distinct(comparer); } } \ No newline at end of file diff --git a/src/Spectre.IO/GlobberSettings.cs b/src/Spectre.IO/GlobberSettings.cs index e641d33..eb3de9c 100644 --- a/src/Spectre.IO/GlobberSettings.cs +++ b/src/Spectre.IO/GlobberSettings.cs @@ -25,5 +25,5 @@ public sealed class GlobberSettings /// /// Gets or sets the comparer to use. /// - public PathComparer? Comparer { get; set; } + public IPathComparer? Comparer { get; set; } } \ No newline at end of file diff --git a/src/Spectre.IO/IFileSystem.cs b/src/Spectre.IO/IFileSystem.cs index 23a8542..473577b 100644 --- a/src/Spectre.IO/IFileSystem.cs +++ b/src/Spectre.IO/IFileSystem.cs @@ -5,6 +5,11 @@ /// public interface IFileSystem { + /// + /// Gets the file system's . + /// + IPathComparer Comparer { get; } + /// /// Gets the belonging to this >. /// diff --git a/src/Spectre.IO/IPathComparer.cs b/src/Spectre.IO/IPathComparer.cs new file mode 100644 index 0000000..9d02088 --- /dev/null +++ b/src/Spectre.IO/IPathComparer.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Spectre.IO; + +/// +/// Compares instances. +/// +public interface IPathComparer : IEqualityComparer, IComparer +{ + /// + /// Gets a value indicating whether comparison is case sensitive. + /// + /// + /// true if comparison is case sensitive; otherwise, false. + /// + bool IsCaseSensitive { get; } +} \ No newline at end of file diff --git a/src/Spectre.IO/Internal/Globbing/GlobParser.cs b/src/Spectre.IO/Internal/Globbing/GlobParser.cs index c6e9649..66f1d1f 100644 --- a/src/Spectre.IO/Internal/Globbing/GlobParser.cs +++ b/src/Spectre.IO/Internal/Globbing/GlobParser.cs @@ -13,7 +13,7 @@ public GlobParser(IEnvironment environment) _environment = environment; } - public GlobNode Parse(string pattern, PathComparer comparer) + public GlobNode Parse(string pattern, IPathComparer comparer) { return Parse(new GlobParserContext(pattern, comparer)); } diff --git a/src/Spectre.IO/Internal/Globbing/GlobParserContext.cs b/src/Spectre.IO/Internal/Globbing/GlobParserContext.cs index 50a4c5d..b9d6984 100644 --- a/src/Spectre.IO/Internal/Globbing/GlobParserContext.cs +++ b/src/Spectre.IO/Internal/Globbing/GlobParserContext.cs @@ -13,7 +13,7 @@ internal sealed class GlobParserContext public GlobToken? CurrentToken { get; private set; } public RegexOptions Options { get; } - public GlobParserContext(string pattern, PathComparer comparer) + public GlobParserContext(string pattern, IPathComparer comparer) { _buffer = GlobTokenizer.Tokenize(pattern); diff --git a/src/Spectre.IO/PathCollection.cs b/src/Spectre.IO/PathCollection.cs index 9cf7687..d5b3565 100644 --- a/src/Spectre.IO/PathCollection.cs +++ b/src/Spectre.IO/PathCollection.cs @@ -19,13 +19,13 @@ public sealed class PathCollection : IEnumerable /// The number of paths in the collection. public int Count => _paths.Count; - internal PathComparer Comparer { get; } + internal IPathComparer Comparer { get; } /// /// Initializes a new instance of the class. /// public PathCollection() - : this(PathComparer.Default) + : this(Enumerable.Empty(), null) { } @@ -33,7 +33,7 @@ public PathCollection() /// Initializes a new instance of the class. /// /// The comparer. - public PathCollection(PathComparer comparer) + public PathCollection(IPathComparer comparer) : this(Enumerable.Empty(), comparer) { } @@ -43,7 +43,7 @@ public PathCollection(PathComparer comparer) /// /// The paths. public PathCollection(IEnumerable paths) - : this(paths, PathComparer.Default) + : this(paths, null) { } @@ -53,9 +53,11 @@ public PathCollection(IEnumerable paths) /// The paths. /// The comparer. /// is null. - public PathCollection(IEnumerable paths, PathComparer comparer) + public PathCollection(IEnumerable paths, IPathComparer? comparer = null) { - Comparer = comparer ?? throw new ArgumentNullException(nameof(comparer)); + ArgumentNullException.ThrowIfNull(paths); + + Comparer = comparer ?? PathComparer.Default; _paths = new HashSet(paths, comparer); } diff --git a/src/Spectre.IO/PathComparer.cs b/src/Spectre.IO/PathComparer.cs index 018df11..f58aaaa 100644 --- a/src/Spectre.IO/PathComparer.cs +++ b/src/Spectre.IO/PathComparer.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using Spectre.IO.Internal; namespace Spectre.IO; @@ -8,12 +6,11 @@ namespace Spectre.IO; /// /// Compares instances. /// -public sealed class PathComparer : IEqualityComparer, IComparer +public sealed class PathComparer : IPathComparer { /// /// Gets the default path comparer. /// - [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")] public static PathComparer Default { get; } = new PathComparer(EnvironmentHelper.IsUnix()); ///