Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use getopt for cli args #58

Merged
merged 11 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Print pokemon in the CLI! An adaptation of the classic "cowsay"
- [pokesay](#pokesay)
- [One-line installs](#one-line-installs)
- [Usage](#usage)
- [Full Usage](#full-usage)
- [How it works](#how-it-works)
- [Building binaries](#building-binaries)
- [On your host OS](#on-your-host-os)
Expand Down Expand Up @@ -64,6 +65,38 @@ echo 'fortune | pokesay' >> $HOME/.bashrc

> _Note: The pokesay tool is intended to only be used with piped text input from STDIN, entering text by typing (or other methods) might not work as expected!_

### Full Usage

> Run pokesay with `-h` or `--help` to see the full usage

```shell
Usage: pokesay [-bCfhjLlsuvW] [-c value] [-n value] [-t value] [-w value] [parameters ...]
-b, --info-border draw a border around the info box
-c, --category=value
choose a pokemon from a specific category
-C, --no-category-info
do not print pokemon category information in the info box
-f, --fastest run with the fastest possible configuration (--nowrap &
--notabspaces)
-h, --help display this help message
-j, --japanese-name
print the japanese name in the info box
-L, --list-categories
list all available categories
-l, --list-names list all available names
-n, --name=value choose a pokemon from a specific name
-s, --no-tab-spaces
do not replace tab characters (fastest)
-t, --tab-width=value
replace any tab characters with N spaces [4]
-u, --unicode-borders
use unicode characters to draw the border around the speech
box (and info box if --info-border is enabled)
-v, --verbose print verbose output
-W, --no-wrap disable text wrapping (fastest)
-w, --width=value the max speech bubble width [80]
```

---

## How it works
Expand Down Expand Up @@ -168,9 +201,10 @@ DEBUG=test go test -v ./test/
## TODO

- Short-term
- [ ] support long and short cli args (e.g. --name/-n)
- [ ] optionally print ID assigned to each pokemon, support deterministic selection via the same ID
- Longer-term
- In Beta
- [x] support long and short cli args (e.g. --name/-n)
- Completed
- [x] Make the category struct faster to load - currently takes up to 80% of the execution time
- [x] Store metadata and names in a more storage-efficient manner
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require (
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/pborman/getopt/v2 v2.1.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2Em
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/pborman/getopt/v2 v2.1.0 h1:eNfR+r+dWLdWmV8g5OlpyrTYHkhVNxHBdN2cCrJmOEA=
github.com/pborman/getopt/v2 v2.1.0/go.mod h1:4NtW75ny4eBw9fO1bhtNdYTlZKYX5/tBLtsOpwKIKd0=
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/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
Expand Down
55 changes: 37 additions & 18 deletions pokesay.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package main

import (
"embed"
"flag"
"fmt"
"strings"

"github.com/pborman/getopt/v2"
"github.com/tmck-code/pokesay/src/pokedex"
"github.com/tmck-code/pokesay/src/pokesay"
"github.com/tmck-code/pokesay/src/timer"
Expand All @@ -32,30 +32,35 @@ var (
)

func parseFlags() pokesay.Args {
// list operations
listCategories := flag.Bool("list-categories", false, "list all available categories")
listNames := flag.Bool("list-names", false, "list all available names")
help := getopt.BoolLong("help", 'h', "display this help message")
// print verbose output (currently timer output)
verbose := getopt.BoolLong("verbose", 'v', "print verbose output", "verbose")

// selection/filtering
category := flag.String("category", "", "choose a pokemon from a specific category")
name := flag.String("name", "", "choose a pokemon from a specific name")
width := flag.Int("width", 80, "the max speech bubble width")
name := getopt.StringLong("name", 'n', "", "choose a pokemon from a specific name")
category := getopt.StringLong("category", 'c', "", "choose a pokemon from a specific category")

// list operations
listNames := getopt.BoolLong("list-names", 'l', "list all available names")
listCategories := getopt.BoolLong("list-categories", 'L', "list all available categories")

width := getopt.IntLong("width", 'w', 80, "the max speech bubble width")

// speech bubble options
noWrap := flag.Bool("no-wrap", false, "disable text wrapping (fastest)")
tabWidth := flag.Int("tab-width", 4, "replace any tab characters with N spaces")
noTabSpaces := flag.Bool("no-tab-spaces", false, "do not replace tab characters (fastest)")
fastest := flag.Bool("fastest", false, "run with the fastest possible configuration (-nowrap -notabspaces)")
tabWidth := getopt.IntLong("tab-width", 't', 4, "replace any tab characters with N spaces")
noWrap := getopt.BoolLong("no-wrap", 'W', "disable text wrapping (fastest)")
noTabSpaces := getopt.BoolLong("no-tab-spaces", 's', "do not replace tab characters (fastest)")
fastest := getopt.BoolLong("fastest", 'f', "run with the fastest possible configuration (--nowrap & --notabspaces)")

// info box options
japaneseName := flag.Bool("japanese-name", false, "print the japanese name")
noCategoryInfo := flag.Bool("no-category-info", false, "do not print pokemon categories")
drawInfoBorder := flag.Bool("info-border", false, "draw a border around the info line")
japaneseName := getopt.BoolLong("japanese-name", 'j', "print the japanese name in the info box")
noCategoryInfo := getopt.BoolLong("no-category-info", 'C', "do not print pokemon category information in the info box")
drawInfoBorder := getopt.BoolLong("info-border", 'b', "draw a border around the info box")

// other option
unicodeBorders := flag.Bool("unicode-borders", false, "use unicode characters to draw the border around the speech box (and info box if -info-border is enabled)")
unicodeBorders := getopt.BoolLong("unicode-borders", 'u', "use unicode characters to draw the border around the speech box (and info box if --info-border is enabled)")

flag.Parse()
getopt.Parse()
var args pokesay.Args

if *fastest {
Expand All @@ -65,6 +70,8 @@ func parseFlags() pokesay.Args {
TabSpaces: " ",
NoTabSpaces: true,
BoxCharacters: pokesay.DetermineBoxCharacters(false),
Help: *help,
Verbose: *verbose,
}
} else {
args = pokesay.Args{
Expand All @@ -80,6 +87,8 @@ func parseFlags() pokesay.Args {
JapaneseName: *japaneseName,
BoxCharacters: pokesay.DetermineBoxCharacters(*unicodeBorders),
DrawInfoBorder: *drawInfoBorder,
Help: *help,
Verbose: *verbose,
}
}
return args
Expand Down Expand Up @@ -115,7 +124,7 @@ func runPrintByName(args pokesay.Args) {
t.Mark("read name struct")

metadata, final := pokesay.ChooseByName(names, args.NameToken, GOBCowNames, MetadataRoot)
t.Mark("find and read metadata")
t.Mark("find/read metadata")

pokesay.Print(args, final.EntryIndex, GenerateNames(metadata, args), final.Categories, GOBCowData)
t.Mark("print")
Expand Down Expand Up @@ -145,7 +154,7 @@ func runPrintByNameAndCategory(args pokesay.Args) {
t.Mark("read name struct")

metadata, final := pokesay.ChooseByNameAndCategory(names, args.NameToken, GOBCowNames, MetadataRoot, args.Category)
t.Mark("find and read metadata")
t.Mark("find/read metadata")

pokesay.Print(args, final.EntryIndex, GenerateNames(metadata, args), final.Categories, GOBCowData)
t.Mark("print")
Expand Down Expand Up @@ -173,6 +182,16 @@ func runPrintRandom(args pokesay.Args) {

func main() {
args := parseFlags()
// if the -h/--help flag is set, print usage and exit
if args.Help {
getopt.Usage()
return
}
if args.Verbose {
fmt.Println("Verbose output enabled")
timer.DEBUG = true
}

t := timer.NewTimer("main", true)

if args.ListCategories {
Expand Down
2 changes: 2 additions & 0 deletions src/pokesay/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type Args struct {
JapaneseName bool
BoxCharacters *BoxCharacters
DrawInfoBorder bool
Help bool
Verbose bool
}

var (
Expand Down
8 changes: 4 additions & 4 deletions src/timer/timer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ type Timer struct {
Enabled bool
}

func NewTimer(name string, alignKeys ...bool) *Timer {
func NewTimer(name string, boolArgs ...bool) *Timer {
align := false
if len(alignKeys) == 1 {
align = alignKeys[0]
if len(boolArgs) == 1 {
align = boolArgs[0]
}
t := &Timer{
Name: name,
Expand All @@ -48,7 +48,7 @@ func (t *Timer) Mark(stage string) {
}
now := time.Now()
if t.AlignKeys {
stage = fmt.Sprintf("%02d.%-15s", len(t.stageNames), stage)
stage = fmt.Sprintf("%02d.%-20s", len(t.stageNames), stage)
} else {
stage = fmt.Sprintf("%02d.%s", len(t.stageNames), stage)
}
Expand Down
Loading