main.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "log"
  6. "os"
  7. "time"
  8. "git.lattuga.net/blallo/ruspa/tree"
  9. "golang.org/x/crypto/ssh/terminal"
  10. )
  11. type UnitValue struct {
  12. unit string
  13. }
  14. func (u *UnitValue) String() string {
  15. return u.unit
  16. }
  17. func (u *UnitValue) Set(value string) error {
  18. switch value {
  19. case "B":
  20. u.unit = "B"
  21. return nil
  22. case "KB":
  23. u.unit = "KB"
  24. return nil
  25. case "MB":
  26. u.unit = "MB"
  27. return nil
  28. case "GB":
  29. u.unit = "GB"
  30. return nil
  31. case "TB":
  32. u.unit = "TB"
  33. return nil
  34. case "PB":
  35. u.unit = "PB"
  36. return nil
  37. default:
  38. return tree.ErrUnknownUnit
  39. }
  40. }
  41. type LimitValue struct {
  42. limit int64
  43. input string
  44. }
  45. func (l *LimitValue) String() string {
  46. return fmt.Sprintf("%d", l.limit)
  47. }
  48. func (l *LimitValue) Set(size string) error {
  49. value, err := tree.ParseSize(size)
  50. l.limit = value
  51. l.input = size
  52. return err
  53. }
  54. func validateLimits(min, max *LimitValue) bool {
  55. if max.limit != 0 && min.limit > max.limit {
  56. fmt.Fprintf(os.Stderr, "Given min-limit (%s) is above max-limit (%s)\n", min.input, max.input)
  57. return false
  58. }
  59. return true
  60. }
  61. func min(a, b int) int {
  62. if a < b {
  63. return a
  64. }
  65. return b
  66. }
  67. func main() {
  68. var path string
  69. var depth int
  70. var root tree.Node
  71. var interval time.Duration
  72. var unit = &UnitValue{unit: "KB"}
  73. var minLimit = &LimitValue{limit: 0}
  74. var maxLimit = &LimitValue{limit: 0}
  75. cli := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
  76. cli.IntVar(&depth, "depth", 0, "Depth to display")
  77. cli.Var(unit, "unit", "Unit in which to report size")
  78. cli.Var(minLimit, "limit-min", "Mininmum size of directories to display, with unit (0 means no limit)")
  79. cli.Var(maxLimit, "limit-max", "Maximum size of directories to display, with unit (0 means no limit)")
  80. cli.DurationVar(&interval, "interval", 100*time.Millisecond, "The update interval")
  81. cli.Usage = func() {
  82. fmt.Fprintf(cli.Output(), "Usage:\n%s [opts] [PATH]\n\n PATH: the root path to start from. Defaults to $PWD.\n\nopts:\n", os.Args[0])
  83. cli.PrintDefaults()
  84. }
  85. cli.Parse(os.Args[1:])
  86. if !validateLimits(minLimit, maxLimit) {
  87. os.Exit(-1)
  88. }
  89. switch narg := cli.NArg(); narg {
  90. case 0:
  91. path = "."
  92. case 1:
  93. path = cli.Args()[0]
  94. default:
  95. fmt.Fprintln(os.Stderr, "Too many arguments")
  96. os.Exit(-1)
  97. }
  98. if depth == 0 || !tree.AnyDirectoryDownThere(path) {
  99. root = tree.NewSingle(path)
  100. } else {
  101. root = tree.NewTop(path)
  102. }
  103. root.SetUnit(unit.String())
  104. root.SetLimits(minLimit.limit, maxLimit.limit)
  105. out := log.New(os.Stdout, "", 0)
  106. go root.Spawn(depth)
  107. _, height, err := terminal.GetSize(int(os.Stdin.Fd()))
  108. if err != nil {
  109. fmt.Fprintln(os.Stderr, "Could not get terminal size")
  110. os.Exit(1)
  111. }
  112. treeDepth := 0
  113. for {
  114. select {
  115. case <-time.After(interval):
  116. if treeDepth != 0 {
  117. out.Printf("\r\033[%dA", treeDepth)
  118. } else {
  119. out.Print("\r\033[A")
  120. }
  121. newTreeDepth := min(root.Depth()+2, height)
  122. out.Print(root)
  123. if newTreeDepth <= treeDepth {
  124. //for i := treeDepth; i < newTreeDepth; i++ {
  125. // out.Print("\n\033[2K")
  126. //}
  127. out.Print("\033[J\033[A")
  128. }
  129. treeDepth = newTreeDepth
  130. if root.Complete() {
  131. return
  132. }
  133. }
  134. }
  135. }