Skip to content

Commit

Permalink
feat: update for 2024
Browse files Browse the repository at this point in the history
This contains a bunch of small updates and changes.

+ Add go.mod file
+ Add Makefile, linters, and GitHub action
+ Update LICENSE and README
+ Add TODO
+ Make some initial changes to the code
  • Loading branch information
telemachus committed Dec 30, 2024
1 parent 20be209 commit 50b97a6
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 144 deletions.
23 changes: 23 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: gitmirror test
on:
push:
pull_request:

jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- windows-latest
go: ['1.22', '1.23']
name: humane test (using go ${{ matrix.go }} on ${{ matrix.os }})
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- run: make test
78 changes: 78 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
linters-settings:
copyloopvar:
check-alias: true
errcheck:
check-type-assertions: true
check-blank: true
exclude-functions:
- fmt.Printf
- fmt.Println
- fmt.Fprintf
- fmt.Fprintln
- (*flag.FlagSet).Set
exhaustive:
default-signifies-exhaustive: true
goconst:
min-len: 2
min-occurrences: 3
gocritic:
disabled-checks:
- hugeParam
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
govet:
enable-all: true
shadow:
strict: true
nolintlint:
require-explanation: true
require-specific: true

linters:
disable-all: true
enable:
- bodyclose
- copyloopvar
- cyclop
- dogsled
- dupl
- errcheck
- errchkjson
- errname
- errorlint
- exhaustive
- goconst
- gocritic
- gosec
- gosimple
- govet
- ineffassign
- ireturn
- maintidx
- misspell
- nolintlint
- nakedret
- prealloc
- predeclared
- stylecheck
- thelper
- typecheck
- unconvert
- unparam
- unused
- whitespace

run:
concurrency: 8
issues-exit-code: 1
timeout: 30m
tests: true
allow-parallel-runners: false

issues:
exclude-dirs:
- internal
1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
Copyright (c) 2009 The Go Authors. All rights reserved.
Copyright (c) 2024 Peter Aronoff. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
Expand Down
39 changes: 39 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.DEFAULT_GOAL := test

fmt:
golangci-lint run --disable-all --no-config -Egofmt --fix
golangci-lint run --disable-all --no-config -Egofumpt --fix

lint: fmt
staticcheck ./...
revive -config revive.toml ./...
golangci-lint run

golangci: fmt
golangci-lint run

staticcheck: fmt
staticcheck ./...

revive: fmt
revive -config revive.toml ./...

test:
go test -shuffle on .

testv:
go test -shuffle on -v .

testr:
go test -race -shuffle on .

build: lint testr
go build .

install: build
go install .

clean:
go clean -i -r -cache

.PHONY: fmt lint build install test testv testr clean
86 changes: 49 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,54 +1,66 @@
# rsc.io/getopt
# getopt (forked from rsc.io/getopt)

