mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-16 20:20:57 +01:00
added -k parameter to sort by columns
This commit is contained in:
@@ -90,6 +90,7 @@ func init() {
|
||||
rootCmd.PersistentFlags().BoolVarP(&ShowManual, "man", "m", false, "Display manual page")
|
||||
rootCmd.PersistentFlags().StringVarP(&lib.Separator, "separator", "s", lib.DefaultSeparator, "Custom field separator")
|
||||
rootCmd.PersistentFlags().StringVarP(&lib.Columns, "columns", "c", "", "Only show the speficied columns (separated by ,)")
|
||||
rootCmd.PersistentFlags().IntVarP(&lib.SortByColumn, "sort-by", "k", 0, "Sort by column (default: 1)")
|
||||
|
||||
// output flags, only 1 allowed, hidden, since just short cuts
|
||||
rootCmd.PersistentFlags().BoolVarP(&lib.OutflagExtended, "extended", "X", false, "Enable extended output")
|
||||
|
||||
@@ -20,6 +20,7 @@ SYNOPSIS
|
||||
-M, --markdown Enable markdown table output
|
||||
-O, --orgtbl Enable org-mode table output
|
||||
-s, --separator string Custom field separator
|
||||
-k, --sort-by int Sort by column (default: 1)
|
||||
-v, --version Print program version
|
||||
|
||||
DESCRIPTION
|
||||
@@ -74,6 +75,10 @@ DESCRIPTION
|
||||
By default, if a pattern has been speficied, matches will be
|
||||
highlighted. You can disable this behavior with the -N option.
|
||||
|
||||
Use the -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
|
||||
disable sorting at all, supply 0 (Zero) to -k.
|
||||
|
||||
Finally the -d option enables debugging output which is mostly usefull
|
||||
for the developer.
|
||||
|
||||
|
||||
@@ -68,10 +68,22 @@ var (
|
||||
validOutputmodes = "(orgtbl|markdown|extended|ascii)"
|
||||
|
||||
// main program version
|
||||
Version = "v1.0.7"
|
||||
Version = "v1.0.8"
|
||||
|
||||
// generated version string, used by -v contains lib.Version on
|
||||
// main branch, and lib.Version-$branch-$lastcommit-$date on
|
||||
// development branch
|
||||
VERSION string
|
||||
|
||||
// sorting
|
||||
SortByColumn int
|
||||
)
|
||||
|
||||
// contains a whole parsed table
|
||||
type Tabdata struct {
|
||||
maxwidthHeader int // longest header
|
||||
maxwidthPerCol []int // max width per column
|
||||
columns int // count
|
||||
headers []string // [ "ID", "NAME", ...]
|
||||
entries [][]string
|
||||
}
|
||||
|
||||
@@ -27,15 +27,6 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// contains a whole parsed table
|
||||
type Tabdata struct {
|
||||
maxwidthHeader int // longest header
|
||||
maxwidthPerCol []int // max width per column
|
||||
columns int // count
|
||||
headers []string // [ "ID", "NAME", ...]
|
||||
entries [][]string
|
||||
}
|
||||
|
||||
/*
|
||||
Parse tabular input.
|
||||
*/
|
||||
|
||||
@@ -26,11 +26,19 @@ import (
|
||||
)
|
||||
|
||||
func printData(data *Tabdata) {
|
||||
// some output preparations:
|
||||
|
||||
if OutputMode != "shell" {
|
||||
// not needed in eval string
|
||||
numberizeHeaders(data)
|
||||
}
|
||||
|
||||
// remove unwanted columns, if any
|
||||
reduceColumns(data)
|
||||
|
||||
// sort the data
|
||||
sortTable(data, SortByColumn)
|
||||
|
||||
switch OutputMode {
|
||||
case "extended":
|
||||
printExtendedData(data)
|
||||
|
||||
@@ -25,6 +25,20 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func stdout2pipe(t *testing.T) (*os.File, *os.File) {
|
||||
reader, writer, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
origStdout := os.Stdout
|
||||
os.Stdout = writer
|
||||
|
||||
// we need to tell the color mode the io.Writer, even if we don't usw colorization
|
||||
color.SetOutput(writer)
|
||||
|
||||
return origStdout, reader
|
||||
}
|
||||
|
||||
func TestPrinter(t *testing.T) {
|
||||
startdata := Tabdata{
|
||||
maxwidthHeader: 5,
|
||||
@@ -51,18 +65,22 @@ func TestPrinter(t *testing.T) {
|
||||
"ascii": `ONE(1) TWO(2) THREE(3)
|
||||
asd igig cxxxncnc
|
||||
19191 EDD 1 X`,
|
||||
|
||||
"orgtbl": `|--------+--------+----------|
|
||||
| ONE(1) | TWO(2) | THREE(3) |
|
||||
|--------+--------+----------|
|
||||
| asd | igig | cxxxncnc |
|
||||
| 19191 | EDD 1 | X |
|
||||
|--------+--------+----------|`,
|
||||
|
||||
"markdown": `| ONE(1) | TWO(2) | THREE(3) |
|
||||
|--------|--------|----------|
|
||||
| asd | igig | cxxxncnc |
|
||||
| 19191 | EDD 1 | X |`,
|
||||
|
||||
"shell": `ONE="asd" TWO="igig" THREE="cxxxncnc"
|
||||
ONE="19191" TWO="EDD 1" THREE="X"`,
|
||||
|
||||
"extended": `ONE(1): asd
|
||||
TWO(2): igig
|
||||
THREE(3): cxxxncnc
|
||||
@@ -73,16 +91,9 @@ THREE(3): X`,
|
||||
}
|
||||
|
||||
NoColor = true
|
||||
SortByColumn = 0 // disable sorting
|
||||
|
||||
r, w, err := os.Pipe()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
origStdout := os.Stdout
|
||||
os.Stdout = w
|
||||
|
||||
// we need to tell the color mode the io.Writer, even if we don't usw colorization
|
||||
color.SetOutput(w)
|
||||
origStdout, reader := stdout2pipe(t)
|
||||
|
||||
for mode, expect := range expects {
|
||||
testname := fmt.Sprintf("print-%s", mode)
|
||||
@@ -93,7 +104,7 @@ THREE(3): X`,
|
||||
printData(&data)
|
||||
|
||||
buf := make([]byte, 1024)
|
||||
n, err := r.Read(buf)
|
||||
n, err := reader.Read(buf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -101,7 +112,8 @@ THREE(3): X`,
|
||||
output := strings.TrimSpace(string(buf))
|
||||
|
||||
if output != expect {
|
||||
t.Errorf("output mode: %s, got:\n%s\nwant:\n%s\n (%d <=> %d)", mode, output, expect, len(output), len(expect))
|
||||
t.Errorf("output mode: %s, got:\n%s\nwant:\n%s\n (%d <=> %d)",
|
||||
mode, output, expect, len(output), len(expect))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -110,3 +122,91 @@ THREE(3): X`,
|
||||
os.Stdout = origStdout
|
||||
|
||||
}
|
||||
|
||||
func TestSortPrinter(t *testing.T) {
|
||||
startdata := Tabdata{
|
||||
maxwidthHeader: 5,
|
||||
maxwidthPerCol: []int{
|
||||
3,
|
||||
3,
|
||||
2,
|
||||
},
|
||||
columns: 3,
|
||||
headers: []string{
|
||||
"ONE", "TWO", "THREE",
|
||||
},
|
||||
entries: [][]string{
|
||||
[]string{
|
||||
"abc", "345", "b1",
|
||||
},
|
||||
[]string{
|
||||
"bcd", "234", "a2",
|
||||
},
|
||||
[]string{
|
||||
"cde", "123", "c3",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
data Tabdata
|
||||
sortby int
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
data: startdata,
|
||||
sortby: 1,
|
||||
expect: `ONE(1) TWO(2) THREE(3)
|
||||
abc 345 b1
|
||||
bcd 234 a2
|
||||
cde 123 c3`,
|
||||
},
|
||||
|
||||
{
|
||||
data: startdata,
|
||||
sortby: 2,
|
||||
expect: `ONE(1) TWO(2) THREE(3)
|
||||
cde 123 c3
|
||||
bcd 234 a2
|
||||
abc 345 b1`,
|
||||
},
|
||||
|
||||
{
|
||||
data: startdata,
|
||||
sortby: 3,
|
||||
expect: `ONE(1) TWO(2) THREE(3)
|
||||
bcd 234 a2
|
||||
abc 345 b1
|
||||
cde 123 c3`,
|
||||
},
|
||||
}
|
||||
|
||||
NoColor = true
|
||||
OutputMode = "ascii"
|
||||
origStdout, reader := stdout2pipe(t)
|
||||
|
||||
for _, tt := range tests {
|
||||
testname := fmt.Sprintf("print-sorted-table-%d", tt.sortby)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
SortByColumn = tt.sortby
|
||||
|
||||
printData(&tt.data)
|
||||
|
||||
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, got:\n%s\nwant:\n%s",
|
||||
tt.sortby, output, tt.expect)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Restore
|
||||
os.Stdout = origStdout
|
||||
}
|
||||
|
||||
46
lib/sort.go
Normal file
46
lib/sort.go
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright © 2022 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package lib
|
||||
|
||||
import (
|
||||
"sort"
|
||||
)
|
||||
|
||||
func sortTable(data *Tabdata, col int) {
|
||||
if col <= 0 {
|
||||
// no sorting wanted
|
||||
return
|
||||
}
|
||||
|
||||
col-- // ui starts counting by 1, but use 0 internally
|
||||
|
||||
// sanity checks
|
||||
if len(data.entries) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if col >= len(data.headers) {
|
||||
// fall back to default column
|
||||
col = 0
|
||||
}
|
||||
|
||||
// actual sorting
|
||||
sort.SliceStable(data.entries, func(i, j int) bool {
|
||||
return data.entries[i][col] < data.entries[j][col]
|
||||
})
|
||||
}
|
||||
@@ -133,7 +133,7 @@
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "TABLIZER 1"
|
||||
.TH TABLIZER 1 "2022-10-10" "1" "User Commands"
|
||||
.TH TABLIZER 1 "2022-10-13" "1" "User Commands"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.if n .ad l
|
||||
@@ -159,6 +159,7 @@ tablizer \- Manipulate tabular output of other programs
|
||||
\& \-M, \-\-markdown Enable markdown table output
|
||||
\& \-O, \-\-orgtbl Enable org\-mode table output
|
||||
\& \-s, \-\-separator string Custom field separator
|
||||
\& \-k, \-\-sort\-by int Sort by column (default: 1)
|
||||
\& \-v, \-\-version Print program version
|
||||
.Ve
|
||||
.SH "DESCRIPTION"
|
||||
@@ -222,6 +223,10 @@ The numbering can be suppressed by using the \fB\-n\fR option.
|
||||
By default, if a \fBpattern\fR has been speficied, matches will be
|
||||
highlighted. You can disable this behavior with the \fB\-N\fR option.
|
||||
.PP
|
||||
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
|
||||
disable sorting at all, supply 0 (Zero) to \-k.
|
||||
.PP
|
||||
Finally the \fB\-d\fR option enables debugging output which is mostly
|
||||
usefull for the developer.
|
||||
.SS "\s-1PATTERNS\s0"
|
||||
|
||||
@@ -20,6 +20,7 @@ tablizer - Manipulate tabular output of other programs
|
||||
-M, --markdown Enable markdown table output
|
||||
-O, --orgtbl Enable org-mode table output
|
||||
-s, --separator string Custom field separator
|
||||
-k, --sort-by int Sort by column (default: 1)
|
||||
-v, --version Print program version
|
||||
|
||||
|
||||
@@ -78,6 +79,10 @@ The numbering can be suppressed by using the B<-n> option.
|
||||
By default, if a B<pattern> has been speficied, matches will be
|
||||
highlighted. You can disable this behavior with the B<-N> option.
|
||||
|
||||
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
|
||||
disable sorting at all, supply 0 (Zero) to -k.
|
||||
|
||||
Finally the B<-d> option enables debugging output which is mostly
|
||||
usefull for the developer.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user