Add basic username/id autocompletion

This commit is contained in:
Tulir Asokan 2018-03-17 14:32:01 +02:00
parent dacc7fd6a3
commit ba379a1b4a
2 changed files with 45 additions and 5 deletions

View File

@ -79,7 +79,7 @@ type AdvancedInputField struct {
done func(tcell.Key) done func(tcell.Key)
// An optional function which is called when the user presses tab. // An optional function which is called when the user presses tab.
tabComplete func(text string, cursorOffset int) tabComplete func(text string, cursorOffset int) string
} }
// NewAdvancedInputField returns a new input field. // NewAdvancedInputField returns a new input field.
@ -205,7 +205,7 @@ func (field *AdvancedInputField) SetDoneFunc(handler func(key tcell.Key)) *Advan
return field return field
} }
func (field *AdvancedInputField) SetTabCompleteFunc(handler func(text string, cursorOffset int)) *AdvancedInputField { func (field *AdvancedInputField) SetTabCompleteFunc(handler func(text string, cursorOffset int) string) *AdvancedInputField {
field.tabComplete = handler field.tabComplete = handler
return field return field
} }
@ -429,7 +429,12 @@ func (field *AdvancedInputField) InputHandler() func(event *tcell.EventKey, setF
} }
case tcell.KeyTab: // Tab-completion case tcell.KeyTab: // Tab-completion
if field.tabComplete != nil { if field.tabComplete != nil {
field.tabComplete(field.text, field.cursorOffset) oldWidth := runewidth.StringWidth(field.text)
field.text = field.tabComplete(field.text, field.cursorOffset)
newWidth := runewidth.StringWidth(field.text)
if oldWidth != newWidth {
field.cursorOffset += newWidth - oldWidth
}
} }
case tcell.KeyEnter, tcell.KeyEscape: // We're done. case tcell.KeyEnter, tcell.KeyEscape: // We're done.
if field.done != nil { if field.done != nil {

View File

@ -17,10 +17,13 @@
package main package main
import ( import (
"fmt"
"strings" "strings"
"time" "time"
"unicode"
"github.com/gdamore/tcell" "github.com/gdamore/tcell"
"github.com/mattn/go-runewidth"
"maunium.net/go/gomatrix" "maunium.net/go/gomatrix"
"maunium.net/go/tview" "maunium.net/go/tview"
) )
@ -96,11 +99,43 @@ func (view *MainView) InputChanged(text string) {
} }
} }
func (view *MainView) InputTabComplete(text string, cursorOffset int) { func findWordToTabComplete(text string) string {
output := ""
runes := []rune(text)
for i := len(runes) - 1; i >= 0; i-- {
if unicode.IsSpace(runes[i]) {
break
}
output = string(runes[i]) + output
}
return output
}
func (view *RoomView) AutocompleteUser(existingText string) (completions []string) {
for _, user := range view.room.GetMembers() {
if strings.HasPrefix(user.DisplayName, existingText) {
completions = append(completions, user.DisplayName)
} else if strings.HasPrefix(user.UserID, existingText) {
completions = append(completions, user.UserID)
}
}
return
}
func (view *MainView) InputTabComplete(text string, cursorOffset int) string {
roomView, _ := view.rooms[view.CurrentRoomID()] roomView, _ := view.rooms[view.CurrentRoomID()]
if roomView != nil { if roomView != nil {
// text[0:cursorOffset] str := runewidth.Truncate(text, cursorOffset, "")
word := findWordToTabComplete(str)
userCompletions := roomView.AutocompleteUser(word)
if len(userCompletions) == 1 {
text = str[0:len(str)-len(word)] + userCompletions[0] + text[len(str):]
} else if len(userCompletions) > 1 && len(userCompletions) < 6 {
roomView.status.Clear()
fmt.Fprintf(roomView.status, "Completions: %s", strings.Join(userCompletions, ", "))
}
} }
return text
} }
func (view *MainView) InputDone(key tcell.Key) { func (view *MainView) InputDone(key tcell.Key) {