~taiite/senpai

85482b9e6b4f82dbcd41d4c35846f13ea1b42383 — Hubert Hirtz 5 months ago ee21112
Merge redundant events
3 files changed, 112 insertions(+), 18 deletions(-)

M app.go
M ui/buffers.go
M ui/ui.go
M app.go => app.go +87 -1
@@ 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()

M ui/buffers.go => ui/buffers.go +23 -16
@@ 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()

M ui/ui.go => ui/ui.go +2 -1
@@ 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()