added unit test + docs for the various sort modes.

This commit is contained in:
2022-10-15 19:31:42 +02:00
parent ca87c339b0
commit 9c49b78593
10 changed files with 183 additions and 15 deletions

View File

@@ -2,10 +2,6 @@
## Features to be implemented ## Features to be implemented
- sorting by: numerical, time, duration, string(default) [DONE]
- add unit tests for the above
- add output modes yaml and csv - add output modes yaml and csv
- add --no-headers option - add --no-headers option

View File

@@ -65,6 +65,8 @@ var rootCmd = &cobra.Command{
return err return err
} }
lib.PrepareSortFlags()
return lib.ProcessFiles(args) return lib.ProcessFiles(args)
}, },
} }

View File

@@ -21,8 +21,11 @@ SYNOPSIS
-M, --markdown Enable markdown table output -M, --markdown Enable markdown table output
-O, --orgtbl Enable org-mode table output -O, --orgtbl Enable org-mode table output
-s, --separator string Custom field separator -s, --separator string Custom field separator
-a, --sort-age sort according to age (duration) string
-k, --sort-by int Sort by column (default: 1) -k, --sort-by int Sort by column (default: 1)
-D, --sort-desc Sort in descending order (default: ascending) -D, --sort-desc Sort in descending order (default: ascending)
-i, --sort-numeric sort according to string numerical value
-t, --sort-time sort according to time string
-v, --version Print program version -v, --version Print program version
DESCRIPTION DESCRIPTION
@@ -81,6 +84,16 @@ DESCRIPTION
(as in GNU sort(1)). The default sort column is the first one. To (as in GNU sort(1)). The default sort column is the first one. To
disable sorting at all, supply 0 (Zero) to -k. The default sort order is disable sorting at all, supply 0 (Zero) to -k. The default sort order is
ascending. You can change this to descending order using the option -D. ascending. You can change this to descending order using the option -D.
The default sort order is by string, but there are other sort modes:
-a --sort-age
Sorts duration strings like "1d4h32m51s".
-i --sort-numeric
Sorts numeric fields.
-t --sort-time
Sorts timestamps.
Finally the -d option enables debugging output which is mostly useful Finally the -d option enables debugging output which is mostly useful
for the developer. for the developer.

View File

@@ -78,9 +78,11 @@ var (
// sorting // sorting
SortByColumn int SortByColumn int
SortDescending bool SortDescending bool
SortNumeric bool SortNumeric bool
SortTime bool SortTime bool
SortAge bool SortAge bool
SortMode string
) )
// contains a whole parsed table // contains a whole parsed table

View File

