File tree Expand file tree Collapse file tree 3 files changed +89
-0
lines changed
Expand file tree Collapse file tree 3 files changed +89
-0
lines changed Original file line number Diff line number Diff line change @@ -19,6 +19,9 @@ type Terminal interface {
1919 // buffer empties. State is locked as soon as first rune is read, and unlocked
2020 // when buffer is empty.
2121 Parse (bf * bufio.Reader ) error
22+
23+ // WriteWithChanges writes terminal changes to state and returns the line numbers that changed.
24+ WriteWithChanges (p []byte ) ([]int , error )
2225}
2326
2427// View represents the view of the virtual terminal emulator.
Original file line number Diff line number Diff line change @@ -56,6 +56,36 @@ func (t *terminal) Write(p []byte) (int, error) {
5656 return written , nil
5757}
5858
59+ // WriteWithChanges writes to the terminal state and returns the line numbers that changed.
60+ func (t * terminal ) WriteWithChanges (p []byte ) ([]int , error ) {
61+ var dirtyLines = make (map [int ]bool )
62+ var written int
63+ r := bytes .NewReader (p )
64+ t .lock ()
65+ defer t .unlock ()
66+ for {
67+ c , sz , err := r .ReadRune ()
68+ if err != nil {
69+ if err == io .EOF {
70+ break
71+ }
72+ return nil , err
73+ }
74+ written += sz
75+ if c == unicode .ReplacementChar && sz == 1 {
76+ if r .Len () == 0 {
77+ // not enough bytes for a full rune
78+ return nil , nil
79+ }
80+ t .logln ("invalid utf8 sequence" )
81+ continue
82+ }
83+ t .put (c )
84+ dirtyLines [t .cur .Y ] = true
85+ }
86+ return uniqueSorted (dirtyLines ), nil
87+ }
88+
5989// TODO: add tests for expected blocking behavior
6090func (t * terminal ) Parse (br * bufio.Reader ) error {
6191 var locked bool
Original file line number Diff line number Diff line change 66 "bufio"
77 "bytes"
88 "io"
9+ "slices"
910 "unicode"
1011 "unicode/utf8"
1112)
@@ -57,6 +58,61 @@ func (t *terminal) Write(p []byte) (int, error) {
5758 return written , nil
5859}
5960
61+ // WriteWithChanges writes to the terminal state and returns the line numbers that changed.
62+ func (t * terminal ) WriteWithChanges (p []byte ) ([]int , error ) {
63+ var dirtyLines = make (map [int ]bool )
64+ r := bytes .NewReader (p )
65+ t .lock ()
66+
67+ prevRow := t .cur .Y
68+
69+ defer t .unlock ()
70+ for {
71+ c , sz , err := r .ReadRune ()
72+ if err != nil {
73+ if err == io .EOF {
74+ break
75+ }
76+ return uniqueSorted (dirtyLines ), err
77+ }
78+ if c == unicode .ReplacementChar && sz == 1 {
79+ if r .Len () == 0 {
80+ return uniqueSorted (dirtyLines ), nil
81+ }
82+ t .logln ("invalid utf8 sequence" )
83+ continue
84+ }
85+
86+ beforeRow := t .cur .Y
87+ t .put (c )
88+ afterRow := t .cur .Y
89+
90+ dirtyLines [beforeRow ] = true
91+ if afterRow != beforeRow {
92+ dirtyLines [afterRow ] = true
93+ }
94+
95+ if t .cur .Y != prevRow {
96+ prevRow = t .cur .Y
97+ }
98+ }
99+
100+ return uniqueSorted (dirtyLines ), nil
101+ }
102+
103+ func uniqueSorted (m map [int ]bool ) []int {
104+ lines := make ([]int , 0 , len (m ))
105+ for line := range m {
106+ lines = append (lines , line )
107+ }
108+ if len (lines ) == 0 {
109+ return lines
110+ }
111+
112+ slices .Sort (lines )
113+ return lines
114+ }
115+
60116// TODO: add tests for expected blocking behavior
61117func (t * terminal ) Parse (br * bufio.Reader ) error {
62118 var locked bool
You can’t perform that action at this time.
0 commit comments