Angus Gibson: 1 Enable recent-priority tab completion 5 files changed, 34 insertions(+), 15 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~delthas/senpai-dev/patches/55413/mbox | git am -3Learn more about email & git
An attempt to address https://todo.sr.ht/~delthas/senpai/139. A session can now return the names for a given target in order of recency (but still preferring higher modes -- maybe this should be changed). --- app.go | 4 ++-- commands.go | 2 +- completions.go | 2 +- irc/session.go | 35 +++++++++++++++++++++++++---------- irc/tokens.go | 6 +++++- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/app.go b/app.go index 3425d66..4db0f00 100644 --- a/app.go +++ b/app.go @@ -301,7 +301,7 @@ func (app *App) eventLoop() { netID, buffer := app.win.CurrentBuffer() s := app.sessions[netID] if s != nil && buffer != "" { - currentMembers = s.Names(buffer) + currentMembers = s.Names(buffer, false) } app.win.Draw(currentMembers) var title strings.Builder @@ -705,7 +705,7 @@ func (app *App) handleMouseEvent(ev vaxis.Mouse) { } else { s := app.sessions[netID] if s != nil && target != "" { - members := s.Names(target) + members := s.Names(target, false) if i < len(members) { buffer := members[i].Name.Name i, added := app.win.AddBuffer(netID, "", buffer) diff --git a/commands.go b/commands.go index 6ef0ddb..c3fe257 100644 --- a/commands.go +++ b/commands.go @@ -540,7 +540,7 @@ func commandDoNames(app *App, args []string) (err error) { Foreground: app.cfg.Colors.Status, }) sb.WriteString("Names: ") - for _, name := range s.Names(buffer) { + for _, name := range s.Names(buffer, false) { if name.PowerLevel != "" { sb.SetStyle(vaxis.Style{ Foreground: vaxis.IndexColor(2), diff --git a/completions.go b/completions.go index e641c14..079c266 100644 --- a/completions.go +++ b/completions.go @@ -27,7 +27,7 @@ func (app *App) completionsChannelMembers(cs []ui.Completion, cursorIdx int, tex netID, buffer := app.win.CurrentBuffer() s := app.sessions[netID] // is not nil wordCf := s.Casemap(string(word)) - for _, name := range s.Names(buffer) { + for _, name := range s.Names(buffer, true) { if strings.HasPrefix(s.Casemap(name.Name.Name), wordCf) { nickComp := []rune(name.Name.Name) if start == 0 { diff --git a/irc/session.go b/irc/session.go index d05a20a..c0659bd 100644 --- a/irc/session.go +++ b/irc/session.go @@ -91,12 +91,13 @@ type User struct { // Channel is a joined channel. type Channel struct { - Name string // the name of the channel. - Members map[*User]string // the set of members associated with their membership. - Topic string // the topic of the channel, or "" if absent. - TopicWho *Prefix // the name of the last user who set the topic. - TopicTime time.Time // the last time the topic has been changed. - Read time.Time // the time until which messages were read. + Name string // the name of the channel. + Members map[*User]string // the set of members associated with their membership. + LastActive map[*User]time.Time // when a member last sent a message to the channel. + Topic string // the topic of the channel, or "" if absent. + TopicWho *Prefix // the name of the last user who set the topic. + TopicTime time.Time // the last time the topic has been changed. + Read time.Time // the time until which messages were read. complete bool // whether this structure is fully initialized. } @@ -294,18 +295,23 @@ func (s *Session) Users() []string { // Names returns the list of users in the given target, or nil if the target // is not a known channel or nick in the session. // The list is sorted according to member name. -func (s *Session) Names(target string) []Member { +func (s *Session) Names(target string, recent bool) []Member { var names []Member if s.IsChannel(target) { if c, ok := s.channels[s.Casemap(target)]; ok { names = make([]Member, 0, len(c.Members)) for u, pl := range c.Members { + var lastActive time.Time + if t, ok := c.LastActive[u]; ok { + lastActive = t + } names = append(names, Member{ PowerLevel: pl, Name: u.Name.Copy(), Away: u.Away, Disconnected: u.Disconnected, Self: s.nickCf == s.casemap(u.Name.Name), + LastActive: lastActive, }) } } @@ -914,8 +920,9 @@ func (s *Session) handleMessageRegistered(msg Message, playback bool) (Event, er if s.IsMe(nickCf) { s.channels[channelCf] = Channel{ - Name: msg.Params[0], - Members: map[*User]string{}, + Name: msg.Params[0], + Members: map[*User]string{}, + LastActive: map[*User]time.Time{}, } if _, ok := s.enabledCaps["away-notify"]; ok { // Only try to know who is away if the list is @@ -1979,12 +1986,14 @@ func (s *Session) newMessageEvent(msg Message) (ev MessageEvent, err error) { return ev, err } + msgTime := msg.TimeOrNow() + ev = MessageEvent{ User: msg.Prefix.Name, // TODO correctly casemap Target: target, // TODO correctly casemap Command: msg.Command, Content: content, - Time: msg.TimeOrNow(), + Time: msgTime, } if s.IsMe(target) { @@ -1993,9 +2002,15 @@ func (s *Session) newMessageEvent(msg Message) (ev MessageEvent, err error) { } } targetCf := s.Casemap(target) + nameCf := s.Casemap(msg.Prefix.Name) if c, ok := s.channels[targetCf]; ok { ev.Target = c.Name ev.TargetIsChannel = true + if u, ok := s.users[nameCf]; ok { + if msgTime.After(c.LastActive[u]) { + c.LastActive[u] = msgTime + } + } } return ev, nil diff --git a/irc/tokens.go b/irc/tokens.go index db94ae4..ea4c36c 100644 --- a/irc/tokens.go +++ b/irc/tokens.go @@ -467,6 +467,7 @@ type Member struct { Away bool Disconnected bool Self bool // Added by senpai + LastActive time.Time } type members struct { @@ -493,7 +494,10 @@ func (m members) Less(i, j int) bool { if pi != pj { return pi < pj } - return strings.ToLower(m.m[i].Name.Name) < strings.ToLower(m.m[j].Name.Name) + if m.m[i].LastActive.IsZero() && m.m[j].LastActive.IsZero() { + return strings.ToLower(m.m[i].Name.Name) < strings.ToLower(m.m[j].Name.Name) + } + return m.m[i].LastActive.After(m.m[j].LastActive) } func (m members) Swap(i, j int) { base-commit: 18998b07376644d4450d03107d04fb188fd6c5b9 -- 2.46.2