~taiite/senpai

2c7bc6ac7a8adcb591a975fbc3ab3abe47fa99fa — delthas 1 year, 26 days ago fbe14ad
Add notify types for fine-grained control of unread/highlight state

Namely, we want the unread light to show up only on actual messages, not
commands etc.

This opens the way for not showing an unread light when printing topic
on join.
5 files changed, 45 insertions(+), 31 deletions(-)

M app.go
M commands.go
M ui/buffers.go
M ui/ui.go
M window.go
M app.go => app.go +14 -8
@@ 405,7 405,7 @@ func (app *App) handleKeyEvent(ev *tcell.EventKey) {
		input := app.win.InputEnter()
		err := app.handleInput(buffer, input)
		if err != nil {
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyUnread, ui.Line{
				At:        time.Now(),
				Head:      "!!",
				HeadColor: tcell.ColorRed,


@@ 468,7 468,7 @@ func (app *App) handleIRCEvent(ev interface{}) {
			body.WriteString(" as ")
			body.WriteString(app.s.Nick())
		}
		app.win.AddLine(Home, false, ui.Line{
		app.win.AddLine(Home, ui.NotifyUnread, ui.Line{
			At:   msg.TimeOrNow(),
			Head: "--",
			Body: body.StyledString(),


@@ 499,7 499,7 @@ func (app *App) handleIRCEvent(ev interface{}) {
		body.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorGray))
		body.WriteString(ev.User)
		for _, c := range app.s.ChannelsSharedWith(ev.User) {
			app.win.AddLine(c, false, ui.Line{
			app.win.AddLine(c, ui.NotifyNone, ui.Line{
				At:        msg.TimeOrNow(),
				Head:      "--",
				HeadColor: tcell.ColorGray,


@@ 522,7 522,7 @@ func (app *App) handleIRCEvent(ev interface{}) {
		body.WriteByte('+')
		body.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorGray))
		body.WriteString(ev.User)
		app.win.AddLine(ev.Channel, false, ui.Line{
		app.win.AddLine(ev.Channel, ui.NotifyNone, ui.Line{
			At:        msg.TimeOrNow(),
			Head:      "--",
			HeadColor: tcell.ColorGray,


@@ 538,7 538,7 @@ func (app *App) handleIRCEvent(ev interface{}) {
		body.WriteByte('-')
		body.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorGray))
		body.WriteString(ev.User)
		app.win.AddLine(ev.Channel, false, ui.Line{
		app.win.AddLine(ev.Channel, ui.NotifyNone, ui.Line{
			At:        msg.TimeOrNow(),
			Head:      "--",
			HeadColor: tcell.ColorGray,


@@ 553,7 553,7 @@ func (app *App) handleIRCEvent(ev interface{}) {
		body.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorGray))
		body.WriteString(ev.User)
		for _, c := range ev.Channels {
			app.win.AddLine(c, false, ui.Line{
			app.win.AddLine(c, ui.NotifyNone, ui.Line{
				At:        msg.TimeOrNow(),
				Head:      "--",
				HeadColor: tcell.ColorGray,


@@ 567,7 567,7 @@ func (app *App) handleIRCEvent(ev interface{}) {
		body.SetStyle(tcell.StyleDefault.Foreground(tcell.ColorGray))
		body.WriteString("Topic changed to: ")
		body.WriteString(ev.Topic)
		app.win.AddLine(ev.Channel, false, ui.Line{
		app.win.AddLine(ev.Channel, ui.NotifyUnread, ui.Line{
			At:        msg.TimeOrNow(),
			Head:      "--",
			HeadColor: tcell.ColorGray,


@@ 575,7 575,13 @@ func (app *App) handleIRCEvent(ev interface{}) {
		})
	case irc.MessageEvent:
		buffer, line, hlNotification := app.formatMessage(ev)
		app.win.AddLine(buffer, hlNotification, line)
		var notify ui.NotifyType
		if hlNotification {
			notify = ui.NotifyHighlight
		} else {
			notify = ui.NotifyUnread
		}
		app.win.AddLine(buffer, notify, line)
		if hlNotification {
			app.notifyHighlight(buffer, ev.User, line.Body.String())
		}

M commands.go => commands.go +15 -15
@@ 140,7 140,7 @@ func noCommand(app *App, buffer, content string) error {
			Content:         content,
			Time:            time.Now(),
		})
		app.win.AddLine(buffer, false, line)
		app.win.AddLine(buffer, ui.NotifyNone, line)
	}

	return nil


@@ 149,7 149,7 @@ func noCommand(app *App, buffer, content string) error {
func commandDoHelp(app *App, buffer string, args []string) (err error) {
	t := time.Now()
	if len(args) == 0 {
		app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
		app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
			At:   t,
			Head: "--",
			Body: ui.PlainString("Available commands:"),


@@ 158,22 158,22 @@ func commandDoHelp(app *App, buffer string, args []string) (err error) {
			if cmd.Desc == "" {
				continue
			}
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
				At:   t,
				Body: ui.PlainSprintf("  \x02%s\x02 %s", cmdName, cmd.Usage),
			})
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
				At:   t,
				Body: ui.PlainSprintf("    %s", cmd.Desc),
			})
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
				At: t,
			})
		}
	} else {
		search := strings.ToUpper(args[0])
		found := false
		app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
		app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
			At:   t,
			Head: "--",
			Body: ui.PlainSprintf("Commands that match \"%s\":", search),


@@ 189,21 189,21 @@ func commandDoHelp(app *App, buffer string, args []string) (err error) {
			usage.SetStyle(tcell.StyleDefault)
			usage.WriteByte(' ')
			usage.WriteString(cmd.Usage)
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
				At:   t,
				Body: usage.StyledString(),
			})
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
				At:   t,
				Body: ui.PlainSprintf("  %s", cmd.Desc),
			})
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
				At: t,
			})
			found = true
		}
		if !found {
			app.win.AddLine(app.win.CurrentBuffer(), false, ui.Line{
			app.win.AddLine(app.win.CurrentBuffer(), ui.NotifyNone, ui.Line{
				At:   t,
				Body: ui.PlainSprintf("  no command matches %q", args[0]),
			})


@@ 236,7 236,7 @@ func commandDoMe(app *App, buffer string, args []string) (err error) {
			Content:         content,
			Time:            time.Now(),
		})
		app.win.AddLine(buffer, false, line)
		app.win.AddLine(buffer, ui.NotifyNone, line)
	}
	return
}


@@ 254,7 254,7 @@ func commandDoMsg(app *App, buffer string, args []string) (err error) {
			Content:         content,
			Time:            time.Now(),
		})
		app.win.AddLine(buffer, false, line)
		app.win.AddLine(buffer, ui.NotifyNone, line)
	}
	return
}


@@ 274,7 274,7 @@ func commandDoNames(app *App, buffer string, args []string) (err error) {
	}
	body := sb.StyledString()
	// TODO remove last space
	app.win.AddLine(buffer, false, ui.Line{
	app.win.AddLine(buffer, ui.NotifyNone, ui.Line{
		At:        time.Now(),
		Head:      "--",
		HeadColor: tcell.ColorGray,


@@ 351,7 351,7 @@ func commandDoR(app *App, buffer string, args []string) (err error) {
			Content:         args[0],
			Time:            time.Now(),
		})
		app.win.AddLine(buffer, false, line)
		app.win.AddLine(buffer, ui.NotifyNone, line)
	}
	return
}


@@ 366,7 366,7 @@ func commandDoTopic(app *App, buffer string, args []string) (err error) {
		} else {
			body = fmt.Sprintf("Topic (by %s, %s): %s", who, at.Local().Format("Mon Jan 2 15:04:05"), topic)
		}
		app.win.AddLine(buffer, false, ui.Line{
		app.win.AddLine(buffer, ui.NotifyNone, ui.Line{
			At:        time.Now(),
			Head:      "--",
			HeadColor: tcell.ColorGray,

M ui/buffers.go => ui/buffers.go +11 -3
@@ 16,6 16,14 @@ type point struct {
	Split bool
}

type NotifyType int

const (
	NotifyNone NotifyType = iota
	NotifyUnread
	NotifyHighlight
)

type Line struct {
	At        time.Time
	Head      string


@@ 251,7 259,7 @@ func (bs *BufferList) Remove(title string) (ok bool) {
	return
}

func (bs *BufferList) AddLine(title string, highlight bool, line Line) {
func (bs *BufferList) AddLine(title string, notify NotifyType, line Line) {
	idx := bs.idx(title)
	if idx < 0 {
		return


@@ 280,10 288,10 @@ func (bs *BufferList) AddLine(title string, highlight bool, line Line) {
		}
	}

	if !line.Mergeable && idx != bs.current {
	if notify != NotifyNone && idx != bs.current {
		b.unread = true
	}
	if highlight && idx != bs.current {
	if notify == NotifyHighlight && idx != bs.current {
		b.highlights++
	}
}

M ui/ui.go => ui/ui.go +2 -2
@@ 136,8 136,8 @@ func (ui *UI) RemoveBuffer(title string) {
	_ = ui.bs.Remove(title)
}

func (ui *UI) AddLine(buffer string, highlight bool, line Line) {
	ui.bs.AddLine(buffer, highlight, line)
func (ui *UI) AddLine(buffer string, notify NotifyType, line Line) {
	ui.bs.AddLine(buffer, notify, line)
}

func (ui *UI) AddLines(buffer string, lines []Line) {

M window.go => window.go +3 -3
@@ 15,7 15,7 @@ const welcomeMessage = "senpai dev build. See senpai(1) for a list of keybinding

func (app *App) initWindow() {
	app.win.AddBuffer(Home)
	app.win.AddLine(Home, false, ui.Line{
	app.win.AddLine(Home, ui.NotifyNone, ui.Line{
		Head: "--",
		Body: ui.PlainString(welcomeMessage),
		At:   time.Now(),


@@ 35,9 35,9 @@ func (app *App) queueStatusLine(line ui.Line) {
func (app *App) addStatusLine(line ui.Line) {
	buffer := app.win.CurrentBuffer()
	if buffer != Home {
		app.win.AddLine(Home, false, line)
		app.win.AddLine(Home, ui.NotifyNone, line)
	}
	app.win.AddLine(buffer, false, line)
	app.win.AddLine(buffer, ui.NotifyNone, line)
}

func (app *App) setStatus() {