Compare commits
	
		
			57 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 | |||
| 25c1a6e891 | |||
| 439fe48230 | |||
| 9d8737079f | |||
| 1d235af876 | |||
| 921020d9fd | |||
| 67f472a2c6 | |||
| 28803e6a28 | 
					 30 changed files with 1307 additions and 246 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 | ||||||
							
								
								
									
										101
									
								
								CHANGELOG.md
									
										
									
									
									
								
							
							
						
						
									
										101
									
								
								CHANGELOG.md
									
										
									
									
									
								
							|  | @ -1,28 +1,111 @@ | ||||||
| # Changelog | # Changelog | ||||||
| 
 | 
 | ||||||
| ## [0.0.3] - 2025-03-11 | ### [1.0.0] - 2025-03-31 - 🚀 Stable release! | ||||||
|  | 
 | ||||||
|  | #### Support | ||||||
|  | 
 | ||||||
|  | - 📝 Vastly improved [go docs](https://pkg.go.dev/codeberg.org/danjones000/nomino). | ||||||
|  | - 📝 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. | ||||||
|  | 
 | ||||||
|  | ## [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 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ import ( | ||||||
| func TestNewConf(t *testing.T) { | func TestNewConf(t *testing.T) { | ||||||
| 	c := NewConfig() | 	c := NewConfig() | ||||||
| 	assert.Equal(t, ".txt", c.extension) | 	assert.Equal(t, ".txt", c.extension) | ||||||
| 	st, _ := c.generator() | 	st, _ := c.generator(&c) | ||||||
| 	_, parseErr := uuid.Parse(st) | 	_, parseErr := uuid.Parse(st) | ||||||
| 	assert.NoError(t, parseErr) | 	assert.NoError(t, parseErr) | ||||||
| } | } | ||||||
|  | @ -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) | ||||||
|  | } | ||||||
|  | @ -2,32 +2,41 @@ package nomino | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"time" | 	"math/rand" | ||||||
| 
 |  | ||||||
