From 3bb4bbf991a744cedcc474f545161d7ea2f8b00f Mon Sep 17 00:00:00 2001 From: Andrey Petrov Date: Thu, 25 Dec 2014 00:37:50 -0800 Subject: [PATCH] AutoCompleteFunction is back. --- chat/channel.go | 11 +++++++++++ host.go | 35 ++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/chat/channel.go b/chat/channel.go index d9ace6e..27a4e86 100644 --- a/chat/channel.go +++ b/chat/channel.go @@ -83,3 +83,14 @@ func (ch *Channel) Topic() string { func (ch *Channel) SetTopic(s string) { ch.topic = s } + +// NamesPrefix lists all members' names with a given prefix, used to query +// for autocompletion purposes. +func (ch *Channel) NamesPrefix(prefix string) []string { + users := ch.users.ListPrefix(prefix) + names := make([]string, len(users)) + for i, u := range users { + names[i] = u.(*User).Name() + } + return names +} diff --git a/host.go b/host.go index 885ef0d..1aa4b0f 100644 --- a/host.go +++ b/host.go @@ -3,6 +3,7 @@ package main import ( "fmt" "io" + "strings" "github.com/shazow/ssh-chat/chat" "github.com/shazow/ssh-chat/sshd" @@ -29,7 +30,7 @@ func (h *Host) Connect(term *sshd.Terminal) { defer term.Close() name := term.Conn.User() term.SetPrompt(fmt.Sprintf("[%s] ", name)) - // TODO: term.AutoCompleteCallback = ... + term.AutoCompleteCallback = h.AutoCompleteFunction user := chat.NewUserScreen(name, term) defer user.Close() @@ -70,30 +71,34 @@ func (h *Host) Serve() { } } -/* TODO: ... +// AutoCompleteFunction is a callback for terminal autocompletion func (h *Host) AutoCompleteFunction(line string, pos int, key rune) (newLine string, newPos int, ok bool) { if key != 9 { return } - shortLine := strings.Split(line[:pos], " ") - partialNick := shortLine[len(shortLine)-1] - nicks := h.channel.users.ListPrefix(&partialNick) - if len(nicks) == 0 { + fields := strings.Fields(line[:pos]) + partial := fields[len(fields)-1] + names := h.channel.NamesPrefix(partial) + if len(names) == 0 { + // Didn't find anything return } - nick := nicks[len(nicks)-1] - posPartialNick := pos - len(partialNick) - if len(shortLine) < 2 { - nick += ": " + name := names[len(names)-1] + posPartial := pos - len(partial) + + // Append suffix separator + if len(fields) < 2 { + name += ": " } else { - nick += " " + name += " " } - newLine = strings.Replace(line[posPartialNick:], partialNick, nick, 1) - newLine = line[:posPartialNick] + newLine - newPos = pos + (len(nick) - len(partialNick)) + + // Reposition the cursor + newLine = strings.Replace(line[posPartial:], partial, name, 1) + newLine = line[:posPartial] + newLine + newPos = pos + (len(name) - len(partial)) ok = true return } -*/