-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconsole.go
132 lines (109 loc) · 2.79 KB
/
console.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
package main
import (
"bufio"
"fmt"
"io"
"sort"
"strings"
"github.com/mauricioklein/text-search-engine/ranking"
"github.com/mauricioklein/text-search-engine/report"
)
// QuitSentence defines the sentence, read from the
// input stream, to quit the console
const QuitSentence = ":quit"
// Console defines an instance of the
// interactive console
type Console struct {
Processor ranking.Processor
Reporter report.Reporter
InputStream *bufio.Reader
OutputStream *bufio.Writer
ErrorStream *bufio.Writer
}
// NewConsole creates a new instance of Console
func NewConsole(processor ranking.Processor, reporter report.Reporter, inputStream io.Reader, outputStream io.Writer, errStream io.Writer) Console {
inputBuffer := bufio.NewReader(inputStream)
outputBuffer := bufio.NewWriter(outputStream)
errBuffer := bufio.NewWriter(errStream)
return Console{
Processor: processor,
Reporter: reporter,
InputStream: inputBuffer,
OutputStream: outputBuffer,
ErrorStream: errBuffer,
}
}
// Write writes a string to the console's output stream
func (c Console) Write(line string) {
c.OutputStream.Write([]byte(line))
c.OutputStream.Flush()
}
func (c Console) Error(line string) {
c.ErrorStream.Write([]byte(line))
c.ErrorStream.Flush()
}
// Read reads a string from the console's input stream
func (c Console) Read() (string, error) {
rawInput, err := c.InputStream.ReadString('\n')
if err != nil {
return "", err
}
return strings.Replace(rawInput, "\n", "", -1), nil
}
// Flush flushes the content of output stream
func (c Console) Flush() {
c.OutputStream.Flush()
c.ErrorStream.Flush()
}
// Run executes and controls the IO of
// the console with the user
func (c Console) Run() {
for {
c.Write("search> ")
userInput, err := c.Read()
if err != nil {
c.Error(fmt.Sprintf("Failed to read input: %s", err))
continue
}
if isStopCondition(userInput) {
break
}
// calculate the ranks
ranks := c.Processor.Calculate(userInput)
// order ranks by score/filename
sort.Sort(
sort.Reverse(
ranking.ByScoreAndName(ranks),
),
)
// get only the top 10
ranks = selectTop(ranks, 10)
// print out the results
for _, rank := range ranks {
c.ReportRank(rank)
}
// flush the output stream
c.Flush()
}
}
// ReportRank reports a given result
func (c Console) ReportRank(rr ranking.RankResult) {
c.Reporter.Report(
c.OutputStream,
rr.File.Name(),
rr.Score,
)
}
// selectTop returns the "n" first ranks,
// or the entire ranks if n > len(ranks)
func selectTop(ranks []ranking.RankResult, n int) []ranking.RankResult {
if n <= len(ranks) {
return ranks[:n]
}
return ranks
}
// isStopCondition checks if the input stream contains
// the console's stop sentence
func isStopCondition(userInput string) bool {
return userInput == QuitSentence
}