Skip to content
Open
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
2 changes: 1 addition & 1 deletion pkg/cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ func handleBuildsCreate(ctx context.Context, cmd *cli.Command) error {
Build: cbuild.NewModel(client, ctx, *build, cmd.String("branch"), downloadPaths),
WaitMode: waitMode,
})
model, err = tea.NewProgram(model).Run()
model, err = console.NewProgram(model).Run()
if err != nil {
console.Warn("%s", err.Error())
}
Expand Down
3 changes: 1 addition & 2 deletions pkg/cmd/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import (
"strings"
"time"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/huh"
"github.com/stainless-api/stainless-api-cli/pkg/components/build"
"github.com/stainless-api/stainless-api-cli/pkg/components/dev"
Expand Down Expand Up @@ -255,7 +254,7 @@ func runDevBuild(ctx context.Context, client stainless.Client, wc workspace.Conf
cmd.Bool("watch"),
)

p := tea.NewProgram(model)
p := console.NewProgram(model)
finalModel, err := p.Run()

if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions pkg/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/stainless-api/stainless-api-cli/pkg/workspace"
"github.com/stainless-api/stainless-api-go/option"

tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/huh"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/term"
Expand Down Expand Up @@ -426,7 +425,7 @@ func initializeWorkspace(ctx context.Context, cmd *cli.Command, client stainless
Build: cbuild.NewModel(client, ctx, *build, "main", downloadPaths),
}

_, err = tea.NewProgram(model).Run()
_, err = console.NewProgram(model).Run()
if err != nil {
console.Warn("%s", err.Error())
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/cmd/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/stainless-api/stainless-api-cli/pkg/components/build"
"github.com/stainless-api/stainless-api-cli/pkg/console"
"github.com/stainless-api/stainless-api-cli/pkg/workspace"
"github.com/stainless-api/stainless-api-go"
"github.com/urfave/cli/v3"
Expand Down Expand Up @@ -211,7 +212,7 @@ func runLinter(ctx context.Context, cmd *cli.Command, canSkip bool) error {
help: help.New(),
}

p := tea.NewProgram(m, tea.WithContext(ctx))
p := console.NewProgram(m, tea.WithContext(ctx))

// Start the diagnostics process
go func() {
Expand Down
19 changes: 18 additions & 1 deletion pkg/console/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,25 @@ import (
"github.com/charmbracelet/x/ansi"
"github.com/logrusorgru/aurora/v4"
"github.com/urfave/cli/v3"
"golang.org/x/term"
)

// NewProgram wraps tea.NewProgram with better handling for tty environments
func NewProgram(model tea.Model, opts ...tea.ProgramOption) *tea.Program {
// Always output to stderr, in case we want to also output JSON so that the json is redirectable e.g. to jq.
opts = append(opts, tea.WithOutput(os.Stderr))

// If not a TTY, use stdin and disable renderer
if !term.IsTerminal(int(os.Stderr.Fd())) {
opts = append(opts,
tea.WithInput(os.Stdin),
tea.WithoutRenderer(),
)
}
Comment on lines +20 to +29
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic is a bit suspicious to me. I think it would be helpful to expand on the comments here and/or rework the logic a bit.

Scenario 1: using the tool with no pipes -> output to stderr?
Scenario 2: using the tool and piping stdout somewhere -> output charm stuff to stderr?
Scenario 3: using the tool and piping stderr somewhere -> read from stdin, output charm stuff to stderr, and no charm rendering?

I would expect the logic to look more like:

if !isatty(stdout) { // stdout is being piped somewhere
  if isatty(stderr) { // stderr is still a tty, we can use that for TUI stuff
    // output = stderr
  } else { // no tty on either stdout/stderr, this would be the agent case
    // disable output, force stdin as input instead of tty input
  }
}


return tea.NewProgram(model, opts...)
}

// Group represents a nested logging group
type Group struct {
prefix string
Expand Down Expand Up @@ -255,7 +272,7 @@ func spinnerWithIndent(indent int, message string, operation func() error) error
execute: operation,
}

finalModel, err := tea.NewProgram(model).Run()
finalModel, err := NewProgram(model).Run()
if err != nil {
return err
}
Expand Down
Loading