-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
151 lines (130 loc) · 3.14 KB
/
main.go
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"unicode/utf8"
flag "github.com/spf13/pflag"
)
type options struct {
bytet bool
character bool
word bool
line bool
help bool
args []string
}
type counts struct {
bytes int
chars int
words int
lines int
}
func helpMessage(originalProgramname string) string {
programName := filepath.Base(originalProgramname)
return fmt.Sprintf(`%s [OPTIONS] [FILEs...|DIRs...]
OPTIONS
-b, --byte バイト数表示
-c, --character 文字数表示
-l, --line 行数表示
-n, --no-ignore ignoreファイルを参照しない
-h, --help ヘルプ表示
ARGUMENTS
FILEs... ファイル名の指定.zip/tar/tar.gz/tar.bz2/jar/warファイルも可
DIRs... ディレクトリの中のファイルをカウントする
`, programName)
}
func parseArgs(args []string) (*options, error) {
opts := &options{}
flags := flag.NewFlagSet("oilio", flag.ContinueOnError)
flags.Usage = func() { fmt.Println(helpMessage(args[0])) }
flags.BoolVarP(&opts.bytet, "byte", "b", false, "バイト数")
flags.BoolVarP(&opts.character, "character", "c", false, "文字数")
flags.BoolVarP(&opts.word, "word", "w", false, "単語数")
flags.BoolVarP(&opts.line, "line", "l", false, "行数")
flags.BoolVarP(&opts.help, "help", "h", false, "ヘルプ表示")
if err := flags.Parse(args); err != nil {
return nil, err
}
if !opts.bytet && !opts.character && !opts.word && !opts.line {
opts.bytet = true
opts.character = true
opts.word = true
opts.line = true
}
opts.args = flags.Args()[1:]
return opts, nil
}
func printer(o *options, c counts, filename string) {
if o.line {
fmt.Printf("line: %5d ", c.lines)
}
if o.bytet {
fmt.Printf("byte: %5d ", c.bytes)
}
if o.character {
fmt.Printf("char: %5d ", c.chars)
}
if o.word {
fmt.Printf("word: %5d ", c.words)
}
fmt.Println(filename)
}
func Count(o *options, filenames []string) {
var c counts
for _, filename := range filenames {
fileInfo, _ := os.Stat(filename)
if fileInfo.IsDir() {
/*
root := fileInfo.Name()
fmt.Println(filename)
*/
rootFiles, _ := ioutil.ReadDir(filename)
for _, rootFile := range rootFiles {
if rootFile.IsDir() {
continue
}
fullPath := filepath.Join(filename, rootFile.Name())
rfp, err := os.Open(fullPath)
if err != nil {
continue
}
r, _ := ioutil.ReadAll(rfp)
c.lines = bytes.Count(r, []byte{'\n'})
c.bytes = len(r)
c.chars = utf8.RuneCountInString(string(r))
c.words = len(bytes.Fields(r))
printer(o, c, fullPath)
}
continue
}
fp, err := os.Open(filename)
if err != nil {
continue
}
a, _ := ioutil.ReadAll(fp)
c.lines = bytes.Count(a, []byte{'\n'})
c.bytes = len(a)
c.chars = utf8.RuneCountInString(string(a))
c.words = len(bytes.Fields(a))
printer(o, c, filename)
}
}
func goMain(args []string) int {
opts, err := parseArgs(args)
if err != nil {
fmt.Printf("%s", err.Error())
}
if opts.help || len(args) == 1 {
fmt.Println(helpMessage(args[0]))
return 0
}
Count(opts, opts.args)
return 0
}
func main() {
status := goMain(os.Args)
os.Exit(status)
}