mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-17 04:30:56 +01:00
added unit test + docs for the various sort modes.
This commit is contained in:
4
TODO.md
4
TODO.md
@@ -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
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ var rootCmd = &cobra.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lib.PrepareSortFlags()
|
||||||
|
|
||||||
return lib.ProcessFiles(args)
|
return lib.ProcessFiles(args)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
15
tablizer.1
15
tablizer.1
@@ -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.
|
||||||
|
|||||||
22
tablizer.pod
22
tablizer.pod
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user