mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-18 21:11:03 +01:00
Compare commits
22 Commits
transpose
...
feature/ya
| Author | SHA1 | Date | |
|---|---|---|---|
| 200f1f32f8 | |||
| 768a19b4d6 | |||
|
|
dc718392b6 | ||
|
|
e8f4fef41c | ||
| 82f54c120d | |||
|
|
2d5799e2f2 | ||
| 8e33cadcaa | |||
| 03f3225f24 | |||
| 63c7ef26b6 | |||
|
|
c2e7d8037a | ||
| 323c070caa | |||
| 53cf1e2ebe | |||
| 16c5053752 | |||
| 7d2d9a55d3 | |||
| 14c50b4e63 | |||
| 0e68dc585d | |||
| 6ca835add1 | |||
| 306f583522 | |||
| 9f971ed3b9 | |||
| 2ae2d2b33d | |||
| cf1a555b9b | |||
| 4d894a728b |
32
.github/workflows/release.yaml
vendored
Normal file
32
.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: build-and-test
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Build Release Assets
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v1
|
||||
with:
|
||||
go-version: 1.22.11
|
||||
|
||||
- name: Build the executables
|
||||
run: ./mkrel.sh tablizer ${{ github.ref_name}}
|
||||
|
||||
- name: List the executables
|
||||
run: ls -l ./releases
|
||||
|
||||
- name: Upload the binaries
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: ${{ github.ref_name }}
|
||||
file: ./releases/*
|
||||
file_glob: true
|
||||
5
Makefile
5
Makefile
@@ -53,8 +53,7 @@ buildlocal:
|
||||
go build -ldflags "-X 'github.com/tlinden/tablizer/cfg.VERSION=$(VERSION)'"
|
||||
|
||||
release:
|
||||
./mkrel.sh $(tool) $(version)
|
||||
gh release create $(version) --generate-notes releases/*
|
||||
gh release create $(version) --generate-notes
|
||||
|
||||
install: buildlocal
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
|
||||
@@ -70,7 +69,7 @@ test:
|
||||
|
||||
singletest:
|
||||
@echo "Call like this: 'make singletest TEST=TestPrepareColumns MOD=lib'"
|
||||
go test -run $(TEST) github.com/tlinden/tablizer/$(MOD)
|
||||
go test -run $(TEST) github.com/tlinden/tablizer/$(MOD) $(OPTS)
|
||||
|
||||
cover-report:
|
||||
go test ./... -cover -coverprofile=coverage.out
|
||||
|
||||
@@ -35,6 +35,8 @@ Output Flags (mutually exclusive):
|
||||
-C, --csv Enable CSV output
|
||||
-A, --ascii Default output mode, ascii tabular
|
||||
-L, --hightlight-lines Use alternating background colors for tables
|
||||
-y, --yank-columns Yank specified columns (separated by ,) to clipboard,
|
||||
space separated
|
||||
|
||||
Sort Mode Flags (mutually exclusive):
|
||||
-a, --sort-age sort according to age (duration) string
|
||||
|
||||
@@ -28,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
const DefaultSeparator string = `(\s\s+|\t)`
|
||||
const Version string = "v1.3.0"
|
||||
const Version string = "v1.3.1"
|
||||
const MAXPARTS = 2
|
||||
|
||||
var DefaultConfigfile = os.Getenv("HOME") + "/.config/tablizer/config"
|
||||
@@ -59,6 +59,8 @@ type Config struct {
|
||||
NoHeaders bool
|
||||
Columns string
|
||||
UseColumns []int
|
||||
YankColumns string
|
||||
UseYankColumns []int
|
||||
Separator string
|
||||
OutputMode int
|
||||
InvertMatch bool
|
||||
@@ -67,9 +69,10 @@ type Config struct {
|
||||
UseFuzzySearch bool
|
||||
UseHighlight bool
|
||||
|
||||
SortMode string
|
||||
SortDescending bool
|
||||
SortByColumn int
|
||||
SortMode string
|
||||
SortDescending bool
|
||||
SortByColumn string // 1,2
|
||||
UseSortByColumn []int // []int{1,2}
|
||||
|
||||
TransposeColumns string // 1,2
|
||||
UseTransposeColumns []int // []int{1,2}
|
||||
|
||||
@@ -147,11 +147,13 @@ func Execute() {
|
||||
"Custom field separator")
|
||||
rootCmd.PersistentFlags().StringVarP(&conf.Columns, "columns", "c", "",
|
||||
"Only show the speficied columns (separated by ,)")
|
||||
rootCmd.PersistentFlags().StringVarP(&conf.YankColumns, "yank-columns", "y", "",
|
||||
"Yank the speficied columns (separated by ,) to the clipboard")
|
||||
rootCmd.PersistentFlags().StringVarP(&conf.TransposeColumns, "transpose-columns", "T", "",
|
||||
"Transpose the speficied columns (separated by ,)")
|
||||
|
||||
// sort options
|
||||
rootCmd.PersistentFlags().IntVarP(&conf.SortByColumn, "sort-by", "k", 0,
|
||||
rootCmd.PersistentFlags().StringVarP(&conf.SortByColumn, "sort-by", "k", "",
|
||||
"Sort by column (default: 1)")
|
||||
|
||||
// sort mode, only 1 allowed
|
||||
|
||||
@@ -15,7 +15,7 @@ SYNOPSIS
|
||||
-N, --no-color Disable pattern highlighting
|
||||
-H, --no-headers Disable headers display
|
||||
-s, --separator string Custom field separator
|
||||
-k, --sort-by int Sort by column (default: 1)
|
||||
-k, --sort-by int|name Sort by column (default: 1)
|
||||
-z, --fuzzy Use fuzzy search [experimental]
|
||||
-F, --filter field=reg Filter given field with regex, can be used multiple times
|
||||
-T, --transpose-columns string Transpose the speficied columns (separated by ,)
|
||||
@@ -30,6 +30,8 @@ SYNOPSIS
|
||||
-C, --csv Enable CSV output
|
||||
-A, --ascii Default output mode, ascii tabular
|
||||
-L, --hightlight-lines Use alternating background colors for tables
|
||||
-y, --yank-columns Yank specified columns (separated by ,) to clipboard,
|
||||
space separated
|
||||
|
||||
Sort Mode Flags (mutually exclusive):
|
||||
-a, --sort-age sort according to age (duration) string
|
||||
@@ -103,10 +105,19 @@ DESCRIPTION
|
||||
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. The default sort order is
|
||||
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:
|
||||
(as in GNU sort(1)). The default sort column is the first one. You can
|
||||
specify column numbers or names. Column numbers start with 1, names are
|
||||
case insensitive. You can specify multiple columns separated by comma to
|
||||
sort, but the type must be the same. For example if you want to sort
|
||||
numerically, all columns must be numbers. If you use column numbers,
|
||||
then be aware, that these are the numbers before column extraction. For
|
||||
example if you have a table with 4 columns and specify "-c4", then only
|
||||
1 column (the fourth) will be printed, however if you want to sort by
|
||||
this column, you'll have to specify "-k4".
|
||||
|
||||
The default sort order is ascending. You can change this to descending
|
||||
order using the option -D. The default sort order is by alphanumeric
|
||||
string, but there are other sort modes:
|
||||
|
||||
-a --sort-age
|
||||
Sorts duration strings like "1d4h32m51s".
|
||||
@@ -258,6 +269,18 @@ DESCRIPTION
|
||||
markdown which prints a Markdown table, yaml, which prints yaml encoding
|
||||
and CSV mode, which prints a comma separated value file.
|
||||
|
||||
PUT FIELDS TO CLIPBOARD
|
||||
You can let tablizer put fields to the clipboard using the option "-y".
|
||||
This best fits the use-case when the result of your filtering yields
|
||||
just one row. For example:
|
||||
|
||||
cloudctl cluster ls | tablizer -yid matchbox
|
||||
|
||||
If "matchbox" matches one cluster, you can immediately use the id of
|
||||
that cluster somewhere else and paste it. Of course, if there are
|
||||
multiple matches, then all id's will be put into the clipboard separated
|
||||
by one space.
|
||||
|
||||
ENVIRONMENT VARIABLES
|
||||
tablizer supports certain environment variables which use can use to
|
||||
influence program behavior. Commandline flags have always precedence
|
||||
@@ -392,7 +415,7 @@ Operational Flags:
|
||||
-N, --no-color Disable pattern highlighting
|
||||
-H, --no-headers Disable headers display
|
||||
-s, --separator string Custom field separator
|
||||
-k, --sort-by int Sort by column (default: 1)
|
||||
-k, --sort-by int|name Sort by column (default: 1)
|
||||
-z, --fuzzy Use fuzzy search [experimental]
|
||||
-F, --filter field=reg Filter given field with regex, can be used multiple times
|
||||
-T, --transpose-columns string Transpose the speficied columns (separated by ,)
|
||||
@@ -407,6 +430,8 @@ Output Flags (mutually exclusive):
|
||||
-C, --csv Enable CSV output
|
||||
-A, --ascii Default output mode, ascii tabular
|
||||
-L, --hightlight-lines Use alternating background colors for tables
|
||||
-y, --yank-columns Yank specified columns (separated by ,) to clipboard,
|
||||
space separated
|
||||
|
||||
Sort Mode Flags (mutually exclusive):
|
||||
-a, --sort-age sort according to age (duration) string
|
||||
|
||||
20
go.mod
20
go.mod
@@ -5,11 +5,12 @@ go 1.22
|
||||
require (
|
||||
github.com/alecthomas/repr v0.4.0
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
|
||||
github.com/glycerine/zygomys v5.1.2+incompatible
|
||||
github.com/atotto/clipboard v0.1.4
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/hashicorp/hcl/v2 v2.22.0
|
||||
github.com/hashicorp/hcl/v2 v2.23.0
|
||||
github.com/lithammer/fuzzysearch v1.1.8
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/rogpeppe/go-internal v1.13.1
|
||||
github.com/spf13/cobra v1.8.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
@@ -18,27 +19,18 @@ require (
|
||||
github.com/agext/levenshtein v1.2.3 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
|
||||
github.com/glycerine/blake2b v0.0.0-20151022103502-3c8c640cd7be // indirect
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 // indirect
|
||||
github.com/glycerine/greenpack v5.1.1+incompatible // indirect
|
||||
github.com/glycerine/liner v0.0.0-20160121172638-72909af234e0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/gopherjs/gopherjs v1.17.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
|
||||
github.com/philhofer/fwd v1.1.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/shurcooL/go v0.0.0-20230706063926-5fe729b41b3a // indirect
|
||||
github.com/shurcooL/go-goon v1.0.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tinylib/msgp v1.1.9 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/tiagomelo/go-clipboard v0.1.2-0.20250126153310-fcc1f95408cf // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/zclconf/go-cty v1.13.3 // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
golang.org/x/text v0.11.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
|
||||
63
go.sum
63
go.sum
@@ -1,5 +1,3 @@
|
||||
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
|
||||
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
|
||||
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
@@ -10,36 +8,25 @@ github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew
|
||||
github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
|
||||
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/glycerine/blake2b v0.0.0-20151022103502-3c8c640cd7be h1:XBJdPGgA3qqhW+p9CANCAVdF7ZIXdu3pZAkypMkKAjE=
|
||||
github.com/glycerine/blake2b v0.0.0-20151022103502-3c8c640cd7be/go.mod h1:OSCrScrFAjcBObrulk6BEQlytA462OkG1UGB5NYj9kE=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31 h1:gclg6gY70GLy3PbkQ1AERPfmLMMagS60DKF78eWwLn8=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/glycerine/greenpack v5.1.1+incompatible h1:fDr9i6MkSGZmAy4VXPfJhW+SyK2/LNnzIp5nHyDiaIM=
|
||||
github.com/glycerine/greenpack v5.1.1+incompatible/go.mod h1:us0jVISAESGjsEuLlAfCd5nkZm6W6WQF18HPuOecIg4=
|
||||
github.com/glycerine/liner v0.0.0-20160121172638-72909af234e0 h1:4ZegphJXBTc4uFQ08UVoWYmQXorGa+ipXetUj83sMBc=
|
||||
github.com/glycerine/liner v0.0.0-20160121172638-72909af234e0/go.mod h1:AqJLs6UeoC65dnHxyCQ6MO31P5STpjcmgaANAU+No8Q=
|
||||
github.com/glycerine/zygomys v5.1.2+incompatible h1:jmcdmA3XPxgfOunAXFpipE9LQoUL6eX6d2mhYyjV4GE=
|
||||
github.com/glycerine/zygomys v5.1.2+incompatible/go.mod h1:i3SPKZpmy9dwF/3iWrXJ/ZLyzZucegwypwOmqRkUUaQ=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
|
||||
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g=
|
||||
github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k=
|
||||
github.com/hashicorp/hcl/v2 v2.22.0 h1:hkZ3nCtqeJsDhPRFz5EA9iwcG1hNWGePOTw6oyul12M=
|
||||
github.com/hashicorp/hcl/v2 v2.22.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
|
||||
github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos=
|
||||
github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
||||
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
@@ -47,11 +34,10 @@ github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzC
|
||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
|
||||
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
@@ -59,12 +45,6 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
||||
github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636 h1:aSISeOcal5irEhJd1M+IrApc0PdcN7e7Aj4yuEnOrfQ=
|
||||
github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go v0.0.0-20230706063926-5fe729b41b3a h1:ZHfoO7ZJhws9NU1kzZhStUnnVQiPtDe1PzpUnc6HirU=
|
||||
github.com/shurcooL/go v0.0.0-20230706063926-5fe729b41b3a/go.mod h1:DNrlr0AR9NsHD/aoc2pPeu4uSBZ/71yCHkR42yrzW3M=
|
||||
github.com/shurcooL/go-goon v1.0.0 h1:BCQPvxGkHHJ4WpBO4m/9FXbITVIsvAm/T66cCcCGI7E=
|
||||
github.com/shurcooL/go-goon v1.0.0/go.mod h1:2wTHMsGo7qnpmqA8ADYZtP4I1DD94JpXGQ3Dxq2YQ5w=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
@@ -72,28 +52,24 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU=
|
||||
github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tiagomelo/go-clipboard v0.1.1 h1:nddQ5DsEnKW0KdzTILhbLpSq3e9y2dkJXEOtsMs6H7A=
|
||||
github.com/tiagomelo/go-clipboard v0.1.1/go.mod h1:kXtjJBIMimZaGbxmcKZ8+JqK+acSNf5tAJiChlZBOr8=
|
||||
github.com/tiagomelo/go-clipboard v0.1.2-0.20250126153310-fcc1f95408cf h1:csb/+rmJBAtOP6OP+9soTnwJVuhlUpedjb5dPlNZasY=
|
||||
github.com/tiagomelo/go-clipboard v0.1.2-0.20250126153310-fcc1f95408cf/go.mod h1:kXtjJBIMimZaGbxmcKZ8+JqK+acSNf5tAJiChlZBOr8=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zclconf/go-cty v1.13.0 h1:It5dfKTTZHe9aeppbNOda3mN7Ag7sg6QkBNm6TkyFa0=
|
||||
github.com/zclconf/go-cty v1.13.0/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
github.com/zclconf/go-cty v1.13.3 h1:m+b9q3YDbg6Bec5rr+KGy1MzEVzY/jC2X+YX4yqKtHI=
|
||||
github.com/zclconf/go-cty v1.13.3/go.mod h1:YKQzy/7pZ7iq2jNFzy5go57xdxdWoLLpaEp4u238AE0=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
|
||||
github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
|
||||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -103,15 +79,14 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
@@ -128,8 +103,6 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -77,6 +77,14 @@ func PrepareColumns(conf *cfg.Config, data *Tabdata) error {
|
||||
|
||||
conf.UseColumns = usecolumns
|
||||
|
||||
// -y columns
|
||||
useyankcolumns, err := PrepareColumnVars(conf.YankColumns, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.UseYankColumns = useyankcolumns
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -99,6 +107,19 @@ func PrepareTransposerColumns(conf *cfg.Config, data *Tabdata) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// output option, prepare -k1,2 sort fields
|
||||
func PrepareSortColumns(conf *cfg.Config, data *Tabdata) error {
|
||||
// -c columns
|
||||
usecolumns, err := PrepareColumnVars(conf.SortByColumn, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conf.UseSortByColumn = usecolumns
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func PrepareColumnVars(columns string, data *Tabdata) ([]int, error) {
|
||||
if columns == "" {
|
||||
return nil, nil
|
||||
|
||||
@@ -48,6 +48,11 @@ func ProcessFiles(conf *cfg.Config, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err = PrepareSortColumns(conf, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = PrepareColumns(conf, &data)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright © 2022 Thomas von Dein
|
||||
Copyright © 2022-2025 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
|
||||
@@ -33,15 +33,20 @@ import (
|
||||
)
|
||||
|
||||
func printData(writer io.Writer, conf cfg.Config, data *Tabdata) {
|
||||
// add numbers to headers and remove this we're not interested in
|
||||
// Sort the data first, before headers+entries are being
|
||||
// reduced. That way the user can specify any valid column to sort
|
||||
// by, independently if it's being used for display or not.
|
||||
sortTable(conf, data)
|
||||
|
||||
// put one or more columns into clipboard
|
||||
yankColumns(conf, data)
|
||||
|
||||
// add numbers to headers and remove those we're not interested in
|
||||
numberizeAndReduceHeaders(conf, data)
|
||||
|
||||
// remove unwanted columns, if any
|
||||
reduceColumns(conf, data)
|
||||
|
||||
// sort the data
|
||||
sortTable(conf, data)
|
||||
|
||||
switch conf.OutputMode {
|
||||
case cfg.Extended:
|
||||
printExtendedData(writer, conf, data)
|
||||
|
||||
@@ -63,7 +63,7 @@ var tests = []struct {
|
||||
name string // so we can identify which one fails, can be the same
|
||||
// for multiple tests, because flags will be appended to the name
|
||||
sortby string // empty == default
|
||||
column int // sort by this column, 0 == default first or NO Sort
|
||||
column int // sort by this column (numbers start by 1)
|
||||
desc bool // sort in descending order, default == ascending
|
||||
nonum bool // hide numbering
|
||||
mode int // shell, orgtbl, etc. empty == default: ascii
|
||||
@@ -162,7 +162,7 @@ DURATION(2): 33d12h
|
||||
|
||||
//------------------------ SORT TESTS
|
||||
{
|
||||
name: "sortbycolumn",
|
||||
name: "sortbycolumn3",
|
||||
column: 3,
|
||||
sortby: "numeric",
|
||||
desc: false,
|
||||
@@ -173,7 +173,7 @@ beta 1d10h5m1s 33 3/1/2014
|
||||
alpha 4h35m 170 2013-Feb-03`,
|
||||
},
|
||||
{
|
||||
name: "sortbycolumn",
|
||||
name: "sortbycolumn4",
|
||||
column: 4,
|
||||
sortby: "time",
|
||||
desc: false,
|
||||
@@ -184,7 +184,7 @@ alpha 4h35m 170 2013-Feb-03
|
||||
beta 1d10h5m1s 33 3/1/2014`,
|
||||
},
|
||||
{
|
||||
name: "sortbycolumn",
|
||||
name: "sortbycolumn2",
|
||||
column: 2,
|
||||
sortby: "duration",
|
||||
desc: false,
|
||||
@@ -251,15 +251,14 @@ DURATION(2) WHEN(4)
|
||||
|
||||
func TestPrinter(t *testing.T) {
|
||||
for _, testdata := range tests {
|
||||
testname := fmt.Sprintf("print-sortcol-%d-desc-%t-sortby-%s-mode-%d-usecolumns-%s",
|
||||
testdata.column, testdata.desc, testdata.sortby, testdata.mode, testdata.usecolstr)
|
||||
testname := fmt.Sprintf("print-%s-%d-desc-%t-sortby-%s-mode-%d-usecolumns-%s",
|
||||
testdata.name, testdata.column, testdata.desc, testdata.sortby, testdata.mode, testdata.usecolstr)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
// replaces os.Stdout, but we ignore it
|
||||
var writer bytes.Buffer
|
||||
|
||||
// cmd flags
|
||||
conf := cfg.Config{
|
||||
SortByColumn: testdata.column,
|
||||
SortDescending: testdata.desc,
|
||||
SortMode: testdata.sortby,
|
||||
OutputMode: testdata.mode,
|
||||
@@ -268,6 +267,10 @@ func TestPrinter(t *testing.T) {
|
||||
NoColor: true,
|
||||
}
|
||||
|
||||
if testdata.column > 0 {
|
||||
conf.UseSortByColumn = []int{testdata.column}
|
||||
}
|
||||
|
||||
conf.ApplyDefaults()
|
||||
|
||||
// the test checks the len!
|
||||
|
||||
41
lib/sort.go
41
lib/sort.go
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package lib
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -27,34 +28,41 @@ import (
|
||||
)
|
||||
|
||||
func sortTable(conf cfg.Config, data *Tabdata) {
|
||||
if conf.SortByColumn <= 0 {
|
||||
if len(conf.UseSortByColumn) == 0 {
|
||||
// no sorting wanted
|
||||
return
|
||||
}
|
||||
|
||||
// slightly modified here to match internal array indicies
|
||||
col := conf.SortByColumn
|
||||
|
||||
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 compare(&conf, data.entries[i][col], data.entries[j][col])
|
||||
// holds the result of a sort of one column
|
||||
comparators := []int{}
|
||||
|
||||
// iterate over all columns to be sorted, conf.SortMode must be identical!
|
||||
for _, column := range conf.UseSortByColumn {
|
||||
comparators = append(comparators, compare(&conf, data.entries[i][column-1], data.entries[j][column-1]))
|
||||
}
|
||||
|
||||
// return the combined result
|
||||
res := cmp.Or(comparators...)
|
||||
|
||||
switch res {
|
||||
case 0:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// config is not modified here, but it would be inefficient to copy it every loop
|
||||
func compare(conf *cfg.Config, left string, right string) bool {
|
||||
func compare(conf *cfg.Config, left string, right string) int {
|
||||
var comp bool
|
||||
|
||||
switch conf.SortMode {
|
||||
@@ -88,7 +96,12 @@ func compare(conf *cfg.Config, left string, right string) bool {
|
||||
comp = !comp
|
||||
}
|
||||
|
||||
return comp
|
||||
switch comp {
|
||||
case true:
|
||||
return 0
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -53,18 +53,18 @@ func TestCompare(t *testing.T) {
|
||||
mode string
|
||||
a string
|
||||
b string
|
||||
want bool
|
||||
want int
|
||||
desc bool
|
||||
}{
|
||||
// ascending
|
||||
{"numeric", "10", "20", true, false},
|
||||
{"duration", "2d4h5m", "45m", false, false},
|
||||
{"time", "12/24/2022", "1/1/1970", false, false},
|
||||
{"numeric", "10", "20", 0, false},
|
||||
{"duration", "2d4h5m", "45m", 1, false},
|
||||
{"time", "12/24/2022", "1/1/1970", 1, false},
|
||||
|
||||
// descending
|
||||
{"numeric", "10", "20", false, true},
|
||||
{"duration", "2d4h5m", "45m", true, true},
|
||||
{"time", "12/24/2022", "1/1/1970", true, true},
|
||||
{"numeric", "10", "20", 1, true},
|
||||
{"duration", "2d4h5m", "45m", 0, true},
|
||||
{"time", "12/24/2022", "1/1/1970", 0, true},
|
||||
}
|
||||
|
||||
for _, testdata := range tests {
|
||||
@@ -75,7 +75,7 @@ func TestCompare(t *testing.T) {
|
||||
c := cfg.Config{SortMode: testdata.mode, SortDescending: testdata.desc}
|
||||
got := compare(&c, testdata.a, testdata.b)
|
||||
if got != testdata.want {
|
||||
t.Errorf("got %t, want %t", got, testdata.want)
|
||||
t.Errorf("got %d, want %d", got, testdata.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
51
lib/yank.go
Normal file
51
lib/yank.go
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright © 2022-2025 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 (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"github.com/tiagomelo/go-clipboard/clipboard"
|
||||
"github.com/tlinden/tablizer/cfg"
|
||||
)
|
||||
|
||||
func yankColumns(conf cfg.Config, data *Tabdata) {
|
||||
var yank []string
|
||||
|
||||
if len(data.entries) == 0 || len(conf.UseYankColumns) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _, row := range data.entries {
|
||||
for i, field := range row {
|
||||
for _, idx := range conf.UseYankColumns {
|
||||
if i == idx-1 {
|
||||
yank = append(yank, field)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(yank) > 0 {
|
||||
cb := clipboard.New(clipboard.ClipboardOptions{Primary: true})
|
||||
if err := cb.CopyText(strings.Join(yank, " ")); err != nil {
|
||||
log.Fatalln("error writing string to clipboard:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
72
lib/yank_test.go
Normal file
72
lib/yank_test.go
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright © 2025 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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/tiagomelo/go-clipboard/clipboard"
|
||||
"github.com/tlinden/tablizer/cfg"
|
||||
)
|
||||
|
||||
var yanktests = []struct {
|
||||
name string
|
||||
yank []int // -y$colum,$column... after processing
|
||||
filter string
|
||||
expect string
|
||||
}{
|
||||
{
|
||||
name: "one",
|
||||
yank: []int{1},
|
||||
filter: "beta",
|
||||
},
|
||||
}
|
||||
|
||||
func DISABLED_TestYankColumns(t *testing.T) {
|
||||
cb := clipboard.New()
|
||||
|
||||
for _, testdata := range yanktests {
|
||||
testname := fmt.Sprintf("yank-%s-filter-%s",
|
||||
testdata.name, testdata.filter)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
conf := cfg.Config{
|
||||
OutputMode: cfg.ASCII,
|
||||
UseYankColumns: testdata.yank,
|
||||
NoColor: true,
|
||||
}
|
||||
|
||||
conf.ApplyDefaults()
|
||||
data := newData() // defined in printer_test.go, reused here
|
||||
|
||||
var writer bytes.Buffer
|
||||
printData(&writer, conf, &data)
|
||||
|
||||
got, err := cb.PasteText()
|
||||
if err != nil {
|
||||
t.Errorf("failed to fetch yanked text from clipboard")
|
||||
}
|
||||
|
||||
if got != testdata.expect {
|
||||
t.Errorf("not yanked correctly:\n+++ got:\n%s\n+++ want:\n%s",
|
||||
got, testdata.expect)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
6
t/testtable3
Normal file
6
t/testtable3
Normal file
@@ -0,0 +1,6 @@
|
||||
NAME READY STATUS STARTS AGE
|
||||
alertmanager-kube-prometheus-alertmanager-0 2/2 Running 35 11d
|
||||
kube-prometheus-blackbox-exporter-5d85b5d8f4-tskh7 1/1 Running 17 1h44m
|
||||
grafana-fcc54cbc9-bk7s8 1/1 Running 17 1d
|
||||
kube-prometheus-kube-state-metrics-b4cd9487-75p7f 1/1 Running 20 45m
|
||||
kube-prometheus-node-exporter-bfzpl 1/1 Running 17 54s
|
||||
4
t/testtable4
Normal file
4
t/testtable4
Normal file
@@ -0,0 +1,4 @@
|
||||
ONE TWO
|
||||
1 4
|
||||
3 1
|
||||
5 2
|
||||
39
tablizer.1
39
tablizer.1
@@ -133,7 +133,7 @@
|
||||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "TABLIZER 1"
|
||||
.TH TABLIZER 1 "2025-01-14" "1" "User Commands"
|
||||
.TH TABLIZER 1 "2025-01-23" "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
|
||||
@@ -153,7 +153,7 @@ tablizer \- Manipulate tabular output of other programs
|
||||
\& \-N, \-\-no\-color Disable pattern highlighting
|
||||
\& \-H, \-\-no\-headers Disable headers display
|
||||
\& \-s, \-\-separator string Custom field separator
|
||||
\& \-k, \-\-sort\-by int Sort by column (default: 1)
|
||||
\& \-k, \-\-sort\-by int|name Sort by column (default: 1)
|
||||
\& \-z, \-\-fuzzy Use fuzzy search [experimental]
|
||||
\& \-F, \-\-filter field=reg Filter given field with regex, can be used multiple times
|
||||
\& \-T, \-\-transpose\-columns string Transpose the speficied columns (separated by ,)
|
||||
@@ -168,6 +168,8 @@ tablizer \- Manipulate tabular output of other programs
|
||||
\& \-C, \-\-csv Enable CSV output
|
||||
\& \-A, \-\-ascii Default output mode, ascii tabular
|
||||
\& \-L, \-\-hightlight\-lines Use alternating background colors for tables
|
||||
\& \-y, \-\-yank\-columns Yank specified columns (separated by ,) to clipboard,
|
||||
\& space separated
|
||||
\&
|
||||
\& Sort Mode Flags (mutually exclusive):
|
||||
\& \-a, \-\-sort\-age sort according to age (duration) string
|
||||
@@ -250,11 +252,20 @@ 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. The default sort order
|
||||
is ascending. You can change this to descending order using the option
|
||||
\&\fB\-D\fR. The default sort order is by string, but there are other sort
|
||||
modes:
|
||||
data (as in \s-1GNU\s0 \fBsort\fR\|(1)). The default sort column is the first
|
||||
one. You can specify column numbers or names. Column numbers start
|
||||
with 1, names are case insensitive. You can specify multiple columns
|
||||
separated by comma to sort, but the type must be the same. For example
|
||||
if you want to sort numerically, all columns must be numbers. If you
|
||||
use column numbers, then be aware, that these are the numbers before
|
||||
column extraction. For example if you have a table with 4 columns and
|
||||
specify \f(CW\*(C`\-c4\*(C'\fR, then only 1 column (the fourth) will be printed,
|
||||
however if you want to sort by this column, you'll have to specify
|
||||
\&\f(CW\*(C`\-k4\*(C'\fR.
|
||||
.PP
|
||||
The default sort order is ascending. You can change this to
|
||||
descending order using the option \fB\-D\fR. The default sort order is by
|
||||
alphanumeric 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".
|
||||
@@ -433,6 +444,20 @@ more output modes available: \fBorgtbl\fR which prints an Emacs org-mode
|
||||
table and \fBmarkdown\fR which prints a Markdown table, \fByaml\fR, which
|
||||
prints yaml encoding and \s-1CSV\s0 mode, which prints a comma separated
|
||||
value file.
|
||||
.SS "\s-1PUT FIELDS TO CLIPBOARD\s0"
|
||||
.IX Subsection "PUT FIELDS TO CLIPBOARD"
|
||||
You can let tablizer put fields to the clipboard using the option
|
||||
\&\f(CW\*(C`\-y\*(C'\fR. This best fits the use-case when the result of your filtering
|
||||
yields just one row. For example:
|
||||
.PP
|
||||
.Vb 1
|
||||
\& cloudctl cluster ls | tablizer \-yid matchbox
|
||||
.Ve
|
||||
.PP
|
||||
If \*(L"matchbox\*(R" matches one cluster, you can immediately use the id of
|
||||
that cluster somewhere else and paste it. Of course, if there are
|
||||
multiple matches, then all id's will be put into the clipboard
|
||||
separated by one space.
|
||||
.SS "\s-1ENVIRONMENT VARIABLES\s0"
|
||||
.IX Subsection "ENVIRONMENT VARIABLES"
|
||||
\&\fBtablizer\fR supports certain environment variables which use can use
|
||||
|
||||
36
tablizer.pod
36
tablizer.pod
@@ -14,7 +14,7 @@ tablizer - Manipulate tabular output of other programs
|
||||
-N, --no-color Disable pattern highlighting
|
||||
-H, --no-headers Disable headers display
|
||||
-s, --separator string Custom field separator
|
||||
-k, --sort-by int Sort by column (default: 1)
|
||||
-k, --sort-by int|name Sort by column (default: 1)
|
||||
-z, --fuzzy Use fuzzy search [experimental]
|
||||
-F, --filter field=reg Filter given field with regex, can be used multiple times
|
||||
-T, --transpose-columns string Transpose the speficied columns (separated by ,)
|
||||
@@ -29,6 +29,8 @@ tablizer - Manipulate tabular output of other programs
|
||||
-C, --csv Enable CSV output
|
||||
-A, --ascii Default output mode, ascii tabular
|
||||
-L, --hightlight-lines Use alternating background colors for tables
|
||||
-y, --yank-columns Yank specified columns (separated by ,) to clipboard,
|
||||
space separated
|
||||
|
||||
Sort Mode Flags (mutually exclusive):
|
||||
-a, --sort-age sort according to age (duration) string
|
||||
@@ -106,11 +108,20 @@ 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. The default sort order
|
||||
is ascending. You can change this to descending order using the option
|
||||
B<-D>. The default sort order is by string, but there are other sort
|
||||
modes:
|
||||
data (as in GNU sort(1)). The default sort column is the first
|
||||
one. You can specify column numbers or names. Column numbers start
|
||||
with 1, names are case insensitive. You can specify multiple columns
|
||||
separated by comma to sort, but the type must be the same. For example
|
||||
if you want to sort numerically, all columns must be numbers. If you
|
||||
use column numbers, then be aware, that these are the numbers before
|
||||
column extraction. For example if you have a table with 4 columns and
|
||||
specify C<-c4>, then only 1 column (the fourth) will be printed,
|
||||
however if you want to sort by this column, you'll have to specify
|
||||
C<-k4>.
|
||||
|
||||
The default sort order is ascending. You can change this to
|
||||
descending order using the option B<-D>. The default sort order is by
|
||||
alphanumeric string, but there are other sort modes:
|
||||
|
||||
=over
|
||||
|
||||
@@ -281,6 +292,19 @@ table and B<markdown> which prints a Markdown table, B<yaml>, which
|
||||
prints yaml encoding and CSV mode, which prints a comma separated
|
||||
value file.
|
||||
|
||||
=head2 PUT FIELDS TO CLIPBOARD
|
||||
|
||||
You can let tablizer put fields to the clipboard using the option
|
||||
C<-y>. This best fits the use-case when the result of your filtering
|
||||
yields just one row. For example:
|
||||
|
||||
cloudctl cluster ls | tablizer -yid matchbox
|
||||
|
||||
If "matchbox" matches one cluster, you can immediately use the id of
|
||||
that cluster somewhere else and paste it. Of course, if there are
|
||||
multiple matches, then all id's will be put into the clipboard
|
||||
separated by one space.
|
||||
|
||||
=head2 ENVIRONMENT VARIABLES
|
||||
|
||||
B<tablizer> supports certain environment variables which use can use
|
||||
|
||||
Reference in New Issue
Block a user