Skip to content

Commit

Permalink
feat: add display decorator (#11)
Browse files Browse the repository at this point in the history
* add display decorator

* rename decorator name

* add header

* update type

* add tests and uses cobra stdout and err

* add header

* update description
  • Loading branch information
raulb authored Jan 27, 2025
1 parent 2097505 commit 964e246
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 0 deletions.
32 changes: 32 additions & 0 deletions decorators.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import (

var DefaultDecorators = []Decorator{
CommandWithLoggerDecorator{},
CommandWithOutputDecorator{},

CommandWithAliasesDecorator{},
CommandWithFlagsDecorator{},

Expand Down Expand Up @@ -81,6 +83,36 @@ func (d CommandWithLoggerDecorator) Decorate(_ *Ecdysis, _ *cobra.Command, c Com
return nil
}

// -- OUTPUT -------------------------------------------------------------------

// CommandWithOutput can be implemented by a command to provide its own stdout and stderr.
type CommandWithOutput interface {
Command
Output(output Output)
}

// CommandWithOutputDecorator is a decorator that provides a Stdout to the command.
// If the Stdout field is not set, the default stdout will be provided.
type CommandWithOutputDecorator struct {
Output Output
}

// Decorate provides the logger to the command.
func (d CommandWithOutputDecorator) Decorate(_ *Ecdysis, cmd *cobra.Command, c Command) error {
v, ok := c.(CommandWithOutput)
if !ok {
return nil
}

if d.Output == nil {
v.Output(NewDefaultOutput(cmd))
} else {
v.Output(d.Output)
}

return nil
}

// -- ALIASES ------------------------------------------------------------------

// CommandWithAliases can be implemented by a command to provide aliases.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.23.0

require (
github.com/google/go-cmp v0.6.0
github.com/matryer/is v1.4.1
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.19.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ=
github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
Expand Down
59 changes: 59 additions & 0 deletions output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright © 2025 Meroxa, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ecdysis

import (
"fmt"
"io"

"github.com/spf13/cobra"
)

type Output interface {
Stdout(any)
Stderr(any)
}

type DefaultOutput struct {
stdout io.Writer
stderr io.Writer
}

func NewDefaultOutput(cmd *cobra.Command) *DefaultOutput {
return &DefaultOutput{
stdout: cmd.OutOrStdout(),
stderr: cmd.OutOrStderr(),
}
}

// Stdout writes a message to the configured standard output.
func (d *DefaultOutput) Stdout(msg any) {
fmt.Fprint(d.stdout, msg)
}

// Stderr writes a message to the configured standard error.
func (d *DefaultOutput) Stderr(msg any) {
fmt.Fprint(d.stderr, msg)
}

// Output allows overwriting the stdout and/or stderr for specific use cases (like testing).
func (d *DefaultOutput) Output(stdout, stderr io.Writer) {
if stdout != nil {
d.stdout = stdout
}
if stderr != nil {
d.stderr = stderr
}
}
73 changes: 73 additions & 0 deletions output_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright © 2025 Meroxa, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ecdysis

import (
"bytes"
"testing"

"github.com/matryer/is"
"github.com/spf13/cobra"
)

func TestNewDefaultOutput(t *testing.T) {
is := is.New(t)
cmd := &cobra.Command{}
out := NewDefaultOutput(cmd)

is.Equal(out.stdout, cmd.OutOrStdout())
is.Equal(out.stderr, cmd.OutOrStderr())
}

func TestStdout(t *testing.T) {
is := is.New(t)

var buf bytes.Buffer
out := &DefaultOutput{stdout: &buf}

message := "hello stdout"
out.Stdout(message)

is.Equal(buf.String(), message)
}

func TestStderr(t *testing.T) {
is := is.New(t)

var buf bytes.Buffer
out := &DefaultOutput{stderr: &buf}

message := "hello stderr"
out.Stderr(message)

is.Equal(buf.String(), message)
}

func TestOutput(t *testing.T) {
is := is.New(t)

var stdoutBuf, stderrBuf bytes.Buffer
out := &DefaultOutput{}

out.Output(&stdoutBuf, &stderrBuf)

stdoutMsg := "stdout test"
stderrMsg := "stderr test"
out.Stdout(stdoutMsg)
out.Stderr(stderrMsg)

is.Equal(stdoutMsg, stdoutBuf.String())
is.Equal(stderrMsg, stderrBuf.String())
}

0 comments on commit 964e246

Please sign in to comment.