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

Allow to use io.Writer instead of *os.File for NewColorable func #66

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

cardil
Copy link

@cardil cardil commented Feb 28, 2023

Fixes #65
Require mattn/go-isatty#81

Comment on lines +7 to +8
// FIXME: remove, after merge of https://github.com/mattn/go-isatty/pull/81
replace github.com/mattn/go-isatty => github.com/cardil/mattn-isatty v0.0.0-20230228121058-48002435730c
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this before merge

@dolmen
Copy link
Contributor

dolmen commented Mar 22, 2023

  1. This implementation breaks the existing API. go-colorable is a widely used module
  2. The proposed changes could be implemented in a package on top of go-colorable or as a simple function:
func setColorable(w io.Writer) io.Writer {
    if f, isFile := w.(*os.File); isFile {
        return colorable.NewColorable(f)
    }
    return w
}

So 👎

@cardil
Copy link
Author

cardil commented Apr 1, 2023

  1. This implementation breaks the existing API. go-colorable is a widely used module

Can you explain how it breaks the API? I'm changing here the parameter type from *os.File to io.Writer. The *os.File implements the io.Writer, so every instance of *os.File can be passed to the function that accepts io.Writer, so this widens the API, not breaks it.

@abhinav
Copy link

abhinav commented Apr 16, 2023

Hey @cardil, thanks for the PR and @dolmen, thanks for reviewing.
I'm a lurker who's interested in this PR, hoping to help with this discussion.

First, to answer your question @cardil: changing the function signature is a breaking change.
As an example, this will break all function references. For example, if I was previously doing this:

someFunc(colorable.NewColorable)

// where

func someFunc(newColorable func(*os.File) io.Writer) {
  // ...
}

That code will now stop compiling because newColorable's type won't match. (It's not uncommon to use function references like this to provide stubs from tests.)

@dolmen, unfortunately, that alternative won't suffice because it still requires a specific implementation (*os.File) and doesn't allow for file-like objects that expose their file descriptor, but aren't *os.Files. For example, if I wrote a wrapper around an os.File that modifies some of its reading/writing behavior (e.g. tracks total number of bytes written), I would be unable to use it with go-colorable. And on the cosmetic end, it's nicer to be able to write loosely coupled code: function foo takes an io.Writer and adds special behavior only if the underlying file descriptor (if any) happens to meet these conditions, and isn't required to be an os.File.


To do this in a backwards compatible manner, this needs to be a new function. As a suggestion, consider:

func NewColorableWriter(w io.Writer) io.Writer {
  // ...
}

This could be made easier by putting the existing NewColorable function into a regular file (not tagged with a platform-specific build tag), that just calls the individual platform-specific NewColorableWriter function. Roughly:

// colorable.go
func NewColorable(f *os.File) io.Writer {
  return NewColorableWriter(f)
}

// colorable_windows.go and colorable_others.go
func NewColorableWriter(w io.Writer) io.Writer {
  // ...
}

This change would be completely backwards-compatible and support this functionality on io.Writers.

What do you think, @cardil @dolmen?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow passing io.Writer instead of *os.File to the NewColorable func
3 participants