190 lines
3.4 KiB
Go
190 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"sort"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"github.com/tncardoso/gocurses"
|
|
)
|
|
|
|
var consoleInput []rune
|
|
|
|
func draw(msgs []string) {
|
|
prompt, ok := ConfKey("console_prompt").(string)
|
|
if !ok {
|
|
prefix, ok := ConfKey("command_prefix").(string)
|
|
if !ok {
|
|
prefix = "#"
|
|
}
|
|
|
|
prompt = prefix + ">"
|
|
}
|
|
|
|
gocurses.Clear()
|
|
|
|
row, _ := gocurses.Getmaxyx()
|
|
|
|
i := len(msgs)
|
|
for _, msg := range msgs {
|
|
gocurses.Mvaddstr(row-i-1, 0, msg)
|
|
i--
|
|
}
|
|
gocurses.Mvaddstr(row-i-1, 0, prompt+string(consoleInput))
|
|
|
|
gocurses.Refresh()
|
|
}
|
|
|
|
func autoComplete(all []string, current string) string {
|
|
if len(all) > 1 && len(current) > 0 {
|
|
for k, v := range all {
|
|
if v == current {
|
|
if k+1 < len(all) {
|
|
return all[k+1]
|
|
} else {
|
|
return all[0]
|
|
}
|
|
}
|
|
}
|
|
} else if len(all) >= 1 {
|
|
return all[0]
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func autoCompleteName(input []rune) []rune {
|
|
var name, tmpName []rune
|
|
for i := len(input) - 1; i >= 0; i-- {
|
|
if input[i] == ' ' {
|
|
input = input[:i+1]
|
|
break
|
|
}
|
|
tmpName = append(tmpName, input[i])
|
|
}
|
|
|
|
for i := len(tmpName) - 1; i >= 0; i-- {
|
|
name = append(name, tmpName[i])
|
|
}
|
|
|
|
var names []string
|
|
for _, c2 := range Conns() {
|
|
names = append(names, c2.Username())
|
|
}
|
|
|
|
return append(input, []rune(autoComplete(names, string(name)))...)
|
|
}
|
|
|
|
func autoCompleteCommand(input []rune) []rune {
|
|
var cmds []string
|
|
for cmd := range chatCommands {
|
|
if chatCommands[cmd].console {
|
|
cmds = append(cmds, cmd)
|
|
}
|
|
}
|
|
sort.Strings(cmds)
|
|
|
|
return []rune(autoComplete(cmds, string(input)))
|
|
}
|
|
|
|
func initCurses(l *Logger) {
|
|
gocurses.Initscr()
|
|
gocurses.Cbreak()
|
|
gocurses.Noecho()
|
|
gocurses.Stdscr.Keypad(true)
|
|
|
|
go func() {
|
|
h := &History{}
|
|
|
|
for {
|
|
var ch rune
|
|
ch1 := gocurses.Stdscr.Getch() % 255
|
|
if ch1 > 0x7F {
|
|
ch2 := gocurses.Stdscr.Getch()
|
|
ch, _ = utf8.DecodeRune([]byte{byte(ch1), byte(ch2)})
|
|
} else {
|
|
ch = rune(ch1)
|
|
}
|
|
|
|
switch ch {
|
|
case 3:
|
|
consoleInput = h.Next()
|
|
case 4:
|
|
consoleInput = h.Prev(consoleInput)
|
|
case '\b':
|
|
if len(consoleInput) > 0 {
|
|
consoleInput = consoleInput[:len(consoleInput)-1]
|
|
}
|
|
case '\t':
|
|
if strings.Count(string(consoleInput), " ") > 0 {
|
|
consoleInput = autoCompleteName(consoleInput)
|
|
} else {
|
|
consoleInput = autoCompleteCommand(consoleInput)
|
|
}
|
|
case '\n':
|
|
params := strings.Split(string(consoleInput), " ")
|
|
h.Add(consoleInput)
|
|
consoleInput = []rune{}
|
|
|
|
if chatCommands[params[0]].function == nil {
|
|
log.Print("Unknown command ", params[0])
|
|
continue
|
|
}
|
|
|
|
if !chatCommands[params[0]].console {
|
|
log.Print("This command is not available to the console!")
|
|
continue
|
|
}
|
|
|
|
chatCommands[params[0]].function(nil, strings.Join(params[1:], " "))
|
|
default:
|
|
consoleInput = append(consoleInput, ch)
|
|
}
|
|
|
|
draw(l.visible)
|
|
}
|
|
}()
|
|
}
|
|
|
|
type History struct {
|
|
lines [][]rune
|
|
i int
|
|
}
|
|
|
|
func (h *History) Add(line []rune) {
|
|
for k, v := range h.lines {
|
|
if string(v) == string(line) {
|
|
if k+1 < len(h.lines) {
|
|
h.lines = append(h.lines[:k], h.lines[k+1:]...)
|
|
} else {
|
|
h.lines = h.lines[:k]
|
|
}
|
|
}
|
|
}
|
|
|
|
h.lines = append(h.lines, line)
|
|
h.i = 0
|
|
}
|
|
|
|
func (h *History) Prev(current []rune) []rune {
|
|
h.i++
|
|
i := len(h.lines) - h.i
|
|
if i < 0 || i >= len(h.lines) {
|
|
h.i--
|
|
return current
|
|
}
|
|
|
|
return h.lines[i]
|
|
}
|
|
|
|
func (h *History) Next() []rune {
|
|
h.i--
|
|
if h.i < 1 {
|
|
h.i = 0
|
|
return []rune{}
|
|
}
|
|
|
|
return h.lines[len(h.lines)-h.i]
|
|
}
|