-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support custom split functions in createCommandReaders
Default is (still) split by line, but in some cases interesting command output spans multiple lines (e.g. commit messages) This also provides a split function definition that splits by a string.
- Loading branch information
Showing
3 changed files
with
111 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package io | ||
|
||
import "bytes" | ||
|
||
// This file is meant as extension point for go standard library file bufio/scan.go | ||
|
||
// SplitAt returns a function that splits cmd output by a given string. | ||
// The returned function implements the type SplitFunc as defined in bufio/scan.go! | ||
// Tribute: https://stackoverflow.com/a/57232670/21511203 | ||
func SplitAt(substring string) func(data []byte, atEOF bool) (advance int, token []byte, err error) { | ||
searchBytes := []byte(substring) | ||
searchLen := len(searchBytes) | ||
return func(data []byte, atEOF bool) (advance int, token []byte, err error) { | ||
dataLen := len(data) | ||
|
||
// Return nothing if at end of file and no data passed | ||
if atEOF && dataLen == 0 { | ||
return 0, nil, nil | ||
} | ||
|
||
// Find next separator and return token | ||
if i := bytes.Index(data, searchBytes); i >= 0 { | ||
return i + searchLen, data[0:i], nil | ||
} | ||
|
||
// If we're at EOF, we have a final, non-terminated line. Return it. | ||
if atEOF { | ||
return dataLen, data, nil | ||
} | ||
|
||
// Request more data. | ||
return 0, nil, nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package io | ||
|
||
import ( | ||
"bufio" | ||
"slices" | ||
"strings" | ||
"testing" | ||
) | ||
|
||
func TestSplitAt(t *testing.T) { | ||
// Define test cases | ||
testCases := []struct { | ||
scenarioDescription string | ||
inputData string | ||
substring string | ||
expectedSplits []string | ||
}{ | ||
{ | ||
scenarioDescription: "Empty data", | ||
inputData: "", | ||
substring: "separator", | ||
expectedSplits: []string{}, | ||
}, | ||
{ | ||
scenarioDescription: "Data does not contain the separator", | ||
inputData: "someThing Without a matching SePaRaToR", | ||
substring: "separator", | ||
expectedSplits: []string{"someThing Without a matching SePaRaToR"}, | ||
}, | ||
{ | ||
scenarioDescription: "Data contains the separator once", | ||
inputData: "AseparatorB", | ||
substring: "separator", | ||
expectedSplits: []string{"A", "B"}, | ||
}, | ||
{ | ||
scenarioDescription: "Data contains the separator more than once", | ||
inputData: "AseparatorBseparatorC", | ||
substring: "separator", | ||
expectedSplits: []string{"A", "B", "C"}, | ||
}, | ||
} | ||
|
||
// Run test cases | ||
for _, tc := range testCases { | ||
scanner := bufio.NewScanner(strings.NewReader(tc.inputData)) | ||
scanner.Split(SplitAt(tc.substring)) | ||
actualSplits := []string{} | ||
for scanner.Scan() { | ||
actualSplits = append(actualSplits, scanner.Text()) | ||
} | ||
if !slices.Equal(tc.expectedSplits, actualSplits) { | ||
t.Errorf("Test failed for scenario: %s, input data: %s, substring: %s\nExpected: %s\nActual: %s", tc.scenarioDescription, tc.inputData, tc.substring, tc.expectedSplits, actualSplits) | ||
} | ||
} | ||
} |