123456module cli78import os9import src.fmt10import src.remote11import src.snapshot12import src.view1314fn working(text string) {15 if os.is_atty(2) == 0 {16 return17 }18 width := line_width()19 shown := fmt.fit(' ${text}', width)20 21 22 eprint('\r${fmt.dim(shown)}${' '.repeat(width - fmt.visible_width(shown))}')23 flush_stderr()24}2526fn done_working() {27 if os.is_atty(2) != 0 {28 eprint('\r${' '.repeat(line_width())}\r')29 flush_stderr()30 }31}323334fn line_width() int {35 _, columns := view.terminal_size()36 return if columns > 1 { columns - 1 } else { 79 }37}383940fn reading() snapshot.Hashing {41 return snapshot.Hashing{42 on: fn (done int, total int) {43 if done % 100 == 1 {44 working('reading files · ${done}')45 }46 }47 }48}49505152struct Watched {53 label string54 55 56 whole bool57mut:58 inner remote.Backend59 received int60 sent int61 listed map[string]int62 fetched map[string]int63 kind string64}656667fn watched_backend(label string) !remote.Backend {68 return remote.Backend(watch(label, this_machine_backend()!))69}7071fn watch(label string, backend remote.Backend) Watched {72 return Watched{73 label: label74 inner: backend75 }76}7778fn (mut w Watched) show() {79 mut text := w.label80 if w.kind != '' {81 text += ' · ${w.kind} ${w.fetched[w.kind]} of ${w.listed[w.kind]}'82 }83 if w.sent > 0 {84 text += ' · ${w.sent} sent'85 }86 if w.kind == '' && w.received > 0 {87 text += ' · ${w.received} received'88 }89 working(text)90}9192fn (mut w Watched) get(key string) !remote.Object {93 object := w.inner.get(key)!94 kind := key_kind(os.dir(key))95 if kind in w.listed {96 w.kind = kind97 w.fetched[kind]++98 } else {99 w.received++100 }101 w.show()102 return object103}104105fn (mut w Watched) list(prefix string) ![]string {106 keys := w.inner.list(prefix)!107 if w.whole {108 w.listed[key_kind(prefix)] += keys.len109 }110 return keys111}112113114115fn key_kind(folder string) string {116 kind := os.base(folder)117 return if kind == 'objects' { 'files' } else { kind }118}119120fn (mut w Watched) put_if_absent(key string, body []u8) !bool {121 put := w.inner.put_if_absent(key, body)!122 w.sent++123 w.show()124 return put125}126127fn (mut w Watched) put_if_match(key string, body []u8, tag string) !bool {128 put := w.inner.put_if_match(key, body, tag)!129 w.sent++130 w.show()131 return put132}133134fn (mut w Watched) delete(key string) ! {135 w.inner.delete(key)!136 w.sent++137 w.show()138}