using System.Globalization; using System.IO.Abstractions; namespace Terminal.Gui.FileServices; /// /// Wrapper for that contains additional information (e.g. ) /// and helper methods. /// internal class FileSystemInfoStats { /* ---- Colors used by the ls command line tool ---- * * Blue: Directory * Green: Executable or recognized data file * Cyan (Sky Blue): Symbolic link file * Yellow with black background: Device * Magenta (Pink): Graphic image file * Red: Archive file * Red with black background: Broken link */ private const long BYTE_CONVERSION = 1024; private static readonly List _executableExtensions = [".EXE", ".BAT"]; private static readonly List _imageExtensions = [ ".JPG", ".JPEG", ".JPE", ".BMP", ".GIF", ".PNG" ]; private static readonly string [] _sizeSuffixes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]; /// Initializes a new instance of the class. /// The directory of path to wrap. /// public FileSystemInfoStats (IFileSystemInfo? fsi, CultureInfo culture) { FileSystemInfo = fsi; LastWriteTime = fsi?.LastWriteTime; if (fsi is IFileInfo fi) { MachineReadableLength = fi.Length; HumanReadableLength = GetHumanReadableFileSize (MachineReadableLength, culture); Type = fi.Extension; } else { HumanReadableLength = string.Empty; Type = $"<{Strings.fdDirectory}>"; IsDir = true; } } /// Gets the wrapped (directory or file). public IFileSystemInfo? FileSystemInfo { get; } public string HumanReadableLength { get; } public bool IsDir { get; } public bool IsExecutable () { // TODO: handle linux executable status return FileSystemInfo is { } && _executableExtensions.Contains ( FileSystemInfo.Extension, StringComparer.InvariantCultureIgnoreCase ); } public bool IsImage () { return FileSystemInfo is { } && _imageExtensions.Contains ( FileSystemInfo.Extension, StringComparer.InvariantCultureIgnoreCase ); } /// Gets or Sets a value indicating whether this instance represents the parent of the current state (i.e. ".."). public bool IsParent { get; internal set; } public DateTime? LastWriteTime { get; } public long MachineReadableLength { get; } public string Name => IsParent ? ".." : FileSystemInfo?.Name ?? string.Empty; public string Type { get; } private static string GetHumanReadableFileSize (long value, CultureInfo culture) { if (value < 0) { return "-" + GetHumanReadableFileSize (-value, culture); } if (value == 0) { return "0.0 B"; } var mag = (int)Math.Log (value, BYTE_CONVERSION); double adjustedSize = value / Math.Pow (1000, mag); return string.Format (culture.NumberFormat, "{0:n2} {1}", adjustedSize, _sizeSuffixes [mag]); } }