mirror of
https://codeberg.org/scip/gfn.git
synced 2025-12-16 10:20:57 +01:00
Lots of additions:
- fixed issue#1: break endless loop for non-codes - added config file support - added logo - added unit tests - added ci test pipeline - added issue templates - added binary release builder - enhanced documentation - made the number of columns flexible based on word size
This commit is contained in:
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[bug-report]"
|
||||
labels: bug
|
||||
assignees: TLINDEN
|
||||
|
||||
---
|
||||
|
||||
**Description**
|
||||
<!-- Please provide a clear and concise description of the issue: -->
|
||||
|
||||
|
||||
**Steps To Reproduce**
|
||||
<!-- Please detail the steps to reproduce the behavior, add the -d flag: -->
|
||||
|
||||
|
||||
**Expected behavior**
|
||||
<!-- What do you expected to happen instead? -->
|
||||
|
||||
|
||||
**Version information**
|
||||
<!--
|
||||
Please provide as much version information as possible:
|
||||
- if you have just installed a binary, provide the output of: gfn -v
|
||||
- if you installed from source, provide the output of: make show-version
|
||||
- provide additional details: operating system and version and shell environment
|
||||
-->
|
||||
|
||||
|
||||
**Additional informations**
|
||||
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest a feature
|
||||
title: "[feature-request]"
|
||||
labels: feature-request
|
||||
assignees: TLINDEN
|
||||
|
||||
---
|
||||
|
||||
**Describtion**
|
||||
<!-- Please provide a clear and concise description of the feature you desire: -->
|
||||
|
||||
|
||||
|
||||
**Version information**
|
||||
<!--
|
||||
Just in case the feature is already present, please provide as
|
||||
much version information as possible:
|
||||
- if you have just installed a binary, provide the output of: gfn -v
|
||||
- if you installed from source, provide the output of: make show-version
|
||||
- provide additional details: operating system and version and shell environment
|
||||
-->
|
||||
|
||||
BIN
.github/assets/logo.png
vendored
Normal file
BIN
.github/assets/logo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
36
.github/workflows/ci.yaml
vendored
Normal file
36
.github/workflows/ci.yaml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: build-and-test-gfn
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
version: [1.22]
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
name: Build
|
||||
runs-on: ${{ matrix.os }}
|
||||
steps:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ${{ matrix.version }}
|
||||
id: go
|
||||
|
||||
- name: checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: build
|
||||
run: go build
|
||||
|
||||
- name: test
|
||||
run: make test
|
||||
|
||||
golangci:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.22
|
||||
- uses: actions/checkout@v3
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
gfn
|
||||
coverage.out
|
||||
releases
|
||||
87
Makefile
Normal file
87
Makefile
Normal file
@@ -0,0 +1,87 @@
|
||||
# Copyright © 2024 Thomas von Dein
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
#
|
||||
# no need to modify anything below
|
||||
tool = gfn
|
||||
VERSION = $(shell grep VERSION config.go | head -1 | cut -d '"' -f2)
|
||||
archs = darwin freebsd linux windows
|
||||
PREFIX = /usr/local
|
||||
UID = root
|
||||
GID = 0
|
||||
HAVE_POD := $(shell pod2text -h 2>/dev/null)
|
||||
|
||||
all: buildlocal
|
||||
|
||||
|
||||
buildlocal:
|
||||
CGO_LDFLAGS='-static' go build -tags osusergo,netgo -ldflags "-extldflags=-static" -o $(tool)
|
||||
|
||||
install: buildlocal
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
|
||||
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
|
||||
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/
|
||||
|
||||
clean:
|
||||
rm -rf $(tool) coverage.out testdata t/out
|
||||
|
||||
test: clean
|
||||
mkdir -p t/out
|
||||
go test ./... $(ARGS)
|
||||
|
||||
testlint: test lint
|
||||
|
||||
lint:
|
||||
golangci-lint run
|
||||
|
||||
lint-full:
|
||||
golangci-lint run --enable-all --exclude-use-default --disable exhaustivestruct,exhaustruct,depguard,interfacer,deadcode,golint,structcheck,scopelint,varcheck,ifshort,maligned,nosnakecase,godot,funlen,gofumpt,cyclop,noctx,gochecknoglobals,paralleltest
|
||||
|
||||
testfuzzy: clean
|
||||
go test -fuzz ./... $(ARGS)
|
||||
|
||||
singletest:
|
||||
@echo "Call like this: make singletest TEST=TestPrepareColumns ARGS=-v"
|
||||
go test -run $(TEST) $(ARGS)
|
||||
|
||||
cover-report:
|
||||
go test ./... -cover -coverprofile=coverage.out
|
||||
go tool cover -html=coverage.out
|
||||
|
||||
goupdate:
|
||||
go get -t -u=patch ./...
|
||||
|
||||
buildall:
|
||||
./mkrel.sh $(tool) $(VERSION)
|
||||
|
||||
release: buildall
|
||||
gh release create v$(VERSION) --generate-notes releases/*
|
||||
|
||||
show-versions: buildlocal
|
||||
@echo "### gfn version:"
|
||||
@./gfn -V
|
||||
|
||||
@echo
|
||||
@echo "### go module versions:"
|
||||
@go list -m all
|
||||
|
||||
@echo
|
||||
@echo "### go version used for building:"
|
||||
@grep -m 1 go go.mod
|
||||
|
||||
# lint:
|
||||
# golangci-lint run -p bugs -p unused
|
||||
99
README.md
99
README.md
@@ -1,4 +1,10 @@
|
||||
# gfn
|
||||
# gfn - generate fantasy names for games and stories on the commandline
|
||||
|
||||

|
||||
|
||||
[](https://github.com/tlinden/gfnc/actions)
|
||||
[](https://github.com/tlinden/gfnc/blob/master/LICENSE)
|
||||
[](https://goreportcard.com/report/github.com/tlinden/gfnc)
|
||||
|
||||
Generate fantasy names for games and stories. It uses the fine
|
||||
[fantasyname module](https://github.com/s0rg/fantasyname) by
|
||||
@@ -12,14 +18,51 @@ guide](http://rinkworks.com/namegen/reference.shtml).
|
||||
In case the site vanishes some day, a copy of those documents is
|
||||
contained here in the repository.
|
||||
|
||||
# Install
|
||||
## Installation
|
||||
|
||||
Execute
|
||||
The tool does not have any dependencies. Just download the binary for
|
||||
your platform from the releases page and you're good to go.
|
||||
|
||||
### Installation using a pre-compiled binary
|
||||
|
||||
Go to the [latest release page](https://github.com/TLINDEN/gfn/releases/latest)
|
||||
and look for your OS and platform. There are two options to install the binary:
|
||||
|
||||
Directly download the binary for your platform,
|
||||
e.g. `gfn-linux-amd64-0.0.2`, rename it to `gfn` (or whatever
|
||||
you like more!) and put it into your bin dir (e.g. `$HOME/bin` or as
|
||||
root to `/usr/local/bin`).
|
||||
|
||||
Be sure to verify the signature of the binary file. For this also
|
||||
download the matching `gfn-linux-amd64-0.0.2.sha256` file and:
|
||||
|
||||
```shell
|
||||
% go build
|
||||
% cp gfn $HOME/bin
|
||||
cat gfn-linux-amd64-0.0.2.sha25 && sha256sum gfn-linux-amd64-0.0.2
|
||||
```
|
||||
You should see the same SHA256 hash.
|
||||
|
||||
You may also download a binary tarball for your platform, e.g.
|
||||
`gfn-linux-amd64-0.0.2.tar.gz`, unpack and install it. GNU Make is
|
||||
required for this:
|
||||
|
||||
```shell
|
||||
tar xvfz gfn-linux-amd64-0.0.2.tar.gz
|
||||
cd gfn-linux-amd64-0.0.2
|
||||
sudo make install
|
||||
```
|
||||
|
||||
### Installation from source
|
||||
|
||||
You will need the Golang toolchain in order to build from source. GNU
|
||||
Make will also help but is not strictly neccessary.
|
||||
|
||||
If you want to compile the tool yourself, use `git clone` to clone the
|
||||
repository. Then execute `go mod tidy` to install all
|
||||
dependencies. Then just enter `go build` or - if you have GNU Make
|
||||
installed - `make`.
|
||||
|
||||
To install after building either copy the binary or execute `sudo make
|
||||
install`.
|
||||
|
||||
# Usage
|
||||
|
||||
@@ -34,19 +77,21 @@ To use one of them and limit the number of
|
||||
words generated:
|
||||
|
||||
```shell
|
||||
% gfn JapaneseNamesDiverse -c 24
|
||||
yumufuchi afuchin keyu amorekin ekimuwo ashihewani rosa chireki
|
||||
oterun ruwahi uwamine emiyumu temimon yuwa awayason fuki
|
||||
emiwa nushiron achihora yomichi saniyutan kewaritsu saroru uhashi
|
||||
% gfn JapaneseNamesDiverse -n 24
|
||||
iyonen isuyaro iwamo remi kikune chikeyu iwamun
|
||||
ruri orasenin wamo oramamo ironisuru hokoku kumun
|
||||
ewoyani imanoma enenoya sawo enunumiken wayumu itamachi
|
||||
```
|
||||
|
||||
You can also write a code yourself:
|
||||
|
||||
```shell
|
||||
gfn '!sVm' -c 24
|
||||
Quaoobunker Emeemoopsie Angeepookie Osousmoosh Umuisweetie Ustoesnookum Sulealover Imopookie
|
||||
Skelaesnoogle Echiapookie Cereepoochie Gariwuddle Echaewookie Tiaieschmoopie Queaubooble Athesmoosh
|
||||
Undousnuggy Urnuigooble Mosoesnuggy Eldoegooble Denoipoochie Mosoosmooch Shyucuddly Tiaeylovey
|
||||
gfn '!sVm' -n 25
|
||||
Angeeschnookum Arysmooch Oraepookie Rothaudoodle Hinaypoochie
|
||||
Keloosnookum Esteeschnookum Ageausmoosh Erucuddle Tonuilover
|
||||
Ghaeaschnoogle Seraylover Dynysnoogle Chaibunker Poloebaby
|
||||
Leroepoochie Tinowuggy Baniaschmoopie Banoesnoogy Taseamoopie
|
||||
Entheysmooch Ustamooglie Taneidoodle Hatiesnoogy Belacuddle
|
||||
```
|
||||
|
||||
A short outline of the code will be printed if you add the `-h`
|
||||
@@ -54,11 +99,13 @@ parameter:
|
||||
```shell
|
||||
This is gfn, a fantasy name generator cli.
|
||||
|
||||
Usage: gfn [-vlc] <name|code>
|
||||
Usage: gfn [-vld] [-c <config file>] [-n <number of names>] <name|code>
|
||||
|
||||
Options:
|
||||
-c --count How many names to generate
|
||||
-c --config Config file to use (optional)
|
||||
-n --number Number of names to generate
|
||||
-l --list List pre-compiled shortcuts
|
||||
-d --debug Show debugging output
|
||||
-v --version Show program version
|
||||
|
||||
pattern syntax The letters s, v, V, c, B, C, i, m, M, D, and d
|
||||
@@ -94,6 +141,28 @@ it. For example, !(foo) will emit Foo and v!s will emit a lowercase
|
||||
vowel followed by a capitalized syllable, like eRod.
|
||||
```
|
||||
|
||||
You can use a config file to store your own codes, once you found one
|
||||
you like. A configfile is searched in these locations in this order:
|
||||
|
||||
* `/etc/gfn.conf`
|
||||
* `/usr/local/etc/gfn.conf`
|
||||
* `$HOME/.config/gfn/config`
|
||||
* `$HOME/.gfn`
|
||||
|
||||
You may also specify a config file on the commandline using the `-c`
|
||||
flag.
|
||||
|
||||
You can add multiple codes, here's an example:
|
||||
|
||||
```toml
|
||||
# example config file
|
||||
[[Templates]]
|
||||
morph = "!s(na|ha|ma|va)v"
|
||||
morphium = "!s(na|ha|ma|va)v(ius|ium|aum|oum|eum)"
|
||||
```
|
||||
|
||||
Config files are expected to be in the [TOML format](https://toml.io/en/).
|
||||
|
||||
# Report bugs
|
||||
|
||||
[Please open an issue](https://github.com/TLINDEN/gfn/issues). Thanks!
|
||||
|
||||
BIN
README.pdf
Normal file
BIN
README.pdf
Normal file
Binary file not shown.
95
config.go
95
config.go
@@ -1,11 +1,31 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/knadh/koanf/parsers/toml"
|
||||
"github.com/knadh/koanf/providers/confmap"
|
||||
"github.com/knadh/koanf/providers/file"
|
||||
"github.com/knadh/koanf/providers/posflag"
|
||||
"github.com/knadh/koanf/v2"
|
||||
flag "github.com/spf13/pflag"
|
||||
@@ -104,16 +124,19 @@ var Templates = map[string]string{
|
||||
}
|
||||
|
||||
const (
|
||||
VERSION string = "0.0.1"
|
||||
DefaultCount int = 160 // number of words to generate if -c is omitted
|
||||
Columns int = 8 // number of columns to print
|
||||
Usage string = `This is gfn, a fantasy name generator cli.
|
||||
VERSION string = "0.0.2"
|
||||
DefaultCount int = 160 // number of words to generate if -c is omitted
|
||||
DefaultColumns int = 10 // number of columns to print
|
||||
MaxWidth int = 72 // max width of output, adjusts columns
|
||||
Usage string = `This is gfn, a fantasy name generator cli.
|
||||
|
||||
Usage: gfn [-vlc] <name|code>
|
||||
Usage: gfn [-vld] [-c <config file>] [-n <number of names>] <name|code>
|
||||
|
||||
Options:
|
||||
-c --count How many names to generate
|
||||
-c --config Config file to use (optional)
|
||||
-n --number Number of names to generate
|
||||
-l --list List pre-compiled shortcuts
|
||||
-d --debug Show debugging output
|
||||
-v --version Show program version
|
||||
|
||||
pattern syntax The letters s, v, V, c, B, C, i, m, M, D, and d
|
||||
@@ -150,10 +173,15 @@ vowel followed by a capitalized syllable, like eRod.`
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Showversion bool `koanf:"version"` // -v
|
||||
Listshortcuts bool `koanf:"list"` // -l
|
||||
Code string // arg
|
||||
Count int `koanf:"count"` // -c
|
||||
Showversion bool `koanf:"version"` // -v
|
||||
Debug bool `koanf:"debug"` // -d
|
||||
Listshortcuts bool `koanf:"list"` // -l
|
||||
Number int `koanf:"number"` // -c
|
||||
Templates map[string]string `koanf:"templates"`
|
||||
Config string `koanf:"config"`
|
||||
Columns int `koanf:"columns"` // number of columns to use
|
||||
Code string // arg
|
||||
WordWidth int // max width of generated words
|
||||
}
|
||||
|
||||
func InitConfig(output io.Writer) (*Config, error) {
|
||||
@@ -161,7 +189,8 @@ func InitConfig(output io.Writer) (*Config, error) {
|
||||
|
||||
// Load default values using the confmap provider.
|
||||
if err := kloader.Load(confmap.Provider(map[string]interface{}{
|
||||
"count": DefaultCount,
|
||||
"number": DefaultCount,
|
||||
"columns": DefaultColumns,
|
||||
}, "."), nil); err != nil {
|
||||
return nil, fmt.Errorf("failed to load default values into koanf: %w", err)
|
||||
}
|
||||
@@ -175,13 +204,44 @@ func InitConfig(output io.Writer) (*Config, error) {
|
||||
|
||||
// parse commandline flags
|
||||
flagset.BoolP("list", "l", false, "show list of precompiled codes")
|
||||
flagset.BoolP("version", "V", false, "show program version")
|
||||
flagset.IntP("count", "c", 1, "how many names to generate")
|
||||
flagset.BoolP("version", "v", false, "show program version")
|
||||
flagset.BoolP("debug", "d", false, "enable debug output")
|
||||
flagset.IntP("number", "n", 1, "number of names to generate")
|
||||
flagset.StringP("config", "c", "", "config file")
|
||||
|
||||
if err := flagset.Parse(os.Args[1:]); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse program arguments: %w", err)
|
||||
}
|
||||
|
||||
// generate a list of config files to try to load, including the
|
||||
// one provided via -c, if any
|
||||
var configfiles []string
|
||||
|
||||
configfile, _ := flagset.GetString("config")
|
||||
home, _ := os.UserHomeDir()
|
||||
|
||||
if configfile != "" {
|
||||
configfiles = []string{configfile}
|
||||
} else {
|
||||
configfiles = []string{
|
||||
"/etc/gfn.conf", "/usr/local/etc/gfn.conf", // unix variants
|
||||
filepath.Join(home, ".config", "gfn", "config"),
|
||||
filepath.Join(home, ".gfn"),
|
||||
"gfn.conf",
|
||||
}
|
||||
}
|
||||
|
||||
// Load the config file[s]
|
||||
for _, cfgfile := range configfiles {
|
||||
if path, err := os.Stat(cfgfile); !os.IsNotExist(err) {
|
||||
if !path.IsDir() {
|
||||
if err := kloader.Load(file.Provider(cfgfile), toml.Parser()); err != nil {
|
||||
return nil, fmt.Errorf("error loading config file: %w", err)
|
||||
}
|
||||
}
|
||||
} // else: we ignore the file if it doesn't exists
|
||||
}
|
||||
|
||||
// command line setup
|
||||
if err := kloader.Load(posflag.Provider(flagset, ".", kloader), nil); err != nil {
|
||||
return nil, fmt.Errorf("error loading flags: %w", err)
|
||||
@@ -198,5 +258,14 @@ func InitConfig(output io.Writer) (*Config, error) {
|
||||
conf.Code = flagset.Args()[0]
|
||||
}
|
||||
|
||||
// merge configured and hardcoded templates
|
||||
if conf.Templates == nil {
|
||||
conf.Templates = Templates
|
||||
} else {
|
||||
for name, code := range Templates {
|
||||
conf.Templates[name] = code
|
||||
}
|
||||
}
|
||||
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
52
generate.go
52
generate.go
@@ -1,29 +1,75 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
fn "github.com/s0rg/fantasyname"
|
||||
)
|
||||
|
||||
func Generate(count int, code string) ([]string, error) {
|
||||
// Actual fantasy name generation
|
||||
func Generate(conf *Config) ([]string, error) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
// we register each generated word to avoid duplicates, which
|
||||
// naturally happens every while
|
||||
reg := map[string]int{}
|
||||
|
||||
gen, err := fn.Compile(code, fn.Collapse(true))
|
||||
// library call
|
||||
gen, err := fn.Compile(conf.Code, fn.Collapse(true))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not compile FN code: %w", err)
|
||||
}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
// fetch requested number of names
|
||||
for i := 0; len(reg) < conf.Number; i++ {
|
||||
name := gen.String()
|
||||
|
||||
if !Exists(reg, name) {
|
||||
reg[name] = 1
|
||||
|
||||
if conf.WordWidth < len(name) {
|
||||
conf.WordWidth = len(name)
|
||||
}
|
||||
}
|
||||
|
||||
// static codes (like 'akx', which is no FN code, just a
|
||||
// literal) generates just 1 item
|
||||
if i > conf.Number*2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println("fetched names")
|
||||
|
||||
slog.Debug("Generated fantasy names from code",
|
||||
"code", conf.Code, "count-names", len(reg))
|
||||
|
||||
// adjust columns, if needed
|
||||
if conf.WordWidth*conf.Columns > MaxWidth {
|
||||
conf.Columns = MaxWidth / conf.WordWidth
|
||||
}
|
||||
|
||||
// we just return a slice of names
|
||||
names := make([]string, len(reg))
|
||||
|
||||
i := 0
|
||||
|
||||
77
generate_test.go
Normal file
77
generate_test.go
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
want bool
|
||||
code string
|
||||
}{
|
||||
{
|
||||
name: "code-ok",
|
||||
want: true,
|
||||
code: "!s(na|ha|ma|va)v",
|
||||
},
|
||||
{
|
||||
name: "code-fail",
|
||||
want: false,
|
||||
code: "!s(na|ha|ma|vav",
|
||||
},
|
||||
}
|
||||
|
||||
var conf = &Config{
|
||||
Number: 3,
|
||||
}
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
testname := fmt.Sprintf("generate-%s", tt.name)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
conf.Code = tt.code
|
||||
|
||||
names, err := Generate(conf)
|
||||
|
||||
if err != nil {
|
||||
if tt.want {
|
||||
t.Errorf("Generate() returned an unexpected error: %s", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(names) != 3 {
|
||||
t.Errorf("Generate() returned wrong number of results\nExp: %+v\nGot: %+v\n",
|
||||
conf.Number, len(names))
|
||||
return
|
||||
}
|
||||
|
||||
for idx, name := range names {
|
||||
if len(name) == 0 {
|
||||
t.Errorf("Generate() returned empty results\nIndex: %d\nGot: <%s>\n",
|
||||
idx, name)
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
5
gfn.conf
Normal file
5
gfn.conf
Normal file
@@ -0,0 +1,5 @@
|
||||
# example config file
|
||||
[[Templates]]
|
||||
morph = "!s(na|ha|ma|va)v"
|
||||
morphium = "!s(na|ha|ma|va)v(ius|ium|aum|oum|eum)"
|
||||
|
||||
6
go.mod
6
go.mod
@@ -7,18 +7,24 @@ require github.com/s0rg/fantasyname v1.3.4
|
||||
require (
|
||||
github.com/alecthomas/repr v0.4.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect
|
||||
github.com/knadh/koanf/maps v0.1.1 // indirect
|
||||
github.com/knadh/koanf/parsers/toml v0.1.0 // indirect
|
||||
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
|
||||
github.com/knadh/koanf/providers/file v0.1.0 // indirect
|
||||
github.com/knadh/koanf/providers/posflag v0.1.0 // indirect
|
||||
github.com/knadh/koanf/v2 v2.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tlinden/yadu v0.1.3 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
13
go.sum
13
go.sum
@@ -2,12 +2,18 @@ github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 h1:TQcrn6Wq+sKGkpyPvppOz99zsMBaUOKXq6HSv655U1c=
|
||||
github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs=
|
||||
github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI=
|
||||
github.com/knadh/koanf/parsers/toml v0.1.0 h1:S2hLqS4TgWZYj4/7mI5m1CQQcWurxUz6ODgOub/6LCI=
|
||||
github.com/knadh/koanf/parsers/toml v0.1.0/go.mod h1:yUprhq6eo3GbyVXFFMdbfZSo928ksS+uo0FFqNMnO18=
|
||||
github.com/knadh/koanf/providers/confmap v0.1.0 h1:gOkxhHkemwG4LezxxN8DMOFopOPghxRVp7JbIvdvqzU=
|
||||
github.com/knadh/koanf/providers/confmap v0.1.0/go.mod h1:2uLhxQzJnyHKfxG927awZC7+fyHFdQkd697K4MdLnIU=
|
||||
github.com/knadh/koanf/providers/file v0.1.0 h1:fs6U7nrV58d3CFAFh8VTde8TM262ObYf3ODrc//Lp+c=
|
||||
github.com/knadh/koanf/providers/file v0.1.0/go.mod h1:rjJ/nHQl64iYCtAW2QQnF0eSmDEX/YZ/eNFj5yR6BvA=
|
||||
github.com/knadh/koanf/providers/posflag v0.1.0 h1:mKJlLrKPcAP7Ootf4pBZWJ6J+4wHYujwipe7Ie3qW6U=
|
||||
github.com/knadh/koanf/providers/posflag v0.1.0/go.mod h1:SYg03v/t8ISBNrMBRMlojH8OsKowbkXV7giIbBVgbz0=
|
||||
github.com/knadh/koanf/v2 v2.1.0 h1:eh4QmHHBuU8BybfIJ8mB8K8gsGCD/AUQTdwGq/GzId8=
|
||||
@@ -21,6 +27,10 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/s0rg/fantasyname v1.3.4 h1:zqmKri+2MGVxgRfTm0XViZPtoy0wm9BBc6oqOCuALZw=
|
||||
github.com/s0rg/fantasyname v1.3.4/go.mod h1:XqTfA5mtZAxnjcSkAwijm1FGoI9FkjRyUOWEEbjsRd0=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
@@ -28,11 +38,14 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/tlinden/yadu v0.1.3 h1:5cRCUmj+l5yvlM2irtpFBIJwVV2DPEgYSaWvF19FtcY=
|
||||
github.com/tlinden/yadu v0.1.3/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
69
main.go
69
main.go
@@ -1,16 +1,43 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
|
||||
"log/slog"
|
||||
|
||||
"github.com/tlinden/yadu"
|
||||
)
|
||||
|
||||
func main() {
|
||||
os.Exit(Main(os.Stdout))
|
||||
}
|
||||
|
||||
func TMain() int {
|
||||
return Main(os.Stdout)
|
||||
}
|
||||
|
||||
func Main(output io.Writer) int {
|
||||
// parse config file and command line parameters, if any
|
||||
conf, err := InitConfig(output)
|
||||
if err != nil {
|
||||
return Die(err)
|
||||
@@ -22,25 +49,57 @@ func Main(output io.Writer) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
// enable debugging, if needed. We only use log/slog for
|
||||
// debugging, so there's no need to configure it outside debugging
|
||||
if conf.Debug {
|
||||
logLevel := &slog.LevelVar{}
|
||||
// we're using a more verbose logger in debug mode
|
||||
buildInfo, _ := debug.ReadBuildInfo()
|
||||
opts := &yadu.Options{
|
||||
Level: logLevel,
|
||||
AddSource: true,
|
||||
}
|
||||
|
||||
logLevel.Set(slog.LevelDebug)
|
||||
|
||||
handler := yadu.NewHandler(output, opts)
|
||||
debuglogger := slog.New(handler).With(
|
||||
slog.Group("program_info",
|
||||
slog.Int("pid", os.Getpid()),
|
||||
slog.String("go_version", buildInfo.GoVersion),
|
||||
),
|
||||
)
|
||||
slog.SetDefault(debuglogger)
|
||||
}
|
||||
|
||||
// just show what we have
|
||||
if conf.Listshortcuts {
|
||||
ListTemplates(output)
|
||||
ListTemplates(conf, output)
|
||||
return 0
|
||||
}
|
||||
|
||||
// code argument is mandatory
|
||||
if len(conf.Code) == 0 {
|
||||
fmt.Fprintln(output, Usage)
|
||||
return 1
|
||||
}
|
||||
|
||||
if Exists(Templates, conf.Code) {
|
||||
conf.Code = Templates[conf.Code]
|
||||
// check if we can use a template, otherwise consider the argument
|
||||
// to be FN code
|
||||
if Exists(conf.Templates, conf.Code) {
|
||||
slog.Debug("Argument resolves to template code",
|
||||
"name", conf.Code, "code", conf.Templates[conf.Code])
|
||||
|
||||
conf.Code = conf.Templates[conf.Code]
|
||||
}
|
||||
|
||||
names, err := Generate(conf.Count, conf.Code)
|
||||
// all prepared, run baby run
|
||||
names, err := Generate(conf)
|
||||
if err != nil {
|
||||
return Die(err)
|
||||
}
|
||||
|
||||
if err = PrintColumns(names, output); err != nil {
|
||||
if err = PrintColumns(conf, names, output); err != nil {
|
||||
return Die(err)
|
||||
}
|
||||
|
||||
|
||||
39
main_test.go
Normal file
39
main_test.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/rogpeppe/go-internal/testscript"
|
||||
)
|
||||
|
||||
// see https://bitfieldconsulting.com/golang/test-scripts
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(testscript.RunMain(m, map[string]func() int{
|
||||
"testgfn": TMain,
|
||||
}))
|
||||
}
|
||||
|
||||
func TestFfn(t *testing.T) {
|
||||
testscript.Run(t, testscript.Params{
|
||||
Dir: "t",
|
||||
})
|
||||
}
|
||||
75
mkrel.sh
Executable file
75
mkrel.sh
Executable file
@@ -0,0 +1,75 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright © 2024 Thomas von Dein
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# get list with: go tool dist list
|
||||
DIST="darwin/amd64
|
||||
freebsd/amd64
|
||||
linux/amd64
|
||||
netbsd/amd64
|
||||
openbsd/amd64
|
||||
windows/amd64
|
||||
freebsd/arm64
|
||||
linux/arm64
|
||||
netbsd/arm64
|
||||
openbsd/arm64
|
||||
windows/arm64"
|
||||
|
||||
tool="$1"
|
||||
version="$2"
|
||||
|
||||
if test -z "$version"; then
|
||||
echo "Usage: $0 <tool name> <release version>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf releases
|
||||
mkdir -p releases
|
||||
|
||||
|
||||
for D in $DIST; do
|
||||
os=${D/\/*/}
|
||||
arch=${D/*\//}
|
||||
binfile="releases/${tool}-${os}-${arch}-${version}"
|
||||
|
||||
if test "$os" = "windows"; then
|
||||
binfile="${binfile}.exe"
|
||||
fi
|
||||
|
||||
tardir="${tool}-${os}-${arch}-${version}"
|
||||
tarfile="releases/${tool}-${os}-${arch}-${version}.tar.gz"
|
||||
set -x
|
||||
GOOS=${os} GOARCH=${arch} go build -tags osusergo,netgo -ldflags "-extldflags=-static" -o ${binfile}
|
||||
mkdir -p ${tardir}
|
||||
cp ${binfile} README.md LICENSE ${tardir}/
|
||||
echo 'tool = gfn
|
||||
PREFIX = /usr/local
|
||||
UID = root
|
||||
GID = 0
|
||||
|
||||
install:
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
|
||||
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
|
||||
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
|
||||
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/' > ${tardir}/Makefile
|
||||
tar cpzf ${tarfile} ${tardir}
|
||||
sha256sum ${binfile} | cut -d' ' -f1 > ${binfile}.sha256
|
||||
sha256sum ${tarfile} | cut -d' ' -f1 > ${tarfile}.sha256
|
||||
rm -rf ${tardir}
|
||||
set +x
|
||||
done
|
||||
|
||||
32
printer.go
32
printer.go
@@ -1,15 +1,36 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func ListTemplates(output io.Writer) {
|
||||
// Output a list of hardcoded FN code templates
|
||||
func ListTemplates(conf *Config, output io.Writer) {
|
||||
slog.Debug("Listing configured templates", "templates", conf.Templates)
|
||||
|
||||
names := []string{}
|
||||
|
||||
for name := range Templates {
|
||||
for name := range conf.Templates {
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
@@ -20,11 +41,12 @@ func ListTemplates(output io.Writer) {
|
||||
}
|
||||
}
|
||||
|
||||
func PrintColumns(names []string, output io.Writer) error {
|
||||
// Columnar output
|
||||
func PrintColumns(conf *Config, names []string, output io.Writer) error {
|
||||
count := len(names)
|
||||
|
||||
// no need for the hassle to calculate columns
|
||||
if count <= Columns {
|
||||
if count <= conf.Columns {
|
||||
for _, name := range names {
|
||||
fmt.Fprintln(output, name)
|
||||
}
|
||||
@@ -33,7 +55,7 @@ func PrintColumns(names []string, output io.Writer) error {
|
||||
}
|
||||
|
||||
// get a transposed list of columns
|
||||
padlist, max := Getcolumns(names, Columns)
|
||||
padlist, max := Getcolumns(names, conf.Columns)
|
||||
|
||||
// make sure there's enough spacing between the columns
|
||||
format := fmt.Sprintf("%%-%ds", max+1)
|
||||
|
||||
2
t/debug.txtar
Normal file
2
t/debug.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn -d Vs
|
||||
stdout 'gfn/generate.go:'
|
||||
2
t/help.txtar
Normal file
2
t/help.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn -h
|
||||
stdout 'This is gfn'
|
||||
2
t/list.txtar
Normal file
2
t/list.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn -l
|
||||
stdout 'JapaneseNamesDiverse'
|
||||
1
t/noarg.txtar
Normal file
1
t/noarg.txtar
Normal file
@@ -0,0 +1 @@
|
||||
! exec testgfn
|
||||
2
t/nocode.txtar
Normal file
2
t/nocode.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn akx
|
||||
stdout 'akx'
|
||||
2
t/nocodeloop.txtar
Normal file
2
t/nocodeloop.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn akx
|
||||
! stdout 'akx akx'
|
||||
2
t/template.txtar
Normal file
2
t/template.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn Idiots
|
||||
stdout 'face'
|
||||
2
t/valid.txtar
Normal file
2
t/valid.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn sVdmi(usus|hehe)
|
||||
stdout 'usus'
|
||||
2
t/version.txtar
Normal file
2
t/version.txtar
Normal file
@@ -0,0 +1,2 @@
|
||||
exec testgfn -v
|
||||
stdout 'This is gfn version'
|
||||
17
util.go
17
util.go
@@ -1,3 +1,20 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import "log"
|
||||
|
||||
139
util_test.go
Normal file
139
util_test.go
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright © 2024 Thomas von Dein
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var testexists = []struct {
|
||||
name string
|
||||
want bool
|
||||
key int
|
||||
hash map[int]int
|
||||
}{
|
||||
{
|
||||
name: "have-key",
|
||||
want: true,
|
||||
key: 1,
|
||||
hash: map[int]int{1: 4, 2: 5},
|
||||
},
|
||||
{
|
||||
name: "miss-key",
|
||||
want: false,
|
||||
key: 3,
|
||||
hash: map[int]int{1: 4, 2: 5},
|
||||
},
|
||||
}
|
||||
|
||||
func TestExists(t *testing.T) {
|
||||
for _, tt := range testexists {
|
||||
testname := fmt.Sprintf("exists-%s", tt.name)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
got := Exists(tt.hash, tt.key)
|
||||
|
||||
if got != tt.want {
|
||||
t.Errorf("Exists() returned wrong result\nExp: %+v\nGot: %+v\n",
|
||||
tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var testcontains = []struct {
|
||||
name string
|
||||
want bool
|
||||
key int
|
||||
list []int
|
||||
}{
|
||||
{
|
||||
name: "have-item",
|
||||
want: true,
|
||||
key: 1,
|
||||
list: []int{1, 2},
|
||||
},
|
||||
{
|
||||
name: "miss-item",
|
||||
want: false,
|
||||
key: 3,
|
||||
list: []int{1, 2},
|
||||
},
|
||||
}
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
for _, tt := range testcontains {
|
||||
testname := fmt.Sprintf("contains-%s", tt.name)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
got := Contains(tt.list, tt.key)
|
||||
|
||||
if got != tt.want {
|
||||
t.Errorf("Contains() returned wrong result\nExp: %+v\nGot: %+v\n",
|
||||
tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var testtranspose = []struct {
|
||||
name string
|
||||
slice [][]string
|
||||
expect [][]string
|
||||
}{
|
||||
{
|
||||
name: "2x2-matrix",
|
||||
slice: [][]string{
|
||||
{"a1", "a2"},
|
||||
{"b1", "b2"},
|
||||
},
|
||||
expect: [][]string{
|
||||
{"a1", "b1"},
|
||||
{"a2", "b2"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "2x3-matrix",
|
||||
slice: [][]string{
|
||||
{"a1", "a2", "a3"},
|
||||
{"b1", "b2", "b3"},
|
||||
},
|
||||
expect: [][]string{
|
||||
{"a1", "b1"},
|
||||
{"a2", "b2"},
|
||||
{"a3", "b3"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestTranspose(t *testing.T) {
|
||||
for _, tt := range testtranspose {
|
||||
testname := fmt.Sprintf("transpose-%s", tt.name)
|
||||
t.Run(testname, func(t *testing.T) {
|
||||
got := Transpose(tt.slice)
|
||||
|
||||
if !reflect.DeepEqual(tt.expect, got) {
|
||||
t.Errorf("Transpose() returned wrong result\nExp: %+v\nGot: %+v\n",
|
||||
tt.expect, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user