1package script
2
3import (
4	"bufio"
5	"fmt"
6	"strings"
7
8	"github.com/hashicorp/go-multierror"
9)
10
11// Count represents the output of `wc` shell command.
12type Count struct {
13	// Stream can be used to pipe the output of wc.
14	Stream
15	// Count the number of lines, words and chars in the input.
16	Lines, Words, Chars int
17}
18
19// Wc counts the number of lines, words and characters.
20//
21// Shell command: `wc`.
22func (s Stream) Wc() Count {
23	defer s.Close()
24
25	var (
26		count  Count
27		errors *multierror.Error
28	)
29	scanner := bufio.NewScanner(s)
30	for scanner.Scan() {
31		count.Lines++
32		count.Chars += len(scanner.Text()) + 1
33		count.Words += countWords(scanner.Text())
34	}
35	if err := scanner.Err(); err != nil {
36		errors = multierror.Append(errors, fmt.Errorf("scanning stream: %s", err))
37	}
38
39	count.Stream = Stream{
40		stage: "wc",
41		r:     strings.NewReader(count.String()),
42	}
43	return count
44}
45
46func (c Count) String() string {
47	return fmt.Sprintf("%d\t%d\t%d\n", c.Lines, c.Words, c.Chars)
48}
49
50func countWords(s string) int {
51	// TODO: improve performance.
52	return len(strings.Fields(s))
53}
54