Skip to content

Commit

Permalink
feat: synchronized output
Browse files Browse the repository at this point in the history
  • Loading branch information
nervo committed May 29, 2024
1 parent 2ac3642 commit 1f323a0
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 0 deletions.
1 change: 1 addition & 0 deletions nil_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ func (n nilRenderer) enableMouseSGRMode() {}
func (n nilRenderer) disableMouseSGRMode() {}
func (n nilRenderer) bracketedPasteActive() bool { return false }
func (n nilRenderer) setWindowTitle(_ string) {}
func (n nilRenderer) enableSynchronizedOutput() {}
3 changes: 3 additions & 0 deletions renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ type renderer interface {

// setWindowTitle sets the terminal window title.
setWindowTitle(string)

// enableSynchronizedOutput enables synchronized output.
enableSynchronizedOutput()
}

// repaintMsg forces a full repaint.
Expand Down
21 changes: 21 additions & 0 deletions standard_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ type standardRenderer struct {
// whether or not we're currently using bracketed paste
bpActive bool

// whether or not we're currently using synchronized output
soActive bool

// renderer dimensions; usually the size of the window
width int
height int
Expand Down Expand Up @@ -274,7 +277,18 @@ func (r *standardRenderer) flush() {
buf.WriteString(ansi.CursorLeft(r.width))
}

// Enable synchronized output
if r.soActive {
_, _ = io.WriteString(r.out, ansi.EnableSyncdOutput)
}

_, _ = r.out.Write(buf.Bytes())

// Disable synchronized output
if r.soActive {
_, _ = io.WriteString(r.out, ansi.DisableSyncdOutput)
}

r.lastRender = r.buf.String()
r.buf.Reset()
}
Expand Down Expand Up @@ -459,6 +473,13 @@ func (r *standardRenderer) setWindowTitle(title string) {
r.execute(ansi.SetWindowTitle(title))
}

func (r *standardRenderer) enableSynchronizedOutput() {
r.mtx.Lock()
defer r.mtx.Unlock()

r.bpActive = true
}

// setIgnoredLines specifies lines not to be touched by the standard Bubble Tea
// renderer.
func (r *standardRenderer) setIgnoredLines(from int, to int) {
Expand Down
16 changes: 16 additions & 0 deletions tea.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ import (
"context"
"errors"
"fmt"
"github.com/charmbracelet/x/ansi"
"github.com/charmbracelet/x/input"
"io"
"os"
"os/signal"
"runtime/debug"
"sync"
"sync/atomic"
"syscall"
"time"

"github.com/charmbracelet/x/term"
"github.com/muesli/cancelreader"
Expand Down Expand Up @@ -489,6 +492,19 @@ func (p *Program) Run() (Model, error) {
return p.initialModel, err
}

// See: https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036
_ = term.QueryTerminal(p.input, p.output, time.Millisecond*100, func(events []input.Event) bool {
for _, e := range events {
switch event := e.(type) {
case input.ReportModeEvent:
if event.Mode == 2026 && (event.Value == 2 || event.Value == 4) {
p.renderer.enableSynchronizedOutput()
}
}
}
return true
}, ansi.RequestSyncdOutput)

// Honor program startup options.
if p.startupOptions&withAltScreen != 0 {
p.renderer.enterAltScreen()
Expand Down

0 comments on commit 1f323a0

Please sign in to comment.