https://github.com/miyamo2/filtgen
generate an iterator by go generate that can filter by field values of the item.
https://github.com/miyamo2/filtgen
cli code-generation codegen filter filtering go gogenerate golang iterator iterator-library rangefunc
Last synced: 16 days ago
JSON representation
generate an iterator by go generate that can filter by field values of the item.
- Host: GitHub
- URL: https://github.com/miyamo2/filtgen
- Owner: miyamo2
- License: mit
- Created: 2024-08-27T13:38:41.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2025-05-07T16:02:29.000Z (18 days ago)
- Last Synced: 2025-05-08T23:44:17.759Z (16 days ago)
- Topics: cli, code-generation, codegen, filter, filtering, go, gogenerate, golang, iterator, iterator-library, rangefunc
- Language: Go
- Homepage:
- Size: 79.1 KB
- Stars: 4
- Watchers: 1
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# filtgen
[](https://pkg.go.dev/github.com/miyamo2/filtgen)
[](https://img.shields.io/github/go-mod/go-version/miyamo2/filtgen)
[](https://img.shields.io/github/v/release/miyamo2/filtgen)
[](https://github.com/miyamo2/filtgen/actions/workflows/ci.yaml)
[](https://goreportcard.com/report/github.com/miyamo2/filtgen)
[](https://img.shields.io/github/license/miyamo2/filtgen?&color=blue)CLI tool for generating iterators that selects items by their field values.
## Quick Start
### Install
```sh
go install github.com/miyamo2/filtgen@latest
```### Usage
#### Step 1: Tag your struct with the `filtgen`
```go
//go:generate filtgen generate -s $GOFILE
package mainimport (
"time"
)type Foo struct {
StringField string `filtgen:"*"`
IntField int `filtgen:"*"`
BoolField bool `filtgen:"*"`
TimeField time.Time `filtgen:"*"`
ErrorField error `filtgen:"*"`
}
```#### Step 2: Run `filtgen generate`
##### Run with `go generate`
```sh
go generate ./...
```##### Run with `filtgen` command
```sh
filtgen generate -s your_struct.go
```#### Step 3: Use generated iterator
```go
errSomething := errors.New("something")s := []Foo{
{StringField: "a", IntField: 1, BoolField: true, TimeField: time.Now()},
{StringField: "b", IntField: 2, BoolField: false, TimeField: time.Now(), ErrorField: errSomething},
{StringField: "c", IntField: 3, BoolField: true, TimeField: time.Now().Add(-(time.Hour * 2))},
}for i, v := range FooSlice(s).StringFieldGe("a") {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 0: a
// 1: b
// 2: cfor i, v := range FooSlice(s).IntFieldGt(1) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 1: b
// 2: cfor i, v := range FooSlice(s).BoolFieldEq(true) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 0: a
// 2: cfor i, v := range FooSlice(s).TimeFieldMatches(func(t time.Time) bool { return t.Before(time.Now()) }) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 2: cfor i, v := range FooSlice(s).ErrorFieldIs(errSomething) {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 1: b// with method chaining
for i, v := range FooSlice(s).IntFieldGt(1).StringFieldNe("c") {
fmt.Printf("%d: %s\n", i, v.StringField)
}
// Output: 1: b
```For the actual generated code, see the [example](https://github.com/miyamo2/filtgen/tree/main/example).
## What codes to be generated?
### Types
`filtgen` generates the following defined-types.
- `XxxSlice`(`[]T`)
- `XxxMap[K]`(`map[K compareble]T`)
- `XxxSeq[T]`(`iter.Seq[T]`)
- `XxxSeq2[T]`(`iter.Seq2[T, U]`)
Type name is determined by the struct name; e.g. `User` -> `UserSlice`.
To use the generated methods, cast must be performed.
```go
s := []User{
{Name: "Alice"},
{Name: "Bob"},
}
for i, v := range UserSlice(s).NameEq("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}
```### Methods
Following methods are generated by `filtgen`.
- [`XxxEq`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxeq)
- [`XxxNe`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxne)
- [`XxxGt`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxgt)
- [`XxxLt`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxlt)
- [`XxxGe`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxge)
- [`XxxLe`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxle)
- [`XxxMatches`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxmatches)
- [`XxxIs`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxis)
- [`XxxIsnt`](https://github.com/miyamo2/filtgen/tree/main/README.md#xxxisnt)Method name is determined by the field name; e.g. `Name` -> `NameEq`.
#### `XxxEq`
Selects iterator items whose field values are equal to the specified value.
```go
type User struct {
Name string `filtgen:"eq"`
}
``````go
for i, v := range UserSlice(s).NameEq("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}
```#### `XxxNe`
Selects iterator items whose field values are not equal to the specified value.
```go
type User struct {
Name string `filtgen:"ne"`
}
``````go
for i, v := range UserSlice(s).NameNe("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}
```#### `XxxGt`
Selects iterator items whose field values are greater than the specified value.
```go
type User struct {
Name string `filtgen:"gt"`
}
``````go
for i, v := range UserSlice(s).NameGt("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}
```#### `XxxLt`
Selects iterator items whose field values are less than the specified value.
```go
type User struct {
Name string `filtgen:"lt"`
}
``````go
for i, v := range UserSlice(s).NameLt("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}
```#### `XxxGe`
Selects iterator items whose field values are greater than or equal to the specified value.
```go
type User struct {
Name string `filtgen:"ge"`
}
``````go
for i, v := range UserSlice(s).NameGe("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}
```#### `XxxLe`
Selects iterator items whose field values are less than or equal to the specified value.
```go
type User struct {
Name string `filtgen:"le"`
}
``````go
for i, v := range UserSlice(s).NameLe("Alice") {
fmt.Printf("%d: %s\n", i, v.Name)
}
```#### `XxxMatches`
Selects iterator items whose field values match the specified function.
```go
type User struct {
Name string `filtgen:"matches"`
}
``````go
for i, v := range UserSlice(s).NameMatches(func(s string) bool { return strings.HasPrefix(s, "A") }) {
fmt.Printf("%d: %s\n", i, v.Name)
}
```#### `XxxIs`
Selects iterator items whose field values are equal to the specified `error`.
Equivalence is determined by `errors.Is`.```go
type Transaction struct {
ID string `filtgen:"eq"`
Err error `filtgen:"is"`
}
``````go
for i, v := range TransactionSlice(s).ErrIs(fmt.Errorf("something")) {
fmt.Printf("%d: %s\n", i, v.ID)
}
```#### `XxxIsnt`
Selects iterator items whose field values are not equal to the specified `error`.
Equivalence is determined by `errors.Is`.```go
type Transaction struct {
ID string `filtgen:"eq"`
Err error `filtgen:"isnt"`
}
``````go
for i, v := range TransactionSlice(s).ErrIsnt(fmt.Errorf("something")) {
fmt.Printf("%d: %s\n", i, v.ID)
}
```#### List of compatible filters by type
| Type\Filter | `XxxEq` | `XxxNe` | `XxxGt` | `XxxLt` | `XxxGe` | `XxxLe` | `XxxMatches` | `XxxIs` | `XxxIsnt` |
|--------------|---------|---------|---------|---------|---------|---------|--------------|---------|-----------|
| `string` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `int` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `int8` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `int16` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `int32` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `int64` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `uint` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `uint8` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `uint16` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `uint32` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `uint64` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `float32` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `float64` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `complex64` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| `complex128` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| `byte` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `rune` | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ |
| `error` | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
| `bool` | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |
| other-types | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ |### `filtgen` tags
The following values can be set in the `filtgen` tag.
If you want to set multiple values, separate them with `,`.```go
type A struct {
StringField string `filtgen:"eq,ne"`
}
```| Value | Description |
|-----------|---------------------------------------------------------------------|
| `*` | Generate all methods supported according to the type of that field. |
| `eq` | Generate `XxxEq` methods. |
| `ne` | Generate `XxxNe` methods. |
| `gt` | Generate `XxxGt` methods. |
| `lt` | Generate `XxxLt` methods. |
| `ge` | Generate `XxxGe` methods. |
| `le` | Generate `XxxLe` methods. |
| `matches` | Generate `XxxMatches` methods. |
| `is` | Generate `XxxIs` methods. |
| `isnt` | Generate `XxxIsnt` methods. |## For Contributors
Feel free to open a PR or an Issue.
However, you must promise to follow our [Code of Conduct](https://github.com/miyamo2/filtgen/blob/main/CODE_OF_CONDUCT.md).### Tasks
We recommend that this section be run with [`xc`](https://github.com/joerdav/xc).
#### setup:deps
Install `golangci-lint`.
```sh
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
```#### lint
```sh
golangci-lint run --fix
```## License
**filtgen** released under the [MIT License](https://github.com/miyamo2/filtgen/blob/main/LICENSE)