Compare commits

...

4 Commits

11 changed files with 129 additions and 30 deletions

View File

@@ -5,9 +5,7 @@ jobs:
strategy:
matrix:
version: ['1.22']
# windows-latest removed, see:
# https://github.com/rogpeppe/go-internal/issues/284
os: [ubuntu-latest, macos-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
name: Build
runs-on: ${{ matrix.os }}
steps:

View File

@@ -1,8 +1,8 @@
name: build-and-test
name: build-release
on:
push:
tags:
- "*"
- "v*.*.*"
jobs:
release:
@@ -10,10 +10,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v1
uses: actions/setup-go@v5
with:
go-version: 1.22.11
@@ -30,3 +30,58 @@ jobs:
tag: ${{ github.ref_name }}
file: ./releases/*
file_glob: true
- name: Build Changelog
id: github_release
uses: mikepenz/release-changelog-builder-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
mode: "PR"
configurationJson: |
{
"template": "#{{CHANGELOG}}\n\n**Full Changelog**: #{{RELEASE_DIFF}}",
"pr_template": "- #{{TITLE}} (##{{NUMBER}}) by #{{AUTHOR}}\n#{{BODY}}",
"empty_template": "- no changes",
"categories": [
{
"title": "## New Features",
"labels": ["add", "feature"]
},
{
"title": "## Bug Fixes",
"labels": ["fix", "bug", "revert"]
},
{
"title": "## Documentation Enhancements",
"labels": ["doc"]
},
{
"title": "## Refactoring Efforts",
"labels": ["refactor"]
},
{
"title": "## Miscellaneus Changes",
"labels": []
}
],
"ignore_labels": [
"duplicate", "good first issue", "help wanted", "invalid", "question", "wontfix"
],
"label_extractor": [
{
"pattern": "(.) (.+)",
"target": "$1"
},
{
"pattern": "(.) (.+)",
"target": "$1",
"on_property": "title"
}
]
}
- name: Create Release
uses: softprops/action-gh-release@v2
with:
body: ${{steps.github_release.outputs.changelog}}

View File

@@ -64,7 +64,7 @@ install: buildlocal
clean:
rm -rf $(tool) releases coverage.out
test:
test: clean
go test ./... $(OPTS)
singletest:

View File

@@ -22,7 +22,7 @@ Operational Flags:
-s, --separator string Custom field separator
-k, --sort-by int 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
-F, --filter field[!]=reg Filter given field with regex, can be used multiple times
-T, --transpose-columns string Transpose the speficied columns (separated by ,)
-R, --regex-transposer /from/to/ Apply /search/replace/ regexp to fields given in -T

View File

@@ -1,5 +1,5 @@
/*
Copyright © 2022-2024 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
@@ -28,7 +28,7 @@ import (
)
const DefaultSeparator string = `(\s\s+|\t)`
const Version string = "v1.3.1"
const Version string = "v1.3.2"
const MAXPARTS = 2
var DefaultConfigfile = os.Getenv("HOME") + "/.config/tablizer/config"
@@ -58,6 +58,11 @@ type Pattern struct {
Negate bool
}
type Filter struct {
Regex *regexp.Regexp
Negate bool
}
// internal config
type Config struct {
Debug bool
@@ -100,7 +105,7 @@ type Config struct {
// used for field filtering
Rawfilters []string
Filters map[string]*regexp.Regexp
Filters map[string]Filter //map[string]*regexp.Regexp
// -r <file>
InputFile string
@@ -270,12 +275,20 @@ func (conf *Config) PrepareModeFlags(flag Modeflag) {
}
func (conf *Config) PrepareFilters() error {
conf.Filters = make(map[string]*regexp.Regexp, len(conf.Rawfilters))
conf.Filters = make(map[string]Filter, len(conf.Rawfilters))
for _, filter := range conf.Rawfilters {
parts := strings.Split(filter, "=")
for _, rawfilter := range conf.Rawfilters {
filter := Filter{}
parts := strings.Split(rawfilter, "!=")
if len(parts) != MAXPARTS {
return errors.New("filter field and value must be separated by =")
parts = strings.Split(rawfilter, "=")
if len(parts) != MAXPARTS {
return errors.New("filter field and value must be separated by '=' or '!='")
}
} else {
filter.Negate = true
}
reg, err := regexp.Compile(parts[1])
@@ -284,7 +297,8 @@ func (conf *Config) PrepareFilters() error {
parts[0], err)
}
conf.Filters[strings.ToLower(strings.ToLower(parts[0]))] = reg
filter.Regex = reg
conf.Filters[strings.ToLower(parts[0])] = filter
}
return nil

View File

@@ -1,5 +1,5 @@
/*
Copyright © 2022-2024 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
@@ -190,7 +190,7 @@ func Execute() {
// filters
rootCmd.PersistentFlags().StringArrayVarP(&conf.Rawfilters,
"filter", "F", nil, "Filter by field (field=regexp)")
"filter", "F", nil, "Filter by field (field=regexp || field!=regexp)")
rootCmd.PersistentFlags().StringArrayVarP(&conf.Transposers,
"regex-transposer", "R", nil, "apply /search/replace/ regexp to fields given in -T")

View File

@@ -17,7 +17,7 @@ SYNOPSIS
-s, --separator string Custom field separator
-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
-F, --filter field[!]=reg Filter given field with regex, can be used multiple times
-T, --transpose-columns string Transpose the speficied columns (separated by ,)
-R, --regex-transposer /from/to/ Apply /search/replace/ regexp to fields given in -T
@@ -181,6 +181,10 @@ DESCRIPTION
If you specify more than one filter, both filters have to match (AND
operation).
These field filters can also be negated:
fieldname!=regexp
If the option -v is specified, the filtering is inverted.
COLUMNS
@@ -416,7 +420,7 @@ Operational Flags:
-s, --separator string Custom field separator
-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
-F, --filter field[!]=reg Filter given field with regex, can be used multiple times
-T, --transpose-columns string Transpose the speficied columns (separated by ,)
-R, --regex-transposer /from/to/ Apply /search/replace/ regexp to fields given in -T

View File

@@ -1,5 +1,5 @@
/*
Copyright © 2022-2024 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
@@ -86,15 +86,19 @@ func FilterByFields(conf cfg.Config, data *Tabdata) (*Tabdata, bool, error) {
keep := true
for idx, header := range data.headers {
if !Exists(conf.Filters, strings.ToLower(header)) {
lcheader := strings.ToLower(header)
if !Exists(conf.Filters, lcheader) {
// do not filter by unspecified field
continue
}
if !conf.Filters[strings.ToLower(header)].MatchString(row[idx]) {
// there IS a filter, but it doesn't match
keep = false
match := conf.Filters[lcheader].Regex.MatchString(row[idx])
if conf.Filters[lcheader].Negate {
match = !match
}
if !match {
keep = false
break
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright © 2024 Thomas von Dein
Copyright © 2024-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
@@ -98,6 +98,20 @@ func TestFilterByFields(t *testing.T) {
},
},
{
name: "one-field-negative",
filter: []string{"one!=asd"},
expect: Tabdata{
headers: []string{
"ONE", "TWO", "THREE",
},
entries: [][]string{
{"19191", "EDD 1", "x"},
{"8d8", "AN 1", "y"},
},
},
},
{
name: "one-field-inverted",
filter: []string{"one=19"},

View File

@@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "TABLIZER 1"
.TH TABLIZER 1 "2025-01-22" "1" "User Commands"
.TH TABLIZER 1 "2025-01-30" "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
@@ -155,7 +155,7 @@ tablizer \- Manipulate tabular output of other programs
\& \-s, \-\-separator string Custom field separator
\& \-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
\& \-F, \-\-filter field[!]=reg Filter given field with regex, can be used multiple times
\& \-T, \-\-transpose\-columns string Transpose the speficied columns (separated by ,)
\& \-R, \-\-regex\-transposer /from/to/ Apply /search/replace/ regexp to fields given in \-T
\&
@@ -340,6 +340,12 @@ Fieldnames (== columns headers) are case insensitive.
If you specify more than one filter, both filters have to match (\s-1AND\s0
operation).
.PP
These field filters can also be negated:
.PP
.Vb 1
\& fieldname!=regexp
.Ve
.PP
If the option \fB\-v\fR is specified, the filtering is inverted.
.SS "\s-1COLUMNS\s0"
.IX Subsection "COLUMNS"

View File

@@ -16,7 +16,7 @@ tablizer - Manipulate tabular output of other programs
-s, --separator string Custom field separator
-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
-F, --filter field[!]=reg Filter given field with regex, can be used multiple times
-T, --transpose-columns string Transpose the speficied columns (separated by ,)
-R, --regex-transposer /from/to/ Apply /search/replace/ regexp to fields given in -T
@@ -194,6 +194,10 @@ Fieldnames (== columns headers) are case insensitive.
If you specify more than one filter, both filters have to match (AND
operation).
These field filters can also be negated:
fieldname!=regexp
If the option B<-v> is specified, the filtering is inverted.