output

package
v2.20.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 9, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ErrCodeNotFound         = "not_found"
	ErrCodeAuthFailed       = "auth_failed"
	ErrCodeForbidden        = "forbidden"
	ErrCodeValidationFailed = "validation_failed"
	ErrCodeConflict         = "conflict"
	ErrCodeServerError      = "server_error"
	// ErrCodeJQFailed means the command itself succeeded (any write already
	// happened) but the --jq expression failed on its output. Exception:
	// with `api -i` on a 4xx/5xx response the filter ran on the error
	// response and the request itself did not succeed.
	ErrCodeJQFailed = "jq_failed"
	// ErrCodeJQInvalid means the --jq expression is empty or malformed; the
	// command did not run.
	ErrCodeJQInvalid = "jq_invalid"
	ErrCodeUnknown   = "unknown"
	// ErrCodeStatusNotApplied: Redmine accepted an issue update but silently
	// kept the old status (workflow, open subtasks, open blockers).
	ErrCodeStatusNotApplied = "status_not_applied"
	// ErrCodeParentNotApplied: Redmine saved a wiki page but silently kept
	// the old parent (missing rename_wiki_pages permission).
	ErrCodeParentNotApplied = "parent_not_applied"
	// ErrCodeProjectNotApplied: Redmine accepted an issue update but silently
	// kept the issue in its old project (no Add issues permission in the
	// target project).
	ErrCodeProjectNotApplied = "project_not_applied"
	// ErrCodeTimeout: a connection or request to the server timed out.
	ErrCodeTimeout = "timeout"
	// ErrCodeAlreadyExists: a download target exists and --clobber was not
	// given.
	ErrCodeAlreadyExists = "already_exists"
)

Error codes emitted in JSON error envelopes.

View Source
const (
	ActionCreated     = "created"
	ActionUpdated     = "updated"
	ActionDeleted     = "deleted"
	ActionClosed      = "closed"
	ActionReopened    = "reopened"
	ActionAssigned    = "assigned"
	ActionUnassigned  = "unassigned"
	ActionCommented   = "commented"
	ActionLogged      = "logged"
	ActionUserAdded   = "user_added"
	ActionUserRemoved = "user_removed"
	ActionLoggedIn    = "logged_in"
	ActionLoggedOut   = "logged_out"
	ActionSwitched    = "switched"
	ActionInstalled   = "installed"
	ActionOpened      = "opened"
	ActionUploaded    = "uploaded"
	ActionArchived    = "archived"
	ActionUnarchived  = "unarchived"
	ActionWatched     = "watched"
	ActionUnwatched   = "unwatched"
	ActionRelated     = "related"
	ActionUnrelated   = "unrelated"
)

Action actions exposed by no-body mutators. Keep the vocabulary small.

View Source
const (
	FormatTable = "table"
	FormatJSON  = "json"
)

Format constants for output modes.

View Source
const JQNoEnvVar = "REDMINE_JQ_NO_ENV"

JQNoEnvVar is the environment variable that, when set to a true value, hides the process environment from --jq expressions (`env` and `$ENV` evaluate to {}).

Variables

View Source
var (
	StyleNew        = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("10")))
	StyleInProgress = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("11")))
	StyleResolved   = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("12")))
	StyleClosed     = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("8")))
	StyleRejected   = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("9")))

	StyleHighPrio   = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true))
	StyleNormalPrio = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("7")))
	StyleLowPrio    = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("8")))

	StyleID      = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("6")).Bold(true))
	StyleHeader  = NewStyle(lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("15")))
	StyleLabel   = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("8")))
	StyleSuccess = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("10")))
	StyleError   = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("9")).Bold(true))
	StyleWarning = NewStyle(lipgloss.NewStyle().Foreground(lipgloss.Color("11")))
)

Functions

func IsTerminal

func IsTerminal() bool

IsTerminal checks if stdout is a terminal.

func RenderActionJSON

func RenderActionJSON(w io.Writer, env ActionEnvelope) error

RenderActionJSON writes an action envelope as pretty-printed JSON.

func RenderErrorJSON

func RenderErrorJSON(w io.Writer, env ErrorEnvelope) error

RenderErrorJSON writes an error envelope as a single line of compact JSON, so it can be picked out of stderr even when warnings or --verbose debug output precede it.

