"Fossies" - the Fresh Open Source Software Archive 
Member "sift-0.9.0/output.go" (22 Oct 2016, 11078 Bytes) of package /linux/privat/sift-0.9.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "output.go":
0.8.0_vs_0.9.0.
1 // sift
2 // Copyright (C) 2014-2016 Sven Taute
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, version 3 of the License.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16 package main
17
18 import (
19 "fmt"
20 "path/filepath"
21 "strings"
22 )
23
24 func resultHandler() {
25 for result := range global.resultsChan {
26 if options.TargetsOnly {
27 fmt.Println(result.target)
28 continue
29 }
30 global.totalTargetCount++
31 result.applyConditions()
32 printResult(result)
33 }
34 global.resultsDoneChan <- struct{}{}
35 }
36
37 func writeOutput(format string, a ...interface{}) {
38 output := fmt.Sprintf(format, a...)
39 _, err := global.outputFile.Write([]byte(output))
40 if err != nil {
41 errorLogger.Fatalln("cannot write to output file:", err)
42 }
43 }
44
45 func printFilename(filename string, delim string) {
46 if options.ShowFilename == "on" && !options.GroupByFile {
47 if options.OutputUnixPath {
48 filename = filepath.ToSlash(filename)
49 }
50 writeOutput(global.termHighlightFilename+"%s"+global.termHighlightReset+delim, filename)
51 }
52 }
53
54 func printLineno(lineno int64, delim string) {
55 if options.ShowLineNumbers {
56 writeOutput(global.termHighlightLineno+"%d"+global.termHighlightReset+delim, lineno)
57 }
58 }
59
60 func printColumnNo(m *Match) {
61 if options.ShowColumnNumbers {
62 writeOutput("%d"+options.FieldSeparator, m.start-m.lineStart+1)
63 }
64 }
65
66 func printByteOffset(m *Match) {
67 if options.ShowByteOffset {
68 if options.OnlyMatching {
69 writeOutput("%d"+options.FieldSeparator, m.start)
70 } else {
71 writeOutput("%d"+options.FieldSeparator, m.lineStart)
72 }
73 }
74 }
75
76 // printMatch prints the context after the previous match, the context before the match and the match itself
77 func printMatch(match Match, lastMatch Match, target string, lastPrintedLine *int64) {
78 var matchOutput = match.line
79
80 if !options.InvertMatch {
81 if options.Replace != "" {
82 matchOutput = match.match
83 var matchTest string
84 if options.IgnoreCase {
85 tmp := []byte(match.match)
86 for i := 0; i < len(tmp); i++ {
87 bytesToLower(tmp, tmp, len(tmp))
88 }
89 matchTest = string(tmp)
90 } else {
91 matchTest = match.match
92 }
93
94 var res []byte
95 for _, re := range global.matchRegexes {
96 submatchIndexes := re.FindAllStringSubmatchIndex(matchTest, -1)
97 if len(submatchIndexes) > 0 {
98 for _, subIndex := range submatchIndexes {
99 res = re.ExpandString(res, options.Replace, matchOutput, subIndex)
100 }
101 break
102 }
103 }
104
105 matchOutput = string(res)
106 if options.OutputLimit > 0 {
107 var end int
108 if options.OutputLimit > len(matchOutput) {
109 end = len(matchOutput)
110 } else {
111 end = options.OutputLimit
112 }
113 matchOutput = matchOutput[0:end]
114 }
115 } else {
116 // replace option not used
117 if options.OutputLimit > 0 {
118 var end int
119 if options.OutputLimit > len(matchOutput) {
120 end = len(matchOutput)
121 } else {
122 end = options.OutputLimit
123 }
124 matchOutput = matchOutput[0:end]
125 }
126 if options.Color == "on" {
127 start := match.start - match.lineStart
128 end := match.end - match.lineStart
129 if int(end) <= len(matchOutput) {
130 matchOutput = matchOutput[0:end] + global.termHighlightReset + matchOutput[end:]
131 matchOutput = matchOutput[0:start] + global.termHighlightMatch + matchOutput[start:]
132 }
133 }
134 }
135 }
136
137 // print contextAfter of the previous match
138 contextBlockIncomplete := false
139 if lastMatch.contextAfter != nil {
140 contextLines := strings.Split(*lastMatch.contextAfter, "\n")
141 for index, line := range contextLines {
142 var lineno int64
143 if options.Multiline {
144 multilineLineCount := len(strings.Split(lastMatch.line, "\n")) - 1
145 lineno = lastMatch.lineno + int64(index) + 1 + int64(multilineLineCount)
146 } else {
147 lineno = lastMatch.lineno + int64(index) + 1
148 }
149 // line is not part of the current match
150 if lineno < match.lineno {
151 printFilename(target, "-")
152 printLineno(lineno, "-")
153 writeOutput("%s\n", line)
154 *lastPrintedLine = lineno
155 } else {
156 contextBlockIncomplete = true
157 }
158 }
159 }
160 if (lastMatch.contextAfter != nil || match.contextBefore != nil) && !contextBlockIncomplete {
161 if match.lineno-int64(options.ContextBefore) > *lastPrintedLine+1 {
162 // at least one line between the contextAfter of the previous match and the contextBefore of the current match
163 fmt.Fprintln(global.outputFile, "--")
164 }
165 }
166
167 // print contextBefore of the current match
168 if match.contextBefore != nil {
169 contextLines := strings.Split(*match.contextBefore, "\n")
170 for index, line := range contextLines {
171 lineno := match.lineno - int64(len(contextLines)) + int64(index)
172 if lineno > *lastPrintedLine {
173 printFilename(target, "-")
174 printLineno(lineno, "-")
175 writeOutput("%s\n", line)
176 *lastPrintedLine = lineno
177 }
178 }
179 }
180
181 // print current match
182 if options.Multiline {
183 lines := strings.Split(match.line, "\n")
184 if len(lines) > 1 && options.Replace == "" {
185 firstLine := lines[0]
186 lastLine := lines[len(lines)-1]
187 firstLineOffset := match.start - match.lineStart
188 lastLineOffset := int64(len(lastLine)) - (match.lineEnd - match.end)
189
190 // first line of multiline match with partial highlighting
191 printFilename(target, options.FieldSeparator)
192 printLineno(match.lineno, options.FieldSeparator)
193 printColumnNo(&match)
194 printByteOffset(&match)
195 writeOutput("%s%s%s%s\n", firstLine[0:firstLineOffset], global.termHighlightMatch,
196 firstLine[firstLineOffset:len(firstLine)], global.termHighlightReset)
197
198 // lines 2 upto n-1 of multiline match with full highlighting
199 for i := 1; i < len(lines)-1; i++ {
200 line := lines[i]
201 printFilename(target, options.FieldSeparator)
202 printLineno(match.lineno+int64(i), options.FieldSeparator)
203 writeOutput("%s%s%s\n", global.termHighlightMatch, line, global.termHighlightReset)
204 }
205
206 // last line of multiline match with partial highlighting
207 printFilename(target, options.FieldSeparator)
208 printLineno(match.lineno+int64(len(lines))-1, options.FieldSeparator)
209 writeOutput("%s%s%s%s%s", global.termHighlightMatch, lastLine[0:lastLineOffset],
210 global.termHighlightReset, lastLine[lastLineOffset:len(lastLine)], options.OutputSeparator)
211 *lastPrintedLine = match.lineno + int64(len(lines)-1)
212 } else {
213 // single line output in multiline mode or replace option used
214 printFilename(target, options.FieldSeparator)
215 printLineno(match.lineno, options.FieldSeparator)
216 printColumnNo(&match)
217 printByteOffset(&match)
218 writeOutput("%s%s", matchOutput, options.OutputSeparator)
219 *lastPrintedLine = match.lineno + int64(len(lines)-1)
220 }
221 } else {
222 // single line output
223 printFilename(target, options.FieldSeparator)
224 printLineno(match.lineno, options.FieldSeparator)
225 printColumnNo(&match)
226 printByteOffset(&match)
227 writeOutput("%s%s", matchOutput, options.OutputSeparator)
228 *lastPrintedLine = match.lineno
229 }
230 }
231
232 // printResult prints results using printMatch and handles various output options.
233 func printResult(result *Result) {
234 var matchCount int64
235 target := result.target
236 matches := result.matches
237 if options.FilesWithoutMatch {
238 if len(matches) == 0 {
239 writeOutput("%s\n", target)
240 global.totalResultCount++
241 }
242 return
243 }
244 if options.FilesWithMatches && !options.Count {
245 if len(matches) > 0 {
246 writeOutput("%s\n", target)
247 global.totalMatchCount++
248 global.totalResultCount++
249 }
250 return
251 }
252 if options.Count {
253 matchCount = int64(len(matches))
254 if options.Limit != 0 && matchCount > options.Limit {
255 matchCount = options.Limit
256 }
257 if result.streaming {
258 countingMatchesLoop:
259 for matches := range result.matchChan {
260 matchCount += int64(len(matches))
261 if options.Limit != 0 && matchCount >= options.Limit {
262 matchCount = options.Limit
263 break countingMatchesLoop
264 }
265 }
266 }
267 if options.FilesWithMatches {
268 if matchCount > 0 {
269 writeOutput("%s"+options.FieldSeparator+"%d\n", target, matchCount)
270 }
271 } else {
272 if options.ShowFilename == "on" {
273 writeOutput("%s"+options.FieldSeparator, target)
274 }
275 writeOutput("%d\n", matchCount)
276 }
277 global.totalMatchCount += matchCount
278 if matchCount > 0 {
279 global.totalResultCount++
280 }
281 return
282 }
283
284 if len(matches) == 0 {
285 return
286 }
287
288 // print separator between file results if this is not the first result
289 if global.totalMatchCount > 0 {
290 if options.GroupByFile {
291 fmt.Fprintln(global.outputFile, "")
292 } else {
293 if options.ContextBefore > 0 || options.ContextAfter > 0 {
294 fmt.Fprintln(global.outputFile, "--")
295 }
296 }
297 }
298
299 if result.isBinary && !options.BinarySkip && !options.BinaryAsText {
300 filename := result.target
301 if options.OutputUnixPath {
302 filename = filepath.ToSlash(filename)
303 }
304 writeOutput("Binary file matches: %s\n", filename)
305 global.totalMatchCount++
306 global.totalResultCount++
307 return
308 }
309
310 if options.GroupByFile {
311 filename := result.target
312 if options.OutputUnixPath {
313 filename = filepath.ToSlash(filename)
314 }
315 writeOutput(global.termHighlightFilename+"%s\n"+global.termHighlightReset, filename)
316 }
317
318 var lastPrintedLine int64 = -1
319 var lastMatch Match
320
321 // print contextBefore of first match
322 if m := matches[0]; m.contextBefore != nil {
323 contextLines := strings.Split(*m.contextBefore, "\n")
324 for index, line := range contextLines {
325 lineno := m.lineno - int64(len(contextLines)) + int64(index)
326 printFilename(result.target, "-")
327 printLineno(lineno, "-")
328 writeOutput("%s\n", line)
329 lastPrintedLine = lineno
330 }
331 }
332
333 // print matches with their context
334 lastMatch = matches[0]
335 for _, match := range matches {
336 printMatch(match, lastMatch, result.target, &lastPrintedLine)
337 lastMatch = match
338 matchCount++
339 if options.Limit != 0 && matchCount >= options.Limit {
340 break
341 }
342 }
343 if result.streaming {
344 matchStreamLoop:
345 for matches := range result.matchChan {
346 for _, match := range matches {
347 printMatch(match, lastMatch, result.target, &lastPrintedLine)
348 lastMatch = match
349 matchCount++
350 if options.Limit != 0 && matchCount >= options.Limit {
351 break matchStreamLoop
352 }
353 }
354 }
355 }
356
357 // print contextAfter of last match
358 if lastMatch.contextAfter != nil {
359 contextLines := strings.Split(*lastMatch.contextAfter, "\n")
360 for index, line := range contextLines {
361 var lineno int64
362 if options.Multiline {
363 multilineLineCount := len(strings.Split(lastMatch.line, "\n")) - 1
364 lineno = lastMatch.lineno + int64(index) + 1 + int64(multilineLineCount)
365 } else {
366 lineno = lastMatch.lineno + int64(index) + 1
367 }
368 printFilename(result.target, "-")
369 printLineno(lineno, "-")
370 writeOutput("%s\n", line)
371 lastPrintedLine = lineno
372 }
373 }
374
375 global.totalMatchCount += matchCount
376 global.totalResultCount++
377 }