using System.Globalization; using System.IO.Abstractions; using Terminal.Gui.Resources; namespace Terminal.Gui; /// /// 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 ByteConversion = 1024; private static readonly List ExecutableExtensions = new () { ".EXE", ".BAT" }; private static readonly List ImageExtensions = new () { ".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; } /// 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; public string Type { get; } public bool IsExecutable () { // TODO: handle linux executable status return FileSystemInfo is IFileSystemInfo f && ExecutableExtensions.Contains ( f.Extension, StringComparer.InvariantCultureIgnoreCase ); } public bool IsImage () { return FileSystemInfo is IFileSystemInfo f && ImageExtensions.Contains ( f.Extension, StringComparer.InvariantCultureIgnoreCase ); } 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, ByteConversion); double adjustedSize = value / Math.Pow (1000, mag); return string.Format (culture.NumberFormat, "{0:n2} {1}", adjustedSize, SizeSuffixes [mag]); } }