diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5ac6d36..716c24f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.2.0]
+### Added
+- Search function for filtering resource lists
+ - Ability to filter by any string
+ - Ability to filter by "starts with" using ^
+
## [1.1.1] - 2019-06-22
### Added
- Coverage via Codecov
@@ -31,7 +37,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Resource endpoint for resource lists
- Unit tests for all endpoints
-[Unreleased]: https://github.com/mtslzr/pokeapi-go/compare/v1.1.1...HEAD
+[Unreleased]: https://github.com/mtslzr/pokeapi-go/compare/v1.2.0...HEAD
+[1.2.0]: https://github.com/mtslzr/pokeapi-go/compare/v1.1.1...v1.2.0
[1.1.1]: https://github.com/mtslzr/pokeapi-go/compare/v1.1.0...v1.1.1
[1.1.0]: https://github.com/mtslzr/pokeapi-go/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/mtslzr/pokeapi-go/releases/tag/v1.0.0
\ No newline at end of file
diff --git a/README.md b/README.md
index b2b826f..e98042c 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[](http://godoc.org/github.com/mtslzr/pokeapi-go)
[](https://raw.githubusercontent.com/mtslzr/pokeapi-go/master/LICENSE)
-Wrapper for [Poke API](https://pokeapi.co), written in Go. *Uses PokeAPI v2.*
+Wrapper for [Poke API](https://pokeapi.co), written in Go. *Supports PokeAPI v2.*
- [pokeapi-go](#pokeapi-go)
- [Documentation](#Documentation)
@@ -22,7 +22,9 @@ Wrapper for [Poke API](https://pokeapi.co), written in Go. *Uses PokeAPI v2.*
- [Moves](#Moves)
- [Pokemon](#Pokemon)
- [Utility](#Utility)
- - [Resource List Parameters](#Resource-List-Parameters)
+ - [Additional Options](#Additional-Options)
+ - [Resource List Parameters](#Resource-List-Parameters)
+ - [Resource List Filters](#Resource-List-Filters)
## Documentation
@@ -926,36 +928,70 @@ import "github.com/mtslzr/pokeapi-go"
```
-## Resource List Parameters
+## Additional Options
+
+### Resource List Parameters
When calling `pokeapi.Resource()` for any resource list, you can optionally pass up to two integers. The first will be an offset (defaults to zero), and the second will be the limit (defaults two twenty).
Default
-```go
-r := pokeapi.Resource("pokemon")
-fmt.Println(len(r.Results)) // 20
-fmt.Println(r.Results[0].Name) // "bulbasaur"
-```
+ ```go
+ r := pokeapi.Resource("pokemon")
+ fmt.Println(len(r.Results)) // 20
+ fmt.Println(r.Results[0].Name) // "bulbasaur"
+ ```
Offset
-```go
-r := pokeapi.Resource("pokemon", 3)
-fmt.Println(len(r.Results)) // 20
-fmt.Println(r.Results[0].Name) // "charmander"
-```
+ ```go
+ r := pokeapi.Resource("pokemon", 3)
+ fmt.Println(len(r.Results)) // 20
+ fmt.Println(r.Results[0].Name) // "charmander"
+ ```
Offset and Limit
-```go
-r := pokeapi.Resource("pokemon", 6, 10)
-fmt.Println(len(r.Results)) // 10
-fmt.Println(r.Results[0].Name) // "squirtle"
-```
+ ```go
+ r := pokeapi.Resource("pokemon", 6, 10)
+ fmt.Println(len(r.Results)) // 10
+ fmt.Println(r.Results[0].Name) // "squirtle"
+ ```
+
+
+### Resource List Filters
+
+As an alternative to `pokeapi.Resource()`, you can use Search to filter resource lists. Pass the endpoint, followed by the search term. Or pass a string starting with `^` to search for items starting with the search team.
+
+*result.Count is updated after the search with the new total (to get the full count, use `pokeapi.Resource()`.*
+
+
+ Search
+
+ ```go
+ s := pokeapi.Search("pokemon", "saur")
+ fmt.Println(len(s.Results)) // 4
+ fmt.Println(s.Results[3].Name) // venusaur-mega
+ ```
+
+
+
+ Starts With
+
+ ```go
+ s := pokeapi.Search("pokemon", "^a")
+ fmt.Println(len(s.Results)) // 44
+ fmt.Println(s.Results[0].Name) // arbok
+ ```
+
+ ```go
+ s := pokeapi.Search("pokemon", "^bulb")
+ fmt.Println(len(s.Results)) // 1
+ fmt.Println(s.Results[0].Name) // bulbasaur
+ ```
diff --git a/resource.go b/resource.go
index 14cfce3..acd2f1c 100644
--- a/resource.go
+++ b/resource.go
@@ -2,6 +2,7 @@ package pokeapi
import (
"fmt"
+ "strings"
"github.com/mtslzr/pokeapi-go/structs"
)
@@ -12,7 +13,16 @@ func Resource(endpoint string, params ...int) (result structs.Resource,
offset, limit := parseParams(params)
err = do(fmt.Sprintf("%s?offset=%d&limit=%d", endpoint, offset, limit),
&result)
- return result, err
+ return
+}
+
+// Search returns resource list, filtered by search term.
+func Search(endpoint string, search string) (result structs.Resource,
+ err error) {
+ err = do(fmt.Sprintf("%s?offset=0&limit=9999", endpoint), &result)
+ result.Results = parseSearch(result.Results, search)
+ result.Count = len(result.Results)
+ return
}
func parseParams(params []int) (offset int, limit int) {
@@ -25,3 +35,27 @@ func parseParams(params []int) (offset int, limit int) {
}
return
}
+
+func parseSearch(results []structs.Result, search string) []structs.Result {
+ var x int
+ var substr string
+
+ for _, result := range results {
+ if string(search[0]) == "^" {
+ substr = string(search[1:])
+ if len(substr) > len(result.Name) {
+ continue
+ }
+ if string(result.Name[0:len(substr)]) != string(substr) {
+ continue
+ }
+ } else {
+ if !strings.Contains(result.Name, search) {
+ continue
+ }
+ }
+ results[x] = result
+ x++
+ }
+ return results[:x]
+}
diff --git a/structs/resource.go b/structs/resource.go
index 1d278d2..641b00f 100644
--- a/structs/resource.go
+++ b/structs/resource.go
@@ -5,8 +5,11 @@ type Resource struct {
Count int `json:"count"`
Next string `json:"next"`
Previous interface{} `json:"previous"`
- Results []struct {
- Name string `json:"name"`
- URL string `json:"url"`
- } `json:"results"`
+ Results []Result `json:"results"`
+}
+
+// Result is a resource list result.
+type Result struct {
+ Name string `json:"name"`
+ URL string `json:"url"`
}
diff --git a/tests/resource_test.go b/tests/resource_test.go
index c7de42a..bb7b460 100644
--- a/tests/resource_test.go
+++ b/tests/resource_test.go
@@ -3,7 +3,7 @@ package tests
import (
"testing"
- pokeapi "github.com/mtslzr/pokeapi-go"
+ "github.com/mtslzr/pokeapi-go"
"github.com/stretchr/testify/assert"
)
@@ -43,3 +43,37 @@ func TestResourceOffsetLimit(t *testing.T) {
assert.Equal(t, "charizard", result.Results[2].Name,
"Expect to receive Charizard last.")
}
+
+func TestSearch(t *testing.T) {
+ result, _ := pokeapi.Search("pokemon", "saur")
+ assert.Equal(t, 4, len(result.Results),
+ "Expect to receive four results.")
+ assert.Equal(t, "venusaur", result.Results[2].Name,
+ "Expect to receive Venusaur.")
+}
+
+func TestSearchFail(t *testing.T) {
+ result, _ := pokeapi.Search("pokemon", "asdf")
+ assert.Equal(t, 0, len(result.Results),
+ "Expect to receive zero results.")
+}
+
+func TestSearchStartsWith(t *testing.T) {
+ result, _ := pokeapi.Search("pokemon", "^a")
+ assert.Equal(t, 44, len(result.Results),
+ "Expect to receive four results.")
+ assert.Equal(t, "arbok", result.Results[0].Name,
+ "Expect to receive Arbok.")
+
+ result, _ = pokeapi.Search("pokemon", "^bla")
+ assert.Equal(t, 5, len(result.Results),
+ "Expect to receive four results.")
+ assert.Equal(t, "blastoise", result.Results[0].Name,
+ "Expect to receive Blastoise.")
+}
+
+func TestSearchStartsWithFail(t *testing.T) {
+ result, _ := pokeapi.Search("pokemon", "^zzz")
+ assert.Equal(t, 0, len(result.Results),
+ "Expect to receive zero results.")
+}