mattermost-community-enterp.../vendor/github.com/isacikgoz/prompt/term/bufferedwriter.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
Full Mattermost server source with integrated Community Enterprise features.
Includes vendor directory for offline/air-gapped builds.

Structure:
- enterprise-impl/: Enterprise feature implementations
- enterprise-community/: Init files that register implementations
- enterprise/: Bridge imports (community_imports.go)
- vendor/: All dependencies for offline builds

Build (online):
  go build ./cmd/mattermost

Build (offline/air-gapped):
  go build -mod=vendor ./cmd/mattermost

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 23:59:07 +09:00

189 lines
3.9 KiB
Go

// Package term is influenced by https://github.com/AlecAivazis/survey and
// https://github.com/manifoldco/promptui it might contain some code snippets from those
// A little copying is better than a little dependency. - Go proverbs.
package term
import (
"bytes"
"fmt"
"io"
"github.com/fatih/color"
)
// BufferedWriter creates, clears and, moves up or down lines as needed to write
// the output to the terminal using ANSI escape codes.
type BufferedWriter struct {
w io.Writer
buf *bytes.Buffer
lineWrap bool
reset bool
flush bool
cursor int
height int
}
// NewBufferedWriter creates and initializes a new BufferedWriter.
func NewBufferedWriter(w io.Writer) *BufferedWriter {
return &BufferedWriter{buf: &bytes.Buffer{}, w: w}
}
// Reset truncates the underlining buffer and marks all its previous lines to be
// cleared during the next Write.
func (b *BufferedWriter) Reset() {
b.buf.Reset()
b.reset = true
}
// Write writes a single line to the underlining buffer.
func (b *BufferedWriter) Write(bites []byte) (int, error) {
if bytes.ContainsAny(bites, "\r\n") {
return 0, fmt.Errorf("%q should not contain either \\r or \\n", bites)
}
if !b.lineWrap {
b.buf.Write([]byte(lwoff))
defer b.buf.Write([]byte(lwon))
}
if b.reset {
for i := 0; i < b.height; i++ {
_, err := b.buf.Write(moveUp)
if err != nil {
return 0, err
}
_, err = b.buf.Write(clearLine)
if err != nil {
return 0, err
}
}
b.cursor = 0
b.height = 0
b.reset = false
}
switch {
case b.cursor == b.height:
n, err := b.buf.Write(clearLine)
if err != nil {
return n, err
}
line := append(bites, []byte("\n")...)
n, err = b.buf.Write(line)
if err != nil {
return n, err
}
b.height++
b.cursor++
return n, nil
case b.cursor < b.height:
n, err := b.buf.Write(clearLine)
if err != nil {
return n, err
}
n, err = b.buf.Write(bites)
if err != nil {
return n, err
}
n, err = b.buf.Write(moveDown)
if err != nil {
return n, err
}
b.cursor++
return n, nil
default:
return 0, fmt.Errorf("Invalid write cursor position (%d) exceeded line height: %d", b.cursor, b.height)
}
}
// WriteCells add colored text to the inner buffer
func (b *BufferedWriter) WriteCells(cs []Cell) (int, error) {
bs := make([]byte, 0)
if colored {
for _, c := range cs {
paint := color.New(c.Attr...)
painted := paint.Sprintf(string(c.Ch))
bs = append(bs, []byte(painted)...)
}
} else {
for _, c := range cs {
bs = append(bs, []byte(string(c.Ch))...)
}
}
return b.Write(bs)
}
// Flush writes any buffered data to the underlying io.Writer, ensuring that any pending data is displayed.
func (b *BufferedWriter) Flush() error {
for i := b.cursor; i < b.height; i++ {
if i < b.height {
_, err := b.buf.Write(clearLine)
if err != nil {
return err
}
}
_, err := b.buf.Write(moveDown)
if err != nil {
return err
}
}
_, err := b.buf.WriteTo(b.w)
if err != nil {
return err
}
b.buf.Reset()
// reset cursor position
b.buf.Write(clearLine)
_, err = b.buf.WriteTo(b.w)
if err != nil {
return err
}
b.buf.Reset()
for i := 0; i < b.height; i++ {
_, err := b.buf.Write(moveUp)
if err != nil {
return err
}
}
b.cursor = 0
return nil
}
// ClearScreen solves problems (R) and use it after Reset()
func (b *BufferedWriter) ClearScreen() error {
for i := 0; i < b.height; i++ {
_, err := b.buf.Write(moveUp)
if err != nil {
return err
}
_, err = b.buf.Write(clearLine)
if err != nil {
return err
}
}
b.cursor = 0
b.height = 0
b.reset = false
_, err := b.buf.WriteTo(b.w)
if err != nil {
return err
}
b.buf.Reset()
return nil
}
// ShowCursor writes to os.Stdout that to show cursor
func (b *BufferedWriter) ShowCursor() {
b.w.Write([]byte(showCursor))
}
// HideCursor writes to os.Stdout that to hide cursor
func (b *BufferedWriter) HideCursor() {
b.w.Write([]byte(hideCursor))
}