Compare commits
50 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e3132a5cf | |||
| 2561fe3cff | |||
| 17961ddd41 | |||
| cdb504c1a3 | |||
| 70c74c2b03 | |||
| 81e04ea319 | |||
| b6994e73a8 | |||
| c5a9f09166 | |||
| cdf12a767c | |||
| 5cbd63a227 | |||
| ac3d1a5565 | |||
| c32a15f4a1 | |||
| 4b9bffb1a6 | |||
| 4b1312e293 | |||
| 797c616447 | |||
| 8f02956ecd | |||
| 480e36763f | |||
| 8072ae267a | |||
| 4faf3a5d2f | |||
| c17f23595c | |||
| f20e737f2b | |||
| 1abfaa44d1 | |||
| d7b14f804c | |||
| fee2e3cc2f | |||
| f121b7dbce | |||
| 55038ea295 | |||
| 4d6cd82b74 | |||
| 7c016df30f | |||
| 2440f55563 | |||
| 1008a064d0 | |||
| 1677a692d1 | |||
| 5c1132e414 | |||
| 10eb3f2491 | |||
| fd5413ab21 | |||
| 46a40031dd | |||
| db2f12522d | |||
| 9402d80704 | |||
| bd448eb5db | |||
| 1d0f2238b3 | |||
| 586fe4f1de | |||
| 63d538d889 | |||
| 61a5199699 | |||
| 72791d4fac | |||
| 90f8d22b23 | |||
| e25c1001a5 | |||
| 8888ee3855 | |||
| dd531c1f73 | |||
| 9e84cfe5f9 | |||
| e5a1002e2e | |||
| 3546ab52d1 |
30 changed files with 1208 additions and 463 deletions
39
.golangci.yaml
Normal file
39
.golangci.yaml
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- errcheck
|
||||||
|
- gosimple
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
- copyloopvar
|
||||||
|
- dupl
|
||||||
|
- err113
|
||||||
|
- errname
|
||||||
|
- exptostd
|
||||||
|
- fatcontext
|
||||||
|
- funlen
|
||||||
|
- gocognit
|
||||||
|
- goconst
|
||||||
|
- gocritic
|
||||||
|
- gocyclo
|
||||||
|
- godot
|
||||||
|
- godox
|
||||||
|
- gosec
|
||||||
|
- perfsprint
|
||||||
|
- testifylint
|
||||||
|
|
||||||
|
linters-settings:
|
||||||
|
testifylint:
|
||||||
|
enable-all: true
|
||||||
|
disable:
|
||||||
|
- require-error
|
||||||
|
gocognit:
|
||||||
|
min-complexity: 5
|
||||||
|
gocyclo:
|
||||||
|
min-complexity: 5
|
||||||
|
gocritic:
|
||||||
|
enable-all: true
|
||||||
|
settings:
|
||||||
|
hugeParam:
|
||||||
|
sizeThreshold: 255
|
||||||
102
CHANGELOG.md
102
CHANGELOG.md
|
|
@ -1,37 +1,111 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
### [0.2.0] - 2025-03-14
|
### [1.0.0] - 2025-03-31 - 🚀 Stable release!
|
||||||
|
|
||||||
- Add `IncrementalFormat`* Generators
|
#### Support
|
||||||
- Add `Slug`* Generators
|
|
||||||
- Add `WithOriginalSlug`* Options
|
- 📝 Vastly improved [go docs](https://pkg.go.dev/codeberg.org/danjones000/nomino).
|
||||||
- Change signature of `Generator` function
|
- 📝 Fill out README with examples and links.
|
||||||
|
|
||||||
|
#### Tools
|
||||||
|
|
||||||
|
- 🛠 Replace all linting with golangci-lint
|
||||||
|
|
||||||
|
#### Code quality
|
||||||
|
|
||||||
|
- 🚨 A bunch of small improvements from new linter
|
||||||
|
|
||||||
|
### [0.5.0] - 2025-03-19 - ✨ Different types of UUIDs
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- ✨ Allow for different types of UUIDs in the UUID `Generator`
|
||||||
|
- ✨ `Config.AddOptions` method
|
||||||
|
- ✨ `Generator.MakeWithConfig` method
|
||||||
|
|
||||||
|
#### Support
|
||||||
|
|
||||||
|
- 📝 Some better examples
|
||||||
|
|
||||||
|
### [0.4.0] - 2025-03-15 - ✨ More Generators, and `Generator.Make` method
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- ✨ Add Random Generator
|
||||||
|
- ✨ Add Make method to Generator
|
||||||
|
- ✨ Add MultiGeneratorRandomOrder
|
||||||
|
|
||||||
|
#### Changes
|
||||||
|
|
||||||
|
- 💔 Breaking changes: Replace HashType with Hasher: This supports all crypto.Hash
|
||||||
|
|
||||||
|
#### Support
|
||||||
|
|
||||||
|
- 📝 Add some missing doc comments
|
||||||
|
|
||||||
|
### [0.3.0] - 2025-03-14 - ♻️ Refactor multiple Generators into one
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- ♻️ Simplified multiple `Generator` functions to single function with options
|
||||||
|
- 📝 Added a lot of examples for docs
|
||||||
|
- ✨ Can add extra `Option`s to `Make`
|
||||||
|
|
||||||
|
Multiple breaking changes around Generators.
|
||||||
|
|
||||||
|
#### Bugs
|
||||||
|
|
||||||
|
- 🐛 Fixed date formats
|
||||||
|
|
||||||
|
### [0.2.1] - 2025-03-14 - ✨ New Hash Generator
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- ✨ Add Hash Generator
|
||||||
|
|
||||||
|
#### Dev Tooling
|
||||||
|
|
||||||
|
- 🛠 Added a task to serve docs
|
||||||
|
- 🛠 Added tasts to check code complexity
|
||||||
|
|
||||||
|
#### Miscellaneous
|
||||||
|
|
||||||
|
- 💚 Fixed some `go vet` complaints
|
||||||
|
|
||||||
|
### [0.2.0] - 2025-03-14 - ✨ New `Generator`s
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- ✨ Add `IncrementalFormat`* Generators
|
||||||
|
- ✨ Add `Slug`* Generators
|
||||||
|
- ✨ Add `WithOriginalSlug`* Options
|
||||||
|
- 💔 Change signature of `Generator` function
|
||||||
|
|
||||||
Note that this last change **is** a breaking change from 0.0.3, but only for custom Generators.
|
Note that this last change **is** a breaking change from 0.0.3, but only for custom Generators.
|
||||||
|
|
||||||
## [0.0.3] - 2025-03-11
|
## [0.0.3] - 2025-03-11 - ✨ `WithSeparator`
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
- Added `WithSeparator` to allow for different separators between the parts of the generated filename.
|
- ✨ Added `WithSeparator` to allow for different separators between the parts of the generated filename.
|
||||||
|
|
||||||
## [0.0.2] - 2025-03-11
|
## [0.0.2] - 2025-03-11 - 🐛 Bugfix
|
||||||
|
|
||||||
Bugfix release
|
Bugfix release
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
- Extension being ignored. Original included twice.
|
- 🐛 Extension being ignored. Original included twice.
|
||||||
|
|
||||||
## [0.0.1] - 2025-03-10
|
## [0.0.1] - 2025-03-10 - 🚀 Initial Release
|
||||||
|
|
||||||
Initial Release! Hope you like it!
|
Initial Release! Hope you like it!
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- nomino.Make
|
- ✨ `nomino.Make``
|
||||||
- nomino.Config
|
- ✨ `nomino.Config`
|
||||||
- nomino.Generator
|
- ✨ `nomino.Generator`
|
||||||
+ We needs more of these until I'm ready
|
+ We needs more of these until I'm ready
|
||||||
- Lots of tests!
|
- ✅ Lots of tests!
|
||||||
|
|
||||||
|
|
|
||||||
78
README.md
78
README.md
|
|
@ -4,8 +4,80 @@ The purpose of nomino is to generate (probably random) filenames, for example, i
|
||||||
|
|
||||||
It takes a lot of inspiration (although no actual code) from [Onym](https://github.com/Blaspsoft/onym).
|
It takes a lot of inspiration (although no actual code) from [Onym](https://github.com/Blaspsoft/onym).
|
||||||
|
|
||||||
## TODO
|
Make sure to check out the [official documentation][docs].
|
||||||
|
|
||||||
I'll fill this out more in depth later.
|
## Installation
|
||||||
|
|
||||||
For now, check [official documentation](https://pkg.go.dev/codeberg.org/danjones000/nomino).
|
Add `codeberg.org/danjones000/nomino` to your project. You can do `go get codeberg.org/danjones000/nomino`, or simply add it to an import and run `go mod tidy`.
|
||||||
|
|
||||||
|
But, you probably already know this.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
There are **a lot** of examples in the [official documentation][examples]. Take a look through these to get an idea.
|
||||||
|
|
||||||
|
The main concept in `nomino` is the [Generator][]. The simplest way to generate a random filename, is to use the [Generator][] directly, in this way:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
name, _ := nomino.Random().Make()
|
||||||
|
fmt.Println(name) // Du3Sfh8p.txt
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The second argument is an error. Most of the generators are always successful, and that error will be `nil`, but you should check the errors if you're not sure.
|
||||||
|
|
||||||
|
The second way to generate a new filename is using the [Make][] function.
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
config := nomino.NewConfig(nomino.WithGenerator(nomino.Random()))
|
||||||
|
name, _ := nomino.Make(config)
|
||||||
|
fmt.Println(name) // Du3Sfh8p.txt
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Although in these examples, `nomino.Make` is more verbose, it can be beneficial to using that function if you have some customizations to how you generate the filenames.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
The [Config][] allows you to customize how the generated filename works with various [Options][Option]. The [options][Option] allows you to customize things like [adding a prefix](https://pkg.go.dev/codeberg.org/danjones000/nomino#WithPrefix), or changing the [extension](https://pkg.go.dev/codeberg.org/danjones000/nomino#WithExtension) of the generated filename (by default, it uses `.txt`).
|
||||||
|
|
||||||
|
Have a look at [all the Options][Option].
|
||||||
|
|
||||||
|
### Generator
|
||||||
|
|
||||||
|
The [Generator][] is the piece that returns the "random" portion of the generated filename, although, it doesn't actually have to be random.
|
||||||
|
|
||||||
|
Here are the built-in [Generators][Generator]:
|
||||||
|
|
||||||
|
- [UUID](https://pkg.go.dev/codeberg.org/danjones000/nomino#UUID) generates a UUID. This is the default if none is specified.
|
||||||
|
- [Random](https://pkg.go.dev/codeberg.org/danjones000/nomino#Random) generates a random string. By default, it's 8 characters long, but can be whatever length you provide.
|
||||||
|
- [Incremental](https://pkg.go.dev/codeberg.org/danjones000/nomino#Incremental) will generate just a series of integers, starting at 0.
|
||||||
|
- [Timestamp](https://pkg.go.dev/codeberg.org/danjones000/nomino#Timestamp) generates a string from the current time. It will look like "2009-11-10T23-00-00+0000.txt", although this can be customized.
|
||||||
|
- Both [Slug](https://pkg.go.dev/codeberg.org/danjones000/nomino#Slug) and [Hash](https://pkg.go.dev/codeberg.org/danjones000/nomino#Hash) work on the original name provided by [WithOriginal](https://pkg.go.dev/codeberg.org/danjones000/nomino#WithOriginal). Slug generats a slug from the name, while Hash hashes it. By default, it uses MD5.
|
||||||
|
|
||||||
|
You can also use multiple generators, either [in order](https://pkg.go.dev/codeberg.org/danjones000/nomino#MultiGeneratorInOrder), or [in a random order](https://pkg.go.dev/codeberg.org/danjones000/nomino#MultiGeneratorRandomOrder).
|
||||||
|
|
||||||
|
Finally, you can create a [custom generator](https://pkg.go.dev/codeberg.org/danjones000/nomino#example-WithGenerator-CustomGenerator) as well.
|
||||||
|
|
||||||
|
## RTFM (Read the fabulous manual)
|
||||||
|
|
||||||
|
[Official docs][docs], especially the [examples][]. Especially check out the [full example](https://pkg.go.dev/codeberg.org/danjones000/nomino#example-package), which includes how to use a global configuration.
|
||||||
|
|
||||||
|
[docs]: https://pkg.go.dev/codeberg.org/danjones000/nomino
|
||||||
|
[examples]: https://pkg.go.dev/codeberg.org/danjones000/nomino#pkg-examples
|
||||||
|
[Generator]: https://pkg.go.dev/codeberg.org/danjones000/nomino#Generator
|
||||||
|
[Config]: https://pkg.go.dev/codeberg.org/danjones000/nomino#Config
|
||||||
|
[Option]: https://pkg.go.dev/codeberg.org/danjones000/nomino#Option
|
||||||
|
[Make]: https://pkg.go.dev/codeberg.org/danjones000/nomino#Make
|
||||||
|
|
|
||||||
48
Taskfile.yml
48
Taskfile.yml
|
|
@ -5,7 +5,7 @@ tasks:
|
||||||
cmds:
|
cmds:
|
||||||
- task: fmt
|
- task: fmt
|
||||||
- task: test
|
- task: test
|
||||||
- task: build
|
- task: lint
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
desc: Format go code
|
desc: Format go code
|
||||||
|
|
@ -22,45 +22,16 @@ tasks:
|
||||||
cmds:
|
cmds:
|
||||||
- go generate ./...
|
- go generate ./...
|
||||||
|
|
||||||
vet:
|
|
||||||
desc: Vet go code
|
|
||||||
sources:
|
|
||||||
- '**/*.go'
|
|
||||||
cmds:
|
|
||||||
- go vet ./...
|
|
||||||
|
|
||||||
critic:
|
|
||||||
desc: Critique go code
|
|
||||||
sources:
|
|
||||||
- '**/*.go'
|
|
||||||
cmds:
|
|
||||||
- gocritic check ./...
|
|
||||||
|
|
||||||
staticcheck:
|
|
||||||
desc: Static check go code
|
|
||||||
sources:
|
|
||||||
- '**/*.go'
|
|
||||||
cmds:
|
|
||||||
- staticcheck ./...
|
|
||||||
|
|
||||||
vuln:
|
|
||||||
desc: Check for vulnerabilities
|
|
||||||
sources:
|
|
||||||
- '**/*.go'
|
|
||||||
cmds:
|
|
||||||
- govulncheck ./...
|
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
desc: Do static analysis
|
desc: Do static analysis
|
||||||
deps:
|
sources:
|
||||||
- vet
|
- '**/*.go'
|
||||||
- critic
|
cmds:
|
||||||
- staticcheck
|
- golangci-lint run
|
||||||
- vuln
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
desc: Run unit tests
|
desc: Run unit tests
|
||||||
deps: [fmt, vet]
|
deps: [fmt]
|
||||||
sources:
|
sources:
|
||||||
- '**/*.go'
|
- '**/*.go'
|
||||||
generates:
|
generates:
|
||||||
|
|
@ -83,4 +54,9 @@ tasks:
|
||||||
deps: [coverage-report]
|
deps: [coverage-report]
|
||||||
cmds:
|
cmds:
|
||||||
- ip addr list | grep inet
|
- ip addr list | grep inet
|
||||||
- php -S 0.0.0.0:3265 -t build
|
- php -S 0.0.0.0:3434 -t build
|
||||||
|
|
||||||
|
serve-docs:
|
||||||
|
desc: Serve the current docs
|
||||||
|
cmds:
|
||||||
|
- godoc -http=0.0.0.0:3434 -play
|
||||||
|
|
|
||||||
14
config.go
14
config.go
|
|
@ -1,5 +1,6 @@
|
||||||
package nomino
|
package nomino
|
||||||
|
|
||||||
|
// Config controls how the generatred filename is created.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
original string
|
original string
|
||||||
prefix string
|
prefix string
|
||||||
|
|
@ -9,14 +10,25 @@ type Config struct {
|
||||||
generator Generator
|
generator Generator
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewConfig returns a new [Config] with each [Option] specified.
|
||||||
|
// With no Options, the Config uses an extension of .txt, a separator
|
||||||
|
// of _, and the [UUID] [Generator].
|
||||||
func NewConfig(options ...Option) Config {
|
func NewConfig(options ...Option) Config {
|
||||||
conf := Config{
|
conf := Config{
|
||||||
extension: ".txt",
|
extension: ".txt",
|
||||||
separator: "_",
|
separator: "_",
|
||||||
generator: uuidGen,
|
generator: UUID(nil),
|
||||||
}
|
}
|
||||||
for _, opt := range options {
|
for _, opt := range options {
|
||||||
opt(&conf)
|
opt(&conf)
|
||||||
}
|
}
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddOptions creates a new [Config] with each [Option] added.
|
||||||
|
func (c Config) AddOptions(options ...Option) Config {
|
||||||
|
for _, opt := range options {
|
||||||
|
opt(&c)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,3 +20,12 @@ func TestNewConfWithOpts(t *testing.T) {
|
||||||
assert.Equal(t, "", c.extension)
|
assert.Equal(t, "", c.extension)
|
||||||
assert.Equal(t, "foobar", c.prefix)
|
assert.Equal(t, "foobar", c.prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfAddOpts(t *testing.T) {
|
||||||
|
c := Config{original: "hi"}
|
||||||
|
c2 := c.AddOptions(WithOriginalSlug("Hello, my dear"), WithPrefix("yo"))
|
||||||
|
assert.Equal(t, "", c.prefix)
|
||||||
|
assert.Equal(t, "hi", c.original)
|
||||||
|
assert.Equal(t, "hello-my-dear", c2.original)
|
||||||
|
assert.Equal(t, "yo", c2.prefix)
|
||||||
|
}
|
||||||
|
|
|
||||||
60
examples_test.go
Normal file
60
examples_test.go
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
package nomino_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Define a global Config.
|
||||||
|
func NominoConfig() nomino.Config {
|
||||||
|
return nomino.NewConfig(
|
||||||
|
nomino.WithSeparator("-"),
|
||||||
|
nomino.WithPrefix("upload"),
|
||||||
|
nomino.WithGenerator(nomino.UUID(
|
||||||
|
nomino.UUIDv7,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleImgUploads generates new filenames for images with a png extension.
|
||||||
|
func HandleImgUploads(orig string) string {
|
||||||
|
// Here, we use nomino.Make function to generate the filename.
|
||||||
|
// We use our global config, and add in a few extra Options specific to this.
|
||||||
|
newName, _ := nomino.Make(
|
||||||
|
NominoConfig(),
|
||||||
|
nomino.WithExtension("png"),
|
||||||
|
nomino.WithOriginalSlug(orig),
|
||||||
|
)
|
||||||
|
|
||||||
|
return newName
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleVidUploads generates a new filename for videos.
|
||||||
|
// We ignore the original filename and use a timestamp for the generated part
|
||||||
|
// with a webm extension.
|
||||||
|
func HandleVidUploads() string {
|
||||||
|
// Because we're using a different Generator, we chose to use the Make method on the Generator.
|
||||||
|
// We add in additional Options with the `AddOptions` method on the `Config`
|
||||||
|
newName, _ := nomino.Timestamp(nomino.TimestampUTC()).
|
||||||
|
MakeWithConfig(NominoConfig().AddOptions(
|
||||||
|
nomino.WithExtension("webm"),
|
||||||
|
))
|
||||||
|
return newName
|
||||||
|
}
|
||||||
|
|
||||||
|
// This example shows how to use nomino.
|
||||||
|
func Example() {
|
||||||
|
// Pretend we have an image upload
|
||||||
|
filename := "George"
|
||||||
|
uploadImgName := HandleImgUploads(filename)
|
||||||
|
|
||||||
|
// Upload to storage
|
||||||
|
fmt.Println(uploadImgName)
|
||||||
|
|
||||||
|
// New Video Upload
|
||||||
|
uploadVidName := HandleVidUploads()
|
||||||
|
|
||||||
|
// Upload to storage
|
||||||
|
fmt.Println(uploadVidName)
|
||||||
|
}
|
||||||
75
gen_file.go
Normal file
75
gen_file.go
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
package nomino
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"hash"
|
||||||
|
|
||||||
|
"github.com/gosimple/slug"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ErrMissingOriginal is the error returned by [Slug] if there is no filename.
|
||||||
|
var ErrMissingOriginal = errors.New("missing original filename")
|
||||||
|
|
||||||
|
func getOriginal(c *Config) (string, error) {
|
||||||
|
if c.original == "" {
|
||||||
|
return "", ErrMissingOriginal
|
||||||
|
}
|
||||||
|
name := c.original
|
||||||
|
c.original = ""
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Slug generates a name from the original filename.
|
||||||
|
// When this is used, the original filename will be removed from the final filename.
|
||||||
|
// If a language is specified, that may affect the resulting slug.
|
||||||
|
func Slug(lang ...string) Generator {
|
||||||
|
ret := slug.Make
|
||||||
|
if len(lang) > 0 {
|
||||||
|
ret = func(in string) string {
|
||||||
|
return slug.MakeLang(in, lang[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func(c *Config) (string, error) {
|
||||||
|
name, err := getOriginal(c)
|
||||||
|
return ret(name), err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HashingFunc is a function that generates a [hash.Hash].
|
||||||
|
type HashingFunc func() hash.Hash
|
||||||
|
|
||||||
|
// New allows [HashingFunc] to be used as a [Hasher].
|
||||||
|
func (hf HashingFunc) New() hash.Hash {
|
||||||
|
return hf()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hasher is a type returns a [hash.Hash].
|
||||||
|
// All [crypto.Hash] may be used.
|
||||||
|
type Hasher interface {
|
||||||
|
New() hash.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// ErrInvalidHash is returned by the [Hash] [Generator] when an invalid [Hasher] is passed.
|
||||||
|
var ErrInvalidHash = errors.New("invalid hash type")
|
||||||
|
|
||||||
|
// Hash generates a name from a hash of the filename.
|
||||||
|
// When this is used, the original filename will be removed from the final filename.
|
||||||
|
func Hash(h Hasher) Generator {
|
||||||
|
if h == nil {
|
||||||
|
h = crypto.MD5
|
||||||
|
}
|
||||||
|
return func(c *Config) (string, error) {
|
||||||
|
if h == crypto.MD5SHA1 {
|
||||||
|
return "", ErrInvalidHash
|
||||||
|
}
|
||||||
|
name, err := getOriginal(c)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
hs := h.New()
|
||||||
|
hs.Write([]byte(name))
|
||||||
|
return hex.EncodeToString(hs.Sum(nil)), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
56
gen_file_examples_test.go
Normal file
56
gen_file_examples_test.go
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
package nomino_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"crypto/hmac"
|
||||||
|
"fmt"
|
||||||
|
"hash"
|
||||||
|
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleSlug() {
|
||||||
|
str, _ := nomino.Slug().Make(nomino.WithOriginal("My name is Jimmy"))
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
// Output: my-name-is-jimmy.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleSlug_withLang() {
|
||||||
|
str, _ := nomino.Slug("de").
|
||||||
|
Make(nomino.WithOriginal("Diese & Dass"))
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
// Output: diese-und-dass.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleHash_mD5() {
|
||||||
|
str, _ := nomino.Hash(crypto.MD5).
|
||||||
|
Make(nomino.WithOriginal("foobar"))
|
||||||
|
fmt.Println(str)
|
||||||
|
// Output: 3858f62230ac3c915f300c664312c63f.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleHash_sHA1() {
|
||||||
|
str, _ := nomino.Hash(crypto.SHA1).
|
||||||
|
Make(nomino.WithOriginal("foobar"))
|
||||||
|
fmt.Println(str)
|
||||||
|
// Output: 8843d7f92416211de9ebb963ff4ce28125932878.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleHash_sHA256() {
|
||||||
|
str, _ := nomino.Hash(crypto.SHA256).
|
||||||
|
Make(nomino.WithOriginal("foobar"))
|
||||||
|
fmt.Println(str)
|
||||||
|
// Output: c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleHashingFunc_hMAC() {
|
||||||
|
var hasher nomino.HashingFunc = func() hash.Hash {
|
||||||
|
return hmac.New(crypto.SHA1.New, []byte("hello"))
|
||||||
|
}
|
||||||
|
g := nomino.Hash(hasher)
|
||||||
|
str, _ := g.Make(nomino.WithOriginal("foobar"))
|
||||||
|
fmt.Println(str)
|
||||||
|
// Output: 85f767c284c80a3a59a9635194321d20dd90f31b.txt
|
||||||
|
}
|
||||||
37
gen_file_test.go
Normal file
37
gen_file_test.go
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
package nomino
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSlugMissingFilename(t *testing.T) {
|
||||||
|
conf := NewConfig(WithGenerator(Slug()))
|
||||||
|
st, err := conf.generator(&conf)
|
||||||
|
assert.Zero(t, st)
|
||||||
|
assert.ErrorIs(t, err, ErrMissingOriginal)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSlugRemovesOriginal(t *testing.T) {
|
||||||
|
conf := NewConfig(WithGenerator(Slug()), WithOriginal("Hello, World"))
|
||||||
|
st, err := conf.generator(&conf)
|
||||||
|
assert.Zero(t, conf.original)
|
||||||
|
assert.Equal(t, "hello-world", st)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHashBadHash(t *testing.T) {
|
||||||
|
conf := NewConfig(WithOriginal("foobar"), WithGenerator(Hash(crypto.MD5SHA1)))
|
||||||
|
st, err := conf.generator(&conf)
|
||||||
|
assert.Equal(t, "", st)
|
||||||
|
assert.ErrorIs(t, err, ErrInvalidHash)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHashMissingOriginal(t *testing.T) {
|
||||||
|
conf := NewConfig(WithGenerator(Hash(nil)))
|
||||||
|
st, err := conf.generator(&conf)
|
||||||
|
assert.Equal(t, "", st)
|
||||||
|
assert.ErrorIs(t, err, ErrMissingOriginal)
|
||||||
|
}
|
||||||
55
gen_int.go
Normal file
55
gen_int.go
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
package nomino
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type incConf struct {
|
||||||
|
start int
|
||||||
|
step int
|
||||||
|
cb func(int) string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementalOption sets an option for the [Incremental] [Generator].
|
||||||
|
type IncrementalOption func(c *incConf)
|
||||||
|
|
||||||
|
// Incremental generates a name that is a series of integers.
|
||||||
|
// By default it begins at 0 and increments by 1 each time.
|
||||||
|
func Incremental(opts ...IncrementalOption) Generator {
|
||||||
|
c := incConf{step: 1, cb: strconv.Itoa}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&c)
|
||||||
|
}
|
||||||
|
|
||||||
|
next := c.start
|
||||||
|
return func(*Config) (string, error) {
|
||||||
|
out := c.cb(next)
|
||||||
|
next += c.step
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementalStart sets the starting integer for [Incremental].
|
||||||
|
func IncrementalStart(start int) IncrementalOption {
|
||||||
|
return func(c *incConf) {
|
||||||
|
c.start = start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementalStepsets the step by which [Incremental] increases with each invocation.
|
||||||
|
func IncrementalStep(step int) IncrementalOption {
|
||||||
|
return func(c *incConf) {
|
||||||
|
c.step = step
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementalFormatsets the format for the number generated by [Incremental].
|
||||||
|
// It will be formatted with Printf. This is mostly likely useful with a format like "%02d".
|
||||||
|
func IncrementalFormat(format string) IncrementalOption {
|
||||||
|
return func(c *incConf) {
|
||||||
|
c.cb = func(i int) string {
|
||||||
|
return fmt.Sprintf(format, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
121
gen_int_examples_test.go
Normal file
121
gen_int_examples_test.go
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
package nomino_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleIncremental() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithPrefix("foo"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
|
)
|
||||||
|
|
||||||
|
str, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// foo_0.txt
|
||||||
|
// foo_1.txt
|
||||||
|
// foo_2.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIncrementalStart() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithPrefix("foo"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental(
|
||||||
|
nomino.IncrementalStart(42),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
str, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// foo_42.txt
|
||||||
|
// foo_43.txt
|
||||||
|
// foo_44.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIncrementalStep() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithPrefix("foo"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental(
|
||||||
|
nomino.IncrementalStep(2),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
str, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// foo_0.txt
|
||||||
|
// foo_2.txt
|
||||||
|
// foo_4.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIncremental_withStartAndStep() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithPrefix("foo"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental(
|
||||||
|
nomino.IncrementalStart(42),
|
||||||
|
nomino.IncrementalStep(2),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
str, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// foo_42.txt
|
||||||
|
// foo_44.txt
|
||||||
|
// foo_46.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIncrementalFormat() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithPrefix("foo"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental(
|
||||||
|
nomino.IncrementalFormat("%03d"),
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
|
||||||
|
str, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// foo_000.txt
|
||||||
|
// foo_001.txt
|
||||||
|
// foo_002.txt
|
||||||
|
}
|
||||||
91
gen_rand.go
Normal file
91
gen_rand.go
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
package nomino
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/deatil/go-encoding/base62"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UUIDer is an interface for generating UUIDs, by the [UUID] [Generator].
|
||||||
|
// It is recommended that you use either the [UUIDv4] or [UUIDv7] variables.
|
||||||
|
type UUIDer interface {
|
||||||
|
UUID() (uuid.UUID, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UUIDFunc is a function that generates a UUID.
|
||||||
|
type UUIDFunc func() (uuid.UUID, error)
|
||||||
|
|
||||||
|
// UUID allows [UUIDFunc] to be used as a [UUIDer].
|
||||||
|
func (u UUIDFunc) UUID() (uuid.UUID, error) {
|
||||||
|
return u()
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// UUIDv1. You probably don't want to use this. It is included for completeness sake.
|
||||||
|
UUIDv1 = UUIDFunc(uuid.NewUUID)
|
||||||
|
// UUIDv4 is the default.
|
||||||
|
UUIDv4 = UUIDFunc(uuid.NewRandom)
|
||||||
|
// UUIDv6 is primarily a replacement for UUIDv1. You probably should use 4 or 7.
|
||||||
|
UUIDv6 = UUIDFunc(uuid.NewV6)
|
||||||
|
// UUIDv7 should be used if you want it sortable by time.
|
||||||
|
UUIDv7 = UUIDFunc(uuid.NewV7)
|
||||||
|
)
|
||||||
|
|
||||||
|
// UUID generates a UUID. If nil is passed as an argument,
|
||||||
|
// a UUIDv4 is generated.
|
||||||
|
func UUID(u UUIDer) Generator {
|
||||||
|
if u == nil {
|
||||||
|
u = UUIDv4
|
||||||
|
}
|
||||||
|
return func(*Config) (string, error) {
|
||||||
|
uu, err := u.UUID()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return uu.String(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type randConf struct {
|
||||||
|
length int
|
||||||
|
}
|
||||||
|
|
||||||
|
// RandomOption is an option for the [Random] [Generator].
|
||||||
|
type RandomOption func(*randConf)
|
||||||
|
|
||||||
|
// RandomLength controls the length of the string generated by [Random].
|
||||||
|
func RandomLength(length int) RandomOption {
|
||||||
|
return func(c *randConf) {
|
||||||
|
c.length = length
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRandomBytes(l int) []byte {
|
||||||
|
key := make([]byte, l)
|
||||||
|
_, _ = rand.Read(key)
|
||||||
|
e := base62.StdEncoding.Encode(key)
|
||||||
|
return e[:l]
|
||||||
|
}
|
||||||
|
|
||||||
|
func fillBuffer(buff *strings.Builder, length int) {
|
||||||
|
for buff.Len() < length {
|
||||||
|
buff.Write(getRandomBytes(length - buff.Len()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Random generates a random string containing the characters A-Za-z0-9.
|
||||||
|
// By default, it will be eight characters long.
|
||||||
|
func Random(opts ...RandomOption) Generator {
|
||||||
|
c := randConf{8}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&c)
|
||||||
|
}
|
||||||
|
return func(*Config) (string, error) {
|
||||||
|
var buff strings.Builder
|
||||||
|
buff.Grow(c.length)
|
||||||
|
fillBuffer(&buff, c.length)
|
||||||
|
return buff.String(), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
40
gen_rand_examples_test.go
Normal file
40
gen_rand_examples_test.go
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
package nomino_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleUUID() {
|
||||||
|
gen := nomino.UUID(nil)
|
||||||
|
|
||||||
|
str, _ := gen.Make()
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = gen.Make()
|
||||||
|
fmt.Println(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleUUID_v7() {
|
||||||
|
gen := nomino.UUID(nomino.UUIDv7)
|
||||||
|
|
||||||
|
str, _ := gen.Make()
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = gen.Make()
|
||||||
|
fmt.Println(str)
|
||||||
|
|
||||||
|
str, _ = gen.Make()
|
||||||
|
fmt.Println(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRandom() {
|
||||||
|
str, _ := nomino.Random().Make()
|
||||||
|
fmt.Println(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleRandomLength() {
|
||||||
|
str, _ := nomino.Random(nomino.RandomLength(32)).Make()
|
||||||
|
fmt.Println(str)
|
||||||
|
}
|
||||||
41
gen_rand_test.go
Normal file
41
gen_rand_test.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package nomino
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUUID(t *testing.T) {
|
||||||
|
st, err := UUID(nil)(nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, parseErr := uuid.Parse(st)
|
||||||
|
assert.NoError(t, parseErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
type badRead struct{}
|
||||||
|
|
||||||
|
func (badRead) Read([]byte) (int, error) {
|
||||||
|
return 0, errTest
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUUIDFail(t *testing.T) {
|
||||||
|
uuid.SetRand(badRead{})
|
||||||
|
defer uuid.SetRand(nil)
|
||||||
|
|
||||||
|
_, err := UUID(nil)(nil)
|
||||||
|
assert.ErrorIs(t, err, errTest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRand(t *testing.T) {
|
||||||
|
st, err := Random()(nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, st, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRandLen(t *testing.T) {
|
||||||
|
st, err := Random(RandomLength(32))(nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, st, 32)
|
||||||
|
}
|
||||||
59
gen_ts.go
Normal file
59
gen_ts.go
Normal file
|
|
@ -0,0 +1,59 @@
|
||||||
|
package nomino
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// FileTimestamp is the default format for [Timestamp].
|
||||||
|
const FileTimestamp string = "2006-01-02T15-04-05-0700"
|
||||||
|
|
||||||
|
// FileTimestampNoTZ is the default format when using the [TimestampUTC] [TimestampOption].
|
||||||
|
const FileTimestampNoTZ string = "2006-01-02T15-04-05"
|
||||||
|
|
||||||
|
type timestampConf struct {
|
||||||
|
format string
|
||||||
|
ts time.Time
|
||||||
|
utc bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampOption provides options for the [Timestamp] [Generator].
|
||||||
|
type TimestampOption func(c *timestampConf)
|
||||||
|
|
||||||
|
// Timestamp generates a a date and time. By default, it uses the current time, and will.
|
||||||
|
// be formatted accourding to FileTimestamp.
|
||||||
|
func Timestamp(opts ...TimestampOption) Generator {
|
||||||
|
c := timestampConf{format: FileTimestamp, ts: time.Now()}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&c)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.utc {
|
||||||
|
c.ts = c.ts.UTC()
|
||||||
|
}
|
||||||
|
|
||||||
|
return func(*Config) (string, error) {
|
||||||
|
return c.ts.Format(c.format), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampFormat sets the format for the generated name.
|
||||||
|
// Consult [time.Time.Format] for details on the format.
|
||||||
|
func TimestampFormat(format string) TimestampOption {
|
||||||
|
return func(c *timestampConf) {
|
||||||
|
c.format = format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampTime sets the time for the generated name.
|
||||||
|
// By default, [Timestamp] uses the current time.
|
||||||
|
func TimestampTime(t time.Time) TimestampOption {
|
||||||
|
return func(c *timestampConf) {
|
||||||
|
c.ts = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimestampUTC uses the time in UTC, while also stripping the timezone from the format.
|
||||||
|
func TimestampUTC() TimestampOption {
|
||||||
|
return func(c *timestampConf) {
|
||||||
|
c.utc = true
|
||||||
|
c.format = FileTimestampNoTZ
|
||||||
|
}
|
||||||
|
}
|
||||||
41
gen_ts_examples_test.go
Normal file
41
gen_ts_examples_test.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
package nomino_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleTimestamp() {
|
||||||
|
gen := nomino.Timestamp()
|
||||||
|
s, _ := gen.Make()
|
||||||
|
fmt.Println(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleTimestampTime() {
|
||||||
|
tz, _ := time.LoadLocation("America/New_York")
|
||||||
|
ts := time.Date(2009, time.January, 20, 12, 5, 0, 0, tz)
|
||||||
|
gen := nomino.Timestamp(nomino.TimestampTime(ts))
|
||||||
|
s, _ := gen.Make()
|
||||||
|
fmt.Println(s)
|
||||||
|
// Output: 2009-01-20T12-05-00-0500.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleTimestampFormat() {
|
||||||
|
tz, _ := time.LoadLocation("America/New_York")
|
||||||
|
ts := time.Date(2009, time.January, 20, 12, 5, 0, 0, tz)
|
||||||
|
gen := nomino.Timestamp(nomino.TimestampTime(ts), nomino.TimestampFormat("2006#01#02<>15|04|05-0700"))
|
||||||
|
s, _ := gen.Make()
|
||||||
|
fmt.Println(s)
|
||||||
|
// Output: 2009#01#20<>12|05|00-0500.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleTimestampUTC() {
|
||||||
|
tz, _ := time.LoadLocation("America/New_York")
|
||||||
|
ts := time.Date(2009, time.January, 20, 12, 5, 0, 0, tz)
|
||||||
|
gen := nomino.Timestamp(nomino.TimestampTime(ts), nomino.TimestampUTC())
|
||||||
|
s, _ := gen.Make()
|
||||||
|
fmt.Println(s)
|
||||||
|
// Output: 2009-01-20T17-05-00.txt
|
||||||
|
}
|
||||||
15
gen_ts_test.go
Normal file
15
gen_ts_test.go
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
package nomino
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestTimestamp(t *testing.T) {
|
||||||
|
n := time.Now()
|
||||||
|
st, err := Timestamp()(nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, n.Format(FileTimestamp), st)
|
||||||
|
}
|
||||||
164
generators.go
164
generators.go
|
|
@ -2,12 +2,7 @@ package nomino
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"math/rand"
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/gosimple/slug"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Generator is a function that returns the "random" portion of the returned filename.
|
// Generator is a function that returns the "random" portion of the returned filename.
|
||||||
|
|
@ -15,14 +10,25 @@ import (
|
||||||
// for example.
|
// for example.
|
||||||
type Generator func(conf *Config) (string, error)
|
type Generator func(conf *Config) (string, error)
|
||||||
|
|
||||||
// WithGenerator sets the specified generator
|
// Make allows you to generate a new string directly from a [Generator].
|
||||||
|
func (g Generator) Make(opts ...Option) (string, error) {
|
||||||
|
return g.MakeWithConfig(NewConfig(opts...))
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeWithConfig allows you to generate a new string directly from a [Generator]
|
||||||
|
// with a pre-existing Config.
|
||||||
|
func (g Generator) MakeWithConfig(c Config) (string, error) {
|
||||||
|
return Make(c.AddOptions(WithGenerator(g)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithGenerator sets the specified [Generator].
|
||||||
func WithGenerator(g Generator) Option {
|
func WithGenerator(g Generator) Option {
|
||||||
return func(c *Config) {
|
return func(c *Config) {
|
||||||
c.generator = g
|
c.generator = g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrMissingGenerators is returned by a multi-generator if no generators are supplied.
|
// ErrMissingGenerators is returned by a multi-generator if a [Generator] isn't supplied.
|
||||||
var ErrMissingGenerators = errors.New("no generators supplied")
|
var ErrMissingGenerators = errors.New("no generators supplied")
|
||||||
|
|
||||||
func missingGen(*Config) (string, error) {
|
func missingGen(*Config) (string, error) {
|
||||||
|
|
@ -30,7 +36,7 @@ func missingGen(*Config) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultiGeneratorInOrder allows the use of multiple generators. Each new invokation will use the next generator in turn.
|
// MultiGeneratorInOrder allows the use of multiple generators. Each new invokation will use the next generator in turn.
|
||||||
// If none are passed, the generator will always return ErrMissingGenerators.
|
// If none are passed, the generator will always return [ErrMissingGenerators].
|
||||||
func MultiGeneratorInOrder(gens ...Generator) Generator {
|
func MultiGeneratorInOrder(gens ...Generator) Generator {
|
||||||
if len(gens) == 0 {
|
if len(gens) == 0 {
|
||||||
return missingGen
|
return missingGen
|
||||||
|
|
@ -48,140 +54,20 @@ func MultiGeneratorInOrder(gens ...Generator) Generator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func uuidGen(*Config) (string, error) {
|
// MultiGeneratorRandomOrder allows the use of multiple generators. Each new invokation will use one of the generators randomly.
|
||||||
u, err := uuid.NewRandom()
|
// If none are passed, the generator will always return [ErrMissingGenerators].
|
||||||
if err != nil {
|
func MultiGeneratorRandomOrder(gens ...Generator) Generator {
|
||||||
return "", err
|
if len(gens) == 0 {
|
||||||
|
return missingGen
|
||||||
}
|
}
|
||||||
return u.String(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UUID generates a UUIDv4.
|
if len(gens) == 1 {
|
||||||
func UUID() Generator {
|
return gens[0]
|
||||||
return uuidGen
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileTimestamp is the default format for WithTimestamp and WithTime
|
|
||||||
const FileTimestamp string = "2006-01-02_03-05-06-0700"
|
|
||||||
|
|
||||||
// Timestamp generates a a date and time for the current time.
|
|
||||||
// It is formatted accourding to FileTimestamp
|
|
||||||
func Timestamp() Generator {
|
|
||||||
return TimestampWithFormat(FileTimestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimestampWithFormat generates a date and time for the current time with the supplied format.
|
|
||||||
func TimestampWithFormat(f string) Generator {
|
|
||||||
return FormattedTime(time.Now(), FileTimestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Time generates a date and time for the supplied time.
|
|
||||||
// It is formatted accourding to FileTimestamp
|
|
||||||
func Time(t time.Time) Generator {
|
|
||||||
return FormattedTime(t, FileTimestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormattedTime generates a date and time for the supplied time with the supplied format.
|
|
||||||
func FormattedTime(t time.Time, f string) Generator {
|
|
||||||
return func(*Config) (string, error) {
|
|
||||||
return t.Format(f), nil
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// FileTimestampNoTZ is the default format for WithTimestampUTC and WithTimeUTC
|
|
||||||
const FileTimestampNoTZ string = "2006-01-02_03-05-06"
|
|
||||||
|
|
||||||
// TimestampUTC generates a date and time for the current time in UTC without a timezone in the format.
|
|
||||||
func TimestampUTC() Generator {
|
|
||||||
return TimeUTC(time.Now())
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimeUTC generates a date and time for the supplied time in UTC without a timezone in the format.
|
|
||||||
func TimeUTC(t time.Time) Generator {
|
|
||||||
return FormattedTime(t.UTC(), FileTimestampNoTZ)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Incremental generates a name that is a series of integers starting at 0
|
|
||||||
func Incremental() Generator {
|
|
||||||
return IncrementalWithStartAndStep(0, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementalFormat generates a name that is a series of integers starting at 0, formatted with Printf
|
|
||||||
// This is mostly likely useful with a format like "%02d"
|
|
||||||
func IncrementalFormat(format string) Generator {
|
|
||||||
return IncrementalFormatWithStartAndStep(0, 1, format)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementalWithStart generates a name that is a series of integers starting at the specified number
|
|
||||||
func IncrementalWithStart(start int) Generator {
|
|
||||||
return IncrementalWithStartAndStep(start, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementalFormatWithStart generates a name that is a series of integers starting at the specified number, formatted with Printf
|
|
||||||
func IncrementalFormatWithStart(start int, format string) Generator {
|
|
||||||
return IncrementalFormatWithStartAndStep(start, 1, format)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementalWithStep generates a name that is a series of integers, starting at 0, and increasing the specified number each time
|
|
||||||
func IncrementalWithStep(step int) Generator {
|
|
||||||
return IncrementalWithStartAndStep(0, step)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementalFormatWithStep generates a name that is a series of integers, starting at 0, and increasing the specified number each time,
|
|
||||||
// formatted with Printf
|
|
||||||
func IncrementalFormatWithStep(step int, format string) Generator {
|
|
||||||
return IncrementalFormatWithStartAndStep(0, step, format)
|
|
||||||
}
|
|
||||||
|
|
||||||
func incrementalHelper(start, step int, cb func(int) string) Generator {
|
|
||||||
next := start
|
|
||||||
return func(*Config) (string, error) {
|
|
||||||
out := cb(next)
|
|
||||||
next += step
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// InrementalWithStartAndStep generates a name that is a series of integers, starting at the specified number,
|
|
||||||
// and increasing the specified step each time
|
|
||||||
func IncrementalWithStartAndStep(start, step int) Generator {
|
|
||||||
return incrementalHelper(start, step, strconv.Itoa)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IncrementalFormatWithStartAndStep generates a name that is a series of integers, starting at the specified number,
|
|
||||||
// and increasing the specified step each time, formatted with Printf
|
|
||||||
func IncrementalFormatWithStartAndStep(start, step int, format string) Generator {
|
|
||||||
return incrementalHelper(start, step, func(i int) string {
|
|
||||||
return fmt.Sprintf(format, i)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// ErrMissingOriginal is the error returned by Slug if there is no filename
|
|
||||||
var ErrMissingOriginal = errors.New("missing original filename")
|
|
||||||
|
|
||||||
func getOriginal(c *Config) (string, error) {
|
|
||||||
if c.original == "" {
|
|
||||||
return "", ErrMissingOriginal
|
|
||||||
}
|
|
||||||
name := c.original
|
|
||||||
c.original = ""
|
|
||||||
return name, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Slug generates a name from the original filename.
|
|
||||||
// When this is used, the original filename will be removed from the final filename.
|
|
||||||
func Slug() Generator {
|
|
||||||
return func(c *Config) (string, error) {
|
return func(c *Config) (string, error) {
|
||||||
name, err := getOriginal(c)
|
//nolint:gosec // This is not security sensitive, so a weak number generator is fine.
|
||||||
return slug.Make(name), err
|
idx := rand.Int() % len(gens)
|
||||||
}
|
return gens[idx](c)
|
||||||
}
|
|
||||||
|
|
||||||
// SlugWithLang generates a name from the original filename, accounting for the given language.
|
|
||||||
// When this is used, the original filename will be removed from the final filename.
|
|
||||||
func SlugWithLang(lang string) Generator {
|
|
||||||
return func(c *Config) (string, error) {
|
|
||||||
name, err := getOriginal(c)
|
|
||||||
return slug.MakeLang(name, lang), err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,20 @@
|
||||||
package nomino
|
package nomino_test
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
func ExampleWithGenerator_custom_generator() {
|
"codeberg.org/danjones000/nomino"
|
||||||
gen := func(*Config) (string, error) {
|
)
|
||||||
|
|
||||||
|
func ExampleWithGenerator_customGenerator() {
|
||||||
|
var gen nomino.Generator = func(*nomino.Config) (string, error) {
|
||||||
return "hello", nil
|
return "hello", nil
|
||||||
}
|
}
|
||||||
option := WithGenerator(gen)
|
|
||||||
|
|
||||||
str, _ := Make(NewConfig(option))
|
str, _ := gen.Make()
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
str, _ = Make(NewConfig(option, WithoutExtension()))
|
str, _ = gen.Make(nomino.WithoutExtension())
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
|
|
@ -19,145 +22,58 @@ func ExampleWithGenerator_custom_generator() {
|
||||||
// hello
|
// hello
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleIncremental() {
|
func ExampleGenerator_Make() {
|
||||||
conf := NewConfig(WithPrefix("foo"), WithGenerator(Incremental()))
|
g := nomino.Incremental()
|
||||||
|
st, _ := g.Make()
|
||||||
|
fmt.Println(st)
|
||||||
|
|
||||||
str, _ := Make(conf)
|
st, _ = g.Make(nomino.WithPrefix("foo"))
|
||||||
fmt.Println(str)
|
fmt.Println(st)
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// foo_0.txt
|
// 0.txt
|
||||||
// foo_1.txt
|
// foo_1.txt
|
||||||
// foo_2.txt
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleIncrementalWithStart() {
|
func ExampleMultiGeneratorInOrder() {
|
||||||
conf := NewConfig(WithPrefix("foo"), WithGenerator(IncrementalWithStart(42)))
|
gen1 := func(*nomino.Config) (string, error) {
|
||||||
|
return "bonjour", nil
|
||||||
|
}
|
||||||
|
gen2 := func(*nomino.Config) (string, error) {
|
||||||
|
return "goodbye", nil
|
||||||
|
}
|
||||||
|
gen := nomino.MultiGeneratorInOrder(gen1, gen2)
|
||||||
|
|
||||||
str, _ := Make(conf)
|
str, _ := gen.Make()
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
str, _ = Make(conf)
|
str, _ = gen.Make()
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
str, _ = Make(conf)
|
str, _ = gen.Make()
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
// Output:
|
// Output:
|
||||||
// foo_42.txt
|
// bonjour.txt
|
||||||
// foo_43.txt
|
// goodbye.txt
|
||||||
// foo_44.txt
|
// bonjour.txt
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleIncrementalWithStep() {
|
func ExampleMultiGeneratorRandomOrder() {
|
||||||
conf := NewConfig(WithPrefix("foo"), WithGenerator(IncrementalWithStep(2)))
|
gen1 := func(*nomino.Config) (string, error) {
|
||||||
|
return "guten-tag", nil
|
||||||
|
}
|
||||||
|
gen2 := func(*nomino.Config) (string, error) {
|
||||||
|
return "wiedersehen", nil
|
||||||
|
}
|
||||||
|
gen := nomino.MultiGeneratorRandomOrder(gen1, gen2)
|
||||||
|
|
||||||
str, _ := Make(conf)
|
str, _ := gen.Make()
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
str, _ = Make(conf)
|
str, _ = gen.Make()
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
str, _ = Make(conf)
|
str, _ = gen.Make()
|
||||||
fmt.Println(str)
|
fmt.Println(str)
|
||||||
|
|
||||||
// Output:
|
|
||||||
// foo_0.txt
|
|
||||||
// foo_2.txt
|
|
||||||
// foo_4.txt
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleIncrementalWithStartAndStep() {
|
|
||||||
conf := NewConfig(WithPrefix("foo"), WithGenerator(IncrementalWithStartAndStep(42, 2)))
|
|
||||||
|
|
||||||
str, _ := Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// foo_42.txt
|
|
||||||
// foo_44.txt
|
|
||||||
// foo_46.txt
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleIncrementalFormat() {
|
|
||||||
conf := NewConfig(
|
|
||||||
WithPrefix("foo"),
|
|
||||||
WithGenerator(IncrementalFormat("%03d")),
|
|
||||||
)
|
|
||||||
|
|
||||||
str, _ := Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// foo_000.txt
|
|
||||||
// foo_001.txt
|
|
||||||
// foo_002.txt
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleIncrementalFormatWithStart() {
|
|
||||||
conf := NewConfig(
|
|
||||||
WithPrefix("foo"),
|
|
||||||
WithGenerator(IncrementalFormatWithStart(9, "%02d")),
|
|
||||||
)
|
|
||||||
|
|
||||||
str, _ := Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// foo_09.txt
|
|
||||||
// foo_10.txt
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleIncrementalFormatWithStep() {
|
|
||||||
conf := NewConfig(
|
|
||||||
WithPrefix("foo"),
|
|
||||||
WithGenerator(IncrementalFormatWithStep(10, "%02d")),
|
|
||||||
)
|
|
||||||
|
|
||||||
str, _ := Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
str, _ = Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
// Output:
|
|
||||||
// foo_00.txt
|
|
||||||
// foo_10.txt
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleSlug() {
|
|
||||||
conf := NewConfig(WithGenerator(Slug()), WithOriginal("My name is Jimmy"))
|
|
||||||
str, _ := Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
// Output: my-name-is-jimmy.txt
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExampleSlugWithLang() {
|
|
||||||
conf := NewConfig(WithGenerator(SlugWithLang("de")), WithOriginal("Diese & Dass"))
|
|
||||||
str, _ := Make(conf)
|
|
||||||
fmt.Println(str)
|
|
||||||
|
|
||||||
// Output: diese-und-dass.txt
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,54 +3,59 @@ package nomino
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
out1 string = "abc"
|
||||||
|
out2 string = "def"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
outs = []string{out1, out2}
|
||||||
|
err1 = errors.New("oops")
|
||||||
|
gen1 Generator = func(*Config) (string, error) { return out1, nil }
|
||||||
|
gen2 Generator = func(*Config) (string, error) { return out2, nil }
|
||||||
|
gen3 Generator = func(*Config) (string, error) { return "", err1 }
|
||||||
|
gens = []Generator{gen1, gen2, gen3}
|
||||||
|
)
|
||||||
|
|
||||||
func TestWithGenerator(t *testing.T) {
|
func TestWithGenerator(t *testing.T) {
|
||||||
g := func(*Config) (string, error) { return "abc", nil }
|
g := func(*Config) (string, error) { return out1, nil }
|
||||||
var c Config
|
var c Config
|
||||||
WithGenerator(g)(&c)
|
WithGenerator(g)(&c)
|
||||||
st, err := c.generator(&c)
|
st, err := c.generator(&c)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "abc", st)
|
assert.Equal(t, out1, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiGeneratorInOrder(t *testing.T) {
|
func TestMultiGeneratorInOrder(t *testing.T) {
|
||||||
st1 := "abc"
|
g := MultiGeneratorInOrder(gens...)
|
||||||
st2 := "def"
|
|
||||||
er1 := errors.New("oops")
|
|
||||||
g1 := func(*Config) (string, error) { return st1, nil }
|
|
||||||
g2 := func(*Config) (string, error) { return st2, nil }
|
|
||||||
g3 := func(*Config) (string, error) { return "", er1 }
|
|
||||||
g := MultiGeneratorInOrder(g1, g2, g3)
|
|
||||||
st, err := g(nil)
|
st, err := g(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, st1, st)
|
assert.Equal(t, out1, st)
|
||||||
st, err = g(nil)
|
st, err = g(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, st2, st)
|
assert.Equal(t, out2, st)
|
||||||
st, err = g(nil)
|
st, err = g(nil)
|
||||||
assert.Zero(t, st)
|
assert.Zero(t, st)
|
||||||
assert.ErrorIs(t, err, er1)
|
assert.ErrorIs(t, err, err1)
|
||||||
st, err = g(nil)
|
st, err = g(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, st1, st)
|
assert.Equal(t, out1, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiGeneratorInOrderOne(t *testing.T) {
|
func TestMultiGeneratorInOrderOne(t *testing.T) {
|
||||||
st1 := "abc"
|
g1 := func(*Config) (string, error) { return out1, nil }
|
||||||
g1 := func(*Config) (string, error) { return st1, nil }
|
|
||||||
g := MultiGeneratorInOrder(g1)
|
g := MultiGeneratorInOrder(g1)
|
||||||
|
|
||||||
st, err := g(nil)
|
st, err := g(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, st1, st)
|
assert.Equal(t, out1, st)
|
||||||
st, err = g(nil)
|
st, err = g(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, st1, st)
|
assert.Equal(t, out1, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMultiGeneratorInOrderMissing(t *testing.T) {
|
func TestMultiGeneratorInOrderMissing(t *testing.T) {
|
||||||
|
|
@ -63,60 +68,38 @@ func TestMultiGeneratorInOrderMissing(t *testing.T) {
|
||||||
assert.ErrorIs(t, err, ErrMissingGenerators)
|
assert.ErrorIs(t, err, ErrMissingGenerators)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUUID(t *testing.T) {
|
func TestMultiGeneratorRandomOrder(t *testing.T) {
|
||||||
st, err := UUID()(nil)
|
g := MultiGeneratorRandomOrder(gens...)
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
st, err := g(nil)
|
||||||
|
if err != nil {
|
||||||
|
assert.Zero(t, st)
|
||||||
|
assert.ErrorIs(t, err, err1)
|
||||||
|
} else {
|
||||||
|
assert.Contains(t, outs, st)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMultiGeneratorRandomOrderOne(t *testing.T) {
|
||||||
|
st1 := "abc"
|
||||||
|
g1 := func(*Config) (string, error) { return st1, nil }
|
||||||
|
g := MultiGeneratorRandomOrder(g1)
|
||||||
|
|
||||||
|
st, err := g(nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
_, parseErr := uuid.Parse(st)
|
assert.Equal(t, st1, st)
|
||||||
assert.NoError(t, parseErr)
|
st, err = g(nil)
|
||||||
}
|
|
||||||
|
|
||||||
type badRead struct{}
|
|
||||||
|
|
||||||
func (badRead) Read([]byte) (int, error) {
|
|
||||||
return 0, errors.New("sorry")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUUIDFail(t *testing.T) {
|
|
||||||
uuid.SetRand(badRead{})
|
|
||||||
defer uuid.SetRand(nil)
|
|
||||||
|
|
||||||
_, err := UUID()(nil)
|
|
||||||
assert.Equal(t, errors.New("sorry"), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestamp(t *testing.T) {
|
|
||||||
n := time.Now()
|
|
||||||
st, err := Timestamp()(nil)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, n.Format(FileTimestamp), st)
|
assert.Equal(t, st1, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTime(t *testing.T) {
|
func TestMultiGeneratorRandomOrderMissing(t *testing.T) {
|
||||||
d := time.Date(1986, time.March, 28, 12, 0, 0, 0, time.UTC)
|
g := MultiGeneratorRandomOrder()
|
||||||
|
st, err := g(nil)
|
||||||
st, err := Time(d)(nil)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, d.Format(FileTimestamp), st)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimestampUTC(t *testing.T) {
|
|
||||||
n := time.Now()
|
|
||||||
st, err := TimestampUTC()(nil)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, n.UTC().Format(FileTimestampNoTZ), st)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSlugMissingFilename(t *testing.T) {
|
|
||||||
conf := NewConfig(WithGenerator(Slug()))
|
|
||||||
st, err := conf.generator(&conf)
|
|
||||||
assert.Zero(t, st)
|
assert.Zero(t, st)
|
||||||
assert.ErrorIs(t, err, ErrMissingOriginal)
|
assert.ErrorIs(t, err, ErrMissingGenerators)
|
||||||
}
|
st, err = g(nil)
|
||||||
|
assert.Zero(t, st)
|
||||||
func TestSlugRemovesOriginal(t *testing.T) {
|
assert.ErrorIs(t, err, ErrMissingGenerators)
|
||||||
conf := NewConfig(WithGenerator(Slug()), WithOriginal("Hello, World"))
|
|
||||||
st, err := conf.generator(&conf)
|
|
||||||
assert.Zero(t, conf.original)
|
|
||||||
assert.Equal(t, "hello-world", st)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
go.mod
1
go.mod
|
|
@ -3,6 +3,7 @@ module codeberg.org/danjones000/nomino
|
||||||
go 1.23.6
|
go 1.23.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/deatil/go-encoding v1.0.3003
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gosimple/slug v1.15.0
|
github.com/gosimple/slug v1.15.0
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -1,5 +1,7 @@
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/deatil/go-encoding v1.0.3003 h1:2b05UO+5JfVcXcOa8n/X3pm8aC6L6ET0mBZCb1kj3ck=
|
||||||
|
github.com/deatil/go-encoding v1.0.3003/go.mod h1:lTMMKsG0RRPGZzdW2EPVJCA7HQy4o1ZQKPf5CmVDy2k=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gosimple/slug v1.15.0 h1:wRZHsRrRcs6b0XnxMUBM6WK1U1Vg5B0R7VkIf1Xzobo=
|
github.com/gosimple/slug v1.15.0 h1:wRZHsRrRcs6b0XnxMUBM6WK1U1Vg5B0R7VkIf1Xzobo=
|
||||||
|
|
|
||||||
20
make.go
20
make.go
|
|
@ -2,25 +2,31 @@ package nomino
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
// Make generates a random filename. The behavior can be controlled by specifying Options
|
// Make generates a random filename. The behavior can be controlled by specifying Options.
|
||||||
// In general, the final filename will be [prefix]_[generated_string]_[original_filename]_[suffix].[extension].
|
// In general, the final filename will be [prefix]_[generated_string]_[original_filename]_[suffix].[extension].
|
||||||
// If the name generator returns an error (generally, it shouldn't), that will be returned instead.
|
// If the name generator returns an error (generally, it shouldn't), that error will be returned instead.
|
||||||
func Make(conf Config) (string, error) {
|
func Make(conf Config, opts ...Option) (string, error) {
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&conf)
|
||||||
|
}
|
||||||
|
|
||||||
name, err := conf.generator(&conf)
|
name, err := conf.generator(&conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
seperateConf(&conf)
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s%s%s%s%s", conf.prefix, name, conf.original, conf.suffix, conf.extension), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func seperateConf(conf *Config) {
|
||||||
if conf.prefix != "" {
|
if conf.prefix != "" {
|
||||||
conf.prefix = conf.prefix + conf.separator
|
conf.prefix += conf.separator
|
||||||
}
|
}
|
||||||
if conf.original != "" {
|
if conf.original != "" {
|
||||||
conf.original = conf.separator + conf.original
|
conf.original = conf.separator + conf.original
|
||||||
}
|
}
|
||||||
if conf.suffix != "" {
|
if conf.suffix != "" {
|
||||||
conf.suffix = conf.separator + conf.suffix
|
conf.suffix = conf.separator + conf.suffix
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s%s%s%s%s", conf.prefix, name, conf.original, conf.suffix, conf.extension), nil
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,30 @@
|
||||||
package nomino
|
package nomino_test
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
func ExampleMake_basic() {
|
func ExampleMake_basic() {
|
||||||
// Use default config
|
// Use default config
|
||||||
out, _ := Make(NewConfig())
|
out, _ := nomino.Make(nomino.NewConfig())
|
||||||
fmt.Println(out)
|
fmt.Println(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ExampleMake_withExtraOptions() {
|
||||||
|
gen := nomino.Incremental()
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithGenerator(gen),
|
||||||
|
nomino.WithPrefix("pre"),
|
||||||
|
)
|
||||||
|
|
||||||
|
st, _ := nomino.Make(conf, nomino.WithOriginal("foobar"))
|
||||||
|
fmt.Println(st)
|
||||||
|
st, _ = nomino.Make(conf, nomino.WithOriginal("baz"))
|
||||||
|
fmt.Println(st)
|
||||||
|
|
||||||
|
// Output:
|
||||||
|
// pre_0_foobar.txt
|
||||||
|
// pre_1_baz.txt
|
||||||
|
}
|
||||||
|
|
|
||||||
26
make_test.go
26
make_test.go
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var errTest = errors.New("sorry")
|
||||||
|
|
||||||
func TestMake(t *testing.T) {
|
func TestMake(t *testing.T) {
|
||||||
genOpt := WithGenerator(func(*Config) (string, error) { return "abc", nil })
|
genOpt := WithGenerator(func(*Config) (string, error) { return "abc", nil })
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
|
|
@ -36,7 +38,9 @@ func TestMake(t *testing.T) {
|
||||||
|
|
||||||
for _, testcase := range testcases {
|
for _, testcase := range testcases {
|
||||||
t.Run(testcase.name, func(sub *testing.T) {
|
t.Run(testcase.name, func(sub *testing.T) {
|
||||||
opts := append(testcase.opts, genOpt)
|
opts := testcase.opts
|
||||||
|
opts = append(opts, genOpt)
|
||||||
|
|
||||||
conf := NewConfig(opts...)
|
conf := NewConfig(opts...)
|
||||||
st, err := Make(conf)
|
st, err := Make(conf)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -46,11 +50,10 @@ func TestMake(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeErr(t *testing.T) {
|
func TestMakeErr(t *testing.T) {
|
||||||
retErr := errors.New("oops")
|
conf := NewConfig(WithGenerator(func(*Config) (string, error) { return "foobar", errTest }))
|
||||||
conf := NewConfig(WithGenerator(func(*Config) (string, error) { return "foobar", retErr }))
|
|
||||||
st, err := Make(conf)
|
st, err := Make(conf)
|
||||||
assert.Zero(t, st)
|
assert.Zero(t, st)
|
||||||
assert.ErrorIs(t, err, retErr)
|
assert.ErrorIs(t, err, errTest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMakeDoesntChangeConf(t *testing.T) {
|
func TestMakeDoesntChangeConf(t *testing.T) {
|
||||||
|
|
@ -64,3 +67,18 @@ func TestMakeDoesntChangeConf(t *testing.T) {
|
||||||
assert.Equal(t, "foo.txt", st)
|
assert.Equal(t, "foo.txt", st)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMakeOptsDoesntChangeConf(t *testing.T) {
|
||||||
|
gen := Incremental()
|
||||||
|
conf := NewConfig(WithGenerator(gen), WithPrefix("pre"))
|
||||||
|
|
||||||
|
st, err := Make(conf, WithOriginal("foobar"))
|
||||||
|
assert.Equal(t, "", conf.original)
|
||||||
|
assert.Equal(t, "pre_0_foobar.txt", st)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
st, err = Make(conf, WithOriginal("baz"))
|
||||||
|
assert.Equal(t, "", conf.original)
|
||||||
|
assert.Equal(t, "pre_1_baz.txt", st)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
|
||||||
7
nomino.go
Normal file
7
nomino.go
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Package nomino is a utility that allows us to generate random filenames.
|
||||||
|
//
|
||||||
|
// There are two main methods of using nomino.
|
||||||
|
//
|
||||||
|
// 1. Using the [Make] function.
|
||||||
|
// 2. Creating a generator, and using its [Generator.Make] method.
|
||||||
|
package nomino
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"github.com/gosimple/slug"
|
"github.com/gosimple/slug"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Option sets configuration parameters for Config.
|
// Option sets configuration parameters for [Config].
|
||||||
type Option func(c *Config)
|
type Option func(c *Config)
|
||||||
|
|
||||||
// WithOriginal sets the original filename.
|
// WithOriginal sets the original filename.
|
||||||
|
|
@ -18,7 +18,7 @@ func WithOriginal(o string) Option {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithOriginal sets the original filename as a slug.
|
// WithOriginal sets the original filename as a slug.
|
||||||
// This should not be used with the Slug Generator (as it would be redundant)
|
// This should not be used with the [Slug] [Generator] (as it would be redundant).
|
||||||
func WithOriginalSlug(o string) Option {
|
func WithOriginalSlug(o string) Option {
|
||||||
return func(c *Config) {
|
return func(c *Config) {
|
||||||
c.original = slug.Make(o)
|
c.original = slug.Make(o)
|
||||||
|
|
@ -26,7 +26,7 @@ func WithOriginalSlug(o string) Option {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithOriginal sets the original filename as a slug, taking the language into account.
|
// WithOriginal sets the original filename as a slug, taking the language into account.
|
||||||
// This should not be used with the Slug Generator (as it would be redundant)
|
// This should not be used with the [Slug] [Generator] (as it would be redundant).
|
||||||
func WithOriginalSlugLang(o, lang string) Option {
|
func WithOriginalSlugLang(o, lang string) Option {
|
||||||
return func(c *Config) {
|
return func(c *Config) {
|
||||||
c.original = slug.MakeLang(o, lang)
|
c.original = slug.MakeLang(o, lang)
|
||||||
|
|
@ -47,7 +47,7 @@ func WithSuffix(s string) Option {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithoutExtension sets no extension for the generated filename. By default, it will be txt
|
// WithoutExtension sets no extension for the generated filename. By default, it will be txt.
|
||||||
func WithoutExtension() Option {
|
func WithoutExtension() Option {
|
||||||
return func(c *Config) {
|
return func(c *Config) {
|
||||||
c.extension = ""
|
c.extension = ""
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,91 @@
|
||||||
package nomino
|
package nomino_test
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"codeberg.org/danjones000/nomino"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExampleWithExtension() {
|
||||||
|
st, _ := nomino.Make(nomino.NewConfig(
|
||||||
|
nomino.WithExtension("xml"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
|
))
|
||||||
|
|
||||||
|
fmt.Println(st)
|
||||||
|
// Output: 0.xml
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleWithoutExtension() {
|
||||||
|
st, _ := nomino.Make(nomino.NewConfig(
|
||||||
|
nomino.WithoutExtension(),
|
||||||
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
|
))
|
||||||
|
|
||||||
|
fmt.Println(st)
|
||||||
|
// Output: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleWithPrefix() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithPrefix("pref"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
|
)
|
||||||
|
st, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(st)
|
||||||
|
|
||||||
|
st, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(st)
|
||||||
|
// Output:
|
||||||
|
// pref_0.txt
|
||||||
|
// pref_1.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleWithSeparator() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithPrefix("pref"),
|
||||||
|
nomino.WithSeparator("---"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
|
)
|
||||||
|
st, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(st)
|
||||||
|
|
||||||
|
st, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(st)
|
||||||
|
// Output:
|
||||||
|
// pref---0.txt
|
||||||
|
// pref---1.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleWithSuffix() {
|
||||||
|
conf := nomino.NewConfig(
|
||||||
|
nomino.WithSuffix("suff"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
|
)
|
||||||
|
st, _ := nomino.Make(conf)
|
||||||
|
fmt.Println(st)
|
||||||
|
|
||||||
|
st, _ = nomino.Make(conf)
|
||||||
|
fmt.Println(st)
|
||||||
|
// Output:
|
||||||
|
// 0_suff.txt
|
||||||
|
// 1_suff.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleWithOriginal() {
|
||||||
|
st, _ := nomino.Make(nomino.NewConfig(
|
||||||
|
nomino.WithOriginal("Hello, World"),
|
||||||
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
|
))
|
||||||
|
|
||||||
|
fmt.Println(st)
|
||||||
|
// Output: 0_Hello, World.txt
|
||||||
|
}
|
||||||
|
|
||||||
func ExampleWithOriginalSlug() {
|
func ExampleWithOriginalSlug() {
|
||||||
st, _ := Make(NewConfig(
|
st, _ := nomino.Make(nomino.NewConfig(
|
||||||
WithOriginalSlug("Hello, World"),
|
nomino.WithOriginalSlug("Hello, World"),
|
||||||
WithGenerator(Incremental()),
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
))
|
))
|
||||||
|
|
||||||
fmt.Println(st)
|
fmt.Println(st)
|
||||||
|
|
@ -13,9 +93,9 @@ func ExampleWithOriginalSlug() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleWithOriginalSlugLang() {
|
func ExampleWithOriginalSlugLang() {
|
||||||
st, _ := Make(NewConfig(
|
st, _ := nomino.Make(nomino.NewConfig(
|
||||||
WithOriginalSlugLang("Diese & Dass", "de"),
|
nomino.WithOriginalSlugLang("Diese & Dass", "de"),
|
||||||
WithGenerator(Incremental()),
|
nomino.WithGenerator(nomino.Incremental()),
|
||||||
))
|
))
|
||||||
|
|
||||||
fmt.Println(st)
|
fmt.Println(st)
|
||||||
|
|
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
package nomino
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWithOriginal(t *testing.T) {
|
|
||||||
var c Config
|
|
||||||
name := "foobar"
|
|
||||||
WithOriginal(name)(&c)
|
|
||||||
assert.Equal(t, name, c.original)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithPrefix(t *testing.T) {
|
|
||||||
var c Config
|
|
||||||
pref := "draft"
|
|
||||||
WithPrefix(pref)(&c)
|
|
||||||
assert.Equal(t, pref, c.prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithSuffix(t *testing.T) {
|
|
||||||
var c Config
|
|
||||||
suff := "out"
|
|
||||||
WithSuffix(suff)(&c)
|
|
||||||
assert.Equal(t, suff, c.suffix)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithoutExtension(t *testing.T) {
|
|
||||||
c := Config{extension: ".foobar"}
|
|
||||||
WithoutExtension()(&c)
|
|
||||||
assert.Equal(t, "", c.extension)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithExtension(t *testing.T) {
|
|
||||||
var c Config
|
|
||||||
ext := "yaml"
|
|
||||||
WithExtension(ext)(&c)
|
|
||||||
assert.Equal(t, "."+ext, c.extension)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWithSeparator(t *testing.T) {
|
|
||||||
var c Config
|
|
||||||
sep := "---"
|
|
||||||
WithSeparator(sep)(&c)
|
|
||||||
assert.Equal(t, sep, c.separator)
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue