func (m *Multibar) deleteWord() {
	m.tabComplete = nil
	cursor := m.cursor - 1
	for ; cursor >= 0; cursor-- {
		if !unicode.IsSpace(m.buffer[cursor]) {
			break
		}
	}
	for ; cursor >= 0; cursor-- {
		if unicode.IsSpace(m.buffer[cursor]) {
			cursor++
			break
		}
	}
	runes := deleteBackwards(m.buffer, m.cursor, m.cursor-cursor)
	m.cursor = cursor
	m.setRunes(runes)
	m.History().Reset(m.String())
}
deleteWord deletes the previous word, along with all the backspace
succeeding it.
package multibar
import (
	"strings"
	"unicode"
	"unicode/utf8"
	"github.com/ambientsound/visp/log"
	"github.com/ambientsound/visp/input/lexer"
	"github.com/ambientsound/visp/message"
	"github.com/ambientsound/visp/utils"
	"github.com/gdamore/tcell/v2"
)
type TabCompleter interface {
	Scan() (string, error)
}
type TabCompleterFactory func(input string) TabCompleter
type Multibar struct {
	buffer      []rune
	commands    chan string
	cursor      int
	history     []*history
	mode        InputMode
	msg         message.Message
	orig        []rune
	searches    chan string
	tabComplete TabCompleter
	tcf         TabCompleterFactory
}
func New(tcf TabCompleterFactory) *Multibar {
	hist := make([]*history, 3)
	for i := range hist {
		hist[i] = NewHistory()
	}
	return &Multibar{
		history:  hist,
		buffer:   make([]rune, 0),
		orig:     make([]rune, 0),
		commands: make(chan string, 1),
		searches: make(chan string, 1),
		tcf:      tcf,
	}
}
func (m *Multibar) Input(event tcell.Event) bool {
	ev, ok := event.(*tcell.EventKey)
	if !ok {
		return false
	}
	if m.mode == ModeNormal {
		return false
	}
	log.Debugf("multibar keypress: name=%v key=%v modifiers=%v", ev.Name(), ev.Key(), ev.Modifiers())
	switch ev.Key() {
	case tcell.KeyRune:
		modifiers := ev.Modifiers()
		if modifiers&tcell.ModAlt == 0 {
			m.inputRune(ev.Rune())
		} else {
			switch ev.Rune() {
			case 'b':
				m.wordJump(-1)
			case 'f':
				m.wordJump(1)
			}
		}
	case tcell.KeyCtrlU:
		m.truncate()
	case tcell.KeyEnter:
		m.finish()
	case tcell.KeyTab:
		if m.Mode() == ModeInput {
			m.tab()
		}
	case tcell.KeyLeft, tcell.KeyCtrlB:
		m.moveCursor(-1)
	case tcell.KeyRight, tcell.KeyCtrlF:
		m.moveCursor(1)
	case tcell.KeyUp, tcell.KeyCtrlP:
		m.moveHistory(-1)
	case tcell.KeyDown, tcell.KeyCtrlN:
		m.moveHistory(1)
	case tcell.KeyCtrlG, tcell.KeyCtrlC:
		if m.tabComplete == nil {
			m.abort()
		} else {
			m.untab()
		}
	case tcell.KeyCtrlA, tcell.KeyHome:
		m.moveCursor(-len(m.buffer))
	case tcell.KeyCtrlE, tcell.KeyEnd:
		m.moveCursor(len(m.buffer))
	case tcell.KeyBS, tcell.KeyDEL:
		m.backspace()
	case tcell.KeyCtrlW:
		m.deleteWord()
	default:
		log.Debugf("Unhandled text input event in Multibar: %v", ev.Key())
		return false
	}
	return true
}
func (m *Multibar) History() *history {
	return m.history[m.mode]
}
func (m *Multibar) Clear() {
	m.SetMessage(message.Message{
		Severity: message.Info,
		Text:     "",
	})
}
func (m *Multibar) Error(err error) {
	m.SetMessage(message.Message{
		Severity: message.Error,
		Text:     err.Error(),
	})
}
func (m *Multibar) Message() message.Message {
	return m.msg
}
func (m *Multibar) SetMessage(msg message.Message) {
	m.msg = msg
}
func (m *Multibar) SetMode(mode InputMode) {
	log.Debugf("Switching input mode from %s to %s", m.mode, mode)
	m.mode = mode
	m.setRunes(make([]rune, 0))
	m.History().Reset("")
}
func (m *Multibar) Mode() InputMode {
	return m.mode
}
func (m *Multibar) String() string {
	return string(m.buffer)
}
func (m *Multibar) Len() int {
	return len(m.buffer)
}
func (m *Multibar) Cursor() int {
	return m.cursor
}
func (m *Multibar) Commands() <-chan string {
	return m.commands
}
func (m *Multibar) Searches() <-chan string {
	return m.searches
}
func (m *Multibar) setRunes(r []rune) {
	m.buffer = r
	m.validateCursor()
}
func (m *Multibar) validateCursor() {
	if m.cursor > len(m.buffer) {
		m.cursor = len(m.buffer)
	}
	if m.cursor < 0 {
		m.cursor = 0
	}
}
func (m *Multibar) truncate() {
	m.tabComplete = nil
	m.setRunes(make([]rune, 0))
	m.History().Reset(m.String())
}
func (m *Multibar) inputRune(r rune) {
	m.tabComplete = nil
	runes := make([]rune, len(m.buffer)+1)
	copy(runes, m.buffer[:m.cursor])
	copy(runes[m.cursor+1:], m.buffer[m.cursor:])
	runes[m.cursor] = r
	m.setRunes(runes)
	m.cursor++
	m.History().Reset(m.String())
}
func (m *Multibar) backspace() {
	m.tabComplete = nil
	if len(m.buffer) == 0 {
		m.abort()
		return
	}
	runes := deleteBackwards(m.buffer, m.cursor, 1)
	m.cursor--
	m.setRunes(runes)
	m.History().Reset(m.String())
}