@@ -174,6 +174,19 @@ func PrepareModeFlags() error {
return nil return nil
} }
func PrepareSortFlags() {
switch {
case SortNumeric:
SortMode = "numeric"
case SortAge:
SortMode = "duration"
case SortTime:
SortMode = "time"
default:
SortMode = "string"
}
}
func trimRow(row []string) []string { func trimRow(row []string) []string {
// FIXME: remove this when we only use Tablewriter and strip in ParseFile()! // FIXME: remove this when we only use Tablewriter and strip in ParseFile()!
var fixedrow []string var fixedrow []string

View File

@@ -92,7 +92,7 @@ asd igig cxxxncnc
19191 EDD 1 X` 19191 EDD 1 X`
for _, tt := range tests { for _, tt := range tests {
testname := fmt.Sprintf("parse-with-inverted-pattern-%t", tt.invert) testname := fmt.Sprintf("parse-with-pattern-%s-inverted-%t", tt.pattern, tt.invert)
t.Run(testname, func(t *testing.T) { t.Run(testname, func(t *testing.T) {
InvertMatch = tt.invert InvertMatch = tt.invert

View File

@@ -201,7 +201,8 @@ abc 345 b1`,
origStdout, reader := stdout2pipe(t) origStdout, reader := stdout2pipe(t)
for _, tt := range tests { for _, tt := range tests {
testname := fmt.Sprintf("print-sorted-table-by-%d-desc-%t", tt.sortby, tt.desc) testname := fmt.Sprintf("print-sorted-table-by-column-%d-desc-%t",
tt.sortby, tt.desc)
t.Run(testname, func(t *testing.T) { t.Run(testname, func(t *testing.T) {
SortByColumn = tt.sortby SortByColumn = tt.sortby
SortDescending = tt.desc SortDescending = tt.desc
@@ -226,3 +227,111 @@ abc 345 b1`,
// Restore // Restore
os.Stdout = origStdout os.Stdout = origStdout
} }
func TestSortByPrinter(t *testing.T) {
data := Tabdata{
maxwidthHeader: 8,
maxwidthPerCol: []int{
5,
9,
3,
26,
},
columns: 4,
headers: []string{
"NAME",
"DURATION",
"COUNT",
"WHEN",
},
entries: [][]string{
{
"beta",
"1d10h5m1s",
"33",
"3/1/2014",
},
{
"alpha",
"4h35m",
"170",
"2013-Feb-03",
},
{
"ceta",
"33d12h",
"9",
"06/Jan/2008 15:04:05 -0700",
},
},
}
var tests = []struct {
sortby string
column int
desc bool
expect string
}{
{
column: 3,
sortby: "numeric",
desc: false,
expect: `NAME(1) DURATION(2) COUNT(3) WHEN(4)
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700
beta 1d10h5m1s 33 3/1/2014
alpha 4h35m 170 2013-Feb-03`,
},
{
column: 2,
sortby: "duration",
desc: false,
expect: `NAME(1) DURATION(2) COUNT(3) WHEN(4)
alpha 4h35m 170 2013-Feb-03
beta 1d10h5m1s 33 3/1/2014
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700`,
},
{
column: 4,
sortby: "time",
desc: false,
expect: `NAME(1) DURATION(2) COUNT(3) WHEN(4)
ceta 33d12h 9 06/Jan/2008 15:04:05 -0700
alpha 4h35m 170 2013-Feb-03
beta 1d10h5m1s 33 3/1/2014`,
},
}
NoColor = true
OutputMode = "ascii"
origStdout, reader := stdout2pipe(t)
for _, tt := range tests {
testname := fmt.Sprintf("print-sorted-table-by-column-%d-desc-%t-sort-by-%s",
tt.column, tt.desc, tt.sortby)
t.Run(testname, func(t *testing.T) {
SortByColumn = tt.column
SortDescending = tt.desc
SortMode = tt.sortby
testdata := data
printData(&testdata)
buf := make([]byte, 1024)
n, err := reader.Read(buf)
if err != nil {
t.Fatal(err)
}
buf = buf[:n]
output := strings.TrimSpace(string(buf))
if output != tt.expect {
t.Errorf("sort column: %d, sortby: %s, got:\n%s\nwant:\n%s",
tt.column, tt.sortby, output, tt.expect)
}
})
}
// Restore
os.Stdout = origStdout
}

View File

@@ -51,8 +51,8 @@ func sortTable(data *Tabdata, col int) {
func compare(a string, b string) bool { func compare(a string, b string) bool {
var comp bool var comp bool
switch { switch SortMode {
case SortNumeric: case "numeric":
left, err := strconv.Atoi(a) left, err := strconv.Atoi(a)
if err != nil { if err != nil {
left = 0 left = 0
@@ -62,7 +62,7 @@ func compare(a string, b string) bool {
right = 0 right = 0
} }
comp = left < right comp = left < right
case SortAge: case "duration":
left, err := str2duration.ParseDuration(a) left, err := str2duration.ParseDuration(a)
if err != nil { if err != nil {
left = 0 left = 0
@@ -72,7 +72,7 @@ func compare(a string, b string) bool {
right = 0 right = 0
} }
comp = left.Seconds() < right.Seconds() comp = left.Seconds() < right.Seconds()
case SortTime: case "time":
left, _ := dateparse.ParseAny(a) left, _ := dateparse.ParseAny(a)
right, _ := dateparse.ParseAny(b) right, _ := dateparse.ParseAny(b)
comp = left.Unix() < right.Unix() comp = left.Unix() < right.Unix()

View File

@@ -159,8 +159,11 @@ tablizer \- Manipulate tabular output of other programs
\& \-M, \-\-markdown Enable markdown table output \& \-M, \-\-markdown Enable markdown table output
\& \-O, \-\-orgtbl Enable org\-mode table output \& \-O, \-\-orgtbl Enable org\-mode table output
\& \-s, \-\-separator string Custom field separator \& \-s, \-\-separator string Custom field separator
\& \-a, \-\-sort\-age sort according to age (duration) string
\& \-k, \-\-sort\-by int Sort by column (default: 1) \& \-k, \-\-sort\-by int Sort by column (default: 1)
\& \-D, \-\-sort\-desc Sort in descending order (default: ascending) \& \-D, \-\-sort\-desc Sort in descending order (default: ascending)
\& \-i, \-\-sort\-numeric sort according to string numerical value
\& \-t, \-\-sort\-time sort according to time string
\& \-v, \-\-version Print program version \& \-v, \-\-version Print program version
.Ve .Ve
.SH "DESCRIPTION" .SH "DESCRIPTION"
@@ -228,7 +231,17 @@ Use the \fB\-k\fR option to specify by which column to sort the tabular
data (as in \s-1GNU\s0 \fBsort\fR\|(1)). The default sort column is the first one. To data (as in \s-1GNU\s0 \fBsort\fR\|(1)). The default sort column is the first one. To
disable sorting at all, supply 0 (Zero) to \-k. The default sort order disable sorting at all, supply 0 (Zero) to \-k. The default sort order
is ascending. You can change this to descending order using the option is ascending. You can change this to descending order using the option
\&\fB\-D\fR. \&\fB\-D\fR. The default sort order is by string, but there are other sort
modes:
.IP "\fB\-a \-\-sort\-age\fR" 4
.IX Item "-a --sort-age"
Sorts duration strings like \*(L"1d4h32m51s\*(R".
.IP "\fB\-i \-\-sort\-numeric\fR" 4
.IX Item "-i --sort-numeric"
Sorts numeric fields.
.IP "\fB\-t \-\-sort\-time\fR" 4
.IX Item "-t --sort-time"
Sorts timestamps.
.PP .PP
Finally the \fB\-d\fR option enables debugging output which is mostly Finally the \fB\-d\fR option enables debugging output which is mostly
useful for the developer. useful for the developer.

View File

@@ -20,8 +20,11 @@ tablizer - Manipulate tabular output of other programs
-M, --markdown Enable markdown table output -M, --markdown Enable markdown table output
-O, --orgtbl Enable org-mode table output -O, --orgtbl Enable org-mode table output
-s, --separator string Custom field separator -s, --separator string Custom field separator
-a, --sort-age sort according to age (duration) string
-k, --sort-by int Sort by column (default: 1) -k, --sort-by int Sort by column (default: 1)
-D, --sort-desc Sort in descending order (default: ascending) -D, --sort-desc Sort in descending order (default: ascending)
-i, --sort-numeric sort according to string numerical value
-t, --sort-time sort according to time string
-v, --version Print program version -v, --version Print program version
@@ -84,7 +87,24 @@ Use the B<-k> option to specify by which column to sort the tabular
data (as in GNU sort(1)). The default sort column is the first one. To data (as in GNU sort(1)). The default sort column is the first one. To
disable sorting at all, supply 0 (Zero) to -k. The default sort order disable sorting at all, supply 0 (Zero) to -k. The default sort order
is ascending. You can change this to descending order using the option is ascending. You can change this to descending order using the option
B<-D>. B<-D>. The default sort order is by string, but there are other sort
modes:
=over
=item B<-a --sort-age>
Sorts duration strings like "1d4h32m51s".
=item B<-i --sort-numeric>
Sorts numeric fields.
=item B<-t --sort-time>
Sorts timestamps.
=back
Finally the B<-d> option enables debugging output which is mostly Finally the B<-d> option enables debugging output which is mostly
useful for the developer. useful for the developer.