Skip to content

Commit e62c5ab

Browse files
authored
feat(cmd): add --exclude-dirs option (#101)
1 parent f8aab49 commit e62c5ab

File tree

5 files changed

+163
-8
lines changed

5 files changed

+163
-8
lines changed

README.md

+9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Flags:
4040
-c, --check Check the output to see if it matches the generated documentation. --output must be specified to use this.
4141
--config string File from which to load configuration (default: .gomarkdoc.yml)
4242
-e, --embed Embed documentation into existing markdown files if available, otherwise append to file.
43+
--exclude-dirs strings List of package directories to ignore when producing documentation.
4344
--footer string Additional content to inject at the end of each output file.
4445
--footer-file string File containing additional content to inject at the end of each output file.
4546
-f, --format string Format to use for writing output data. Valid options: github (default), azure-devops, plain (default "github")
@@ -68,6 +69,14 @@ gomarkdoc --output doc.md .
6869

6970
The gomarkdoc tool supports generating documentation for both local packages and remote ones. To specify a local package, start the name of the package with a period \(.\) or specify an absolute path on the filesystem. All other package signifiers are assumed to be remote packages. You may specify both local and remote packages in the same command invocation as separate arguments.
7071

72+
If you have a project with many packages but you want to skip documentation generation for some, you can use the \-\-exclude\-dirs option. This will remove any matching directories from the list of directories to process. Excluded directories are specified using the same pathing syntax as the packages to process. Multiple expressions may be comma\-separated or specified by using the \-\-exclude\-dirs flag multiple times.
73+
74+
For example, in this repository we generate documentation for the entire project while excluding our test packages by running:
75+
76+
```
77+
gomarkdoc --exclude-dirs ./testData/... ./...
78+
```
79+
7180
### Output Redirection
7281

7382
By default, the documentation generated by the gomarkdoc command is sent to standard output, where it can be redirected to a file. This can be useful if you want to perform additional modifications to the documentation or send it somewhere other than a file. However, keep in mind that there are some inconsistencies in how various shells/platforms handle redirected command output \(for example, Powershell encodes in UTF\-16, not UTF\-8\). As a result, the \-\-output option described below is recommended for most use cases.

cmd/gomarkdoc/command.go

+53-1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type commandOptions struct {
5252
footerFile string
5353
format string
5454
tags []string
55+
excludeDirs []string
5556
templateOverrides map[string]string
5657
templateFileOverrides map[string]string
5758
verbosity int
@@ -96,6 +97,7 @@ func buildCommand() *cobra.Command {
9697
opts.footer = viper.GetString("footer")
9798
opts.footerFile = viper.GetString("footerFile")
9899
opts.tags = viper.GetStringSlice("tags")
100+
opts.excludeDirs = viper.GetStringSlice("excludeDirs")
99101
opts.repository.Remote = viper.GetString("repository.url")
100102
opts.repository.DefaultBranch = viper.GetString("repository.defaultBranch")
101103
opts.repository.PathFromRoot = viper.GetString("repository.path")
@@ -197,6 +199,12 @@ func buildCommand() *cobra.Command {
197199
defaultTags(),
198200
"Set of build tags to apply when choosing which files to include for documentation generation.",
199201
)
202+
command.Flags().StringSliceVar(
203+
&opts.excludeDirs,
204+
"exclude-dirs",
205+
nil,
206+
"List of package directories to ignore when producing documentation.",
207+
)
200208
command.Flags().CountVarP(
201209
&opts.verbosity,
202210
"verbose",
@@ -241,6 +249,7 @@ func buildCommand() *cobra.Command {
241249
_ = viper.BindPFlag("footer", command.Flags().Lookup("footer"))
242250
_ = viper.BindPFlag("footerFile", command.Flags().Lookup("footer-file"))
243251
_ = viper.BindPFlag("tags", command.Flags().Lookup("tags"))
252+
_ = viper.BindPFlag("excludeDirs", command.Flags().Lookup("exclude-dirs"))
244253
_ = viper.BindPFlag("repository.url", command.Flags().Lookup("repository.url"))
245254
_ = viper.BindPFlag("repository.defaultBranch", command.Flags().Lookup("repository.default-branch"))
246255
_ = viper.BindPFlag("repository.path", command.Flags().Lookup("repository.path"))
@@ -294,6 +303,13 @@ func runCommand(paths []string, opts commandOptions) error {
294303

295304
specs := getSpecs(paths...)
296305

306+
excluded := getSpecs(opts.excludeDirs...)
307+
if err := validateExcludes(excluded); err != nil {
308+
return err
309+
}
310+
311+
specs = removeExcludes(specs, excluded)
312+
297313
if err := resolveOutput(specs, outputTmpl); err != nil {
298314
return err
299315
}
@@ -565,13 +581,49 @@ func isIgnoredDir(dirname string) bool {
565581
return false
566582
}
567583

584+
// validateExcludes checks that the exclude dirs are all directories, not
585+
// packages.
586+
func validateExcludes(specs []*PackageSpec) error {
587+
for _, s := range specs {
588+
if !s.isLocal {
589+
return fmt.Errorf("gomarkdoc: invalid directory specified as an exclude directory: %s", s.ImportPath)
590+
}
591+
}
592+
593+
return nil
594+
}
595+
596+
// removeExcludes removes any package specs that were specified as excluded.
597+
func removeExcludes(specs []*PackageSpec, excludes []*PackageSpec) []*PackageSpec {
598+
out := make([]*PackageSpec, 0, len(specs))
599+
for _, s := range specs {
600+
var exclude bool
601+
for _, e := range excludes {
602+
if !s.isLocal || !e.isLocal {
603+
continue
604+
}
605+
606+
if r, err := filepath.Rel(s.Dir, e.Dir); err == nil && r == "." {
607+
exclude = true
608+
break
609+
}
610+
}
611+
612+
if !exclude {
613+
out = append(out, s)
614+
}
615+
}
616+
617+
return out
618+
}
619+
568620
const (
569621
cwdPathPrefix = "." + string(os.PathSeparator)
570622
parentPathPrefix = ".." + string(os.PathSeparator)
571623
)
572624

573625
func isLocalPath(path string) bool {
574-
return strings.HasPrefix(path, cwdPathPrefix) || strings.HasPrefix(path, parentPathPrefix) || filepath.IsAbs(path)
626+
return strings.HasPrefix(path, ".") || strings.HasPrefix(path, parentPathPrefix) || filepath.IsAbs(path)
575627
}
576628

577629
func compare(r1, r2 io.Reader) (bool, error) {

doc.go

+13
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
// -c, --check Check the output to see if it matches the generated documentation. --output must be specified to use this.
2929
// --config string File from which to load configuration (default: .gomarkdoc.yml)
3030
// -e, --embed Embed documentation into existing markdown files if available, otherwise append to file.
31+
// --exclude-dirs strings List of package directories to ignore when producing documentation.
3132
// --footer string Additional content to inject at the end of each output file.
3233
// --footer-file string File containing additional content to inject at the end of each output file.
3334
// -f, --format string Format to use for writing output data. Valid options: github (default), azure-devops, plain (default "github")
@@ -61,6 +62,18 @@
6162
// local and remote packages in the same command invocation as separate
6263
// arguments.
6364
//
65+
// If you have a project with many packages but you want to skip documentation
66+
// generation for some, you can use the --exclude-dirs option. This will remove
67+
// any matching directories from the list of directories to process. Excluded
68+
// directories are specified using the same pathing syntax as the packages to
69+
// process. Multiple expressions may be comma-separated or specified by using
70+
// the --exclude-dirs flag multiple times.
71+
//
72+
// For example, in this repository we generate documentation for the entire
73+
// project while excluding our test packages by running:
74+
//
75+
// gomarkdoc --exclude-dirs ./testData/... ./...
76+
//
6477
// # Output Redirection
6578
//
6679
// By default, the documentation generated by the gomarkdoc command is sent to

logger/README.md

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
2+
3+
# logger
4+
5+
```go
6+
import "github.com/princjef/gomarkdoc/logger"
7+
```
8+
9+
Package logger provides a simple console logger for reporting information about execution to stderr.
10+
11+
## Index
12+
13+
- [type Level](<#Level>)
14+
- [type Logger](<#Logger>)
15+
- [func New\(level Level, opts ...Option\) Logger](<#New>)
16+
- [type Option](<#Option>)
17+
- [func WithField\(key string, value interface\{\}\) Option](<#WithField>)
18+
19+
20+
<a name="Level"></a>
21+
## type [Level](<https://github.com/princjef/gomarkdoc/blob/master/logger/logger.go#L24>)
22+
23+
Level defines valid logging levels for a Logger.
24+
25+
```go
26+
type Level int
27+
```
28+
29+
<a name="DebugLevel"></a>Valid logging levels
30+
31+
```go
32+
const (
33+
DebugLevel Level = iota + 1
34+
InfoLevel
35+
WarnLevel
36+
ErrorLevel
37+
)
38+
```
39+
40+
<a name="Logger"></a>
41+
## type [Logger](<https://github.com/princjef/gomarkdoc/blob/master/logger/logger.go#L12-L21>)
42+
43+
Logger provides basic logging capabilities at different logging levels.
44+
45+
```go
46+
type Logger interface {
47+
Debug(a ...interface{})
48+
Debugf(format string, a ...interface{})
49+
Info(a ...interface{})
50+
Infof(format string, a ...interface{})
51+
Warn(a ...interface{})
52+
Warnf(format string, a ...interface{})
53+
Error(a ...interface{})
54+
Errorf(format string, a ...interface{})
55+
}
56+
```
57+
58+
<a name="New"></a>
59+
### func [New](<https://github.com/princjef/gomarkdoc/blob/master/logger/logger.go#L44>)
60+
61+
```go
62+
func New(level Level, opts ...Option) Logger
63+
```
64+
65+
New initializes a new Logger.
66+
67+
<a name="Option"></a>
68+
## type [Option](<https://github.com/princjef/gomarkdoc/blob/master/logger/logger.go#L27>)
69+
70+
Option defines an option for configuring the logger.
71+
72+
```go
73+
type Option func(opts *options)
74+
```
75+
76+
<a name="WithField"></a>
77+
### func [WithField](<https://github.com/princjef/gomarkdoc/blob/master/logger/logger.go#L83>)
78+
79+
```go
80+
func WithField(key string, value interface{}) Option
81+
```
82+
83+
WithField sets the provided key/value pair for use on all logs.
84+
85+
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

magefile.go

+3-7
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func Lint() error {
2222
return err
2323
}
2424

25-
return linter.Command(`run`).Run()
25+
return linter.Command(`run --timeout 5m`).Run()
2626
}
2727

2828
func Generate() error {
@@ -36,18 +36,14 @@ func Build() error {
3636
func Doc() error {
3737
return shellcmd.RunAll(
3838
`go run ./cmd/gomarkdoc .`,
39-
`go run ./cmd/gomarkdoc --header "" ./lang/...`,
40-
`go run ./cmd/gomarkdoc --header "" ./format/...`,
41-
`go run ./cmd/gomarkdoc --header "" ./cmd/...`,
39+
`go run ./cmd/gomarkdoc --header "" --exclude-dirs . --exclude-dirs ./testData/... ./...`,
4240
)
4341
}
4442

4543
func DocVerify() error {
4644
return shellcmd.RunAll(
4745
`go run ./cmd/gomarkdoc -c .`,
48-
`go run ./cmd/gomarkdoc -c --header "" ./lang/...`,
49-
`go run ./cmd/gomarkdoc -c --header "" ./format/...`,
50-
`go run ./cmd/gomarkdoc -c --header "" ./cmd/...`,
46+
`go run ./cmd/gomarkdoc -c --header "" --exclude-dirs . --exclude-dirs ./testData/... ./...`,
5147
)
5248
}
5349

0 commit comments

Comments
 (0)