FileSystemInfoStats.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.IO.Abstractions;
  6. using System.Linq;
  7. namespace Terminal.Gui {
  8. /// <summary>
  9. /// Wrapper for <see cref="FileSystemInfo"/> that contains additional information
  10. /// (e.g. <see cref="IsParent"/>) and helper methods.
  11. /// </summary>
  12. internal class FileSystemInfoStats {
  13. /* ---- Colors used by the ls command line tool ----
  14. *
  15. * Blue: Directory
  16. * Green: Executable or recognized data file
  17. * Cyan (Sky Blue): Symbolic link file
  18. * Yellow with black background: Device
  19. * Magenta (Pink): Graphic image file
  20. * Red: Archive file
  21. * Red with black background: Broken link
  22. */
  23. private const long ByteConversion = 1024;
  24. private static readonly string [] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
  25. private static readonly List<string> ImageExtensions = new List<string> { ".JPG", ".JPEG", ".JPE", ".BMP", ".GIF", ".PNG" };
  26. private static readonly List<string> ExecutableExtensions = new List<string> { ".EXE", ".BAT" };
  27. /// <summary>
  28. /// Initializes a new instance of the <see cref="FileSystemInfoStats"/> class.
  29. /// </summary>
  30. /// <param name="fsi">The directory of path to wrap.</param>
  31. /// <param name="culture"></param>
  32. public FileSystemInfoStats (IFileSystemInfo fsi, CultureInfo culture)
  33. {
  34. this.FileSystemInfo = fsi;
  35. this.LastWriteTime = fsi.LastWriteTime;
  36. if (fsi is IFileInfo fi) {
  37. this.MachineReadableLength = fi.Length;
  38. this.HumanReadableLength = GetHumanReadableFileSize (this.MachineReadableLength, culture);
  39. this.Type = fi.Extension;
  40. } else {
  41. this.HumanReadableLength = string.Empty;
  42. this.Type = "dir";
  43. }
  44. }
  45. /// <summary>
  46. /// Gets the wrapped <see cref="FileSystemInfo"/> (directory or file).
  47. /// </summary>
  48. public IFileSystemInfo FileSystemInfo { get; }
  49. public string HumanReadableLength { get; }
  50. public long MachineReadableLength { get; }
  51. public DateTime? LastWriteTime { get; }
  52. public string Type { get; }
  53. /// <summary>
  54. /// Gets or Sets a value indicating whether this instance represents
  55. /// the parent of the current state (i.e. "..").
  56. /// </summary>
  57. public bool IsParent { get; internal set; }
  58. public string Name => this.IsParent ? ".." : this.FileSystemInfo.Name;
  59. public bool IsDir ()
  60. {
  61. return this.Type == "dir";
  62. }
  63. public bool IsImage ()
  64. {
  65. return this.FileSystemInfo is IFileSystemInfo f &&
  66. ImageExtensions.Contains (
  67. f.Extension,
  68. StringComparer.InvariantCultureIgnoreCase);
  69. }
  70. public bool IsExecutable ()
  71. {
  72. // TODO: handle linux executable status
  73. return this.FileSystemInfo is IFileSystemInfo f &&
  74. ExecutableExtensions.Contains (
  75. f.Extension,
  76. StringComparer.InvariantCultureIgnoreCase);
  77. }
  78. private static string GetHumanReadableFileSize (long value, CultureInfo culture)
  79. {
  80. if (value < 0) {
  81. return "-" + GetHumanReadableFileSize (-value, culture);
  82. }
  83. if (value == 0) {
  84. return "0.0 bytes";
  85. }
  86. int mag = (int)Math.Log (value, ByteConversion);
  87. double adjustedSize = value / Math.Pow (1000, mag);
  88. return string.Format (culture.NumberFormat,"{0:n2} {1}", adjustedSize, SizeSuffixes [mag]);
  89. }
  90. }
  91. }