[For full package documentation, see [https://godoc.org/rsc.io/getopt](https://godoc.org/rsc.io/getopt).]
## Note

package getopt // import "rsc.io/getopt"
This repository is a fork of [rsc's][rsc] [getopt][rgetopt]. I have
updated the code in various ways, and I will probably continue to do so. But
the core idea (and implementation) is his rather than mine. td;dr — credit where
credit is due, but all mistakes and bad ideas are my fault and not rsc's.

Package getopt parses command lines using [_getopt_(3)](http://man7.org/linux/man-pages/man3/getopt.3.html) syntax. It is a
replacement for `flag.Parse` but still expects flags themselves to be defined
in package flag.
[rsc]: https://github.com/rsc
[rgetopt]: https://github.com/rsc/getopt

Flags defined with one-letter names are available as short flags (invoked
using one dash, as in `-x`) and all flags are available as long flags (invoked
using two dashes, as in `--x` or `--xylophone`).
## Introduction

To use, define flags as usual with [package flag](https://godoc.org/flag). Then introduce any aliases
by calling `getopt.Alias`:
Package getopt parses command lines using [`getopt_(3)`][getopt3] syntax. It is
a replacement for [`FlagSet.Parse`][fs.Parse] but still expects flags themselves
to be defined in package `flag`.

getopt.Alias("v", "verbose")
[getopt3]: http://man7.org/linux/man-pages/man3/getopt.3.html
[fs.Parse]: https://pkg.go.dev/flag#FlagSet.Parse

Or call `getopt.Aliases` to define a list of aliases:
Flags defined with one-letter names are available as short flags (invoked using
one dash, as in `-x`) and all flags are available as long flags (invoked using
two dashes, as in `--x` or `--xylophone`).

getopt.Aliases(
"v", "verbose",
"x", "xylophone",
)
To use, define a [`FlagSet`][FlagSet] and flags as usual with [package
flag][flag]. Then introduce any aliases by calling `getopt.Alias`:

One name in each pair must already be defined in package flag (so either
"v" or "verbose", and also either "x" or "xylophone").
```go
type cfg struct {
quiet bool
verbose bool
}

Then parse the command-line:
func main() {
fs := getopt.NewFlagSet("awesome", flag.ContinueOnError)
cfg := &cfg{}

getopt.Parse()
fs.BoolVar(&cfg.quiet, "quiet", false, "Print only errors")
fs.BoolVar(&cfg.help, "v", false, "Print way too much")

If it encounters an error, `Parse` calls `flag.Usage` and then exits the
program.
getopt.Alias("v", "verbose")
getopt.Alias("q", "quiet")
}
```

When writing a custom `flag.Usage` function, call `getopt.PrintDefaults` instead
of `flag.PrintDefaults` to get a usage message that includes the
names of aliases in flag descriptions.
Or call `getopt.Aliases` to define a list of aliases:

At initialization time, package getopt installs a new `flag.Usage` that is the same
as the default `flag.Usage` except that it calls `getopt.PrintDefaults` instead
of `flag.PrintDefaults`.
```go
getopt.Aliases(
"q", "quiet",
"v", "verbose",
)
```

This package also defines a `FlagSet` wrapping the standard `flag.FlagSet`.
[FlagSet]: https://pkg.go.dev/flag#FlagSet
[flag]: https://godoc.org/flag

## Caveat
One name in each pair must already be defined in package `flag` (so either
"q" or "quiet", and also either "v" or "verbose").

In general Go flag parsing is preferred for new programs, because it is not
as pedantic about the number of dashes used to invoke a flag (you can write
`-verbose` or `--verbose` and the program does not care). This package is meant
to be used in situations where, for legacy reasons, it is important to use
exactly _getopt_(3) syntax, such as when rewriting in Go an existing tool that
already uses _getopt_(3).
Then parse the command-line using [`fs.Parse()`][fs.Parse].

When writing a custom `flag.Usage` function, call `getopt.PrintDefaults` instead
of `flag.PrintDefaults` to get a usage message that includes the names of
aliases in flag descriptions.
23 changes: 23 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# TODO

1. Improve and expand tests.
+ Use example tests or cmp to test usage output.
+ Add tests for defaults and isZero check.
+ Check coverage?
1. Change usage display to suit my preferences. Do not special case short
boolean flags; put usage on the same line as the flag. Use a tabwriter and
wrap text to some good default for terminals?
1. Use a generic isZero check rather than reflect?
1. Add `Subcommand` and `Subcommands` (similar to `Alias` and `Aliases`). These
would support display of subcommands in usage, but I do not want to handle
the overall parsing or running of subcommands (for now?). Users will
manually parse and run their subcommands.
1. Read both `flag` and `ff`. Decide how I want to implement both long and
short. Do I want to use something like `Alias` and the stdlib, or should
I do it from scratch. Also, think about how I want to implement help
displays and how much of the stdlib is worth carrying over. E.g., `Visit`
and `VisitAll`.
1. Demand that all flags implement an interface with two methods: `IsZero` and
`Default`? (Maybe call this a `Defaulter` interface?) This could get rid of
brittle, incomplete, `panic`-inducing, or `reflect`-requiring tests for
whether something is a zero value.
Loading

0 comments on commit 50b97a6

Please sign in to comment.