193 lines
6.4 KiB
C#
193 lines
6.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
namespace HashCalculator.GUI
|
|
{
|
|
internal class FileSystemSuggestions
|
|
{
|
|
private static readonly Dictionary<string, InputEntryType> Mapping = new(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
{ ".big", InputEntryType.BigFile },
|
|
{ ".xml", InputEntryType.XmlFile },
|
|
{ ".w3x", InputEntryType.XmlFile },
|
|
{ ".manifest", InputEntryType.ManifestFile },
|
|
{ ".xsd", InputEntryType.XsdFile },
|
|
};
|
|
|
|
private Search _search = new Search();
|
|
|
|
public IEnumerable<InputEntry> ProvideFileSystemSuggestions(string? path)
|
|
{
|
|
var empty = Enumerable.Empty<InputEntry>();
|
|
|
|
if (string.IsNullOrWhiteSpace(path) || path == null)
|
|
{
|
|
return empty;
|
|
}
|
|
|
|
path = Environment.ExpandEnvironmentVariables(path);
|
|
|
|
if (path.IndexOfAny(Path.GetInvalidPathChars()) != -1)
|
|
{
|
|
return empty;
|
|
}
|
|
|
|
_search.Update(path);
|
|
|
|
if (!_search.IsValidPath)
|
|
{
|
|
return empty;
|
|
}
|
|
|
|
var currentFiles = new List<InputEntry>();
|
|
string? fileName;
|
|
string? currentFullPath = null;
|
|
try
|
|
{
|
|
var currentFile = new FileInfo(path);
|
|
fileName = currentFile.Name;
|
|
if (currentFile.Exists)
|
|
{
|
|
currentFullPath = currentFile.FullName;
|
|
var type = CheckExtension(currentFile);
|
|
if (type is InputEntryType entryType)
|
|
{
|
|
currentFiles.Add(new InputEntry(entryType, path, currentFullPath));
|
|
}
|
|
currentFiles.Add(new InputEntry(InputEntryType.BinaryFile, path, currentFullPath));
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return empty;
|
|
}
|
|
|
|
var alternatives = empty;
|
|
try
|
|
{
|
|
var directories = from directory in _search.AllDirectories
|
|
where directory.Name.StartsWith(fileName, StringComparison.OrdinalIgnoreCase)
|
|
select new InputEntry(InputEntryType.Path, _search.GetInputStyleName(directory), directory.FullName);
|
|
|
|
var otherFiles = from file in _search.AllFiles
|
|
where file.Name.StartsWith(fileName, StringComparison.OrdinalIgnoreCase)
|
|
where file.FullName != currentFullPath
|
|
select file;
|
|
|
|
var supportedFiles = from file in otherFiles
|
|
let type = CheckExtension(file)
|
|
where type.HasValue
|
|
select new InputEntry(type.Value, _search.GetInputStyleName(file), file.FullName);
|
|
|
|
var binaryFiles = from file in otherFiles
|
|
select new InputEntry(InputEntryType.BinaryFile, _search.GetInputStyleName(file), file.FullName);
|
|
|
|
alternatives = supportedFiles.Concat(directories).Concat(binaryFiles).ToArray();
|
|
}
|
|
catch { }
|
|
|
|
return currentFiles.Concat(alternatives);
|
|
}
|
|
|
|
private static InputEntryType? CheckExtension(FileInfo info)
|
|
{
|
|
if (Mapping.TryGetValue(info.Extension, out var type))
|
|
{
|
|
return type;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal sealed class Search
|
|
{
|
|
private string? _inputBaseDirectory;
|
|
public bool IsValidPath => _inputBaseDirectory != null;
|
|
public IEnumerable<DirectoryInfo> AllDirectories { get; private set; }
|
|
public IEnumerable<FileInfo> AllFiles { get; private set; }
|
|
|
|
public Search()
|
|
{
|
|
AllDirectories = Array.Empty<DirectoryInfo>();
|
|
AllFiles = Array.Empty<FileInfo>();
|
|
}
|
|
|
|
public string GetInputStyleName(FileSystemInfo entry)
|
|
{
|
|
if (_inputBaseDirectory == null)
|
|
{
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
return Path.Combine(_inputBaseDirectory, entry.Name);
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Performance", "CA1031")]
|
|
public void Update(string path)
|
|
{
|
|
string? newBaseDirectory = null;
|
|
try
|
|
{
|
|
if (Path.GetFileName(path).IndexOfAny(Path.GetInvalidFileNameChars()) != -1)
|
|
{
|
|
_inputBaseDirectory = null;
|
|
return;
|
|
}
|
|
|
|
newBaseDirectory = Path.GetDirectoryName(path);
|
|
var rootDirectory = Path.GetPathRoot(path);
|
|
if(string.IsNullOrEmpty(newBaseDirectory) && !string.IsNullOrEmpty(rootDirectory))
|
|
{
|
|
var last = rootDirectory.LastOrDefault();
|
|
if (last != Path.DirectorySeparatorChar && last != Path.AltDirectorySeparatorChar)
|
|
{
|
|
rootDirectory += Path.DirectorySeparatorChar;
|
|
}
|
|
newBaseDirectory = rootDirectory;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
_inputBaseDirectory = null;
|
|
}
|
|
|
|
if (newBaseDirectory == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (newBaseDirectory == _inputBaseDirectory)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_inputBaseDirectory = newBaseDirectory;
|
|
Update();
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Performance", "CA1031")]
|
|
private void Update()
|
|
{
|
|
AllDirectories = Enumerable.Empty<DirectoryInfo>();
|
|
AllFiles = Enumerable.Empty<FileInfo>();
|
|
try
|
|
{
|
|
var actualPath = _inputBaseDirectory!.Length == 0
|
|
? "."
|
|
: _inputBaseDirectory;
|
|
var directory = new DirectoryInfo(actualPath);
|
|
if (directory.Exists)
|
|
{
|
|
AllDirectories = directory.EnumerateDirectories();
|
|
AllFiles = directory.EnumerateFiles();
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
}
|