Kostis Karantias: 4 Rudimentary support for a nick list bar Complete support for nick list Only display nick list when it makes sense Make nick list width configurable 12 files changed, 137 insertions(+), 27 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~taiite/public-inbox/patches/14856/mbox | git am -3Learn more about email & git
--- ui/buffers.go | 12 ++++++++++++ ui/ui.go | 9 ++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ui/buffers.go b/ui/buffers.go index 633fed2..32289e1 100644 --- a/ui/buffers.go +++ b/ui/buffers.go @@ -352,6 +352,18 @@ func (bs *BufferList) idx(title string) int { return -1 } +func (bs *BufferList) DrawVerticalNickList(screen tcell.Screen, x0, y0, width, height int) { + x0++ + st := tcell.StyleDefault + + for y := y0; y < y0+height; y++ { + for x := x0; x < x0+width; x++ { + screen.SetContent(x, y, ' ', nil, st) + } + screen.SetContent(x0-1, y, 0x2502, nil, st.Dim(true)) + } +} + func (bs *BufferList) DrawVerticalBufferList(screen tcell.Screen, x0, y0, width, height int) { width-- st := tcell.StyleDefault diff --git a/ui/ui.go b/ui/ui.go index 5a30cb1..9a4dfff 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -7,6 +7,8 @@ import ( "github.com/gdamore/tcell/v2" ) +const nickListColWidth = 9 + type Config struct { NickColWidth int ChanColWidth int @@ -202,8 +204,8 @@ func (ui *UI) InputEnter() (content string) { func (ui *UI) Resize() { w, h := ui.screen.Size() - ui.e.Resize(w - 9 - ui.config.ChanColWidth - ui.config.NickColWidth) - ui.bs.ResizeTimeline(w-ui.config.ChanColWidth, h-2, ui.config.NickColWidth) + ui.e.Resize(w - 9 - ui.config.ChanColWidth - ui.config.NickColWidth - nickListColWidth) + ui.bs.ResizeTimeline(w-ui.config.ChanColWidth - nickListColWidth, h-2, ui.config.NickColWidth) } func (ui *UI) Draw() { @@ -213,7 +215,8 @@ func (ui *UI) Draw() { ui.bs.DrawTimeline(ui.screen, ui.config.ChanColWidth, 0, ui.config.NickColWidth) ui.bs.DrawVerticalBufferList(ui.screen, 0, 0, ui.config.ChanColWidth, h) - ui.drawStatusBar(ui.config.ChanColWidth, h-2, w-ui.config.ChanColWidth) + ui.bs.DrawVerticalNickList(ui.screen, w-nickListColWidth, 0, nickListColWidth, h) + ui.drawStatusBar(ui.config.ChanColWidth, h-2, w-ui.config.ChanColWidth-nickListColWidth) for x := ui.config.ChanColWidth; x < 9+ui.config.ChanColWidth+ui.config.NickColWidth; x++ { ui.screen.SetContent(x, h-1, ' ', nil, tcell.StyleDefault) -- 2.29.2
Thank you very much for these patches! (and for splitting them!) Several things to say. On the second commit: - in irc.Session.Channels(), you don't need a "if" block since the "channels" map only contain channels, - thank you for the catch on SelfNickEvent! - please remove the empty line before irc.UserNickEvent here: > @@ -160,6 +166,10 @@ func (app *App) handleIRCEvent(ev irc.Event) { > + for _, c := range app.s.Channels() { > + app.updateMembers(c) > + > + } > case irc.UserNickEvent: > for _, c := range > app.s.ChannelsSharedWith(ev.User.Name) { app.win.AddLine(c, false, > ui.Line{ On the third commit: - please inline BufferList.IsAtHome(), - please move the call to "ui.Resize()" from "UI.Draw()" to "UI.GoToBufferNo()", "UI.PreviousBuffer()" and "UI.NextBuffer()". On the fourth commit: - if i understand correctly, a value of 0 for "ui.cfg.NickListWidth" means it's not shown in "UI.Draw()", could you change the "<=" condition to a "<" to allow users to disable the nick list (and also add a sentence in the man page)?
--- app.go | 15 +++++++++++++++ irc/states.go | 17 ++++++++++++++--- ui/buffers.go | 42 ++++++++++++++++++++++++++++++++++++++++++ ui/ui.go | 7 ++++++- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/app.go b/app.go index 05a5811..856043d 100644 --- a/app.go +++ b/app.go @@ -129,6 +129,12 @@ func (app *App) handleIRCEvents(evs []irc.Event) { } } +func (app *App) updateMembers(buffer string) { + if app.s.IsChannel(buffer) { + app.win.SetMembers(buffer, app.s.Names(buffer)) + } +} + func (app *App) handleIRCEvent(ev irc.Event) { switch ev := ev.(type) { case irc.RawMessageEvent: @@ -160,6 +166,10 @@ func (app *App) handleIRCEvent(ev irc.Event) { Body: fmt.Sprintf("\x0314%s\x03\u2192\x0314%s\x03", ev.FormerNick, app.s.Nick()), Highlight: true, }) + for _, c := range app.s.Channels() { + app.updateMembers(c) + + } case irc.UserNickEvent: for _, c := range app.s.ChannelsSharedWith(ev.User.Name) { app.win.AddLine(c, false, ui.Line{ @@ -168,10 +178,12 @@ func (app *App) handleIRCEvent(ev irc.Event) { Body: fmt.Sprintf("\x0314%s\x03\u2192\x0314%s\x03", ev.FormerNick, ev.User.Name), Mergeable: true, }) + app.updateMembers(c) } case irc.SelfJoinEvent: app.win.AddBuffer(ev.Channel) app.s.RequestHistory(ev.Channel, time.Now()) + app.updateMembers(ev.Channel) case irc.UserJoinEvent: app.win.AddLine(ev.Channel, false, ui.Line{ At: time.Now(), @@ -179,6 +191,7 @@ func (app *App) handleIRCEvent(ev irc.Event) { Body: fmt.Sprintf("\x033+\x0314%s\x03", ev.User.Name), Mergeable: true, }) + app.updateMembers(ev.Channel) case irc.SelfPartEvent: app.win.RemoveBuffer(ev.Channel) case irc.UserPartEvent: @@ -188,6 +201,7 @@ func (app *App) handleIRCEvent(ev irc.Event) { Body: fmt.Sprintf("\x034-\x0314%s\x03", ev.User.Name), Mergeable: true, }) + app.updateMembers(ev.Channel) case irc.UserQuitEvent: for _, c := range ev.Channels { app.win.AddLine(c, false, ui.Line{ @@ -196,6 +210,7 @@ func (app *App) handleIRCEvent(ev irc.Event) { Body: fmt.Sprintf("\x034-\x0314%s\x03", ev.User.Name), Mergeable: true, }) + app.updateMembers(c) } case irc.TopicChangeEvent: app.win.AddLine(ev.Channel, false, ui.Line{ diff --git a/irc/states.go b/irc/states.go index c702c43..3867f7e 100644 --- a/irc/states.go +++ b/irc/states.go @@ -290,6 +290,16 @@ func (s *Session) Typings(target string) []string { return res } +func (s *Session) Channels() []string { + var channels []string + for _, c := range s.channels { + if s.IsChannel(c.Name) { + channels = append(channels, c.Name) + } + } + return channels +} + func (s *Session) ChannelsSharedWith(name string) []string { var user *User if u, ok := s.users[s.Casemap(name)]; ok { @@ -887,12 +897,13 @@ func (s *Session) handle(msg Message) (err error) { } if nickCf == s.nickCf { + formerNick := s.nick + s.nick = newNick + s.nickCf = newNickCf s.evts <- SelfNickEvent{ - FormerNick: s.nick, + FormerNick: formerNick, Time: t, } - s.nick = newNick - s.nickCf = newNickCf } else { s.evts <- UserNickEvent{ User: u, diff --git a/ui/buffers.go b/ui/buffers.go index 32289e1..a04b75a 100644 --- a/ui/buffers.go +++ b/ui/buffers.go @@ -1,10 +1,13 @@ package ui import ( + "fmt" + "sort" "strings" "time" "github.com/gdamore/tcell/v2" + "git.sr.ht/~taiite/senpai/irc" ) func IsSplitRune(r rune) bool { @@ -165,6 +168,8 @@ type buffer struct { scrollAmt int isAtTop bool + + members []irc.Member } type BufferList struct { @@ -187,6 +192,16 @@ func NewBufferList(tlWidth, tlHeight, nickColWidth int) BufferList { } } +func (bs *BufferList) SetMembers(title string, members []irc.Member) { + idx := bs.idx(title) + if idx < 0 { + return + } + + b := &bs.list[idx] + b.members = members +} + func (bs *BufferList) ResizeTimeline(tlWidth, tlHeight, nickColWidth int) { bs.tlWidth = tlWidth bs.tlHeight = tlHeight @@ -352,6 +367,21 @@ func (bs *BufferList) idx(title string) int { return -1 } +func prettifyMembers(members []irc.Member) []string { + privileged, unprivileged := []string{}, []string{} + for _, m := range members { + prettyName := fmt.Sprintf("%s%s", m.PowerLevel, m.Name.Name) + if len(m.PowerLevel) > 0 { + privileged = append(privileged, prettyName) + } else { + unprivileged = append(unprivileged, prettyName) + } + } + sort.Strings(privileged) + sort.Strings(unprivileged) + return append(privileged, unprivileged...) +} + func (bs *BufferList) DrawVerticalNickList(screen tcell.Screen, x0, y0, width, height int) { x0++ st := tcell.StyleDefault @@ -362,6 +392,18 @@ func (bs *BufferList) DrawVerticalNickList(screen tcell.Screen, x0, y0, width, h } screen.SetContent(x0-1, y, 0x2502, nil, st.Dim(true)) } + + currentBuffer := bs.list[bs.current] + prettyMembers := prettifyMembers(currentBuffer.members) + for i, m := range prettyMembers { + if i+1 > height { + break + } + x := x0 + y := y0+i + title := truncate(m, width-1, "\u2026") + printString(screen, &x, y, st, title) + } } func (bs *BufferList) DrawVerticalBufferList(screen tcell.Screen, x0, y0, width, height int) { diff --git a/ui/ui.go b/ui/ui.go index 9a4dfff..7a2a1f8 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -5,9 +5,10 @@ import ( "time" "github.com/gdamore/tcell/v2" + "git.sr.ht/~taiite/senpai/irc" ) -const nickListColWidth = 9 +const nickListColWidth = 15 type Config struct { NickColWidth int @@ -134,6 +135,10 @@ func (ui *UI) RemoveBuffer(title string) { _ = ui.bs.Remove(title) } +func (ui *UI) SetMembers(buffer string, members []irc.Member) { + ui.bs.SetMembers(buffer, members) +} + func (ui *UI) AddLine(buffer string, highlight bool, line Line) { ui.bs.AddLine(buffer, highlight, line) } -- 2.29.2
--- ui/buffers.go | 4 ++++ ui/ui.go | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ui/buffers.go b/ui/buffers.go index a04b75a..b8dc08c 100644 --- a/ui/buffers.go +++ b/ui/buffers.go @@ -192,6 +192,10 @@ func NewBufferList(tlWidth, tlHeight, nickColWidth int) BufferList { } } +func (bs *BufferList) IsAtHome() bool { + return bs.current == 0 +} + func (bs *BufferList) SetMembers(title string, members []irc.Member) { idx := bs.idx(title) if idx < 0 { diff --git a/ui/ui.go b/ui/ui.go index 7a2a1f8..457f41d 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -207,21 +207,32 @@ func (ui *UI) InputEnter() (content string) { return ui.e.Flush() } +func (ui *UI) nickListColWidth() int { + // TODO: also check for /query buffers when we get support + if !ui.bs.IsAtHome() { + return nickListColWidth + } + return 0 +} + func (ui *UI) Resize() { w, h := ui.screen.Size() - ui.e.Resize(w - 9 - ui.config.ChanColWidth - ui.config.NickColWidth - nickListColWidth) - ui.bs.ResizeTimeline(w-ui.config.ChanColWidth - nickListColWidth, h-2, ui.config.NickColWidth) + ui.e.Resize(w - 9 - ui.config.ChanColWidth - ui.config.NickColWidth - ui.nickListColWidth()) + ui.bs.ResizeTimeline(w-ui.config.ChanColWidth - ui.nickListColWidth(), h-2, ui.config.NickColWidth) } func (ui *UI) Draw() { + ui.Resize() w, h := ui.screen.Size() ui.e.Draw(ui.screen, 9+ui.config.ChanColWidth+ui.config.NickColWidth, h-1) ui.bs.DrawTimeline(ui.screen, ui.config.ChanColWidth, 0, ui.config.NickColWidth) ui.bs.DrawVerticalBufferList(ui.screen, 0, 0, ui.config.ChanColWidth, h) - ui.bs.DrawVerticalNickList(ui.screen, w-nickListColWidth, 0, nickListColWidth, h) - ui.drawStatusBar(ui.config.ChanColWidth, h-2, w-ui.config.ChanColWidth-nickListColWidth) + if ui.nickListColWidth() > 0 { + ui.bs.DrawVerticalNickList(ui.screen, w-ui.nickListColWidth(), 0, ui.nickListColWidth(), h) + } + ui.drawStatusBar(ui.config.ChanColWidth, h-2, w-ui.config.ChanColWidth-ui.nickListColWidth()) for x := ui.config.ChanColWidth; x < 9+ui.config.ChanColWidth+ui.config.NickColWidth; x++ { ui.screen.SetContent(x, h-1, ' ', nil, tcell.StyleDefault) -- 2.29.2
--- app.go | 1 + config.go | 12 ++++++++---- doc/senpai.5.scd | 3 +++ ui/ui.go | 23 +++++++++++------------ 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/app.go b/app.go index 856043d..0b97e01 100644 --- a/app.go +++ b/app.go @@ -38,6 +38,7 @@ func NewApp(cfg Config) (app *App, err error) { app.win, err = ui.New(ui.Config{ NickColWidth: cfg.NickColWidth, ChanColWidth: cfg.ChanColWidth, + NickListWidth: cfg.NickListWidth, AutoComplete: func(cursorIdx int, text []rune) []ui.Completion { return app.completions(cursorIdx, text) }, diff --git a/config.go b/config.go index 2515e57..6e8fb07 100644 --- a/config.go +++ b/config.go @@ -13,10 +13,11 @@ type Config struct { User string Password *string - Highlights []string - OnHighlight string `yaml:"on-highlight"` - NickColWidth int `yaml:"nick-column-width"` - ChanColWidth int `yaml:"chan-column-width"` + Highlights []string + OnHighlight string `yaml:"on-highlight"` + NickColWidth int `yaml:"nick-column-width"` + ChanColWidth int `yaml:"chan-column-width"` + NickListWidth int `yaml:"nick-list-width"` Debug bool } @@ -29,6 +30,9 @@ func ParseConfig(buf []byte) (cfg Config, err error) { if cfg.ChanColWidth <= 0 { cfg.ChanColWidth = 16 } + if cfg.NickListWidth <= 0 { + cfg.NickListWidth = 16 + } return } diff --git a/doc/senpai.5.scd b/doc/senpai.5.scd index 5c79060..6fe3edf 100644 --- a/doc/senpai.5.scd +++ b/doc/senpai.5.scd @@ -61,6 +61,9 @@ Some settings are required, the others are optional. *chan-column-width* The number of cell that the column for channels occupies. By default, 16. +*nick-list-width* + The number of cells that the nick list occupies. By default, 16. + # EXAMPLES A minimal configuration file to connect to freenode as "Guest123456": diff --git a/ui/ui.go b/ui/ui.go index 457f41d..6aef320 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -8,12 +8,11 @@ import ( "git.sr.ht/~taiite/senpai/irc" ) -const nickListColWidth = 15 - type Config struct { - NickColWidth int - ChanColWidth int - AutoComplete func(cursorIdx int, text []rune) []Completion + NickColWidth int + ChanColWidth int + NickListWidth int + AutoComplete func(cursorIdx int, text []rune) []Completion } type UI struct { @@ -207,18 +206,18 @@ func (ui *UI) InputEnter() (content string) { return ui.e.Flush() } -func (ui *UI) nickListColWidth() int { +func (ui *UI) nickListWidth() int { // TODO: also check for /query buffers when we get support if !ui.bs.IsAtHome() { - return nickListColWidth + return ui.config.NickListWidth } return 0 } func (ui *UI) Resize() { w, h := ui.screen.Size() - ui.e.Resize(w - 9 - ui.config.ChanColWidth - ui.config.NickColWidth - ui.nickListColWidth()) - ui.bs.ResizeTimeline(w-ui.config.ChanColWidth - ui.nickListColWidth(), h-2, ui.config.NickColWidth) + ui.e.Resize(w - 9 - ui.config.ChanColWidth - ui.config.NickColWidth - ui.nickListWidth()) + ui.bs.ResizeTimeline(w-ui.config.ChanColWidth - ui.nickListWidth(), h-2, ui.config.NickColWidth) } func (ui *UI) Draw() { @@ -229,10 +228,10 @@ func (ui *UI) Draw() { ui.bs.DrawTimeline(ui.screen, ui.config.ChanColWidth, 0, ui.config.NickColWidth) ui.bs.DrawVerticalBufferList(ui.screen, 0, 0, ui.config.ChanColWidth, h) - if ui.nickListColWidth() > 0 { - ui.bs.DrawVerticalNickList(ui.screen, w-ui.nickListColWidth(), 0, ui.nickListColWidth(), h) + if ui.nickListWidth() > 0 { + ui.bs.DrawVerticalNickList(ui.screen, w-ui.nickListWidth(), 0, ui.nickListWidth(), h) } - ui.drawStatusBar(ui.config.ChanColWidth, h-2, w-ui.config.ChanColWidth-ui.nickListColWidth()) + ui.drawStatusBar(ui.config.ChanColWidth, h-2, w-ui.config.ChanColWidth-ui.nickListWidth()) for x := ui.config.ChanColWidth; x < 9+ui.config.ChanColWidth+ui.config.NickColWidth; x++ { ui.screen.SetContent(x, h-1, ' ', nil, tcell.StyleDefault) -- 2.29.2