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

Extend nib API to allow reuse of underlying writer #22

Merged
merged 1 commit into from
Oct 31, 2020
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
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The [`nib.Nib` interface][go-pkg-type-svengreb/nib#nib] consists of six function
- `Infof(format string, args ...interface{})` — writes a message with `info` verbosity level for the given format and arguments.
- `Successf(format string, args ...interface{})` — writes a message with `success` verbosity level for the given format and arguments.
- `Warnf(format string, args ...interface{})` — writes a message with `warn` verbosity level for the given format and arguments.
- `Writer() io.Writer` — returns the underlying [`io.Writer`][go-doc-type-io#writer].

The [`pencil` package][go-pkg-svengreb/nib/pencil] implements this interface including [features like custom prefixes and verbosity level icons](#features).
The [`inkpen` package][go-pkg-svengreb/nib/inkpen] composes [`pencil.Pencil`][go-pkg-type-svengreb/nib/pencil#pencil] and additionally [comes with additional features like colored output including automatic TTY and cross-platform terminal color support detection](#features).
Expand Down Expand Up @@ -276,6 +277,8 @@ func main() {
}
```

<!--lint enable no-tabs-->

### Prefixes

By default only the verbosity level icons are printed as prefix before the given message format and arguments.
Expand All @@ -302,6 +305,8 @@ func main() {
}
```

<!--lint enable no-tabs-->

### Writer

By default `pencil.Pencil` uses [`os.Stderr`][go-doc-os#pkg_vars] while `inkpen.Inkpen` uses `color.Output` which in turn is a exported variable that makes use of [github.com/mattn/go-colorable][mattn/go-colorable], a package for colored TTY output on multiple platforms.
Expand Down Expand Up @@ -332,6 +337,38 @@ func main() {

<!--lint enable no-tabs-->

<!--lint ignore no-duplicate-headings-->

## Writer

Both types [`pencil.Pencil`][go-pkg-type-svengreb/nib/pencil#pencil] and [`inkpen.Inkpen`][go-pkg-type-svengreb/nib/inkpen#inkpen] use recommended [`io.Writer`][go-doc-type-io#writer] by default to provide optimal compatibility for their specific features like colored output.
To allow to either reuse the default or configured `io.Writer` the `Writer() io.Writer` method of the `nib.Nib` API interface can be used:

<!--lint disable no-tabs-->

```go
package main

import (
"os"

"github.com/svengreb/nib/inkpen"
"github.com/svengreb/nib/pencil"
)

func main() {
// Create a new pencil...
pen := pencil.New(pencil.WithWriter(os.Stderr))
// ... or inkpen.
ink := inkpen.New()

_, _ = fmt.Fprintln(pen.Writer(), "Brazil nuts are also a delicious and healthy snack between meals")
_, _ = fmt.Fprintln(ink.Writer(), "Brazil nuts are also a delicious and healthy snack between meals")
}
```

<!--lint enable no-tabs-->

## Contributing

_nib_ is an open source project and contributions are always welcome!
Expand Down
10 changes: 7 additions & 3 deletions inkpen/inkpen.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,17 @@ func (i *Inkpen) formatMsg(v nib.Verbosity, format string, args ...interface{})
return msg
}

// writef writes to the underlying writer and ensures a trailing newline for the given format.
// writef writes to the underlying writer.
// If an error occurs while writing to the underlying io.Writer the message is printed to os.Stdout instead.
// When this also returns an error the error is written to os.Stderr instead.
func (i *Inkpen) writef(v nib.Verbosity, format string, args ...interface{}) {
if i.Enabled(v) {
msg := i.formatMsg(v, format, args...)

if _, err := fmt.Fprint(i.opts.pencilOpts.Writer, msg); err != nil {
_, _ = fmt.Fprint(os.Stderr, msg)
if _, err := fmt.Fprint(i.Pencil.Writer(), msg); err != nil {
if _, err = fmt.Fprint(os.Stdout, msg); err != nil {
_, _ = fmt.Fprint(os.Stderr, err)
}
}
}
}
4 changes: 4 additions & 0 deletions nib.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// This package represents the currently latest API v0.
package nib

import "io"

// Nib is a log-level based line printer for human-facing messages.
type Nib interface {
// Compile compiles a message for the verbosity level using the given format and arguments.
Expand All @@ -21,4 +23,6 @@ type Nib interface {
Successf(format string, args ...interface{})
// Warnf writes a message with nib.WarnVerbosity level for the given format and arguments.
Warnf(format string, args ...interface{})
// Writer returns the underlying io.Writer.
Writer() io.Writer
}
12 changes: 11 additions & 1 deletion pencil/pencil.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package pencil

import (
"fmt"
"io"
"os"
"strings"
"unicode"
Expand Down Expand Up @@ -76,6 +77,11 @@ func (p *Pencil) Warnf(format string, args ...interface{}) {
p.writef(nib.WarnVerbosity, format, args...)
}

// Writer returns the underlying io.Writer.
func (p *Pencil) Writer() io.Writer {
return p.opts.Writer
}

// formatMsg formats the message and ensures a trailing newline for the given format.
func (p *Pencil) formatMsg(v nib.Verbosity, format string, args ...interface{}) string {
if len(args) > 0 || !strings.HasSuffix(format, "\n") {
Expand All @@ -94,11 +100,15 @@ func (p *Pencil) formatMsg(v nib.Verbosity, format string, args ...interface{})
}

// writef writes to the underlying writer.
// If an error occurs while writing to the underlying io.Writer the message is printed to os.Stdout instead.
// When this also returns an error the error is written to os.Stderr instead.
func (p *Pencil) writef(v nib.Verbosity, format string, args ...interface{}) {
if p.Enabled(v) {
msg := p.formatMsg(v, format, args...)
if _, err := fmt.Fprint(p.opts.Writer, msg); err != nil {
_, _ = fmt.Fprint(os.Stderr, msg)
if _, err = fmt.Fprint(os.Stdout, msg); err != nil {
_, _ = fmt.Fprint(os.Stderr, err)
}
}
}
}