summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app.go88
-rw-r--r--ui/buffers.go39
-rw-r--r--ui/ui.go3
3 files changed, 112 insertions, 18 deletions
diff --git a/app.go b/app.go
index 2b0ba82..636efba 100644
--- a/app.go
+++ b/app.go
@@ -124,6 +124,9 @@ func NewApp(cfg Config) (app *App, err error) {
return app.completions(cursorIdx, text)
},
Mouse: mouse,
+ MergeLine: func(former *ui.Line, addition ui.Line) {
+ app.mergeLine(former, addition)
+ },
})
if err != nil {
return
@@ -955,13 +958,13 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
body.AddStyle(0, textStyle)
body.AddStyle(len(ev.FormerNick), arrowStyle)
body.AddStyle(body.Len()-len(ev.User), textStyle)
-
return ui.Line{
At: ev.Time,
Head: "--",
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
+ Data: []interface{}{ev},
}
case irc.UserJoinEvent:
var body ui.StyledStringBuilder
@@ -976,6 +979,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
+ Data: []interface{}{ev},
}
case irc.UserPartEvent:
var body ui.StyledStringBuilder
@@ -990,6 +994,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
+ Data: []interface{}{ev},
}
case irc.UserQuitEvent:
var body ui.StyledStringBuilder
@@ -1004,6 +1009,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: body.StyledString(),
Mergeable: true,
+ Data: []interface{}{ev},
}
case irc.TopicChangeEvent:
topic := ui.IRCString(ev.Topic).String()
@@ -1022,6 +1028,7 @@ func (app *App) formatEvent(ev irc.Event) ui.Line {
HeadColor: tcell.ColorGray,
Body: ui.Styled(body, tcell.StyleDefault.Foreground(tcell.ColorGray)),
Mergeable: true,
+ Data: []interface{}{ev},
}
default:
return ui.Line{}
@@ -1105,6 +1112,85 @@ func (app *App) formatMessage(s *irc.Session, ev irc.MessageEvent) (buffer strin
return
}
+func (app *App) mergeLine(former *ui.Line, addition ui.Line) {
+ partQuitUser := func(ev interface{}) string {
+ if ev, ok := ev.(irc.UserQuitEvent); ok {
+ return ev.User
+ }
+ if ev, ok := ev.(irc.UserPartEvent); ok {
+ return ev.User
+ }
+ panic("unreachable")
+ }
+
+ changed := false
+Outer:
+ for _, addedEvent := range addition.Data {
+ switch addedEvent := addedEvent.(type) {
+ case irc.UserNickEvent:
+ for i := len(former.Data) - 1; i >= 0; i-- {
+ switch ev := former.Data[i].(type) {
+ case irc.UserNickEvent:
+ if ev.User == addedEvent.FormerNick && ev.FormerNick == addedEvent.User {
+ former.Data = append(former.Data[:i], former.Data[i+1:]...)
+ changed = true
+ continue Outer
+ }
+ }
+ }
+ former.Data = append(former.Data, addedEvent)
+ case irc.UserJoinEvent:
+ for i := len(former.Data) - 1; i >= 0; i-- {
+ switch ev := former.Data[i].(type) {
+ case irc.UserPartEvent, irc.UserQuitEvent:
+ if partQuitUser(ev) == addedEvent.User {
+ former.Data = append(former.Data[:i], former.Data[i+1:]...)
+ changed = true
+ continue Outer
+ }
+ }
+ }
+ former.Data = append(former.Data, addedEvent)
+ case irc.UserQuitEvent, irc.UserPartEvent:
+ for i := len(former.Data) - 1; i >= 0; i-- {
+ switch ev := former.Data[i].(type) {
+ case irc.UserJoinEvent:
+ if ev.User == partQuitUser(addedEvent) {
+ former.Data = append(former.Data[:i], former.Data[i+1:]...)
+ changed = true
+ continue Outer
+ }
+ }
+ }
+ former.Data = append(former.Data, addedEvent)
+ //case irc.ModeChangeEvent: //TODO
+ default:
+ former.Data = append(former.Data, addedEvent)
+ }
+ }
+ if changed {
+ if len(former.Data) == 0 {
+ former.Body = ui.PlainString("")
+ return
+ }
+ var body ui.StyledStringBuilder
+ body.Grow(len(former.Body.String()))
+ body.WriteStyledString(app.formatEvent(former.Data[0]).Body)
+ for _, ev := range former.Data[1:] {
+ body.WriteString(" ")
+ body.WriteStyledString(app.formatEvent(ev).Body)
+ }
+ former.Body = body.StyledString()
+ } else {
+ var newBody ui.StyledStringBuilder
+ newBody.Grow(len(former.Body.String()) + 2 + len(addition.Body.String()))
+ newBody.WriteStyledString(former.Body)
+ newBody.WriteString(" ")
+ newBody.WriteStyledString(addition.Body)
+ former.Body = newBody.StyledString()
+ }
+}
+
// updatePrompt changes the prompt text according to the application context.
func (app *App) updatePrompt() {
netID, buffer := app.win.CurrentBuffer()
diff --git a/ui/buffers.go b/ui/buffers.go
index d277491..aa5e9fe 100644
--- a/ui/buffers.go
+++ b/ui/buffers.go
@@ -33,6 +33,7 @@ type Line struct {
HeadColor tcell.Color
Highlight bool
Mergeable bool
+ Data []interface{}
splitPoints []point
width int
@@ -43,17 +44,6 @@ func (l *Line) IsZero() bool {
return l.Body.string == ""
}
-func (l *Line) Merge(line Line) {
- newBody := new(StyledStringBuilder)
- newBody.Grow(len(l.Body.string) + 2 + len(line.Body.string))
- newBody.WriteStyledString(l.Body)
- newBody.WriteString(" ")
- newBody.WriteStyledString(line.Body)
- l.Body = newBody.StyledString()
- l.computeSplitPoints()
- l.width = 0
-}
-
func (l *Line) computeSplitPoints() {
if l.splitPoints == nil {
l.splitPoints = []point{}
@@ -209,14 +199,17 @@ type BufferList struct {
tlHeight int
showBufferNumbers bool
+
+ doMergeLine func(former *Line, addition Line)
}
// NewBufferList returns a new BufferList.
// Call Resize() once before using it.
-func NewBufferList() BufferList {
+func NewBufferList(mergeLine func(*Line, Line)) BufferList {
return BufferList{
- list: []buffer{},
- clicked: -1,
+ list: []buffer{},
+ clicked: -1,
+ doMergeLine: mergeLine,
}
}
@@ -306,6 +299,16 @@ func (bs *BufferList) Remove(netID, title string) bool {
return true
}
+func (bs *BufferList) mergeLine(former *Line, addition Line) (keepLine bool) {
+ bs.doMergeLine(former, addition)
+ if former.Body.string == "" {
+ return false
+ }
+ former.width = 0
+ former.computeSplitPoints()
+ return true
+}
+
func (bs *BufferList) AddLine(netID, title string, notify NotifyType, line Line) {
idx := bs.idx(netID, title)
if idx < 0 {
@@ -322,7 +325,9 @@ func (bs *BufferList) AddLine(netID, title string, notify NotifyType, line Line)
if line.Mergeable && n != 0 && b.lines[n-1].Mergeable {
l := &b.lines[n-1]
- l.Merge(line)
+ if !bs.mergeLine(l, line) {
+ b.lines = b.lines[:n-1]
+ }
// TODO change b.scrollAmt if it's not 0 and bs.current is idx.
} else {
line.computeSplitPoints()
@@ -353,7 +358,9 @@ func (bs *BufferList) AddLines(netID, title string, before, after []Line) {
for _, line := range *buf {
if line.Mergeable && len(lines) > 0 && lines[len(lines)-1].Mergeable {
l := &lines[len(lines)-1]
- l.Merge(line)
+ if !bs.mergeLine(l, line) {
+ lines = lines[:len(lines)-1]
+ }
} else {
if buf != &b.lines {
line.Body = line.Body.ParseURLs()
diff --git a/ui/ui.go b/ui/ui.go
index fe5ceef..7e02812 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -15,6 +15,7 @@ type Config struct {
MemberColWidth int
AutoComplete func(cursorIdx int, text []rune) []Completion
Mouse bool
+ MergeLine func(former *Line, addition Line)
}
type UI struct {
@@ -70,7 +71,7 @@ func New(config Config) (ui *UI, err error) {
close(ui.Events)
}()
- ui.bs = NewBufferList()
+ ui.bs = NewBufferList(ui.config.MergeLine)
ui.e = NewEditor(ui.config.AutoComplete)
ui.Resize()