Skip to content

Commit a11f55e

Browse files
committed
A progress bar will be shown while the remote resource is being read
1 parent 1163438 commit a11f55e

File tree

6 files changed

+218
-44
lines changed

6 files changed

+218
-44
lines changed

daze.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929

3030
"github.com/mohanson/daze/lib/doa"
3131
"github.com/mohanson/daze/lib/lru"
32+
"github.com/mohanson/daze/lib/pretty"
3233
)
3334

3435
// ============================================================================
@@ -1035,7 +1036,11 @@ func OpenFile(name string) (io.ReadCloser, error) {
10351036
if err != nil {
10361037
return nil, err
10371038
}
1038-
return resp.Body, nil
1039+
return &ReadWriteCloser{
1040+
Reader: &PrettyReader{E: 0, F: uint64(resp.ContentLength), R: resp.Body},
1041+
Writer: nil,
1042+
Closer: resp.Body,
1043+
}, nil
10391044
}
10401045
return os.Open(name)
10411046
}
@@ -1052,6 +1057,24 @@ func (r *RandomReader) Read(p []byte) (int, error) {
10521057
return len(p), nil
10531058
}
10541059

1060+
// The PrettyReader struct represents a custom reader that keeps track of read bytes and prints progress.
1061+
type PrettyReader struct {
1062+
E uint64 // Total number of bytes read so far
1063+
F uint64 // Total capacity of the input stream
1064+
R io.Reader // The underlying reader that this object wraps around
1065+
}
1066+
1067+
// The Read method reads data from the wrapped reader and prints progress updates.
1068+
func (r *PrettyReader) Read(p []byte) (int, error) {
1069+
if r.E == 0 {
1070+
pretty.PrintProgress(0)
1071+
}
1072+
n, err := r.R.Read(p)
1073+
r.E += uint64(n)
1074+
pretty.PrintProgress(float64(r.E) / float64(r.F))
1075+
return n, err
1076+
}
1077+
10551078
// Salt converts the stupid password passed in by the user to 32-sized byte array.
10561079
func Salt(s string) []byte {
10571080
h := sha256.Sum256([]byte(s))

lib/pretty/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Pretty
2+
3+
Utilities to prettify console output.
4+
5+
**Progress**
6+
7+
```
8+
$ go run cmd/progress/main.go
9+
10+
2025/03/12 09:53:42 pretty: [=========================> ] 59%
11+
```
12+
13+
14+
15+
**Table**
16+
17+
```
18+
$ go run cmd/table/main.go
19+
20+
2025/03/12 09:51:57 pretty: City name Area Population Annual Rainfall
21+
2025/03/12 09:51:57 pretty: -----------------------------------------
22+
2025/03/12 09:51:57 pretty: Adelaide 1295 1158259 600.5
23+
2025/03/12 09:51:57 pretty: Brisbane 5905 1857594 1146.4
24+
2025/03/12 09:51:57 pretty: Darwin 112 120900 1714.7
25+
2025/03/12 09:51:57 pretty: Hobart 1357 205556 619.5
26+
2025/03/12 09:51:57 pretty: Melbourne 1566 3806092 646.9
27+
2025/03/12 09:51:57 pretty: Perth 5386 1554769 869.4
28+
2025/03/12 09:51:57 pretty: Sydney 2058 4336374 1214.8
29+
```

lib/pretty/cmd/progress/main.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package main
2+
3+
import (
4+
"time"
5+
6+
"github.com/mohanson/daze/lib/pretty"
7+
)
8+
9+
func main() {
10+
pretty.PrintProgress(0)
11+
for i := range 100 {
12+
time.Sleep(time.Millisecond * 16)
13+
pretty.PrintProgress(float64(i+1) / 100)
14+
}
15+
pretty.PrintProgress(1)
16+
}

lib/pretty/cmd/table/main.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package main
2+
3+
import (
4+
"github.com/mohanson/daze/lib/pretty"
5+
)
6+
7+
func main() {
8+
pretty.PrintTable([][]string{
9+
{"City name", "Area", "Population", "Annual Rainfall"},
10+
{"Adelaide", "1295", "1158259", "600.5"},
11+
{"Brisbane", "5905", "1857594", "1146.4"},
12+
{"Darwin", "112", "120900", "1714.7"},
13+
{"Hobart", "1357", "205556", "619.5"},
14+
{"Melbourne", "1566", "3806092", "646.9"},
15+
{"Perth", "5386", "1554769", "869.4"},
16+
{"Sydney", "2058", "4336374", "1214.8"},
17+
})
18+
}

lib/pretty/pretty.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package pretty
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"strings"
8+
9+
"github.com/mohanson/daze/lib/doa"
10+
)
11+
12+
// PrintProgress draw a progress bar in the terminal. The percent takes values ​​from 0 to 1.
13+
func PrintProgress(percent float64) {
14+
doa.Doa(0 <= percent && percent <= 1)
15+
out, _ := os.Stdout.Stat()
16+
// Identify if we are displaying to a terminal or through a pipe or redirect.
17+
if out.Mode()&os.ModeCharDevice == os.ModeCharDevice {
18+
// Save or restore cursor position.
19+
if percent == 0 {
20+
log.Writer().Write([]byte{0x1b, 0x37})
21+
}
22+
if percent != 0 {
23+
log.Writer().Write([]byte{0x1b, 0x38})
24+
}
25+
}
26+
cap := int(percent * 44)
27+
buf := []byte("[ ] 000%")
28+
for i := 1; i < cap+1; i++ {
29+
buf[i] = '='
30+
}
31+
buf[1+cap] = '>'
32+
num := fmt.Sprintf("%3d", int(percent*100))
33+
buf[48] = num[0]
34+
buf[49] = num[1]
35+
buf[50] = num[2]
36+
log.Println("pretty:", string(buf))
37+
}
38+
39+
// PrintTable easily draw tables in terminal/console applications from a list of lists of strings.
40+
func PrintTable(data [][]string) {
41+
size := make([]int, len(data[0]))
42+
for _, r := range data {
43+
for j, c := range r {
44+
size[j] = max(size[j], len(c))
45+
}
46+
}
47+
line := make([]string, len(data[0]))
48+
for j, c := range data[0] {
49+
l := size[j]
50+
line[j] = strings.Repeat(" ", l-len(c)) + c
51+
}
52+
log.Println("pretty:", strings.Join(line, " "))
53+
for i, c := range size {
54+
line[i] = strings.Repeat("-", c)
55+
}
56+
log.Println("pretty:", strings.Join(line, "-"))
57+
for _, r := range data[1:] {
58+
for j, c := range r {
59+
l := size[j]
60+
line[j] = strings.Repeat(" ", l-len(c)) + c
61+
}
62+
log.Println("pretty:", strings.Join(line, " "))
63+
}
64+
}

0 commit comments

Comments
 (0)