/reply command with autocomplete.

This commit is contained in:
Andrey Petrov 2015-01-18 18:11:30 -08:00
parent 12402c2338
commit 544c9789c0
3 changed files with 81 additions and 39 deletions

View File

@ -201,7 +201,7 @@ func InitCommands(c *Commands) {
c.Add(Command{
Prefix: "/quiet",
Help: "Silence announcement-type messages (join, part, rename, etc).",
Help: "Silence room announcements.",
Handler: func(room *Room, msg CommandMsg) error {
u := msg.From()
u.ToggleQuietMode()

View File

@ -64,6 +64,16 @@ func (u *User) SetId(id Id) {
u.SetColorIdx(rand.Int())
}
// ReplyTo returns the last user that messaged this user.
func (u *User) ReplyTo() *User {
return u.replyTo
}
// SetReplyTo sets the last user to message this user.
func (u *User) SetReplyTo(user *User) {
u.replyTo = user
}
// ToggleQuietMode will toggle whether or not quiet mode is enabled
func (u *User) ToggleQuietMode() {
u.Config.Quiet = !u.Config.Quiet
@ -113,10 +123,13 @@ func (u *User) SetHighlight(s string) error {
return nil
}
func (u User) render(m Message) string {
func (u *User) render(m Message) string {
switch m := m.(type) {
case *PublicMsg:
return m.RenderFor(u.Config) + Newline
case *PrivateMsg:
u.SetReplyTo(m.From())
return m.Render(u.Config.Theme) + Newline
default:
return m.Render(u.Config.Theme) + Newline
}

103
host.go
View File

@ -68,8 +68,6 @@ func (h Host) isOp(conn sshd.Connection) bool {
// Connect a specific Terminal to this host and its room.
func (h *Host) Connect(term *sshd.Terminal) {
id := NewIdentity(term.Conn)
term.AutoCompleteCallback = h.AutoCompleteFunction
user := chat.NewUserScreen(id, term)
user.Config.Theme = h.theme
go func() {
@ -92,6 +90,7 @@ func (h *Host) Connect(term *sshd.Terminal) {
// Successfully joined.
term.SetPrompt(GetPrompt(user))
term.AutoCompleteCallback = h.AutoCompleteFunction(user)
user.SetHighlight(user.Name())
h.count++
@ -159,44 +158,52 @@ func (h Host) completeCommand(partial string) string {
return ""
}
// 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
}
if strings.HasSuffix(line[:pos], " ") {
// Don't autocomplete spaces.
return
}
fields := strings.Fields(line[:pos])
isFirst := len(fields) < 2
partial := fields[len(fields)-1]
posPartial := pos - len(partial)
var completed string
if isFirst && strings.HasPrefix(partial, "/") {
// Command
completed = h.completeCommand(partial)
} else {
// Name
completed = h.completeName(partial)
if completed == "" {
// AutoCompleteFunction returns a callback for terminal autocompletion
func (h *Host) AutoCompleteFunction(u *chat.User) func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
return func(line string, pos int, key rune) (newLine string, newPos int, ok bool) {
if key != 9 {
return
}
if isFirst {
completed += ":"
}
}
completed += " "
// Reposition the cursor
newLine = strings.Replace(line[posPartial:], partial, completed, 1)
newLine = line[:posPartial] + newLine
newPos = pos + (len(completed) - len(partial))
ok = true
return
if strings.HasSuffix(line[:pos], " ") {
// Don't autocomplete spaces.
return
}
fields := strings.Fields(line[:pos])
isFirst := len(fields) < 2
partial := fields[len(fields)-1]
posPartial := pos - len(partial)
var completed string
if isFirst && strings.HasPrefix(partial, "/") {
// Command
completed = h.completeCommand(partial)
if completed == "/reply" {
replyTo := u.ReplyTo()
if replyTo != nil {
completed = "/msg " + replyTo.Name()
}
}
} else {
// Name
completed = h.completeName(partial)
if completed == "" {
return
}
if isFirst {
completed += ":"
}
}
completed += " "
// Reposition the cursor
newLine = strings.Replace(line[posPartial:], partial, completed, 1)
newLine = line[:posPartial] + newLine
newPos = pos + (len(completed) - len(partial))
ok = true
return
}
}
// GetUser returns a chat.User based on a name.
@ -235,6 +242,28 @@ func (h *Host) InitCommands(c *chat.Commands) {
},
})
c.Add(chat.Command{
Prefix: "/reply",
PrefixHelp: "MESSAGE",
Help: "Reply with MESSAGE to the previous private message.",
Handler: func(room *chat.Room, msg chat.CommandMsg) error {
args := msg.Args()
switch len(args) {
case 0:
return errors.New("must specify message")
}
target := msg.From().ReplyTo()
if target == nil {
return errors.New("no message to reply to")
}
m := chat.NewPrivateMsg(strings.Join(args, " "), msg.From(), target)
room.Send(m)
return nil
},
})
// Op commands
c.Add(chat.Command{
Op: true,