123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- package main
- import (
- "flag"
- "fmt"
- "log"
- "os"
- "time"
- "git.lattuga.net/blallo/ruspa/tree"
- "golang.org/x/crypto/ssh/terminal"
- )
- type UnitValue struct {
- unit string
- }
- func (u *UnitValue) String() string {
- return u.unit
- }
- func (u *UnitValue) Set(value string) error {
- switch value {
- case "B":
- u.unit = "B"
- return nil
- case "KB":
- u.unit = "KB"
- return nil
- case "MB":
- u.unit = "MB"
- return nil
- case "GB":
- u.unit = "GB"
- return nil
- case "TB":
- u.unit = "TB"
- return nil
- case "PB":
- u.unit = "PB"
- return nil
- default:
- return tree.ErrUnknownUnit
- }
- }
- type LimitValue struct {
- limit int64
- input string
- }
- func (l *LimitValue) String() string {
- return fmt.Sprintf("%d", l.limit)
- }
- func (l *LimitValue) Set(size string) error {
- value, err := tree.ParseSize(size)
- l.limit = value
- l.input = size
- return err
- }
- func validateLimits(min, max *LimitValue) bool {
- if max.limit != 0 && min.limit > max.limit {
- fmt.Fprintf(os.Stderr, "Given min-limit (%s) is above max-limit (%s)\n", min.input, max.input)
- return false
- }
- return true
- }
- func min(a, b int) int {
- if a < b {
- return a
- }
- return b
- }
- func main() {
- var path string
- var depth int
- var root tree.Node
- var interval time.Duration
- var unit = &UnitValue{unit: "KB"}
- var minLimit = &LimitValue{limit: 0}
- var maxLimit = &LimitValue{limit: 0}
- cli := flag.NewFlagSet(os.Args[0], flag.ExitOnError)
- cli.IntVar(&depth, "depth", 0, "Depth to display")
- cli.Var(unit, "unit", "Unit in which to report size")
- cli.Var(minLimit, "limit-min", "Mininmum size of directories to display, with unit (0 means no limit)")
- cli.Var(maxLimit, "limit-max", "Maximum size of directories to display, with unit (0 means no limit)")
- cli.DurationVar(&interval, "interval", 100*time.Millisecond, "The update interval")
- cli.Usage = func() {
- 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])
- cli.PrintDefaults()
- }
- cli.Parse(os.Args[1:])
- if !validateLimits(minLimit, maxLimit) {
- os.Exit(-1)
- }
- switch narg := cli.NArg(); narg {
- case 0:
- path = "."
- case 1:
- path = cli.Args()[0]
- default:
- fmt.Fprintln(os.Stderr, "Too many arguments")
- os.Exit(-1)
- }
- if depth == 0 || !tree.AnyDirectoryDownThere(path) {
- root = tree.NewSingle(path)
- } else {
- root = tree.NewTop(path)
- }
- root.SetUnit(unit.String())
- root.SetLimits(minLimit.limit, maxLimit.limit)
- out := log.New(os.Stdout, "", 0)
- go root.Spawn(depth)
- _, height, err := terminal.GetSize(int(os.Stdin.Fd()))
- if err != nil {
- fmt.Fprintln(os.Stderr, "Could not get terminal size")
- os.Exit(1)
- }
- treeDepth := 0
- for {
- select {
- case <-time.After(interval):
- if treeDepth != 0 {
- out.Printf("\r\033[%dA", treeDepth)
- } else {
- out.Print("\r\033[A")
- }
- newTreeDepth := min(root.Depth()+2, height)
- out.Print(root)
- if newTreeDepth <= treeDepth {
- //for i := treeDepth; i < newTreeDepth; i++ {
- // out.Print("\n\033[2K")
- //}
- out.Print("\033[J\033[A")
- }
- treeDepth = newTreeDepth
- if root.Complete() {
- return
- }
- }
- }
- }
|