using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.IO.Abstractions; using System.Linq; 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 string [] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; private static readonly List ImageExtensions = new List { ".JPG", ".JPEG", ".JPE", ".BMP", ".GIF", ".PNG" }; private static readonly List ExecutableExtensions = new List { ".EXE", ".BAT" }; /// /// Initializes a new instance of the class. /// /// The directory of path to wrap. /// public FileSystemInfoStats (IFileSystemInfo fsi, CultureInfo culture) { this.FileSystemInfo = fsi; this.LastWriteTime = fsi.LastWriteTime; if (fsi is IFileInfo fi) { this.MachineReadableLength = fi.Length; this.HumanReadableLength = GetHumanReadableFileSize (this.MachineReadableLength, culture); this.Type = fi.Extension; } else { this.HumanReadableLength = string.Empty; this.Type = "dir"; } } /// /// Gets the wrapped (directory or file). /// public IFileSystemInfo FileSystemInfo { get; } public string HumanReadableLength { get; } public long MachineReadableLength { get; } public DateTime? LastWriteTime { get; } public string Type { 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 string Name => this.IsParent ? ".." : this.FileSystemInfo.Name; public bool IsDir () { return this.Type == "dir"; } public bool IsImage () { return this.FileSystemInfo is IFileSystemInfo f && ImageExtensions.Contains ( f.Extension, StringComparer.InvariantCultureIgnoreCase); } public bool IsExecutable () { // TODO: handle linux executable status return this.FileSystemInfo is IFileSystemInfo f && ExecutableExtensions.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 bytes"; } int mag = (int)Math.Log (value, ByteConversion); double adjustedSize = value / Math.Pow (1000, mag); return string.Format (culture.NumberFormat,"{0:n2} {1}", adjustedSize, SizeSuffixes [mag]); } } }