func RenderJSON

func RenderJSON(w io.Writer, v interface{}) error

RenderJSON renders a value as pretty-printed JSON to the writer.

func RenderTable

func RenderTable(w io.Writer, headers []string, rows [][]string, noColor bool)

RenderTable renders a table with headers and rows to the writer. Cells are sanitized with SanitizeTerminal unless they are the output of Style.Render.

func SanitizeStyled added in v2.15.0

func SanitizeStyled(s string) string

SanitizeStyled is SanitizeTerminal for text that already went through a renderer such as glamour: SGR sequences (ESC [ params m), which only set colors and text attributes, are kept; every other control character or escape sequence is neutralized like in SanitizeTerminal. Use it when the renderer can turn escaped input back into control characters, as Markdown does with character references like "".

func SanitizeTerminal added in v2.15.0

func SanitizeTerminal(s string) string

SanitizeTerminal neutralizes characters in untrusted text (anything that came from the Redmine server) that a terminal would interpret instead of display. It is applied to every human-readable output path; JSON, --jq results and raw response bodies are left untouched. See textsafe.Terminal for the rules.

func StartSpinner

func StartSpinner(msg string, isTTY bool) func()

StartSpinner starts a spinner with the given message and returns a stop function.

func SupportsWarnings

func SupportsWarnings(format string) bool

SupportsWarnings reports whether human-readable warnings should be emitted for the selected output format.

Types

type ActionEnvelope

type ActionEnvelope struct {
	Ok       bool   `json:"ok"`
	Action   string `json:"action"`
	Resource string `json:"resource"`
	ID       any    `json:"id,omitempty"`
	Message  string `json:"message,omitempty"`
}

ActionEnvelope is the JSON shape emitted by no-body mutators.

type ErrorDetail

type ErrorDetail struct {
	Message string   `json:"message"`
	Code    string   `json:"code,omitempty"`
	Details []string `json:"details,omitempty"`
	// Hint is a short, actionable next step (typically a command to run) to
	// recover from the failure. Omitted when there is nothing useful to add.
	Hint string `json:"hint,omitempty"`
}

ErrorDetail describes a failed command execution.

type ErrorEnvelope

type ErrorEnvelope struct {
	Error ErrorDetail `json:"error"`
}

ErrorEnvelope is the JSON shape written to stderr for command failures in JSON mode, as a single line that is always the last line of stderr. It is never filtered by --jq.

type JQCompileError added in v2.14.0

type JQCompileError struct {
	Err error
}

JQCompileError reports a --jq expression that is empty or does not parse or compile. It is raised before the command runs.

func (*JQCompileError) Error added in v2.14.0

func (e *JQCompileError) Error() string

func (*JQCompileError) Unwrap added in v2.14.0

func (e *JQCompileError) Unwrap() error

type JQFilter added in v2.14.0

type JQFilter struct {
	// contains filtered or unexported fields
}

JQFilter is a compiled --jq expression that is applied to every JSON document a command would otherwise print. String results are printed raw (without quotes), every other value is printed as JSON, and each result goes on its own line. On a terminal, raw strings are neutralized like other server text (see textsafe.Terminal); piped output is left untouched.

func CompileJQ added in v2.14.0

func CompileJQ(expr string) (*JQFilter, error)

CompileJQ parses and compiles a jq expression. Compiling up front lets callers reject a malformed expression before any API request is made. Failures are returned as *JQCompileError.

The expression can read the process environment through `env` and `$ENV` unless REDMINE_JQ_NO_ENV is set.

func (*JQFilter) Evaluate added in v2.14.0

func (q *JQFilter) Evaluate(w io.Writer, v any, terminal bool) error

Evaluate runs the filter against the JSON encoding of v and writes the results to w. The input is exactly the JSON that RenderJSON would print, so expressions can be written against the documented output shape.

terminal reports whether w is a terminal. If so, object and array results are pretty-printed and raw string results go through textsafe.Terminal, so server-controlled text (e.g. `--jq '.[0].subject'` or `@csv` output) can't emit escape sequences. Otherwise containers are written compactly, one per line, and strings are written byte for byte. Results are buffered so a runtime error leaves w untouched, unless the output grows past jqBufferLimit, in which case it is streamed. Filter failures are returned as *JQRuntimeError.

type JQRuntimeError added in v2.14.0

type JQRuntimeError struct {
	Err error
}

JQRuntimeError reports that a --jq expression failed while filtering the output of a command that itself completed successfully. Callers must not treat it as a failure of the underlying operation (e.g. a create that already happened).

func (*JQRuntimeError) Error added in v2.14.0

func (e *JQRuntimeError) Error() string

func (*JQRuntimeError) Unwrap added in v2.14.0

func (e *JQRuntimeError) Unwrap() error

type KeyValue

type KeyValue struct {
	Key   string
	Value string
}

KeyValue is a label-value pair for detail views.

type Printer

type Printer interface {
	Table(headers []string, rows [][]string)
	Detail(pairs []KeyValue)
	JSON(v interface{})
	Success(msg string)
	Error(msg string)
	Warning(msg string)
	// Outcome emits a completed command result. In JSON mode this writes a
	// stable envelope to stdout. In other modes it writes the human message to
	// stderr as either success or warning text.
	Outcome(ok bool, action, resource string, id any, humanMsg string)
	// Resource emits a resource body in JSON mode and a human success message
	// in other formats.
	Resource(v any, humanMsg string)
	// Action emits a completed-mutation result. In JSON mode this writes a
	// compact action envelope to stdout. In any other mode it writes the
	// human message to stderr via Success.
	Action(action, resource string, id any, humanMsg string)
	Spinner(msg string) func()
	Format() string
}

Printer handles all output rendering.

type StdPrinter

type StdPrinter struct {
	// contains filtered or unexported fields
}

StdPrinter is the standard implementation of Printer.

func NewStdPrinter

func NewStdPrinter(out, errOut io.Writer, isTTY, noColor bool, format string) *StdPrinter

NewStdPrinter creates a new StdPrinter.

func (*StdPrinter) Action

func (p *StdPrinter) Action(action, resource string, id any, humanMsg string)

func (*StdPrinter) Detail

func (p *StdPrinter) Detail(pairs []KeyValue)

func (*StdPrinter) Error

func (p *StdPrinter) Error(msg string)

func (*StdPrinter) Format

func (p *StdPrinter) Format() string

func (*StdPrinter) JSON

func (p *StdPrinter) JSON(v interface{})

func (*StdPrinter) Outcome

func (p *StdPrinter) Outcome(ok bool, action, resource string, id any, humanMsg string)

func (*StdPrinter) Resource

func (p *StdPrinter) Resource(v any, humanMsg string)

func (*StdPrinter) SetJQ added in v2.14.0

func (p *StdPrinter) SetJQ(q *JQFilter, onErr func(error))

SetJQ routes every JSON document this printer emits (resource bodies, lists, and action envelopes) through q. Printer methods have no error return, so runtime filter errors are handed to onErr instead.

func (*StdPrinter) Spinner

func (p *StdPrinter) Spinner(msg string) func()

func (*StdPrinter) Success

func (p *StdPrinter) Success(msg string)

func (*StdPrinter) Table

func (p *StdPrinter) Table(headers []string, rows [][]string)

func (*StdPrinter) Warning

func (p *StdPrinter) Warning(msg string)

type Style added in v2.15.0

type Style struct {
	lipgloss.Style
}

Style is a lipgloss style for rendering server data. Render sanitizes its input with SanitizeTerminal before applying the style, so escape sequences in the output only ever come from the style itself. The printer recognizes such output and keeps its styling, while neutralizing escape sequences in any other value.

func NewStyle added in v2.15.0

func NewStyle(s lipgloss.Style) Style

NewStyle wraps a lipgloss style.

func PriorityStyle

func PriorityStyle(name string) Style

PriorityStyle returns the appropriate style for a priority name.

func StatusStyle

func StatusStyle(name string) Style

StatusStyle returns the appropriate style for a status name.

func (Style) Render added in v2.15.0

func (s Style) Render(strs ...string) string

Render sanitizes strs and renders them with the style.

Use the result as a whole table cell or detail value. The printer keeps the styling only of strings that are exactly a Render result; anything built from one, such as Render(a) + " " + b or a fmt.Sprintf around it, is sanitized as a whole, which shows its escape sequences as text ("^[[31m"). Render the combined text in a single call instead.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
⌂ 换网址