commit 85482b9

Hubert Hirtz  ·  2021-12-06 10:30:48 +0000 UTC
parent ee21112
Merge redundant events
3 files changed,  +112, -18
M app.go
M app.go
+87, -1
  1@@ -124,6 +124,9 @@ func NewApp(cfg Config) (app *App, err error) {
  2 			return app.completions(cursorIdx, text)
  3 		},
  4 		Mouse: mouse,
  5+		MergeLine: func(former *ui.Line, addition ui.Line) {
  6+			app.mergeLine(former, addition)
  7+		},
  8 	})
  9 	if err != nil {
 10 		return
 11@@ -955,13 +958,13 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 12 		body.AddStyle(0, textStyle)
 13 		body.AddStyle(len(ev.FormerNick), arrowStyle)
 14 		body.AddStyle(body.Len()-len(ev.User), textStyle)
 15-
 16 		return ui.Line{
 17 			At:        ev.Time,
 18 			Head:      "--",
 19 			HeadColor: tcell.ColorGray,
 20 			Body:      body.StyledString(),
 21 			Mergeable: true,
 22+			Data:      []interface{}{ev},
 23 		}
 24 	case irc.UserJoinEvent:
 25 		var body ui.StyledStringBuilder
 26@@ -976,6 +979,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 27 			HeadColor: tcell.ColorGray,
 28 			Body:      body.StyledString(),
 29 			Mergeable: true,
 30+			Data:      []interface{}{ev},
 31 		}
 32 	case irc.UserPartEvent:
 33 		var body ui.StyledStringBuilder
 34@@ -990,6 +994,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 35 			HeadColor: tcell.ColorGray,
 36 			Body:      body.StyledString(),
 37 			Mergeable: true,
 38+			Data:      []interface{}{ev},
 39 		}
 40 	case irc.UserQuitEvent:
 41 		var body ui.StyledStringBuilder
 42@@ -1004,6 +1009,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 43 			HeadColor: tcell.ColorGray,
 44 			Body:      body.StyledString(),
 45 			Mergeable: true,
 46+			Data:      []interface{}{ev},
 47 		}
 48 	case irc.TopicChangeEvent:
 49 		topic := ui.IRCString(ev.Topic).String()
 50@@ -1022,6 +1028,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
 51 			HeadColor: tcell.ColorGray,
 52 			Body:      ui.Styled(body, tcell.StyleDefault.Foreground(tcell.ColorGray)),
 53 			Mergeable: true,
 54+			Data:      []interface{}{ev},
 55 		}
 56 	default:
 57 		return ui.Line{}
 58@@ -1105,6 +1112,85 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
 59 	return
 60 }
 61 
 62+func (app *App) mergeLine(former *ui.Line, addition ui.Line) {
 63+	partQuitUser := func(ev interface{}) string {
 64+		if ev, ok := ev.(irc.UserQuitEvent); ok {
 65+			return ev.User
 66+		}
 67+		if ev, ok := ev.(irc.UserPartEvent); ok {
 68+			return ev.User
 69+		}
 70+		panic("unreachable")
 71+	}
 72+
 73+	changed := false
 74+Outer:
 75+	for _, addedEvent := range addition.Data {
 76+		switch addedEvent := addedEvent.(type) {
 77+		case irc.UserNickEvent:
 78+			for i := len(former.Data) - 1; i >= 0; i-- {
 79+				switch ev := former.Data[i].(type) {
 80+				case irc.UserNickEvent:
 81+					if ev.User == addedEvent.FormerNick && ev.FormerNick == addedEvent.User {
 82+						former.Data = append(former.Data[:i], former.Data[i+1:]...)
 83+						changed = true
 84+						continue Outer
 85+					}
 86+				}
 87+			}
 88+			former.Data = append(former.Data, addedEvent)
 89+		case irc.UserJoinEvent:
 90+			for i := len(former.Data) - 1; i >= 0; i-- {
 91+				switch ev := former.Data[i].(type) {
 92+				case irc.UserPartEvent, irc.UserQuitEvent:
 93+					if partQuitUser(ev) == addedEvent.User {
 94+						former.Data = append(former.Data[:i], former.Data[i+1:]...)
 95+						changed = true
 96+						continue Outer
 97+					}
 98+				}
 99+			}
100+			former.Data = append(former.Data, addedEvent)
101+		case irc.UserQuitEvent, irc.UserPartEvent:
102+			for i := len(former.Data) - 1; i >= 0; i-- {
103+				switch ev := former.Data[i].(type) {
104+				case irc.UserJoinEvent:
105+					if ev.User == partQuitUser(addedEvent) {
106+						former.Data = append(former.Data[:i], former.Data[i+1:]...)
107+						changed = true
108+						continue Outer
109+					}
110+				}
111+			}
112+			former.Data = append(former.Data, addedEvent)
113+		//case irc.ModeChangeEvent: //TODO
114+		default:
115+			former.Data = append(former.Data, addedEvent)
116+		}
117+	}
118+	if changed {
119+		if len(former.Data) == 0 {
120+			former.Body = ui.PlainString("")
121+			return
122+		}
123+		var body ui.StyledStringBuilder
124+		body.Grow(len(former.Body.String()))
125+		body.WriteStyledString(app.formatEvent(former.Data[0]).Body)
126+		for _, ev := range former.Data[1:] {
127+			body.WriteString("  ")
128+			body.WriteStyledString(app.formatEvent(ev).Body)
129+		}
130+		former.Body = body.StyledString()
131+	} else {
132+		var newBody ui.StyledStringBuilder
133+		newBody.Grow(len(former.Body.String()) + 2 + len(addition.Body.String()))
134+		newBody.WriteStyledString(former.Body)
135+		newBody.WriteString("  ")
136+		newBody.WriteStyledString(addition.Body)
137+		former.Body = newBody.StyledString()
138+	}
139+}
140+
141 // updatePrompt changes the prompt text according to the application context.
142 func (app *App) updatePrompt() {
143 	netID, buffer := app.win.CurrentBuffer()
+23, -16
 1@@ -33,6 +33,7 @@ type Line struct {
 2 	HeadColor tcell.Color
 3 	Highlight bool
 4 	Mergeable bool
 5+	Data      []interface{}
 6 
 7 	splitPoints []point
 8 	width       int
 9@@ -43,17 +44,6 @@ func (l *Line) IsZero() bool {
10 	return l.Body.string == ""
11 }
12 
13-func (l *Line) Merge(line Line) {
14-	newBody := new(StyledStringBuilder)
15-	newBody.Grow(len(l.Body.string) + 2 + len(line.Body.string))
16-	newBody.WriteStyledString(l.Body)
17-	newBody.WriteString("  ")
18-	newBody.WriteStyledString(line.Body)
19-	l.Body = newBody.StyledString()
20-	l.computeSplitPoints()
21-	l.width = 0
22-}
23-
24 func (l *Line) computeSplitPoints() {
25 	if l.splitPoints == nil {
26 		l.splitPoints = []point{}
27@@ -209,14 +199,17 @@ type BufferList struct {
28 	tlHeight     int
29 
30 	showBufferNumbers bool
31+
32+	doMergeLine func(former *Line, addition Line)
33 }
34 
35 // NewBufferList returns a new BufferList.
36 // Call Resize() once before using it.
37-func NewBufferList() BufferList {
38+func NewBufferList(mergeLine func(*Line, Line)) BufferList {
39 	return BufferList{
40-		list:    []buffer{},
41-		clicked: -1,
42+		list:        []buffer{},
43+		clicked:     -1,
44+		doMergeLine: mergeLine,
45 	}
46 }
47 
48@@ -306,6 +299,16 @@ func (bs *BufferList) Remove(netID, title string) bool {
49 	return true
50 }
51 
52+func (bs *BufferList) mergeLine(former *Line, addition Line) (keepLine bool) {
53+	bs.doMergeLine(former, addition)
54+	if former.Body.string == "" {
55+		return false
56+	}
57+	former.width = 0
58+	former.computeSplitPoints()
59+	return true
60+}
61+
62 func (bs *BufferList) AddLine(netID, title string, notify NotifyType, line Line) {
63 	idx := bs.idx(netID, title)
64 	if idx < 0 {
65@@ -322,7 +325,9 @@ func (bs *BufferList) AddLine(netID, title string, notify NotifyType, line Line)
66 
67 	if line.Mergeable && n != 0 && b.lines[n-1].Mergeable {
68 		l := &b.lines[n-1]
69-		l.Merge(line)
70+		if !bs.mergeLine(l, line) {
71+			b.lines = b.lines[:n-1]
72+		}
73 		// TODO change b.scrollAmt if it's not 0 and bs.current is idx.
74 	} else {
75 		line.computeSplitPoints()
76@@ -353,7 +358,9 @@ func (bs *BufferList) AddLines(netID, title string, before, after []Line) {
77 		for _, line := range *buf {
78 			if line.Mergeable && len(lines) > 0 && lines[len(lines)-1].Mergeable {
79 				l := &lines[len(lines)-1]
80-				l.Merge(line)
81+				if !bs.mergeLine(l, line) {
82+					lines = lines[:len(lines)-1]
83+				}
84 			} else {
85 				if buf != &b.lines {
86 					line.Body = line.Body.ParseURLs()
+2, -1
 1@@ -15,6 +15,7 @@ type Config struct {
 2 	MemberColWidth int
 3 	AutoComplete   func(cursorIdx int, text []rune) []Completion
 4 	Mouse          bool
 5+	MergeLine      func(former *Line, addition Line)
 6 }
 7 
 8 type UI struct {
 9@@ -70,7 +71,7 @@ func New(config Config) (ui *UI, err error) {
10 		close(ui.Events)
11 	}()
12 
13-	ui.bs = NewBufferList()
14+	ui.bs = NewBufferList(ui.config.MergeLine)
15 	ui.e = NewEditor(ui.config.AutoComplete)
16 	ui.Resize()
17