| 	"github.com/google/uuid" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // 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. | ||||||
| // Technically, it doesn't necessarily need to be random, and could be based on time, or a counter, | // Technically, it doesn't necessarily need to be random, and could be based on time, or a counter, | ||||||
| // for example. | // for example. | ||||||
| type Generator func() (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() (string, error) { | func missingGen(*Config) (string, error) { | ||||||
| 	return "", ErrMissingGenerators | 	return "", ErrMissingGenerators | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // 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 | ||||||
|  | @ -38,62 +47,27 @@ func MultiGeneratorInOrder(gens ...Generator) Generator { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var idx int | 	var idx int | ||||||
| 	return func() (string, error) { | 	return func(c *Config) (string, error) { | ||||||
| 		st, err := gens[idx]() | 		st, err := gens[idx](c) | ||||||
| 		idx = (idx + 1) % len(gens) | 		idx = (idx + 1) % len(gens) | ||||||
| 		return st, err | 		return st, err | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func uuidGen() (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 | 	return func(c *Config) (string, error) { | ||||||
| const FileTimestamp string = "2006-01-02_03-05-06-0700" | 		//nolint:gosec // This is not security sensitive, so a weak number generator is fine. | ||||||
| 
 | 		idx := rand.Int() % len(gens) | ||||||
| // Timestamp generates a a date and time for the current time. | 		return gens[idx](c) | ||||||
| // 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() (string, error) { |  | ||||||
| 		return t.Format(f), nil |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // FileTimestamp 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) |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -1,20 +1,79 @@ | ||||||
| package nomino | package nomino_test | ||||||
| 
 | 
 | ||||||
| import "fmt" | import ( | ||||||
|  | 	"fmt" | ||||||
| 
 | 
 | ||||||
| func ExampleWithGenerator_custom_generator() { | 	"codeberg.org/danjones000/nomino" | ||||||
| 	gen := func() (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: | ||||||
| 	// hello.txt | 	// hello.txt | ||||||
| 	// hello | 	// hello | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func ExampleGenerator_Make() { | ||||||
|  | 	g := nomino.Incremental() | ||||||
|  | 	st, _ := g.Make() | ||||||
|  | 	fmt.Println(st) | ||||||
|  | 
 | ||||||
|  | 	st, _ = g.Make(nomino.WithPrefix("foo")) | ||||||
|  | 	fmt.Println(st) | ||||||
|  | 
 | ||||||
|  | 	// Output: | ||||||
|  | 	// 0.txt | ||||||
|  | 	// foo_1.txt | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ExampleMultiGeneratorInOrder() { | ||||||
|  | 	gen1 := func(*nomino.Config) (string, error) { | ||||||
|  | 		return "bonjour", nil | ||||||
|  | 	} | ||||||
|  | 	gen2 := func(*nomino.Config) (string, error) { | ||||||
|  | 		return "goodbye", nil | ||||||
|  | 	} | ||||||
|  | 	gen := nomino.MultiGeneratorInOrder(gen1, gen2) | ||||||
|  | 
 | ||||||
|  | 	str, _ := gen.Make() | ||||||
|  | 	fmt.Println(str) | ||||||
|  | 
 | ||||||
|  | 	str, _ = gen.Make() | ||||||
|  | 	fmt.Println(str) | ||||||
|  | 
 | ||||||
|  | 	str, _ = gen.Make() | ||||||
|  | 	fmt.Println(str) | ||||||
|  | 
 | ||||||
|  | 	// Output: | ||||||
|  | 	// bonjour.txt | ||||||
|  | 	// goodbye.txt | ||||||
|  | 	// bonjour.txt | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ExampleMultiGeneratorRandomOrder() { | ||||||
|  | 	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, _ := gen.Make() | ||||||
|  | 	fmt.Println(str) | ||||||
|  | 
 | ||||||
|  | 	str, _ = gen.Make() | ||||||
|  | 	fmt.Println(str) | ||||||
|  | 
 | ||||||
|  | 	str, _ = gen.Make() | ||||||
|  | 	fmt.Println(str) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -3,105 +3,103 @@ 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() (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() | 	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" | 	st, err := g(nil) | ||||||
| 	er1 := errors.New("oops") |  | ||||||
| 	g1 := func() (string, error) { return st1, nil } |  | ||||||
| 	g2 := func() (string, error) { return st2, nil } |  | ||||||
| 	g3 := func() (string, error) { return "", er1 } |  | ||||||
| 	g := MultiGeneratorInOrder(g1, g2, g3) |  | ||||||
| 	st, err := g() |  | ||||||
| 	assert.NoError(t, err) | 	assert.NoError(t, err) | ||||||
| 	assert.Equal(t, st1, st) | 	assert.Equal(t, out1, st) | ||||||
| 	st, err = g() | 	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() | 	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() | 	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() (string, error) { return st1, nil } |  | ||||||
| 	g := MultiGeneratorInOrder(g1) | 	g := MultiGeneratorInOrder(g1) | ||||||
| 
 | 
 | ||||||
| 	st, err := g() | 	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() | 	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) { | ||||||
| 	g := MultiGeneratorInOrder() | 	g := MultiGeneratorInOrder() | ||||||
| 	st, err := g() | 	st, err := g(nil) | ||||||
| 	assert.Zero(t, st) | 	assert.Zero(t, st) | ||||||
| 	assert.ErrorIs(t, err, ErrMissingGenerators) | 	assert.ErrorIs(t, err, ErrMissingGenerators) | ||||||
| 	st, err = g() | 	st, err = g(nil) | ||||||
| 	assert.Zero(t, st) | 	assert.Zero(t, st) | ||||||
| 	assert.ErrorIs(t, err, ErrMissingGenerators) | 	assert.ErrorIs(t, err, ErrMissingGenerators) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestUUID(t *testing.T) { | func TestMultiGeneratorRandomOrder(t *testing.T) { | ||||||
| 	st, err := UUID()() | 	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()() |  | ||||||
| 	assert.Equal(t, errors.New("sorry"), err) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func TestTimestamp(t *testing.T) { |  | ||||||
| 	n := time.Now() |  | ||||||
| 	st, err := Timestamp()() |  | ||||||
| 	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)() | 	assert.Zero(t, st) | ||||||
| 	assert.NoError(t, err) | 	assert.ErrorIs(t, err, ErrMissingGenerators) | ||||||
| 	assert.Equal(t, d.Format(FileTimestamp), st) | 	st, err = g(nil) | ||||||
| } | 	assert.Zero(t, st) | ||||||
| 
 | 	assert.ErrorIs(t, err, ErrMissingGenerators) | ||||||
| func TestTimestampUTC(t *testing.T) { |  | ||||||
| 	n := time.Now() |  | ||||||
| 	st, err := TimestampUTC()() |  | ||||||
| 	assert.NoError(t, err) |  | ||||||
| 	assert.Equal(t, n.UTC().Format(FileTimestampNoTZ), st) |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										3
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
										
									
									
									
								
							|  | @ -3,12 +3,15 @@ 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/stretchr/testify v1.10.0 | 	github.com/stretchr/testify v1.10.0 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| require ( | require ( | ||||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||||
|  | 	github.com/gosimple/unidecode v1.0.1 // indirect | ||||||
| 	github.com/pmezard/go-difflib v1.0.0 // indirect | 	github.com/pmezard/go-difflib v1.0.0 // indirect | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||
| ) | ) | ||||||
|  |  | ||||||
							
								
								
									
										6
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								go.sum
									
										
									
									
									
								
							|  | @ -1,7 +1,13 @@ | ||||||
| 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/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= | ||||||
|  | github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= | ||||||
|  | github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= | ||||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||||
| github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								make.go
									
										
									
									
									
								
							
							
						
						
									
										22
									
								
								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) { | ||||||
| 	name, err := conf.generator() | 	for _, opt := range opts { | ||||||
|  | 		opt(&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 | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										40
									
								
								make_test.go
									
										
									
									
									
								
							
							
						
						
									
										40
									
								
								make_test.go
									
										
									
									
									
								
							|  | @ -7,8 +7,10 @@ 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() (string, error) { return "abc", nil }) | 	genOpt := WithGenerator(func(*Config) (string, error) { return "abc", nil }) | ||||||
| 	testcases := []struct { | 	testcases := []struct { | ||||||
| 		name string | 		name string | ||||||
| 		opts []Option | 		opts []Option | ||||||
|  | @ -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,9 +50,35 @@ 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() (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) { | ||||||
|  | 	gen := func(c *Config) (string, error) { | ||||||
|  | 		c.original = "" | ||||||
|  | 		return "foo", nil | ||||||
|  | 	} | ||||||
|  | 	conf := NewConfig(WithGenerator(gen), WithOriginal("foobar")) | ||||||
|  | 	st, err := Make(conf) | ||||||
|  | 	assert.Equal(t, "foobar", conf.original) | ||||||
|  | 	assert.Equal(t, "foo.txt", st) | ||||||
|  | 	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 | ||||||
							
								
								
									
										26
									
								
								options.go
									
										
									
									
									
								
							
							
						
						
									
										26
									
								
								options.go
									
										
									
									
									
								
							|  | @ -1,8 +1,12 @@ | ||||||
| package nomino | package nomino | ||||||
| 
 | 
 | ||||||
| import "strings" | import ( | ||||||
|  | 	"strings" | ||||||
| 
 | 
 | ||||||
| // Option sets configuration parameters for Config. | 	"github.com/gosimple/slug" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // 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. | ||||||
|  | @ -13,6 +17,22 @@ func WithOriginal(o string) Option { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // WithOriginal sets the original filename as a slug. | ||||||
|  | // This should not be used with the [Slug] [Generator] (as it would be redundant). | ||||||
|  | func WithOriginalSlug(o string) Option { | ||||||
|  | 	return func(c *Config) { | ||||||
|  | 		c.original = slug.Make(o) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // 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). | ||||||
|  | func WithOriginalSlugLang(o, lang string) Option { | ||||||
|  | 	return func(c *Config) { | ||||||
|  | 		c.original = slug.MakeLang(o, lang) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // WithPrefix sets a prefix for the generated name. | // WithPrefix sets a prefix for the generated name. | ||||||
| func WithPrefix(p string) Option { | func WithPrefix(p string) Option { | ||||||
| 	return func(c *Config) { | 	return func(c *Config) { | ||||||
|  | @ -27,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 = "" | ||||||
|  |  | ||||||
							
								
								
									
										103
									
								
								options_examples_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								options_examples_test.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | ||||||
|  | package nomino_test | ||||||
|  | 
 | ||||||
|  | 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() { | ||||||
|  | 	st, _ := nomino.Make(nomino.NewConfig( | ||||||
|  | 		nomino.WithOriginalSlug("Hello, World"), | ||||||
|  | 		nomino.WithGenerator(nomino.Incremental()), | ||||||
|  | 	)) | ||||||
|  | 
 | ||||||
|  | 	fmt.Println(st) | ||||||
|  | 	// Output: 0_hello-world.txt | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ExampleWithOriginalSlugLang() { | ||||||
|  | 	st, _ := nomino.Make(nomino.NewConfig( | ||||||
|  | 		nomino.WithOriginalSlugLang("Diese & Dass", "de"), | ||||||
|  | 		nomino.WithGenerator(nomino.Incremental()), | ||||||
|  | 	)) | ||||||
|  | 
 | ||||||
|  | 	fmt.Println(st) | ||||||
|  | 	// Output: 0_diese-und-dass.txt | ||||||
|  | } | ||||||
|  | @ -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