-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
123 lines (109 loc) · 2.17 KB
/
main.go
File metadata and controls
123 lines (109 loc) · 2.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// wc - word, line, character, and byte count.
package main
import (
"solod.dev/so/flag"
"solod.dev/so/fmt"
"solod.dev/so/io"
"solod.dev/so/os"
)
type counts struct {
lines int
words int
bytes int
chars int
}
var showLines bool
var showWords bool
var showBytes bool
var showChars bool
func main() {
parseFlags()
if !showLines && !showWords && !showBytes && !showChars {
showLines = true
showWords = true
showBytes = true
}
args := flag.Args()
if len(args) == 0 {
c := wc(os.Stdin)
printCounts(c, "")
os.Exit(0)
}
exitCode := 0
var total counts
for _, fname := range args {
f, err := os.Open(fname)
if err != nil {
fmt.Fprintf(os.Stderr, "wc: %s: No such file or directory\n", fname)
exitCode = 1
continue
}
c := wc(&f)
printCounts(c, fname)
total.lines += c.lines
total.words += c.words
total.bytes += c.bytes
total.chars += c.chars
f.Close()
}
if len(args) > 1 {
printCounts(total, "total")
}
os.Exit(exitCode)
}
// parseFlags parses command-line flags.
func parseFlags() {
flag.BoolVar(&showLines, "l", false, "count lines")
flag.BoolVar(&showWords, "w", false, "count words")
flag.BoolVar(&showBytes, "c", false, "count bytes")
flag.BoolVar(&showChars, "m", false, "count characters")
flag.Parse()
}
// wc counts the lines, words, bytes, and characters in r.
func wc(r io.Reader) counts {
var c counts
buf := make([]byte, 4096)
inWord := false
for {
n, err := r.Read(buf)
c.bytes += n
for i := range n {
b := buf[i]
if b == '\n' {
c.lines++
}
if b == ' ' || b == '\t' || b == '\n' || b == '\r' || b == '\f' || b == '\v' {
inWord = false
} else if !inWord {
inWord = true
c.words++
}
if showChars && (b&0xC0) != 0x80 { // start of UTF-8 character
c.chars++
}
}
if err != nil {
break
}
}
return c
}
// printCounts prints the counts in c, optionally with a filename.
func printCounts(c counts, fname string) {
if showLines {
fmt.Printf("%8d", c.lines)
}
if showWords {
fmt.Printf("%8d", c.words)
}
if showBytes {
fmt.Printf("%8d", c.bytes)
}
if showChars {
fmt.Printf("%8d", c.chars)
}
if fname != "" {
fmt.Printf(" %s", fname)
}
fmt.Printf("\n")
}