cli: Improve the feel of using commands in conversation mode
This commit is contained in:
parent
9bd509c3d8
commit
48aab2536a
|
@ -20,6 +20,7 @@ type UI struct {
|
||||||
Client *Client
|
Client *Client
|
||||||
|
|
||||||
CurrentContact *Contact
|
CurrentContact *Contact
|
||||||
|
commandMode bool
|
||||||
|
|
||||||
baseConfig *readline.Config
|
baseConfig *readline.Config
|
||||||
baseChatConfig *readline.Config
|
baseChatConfig *readline.Config
|
||||||
|
@ -54,17 +55,12 @@ func (ui *UI) Execute(line string) error {
|
||||||
ui.Client.Block()
|
ui.Client.Block()
|
||||||
defer ui.Client.Unblock()
|
defer ui.Client.Unblock()
|
||||||
|
|
||||||
words := strings.SplitN(line, " ", 2)
|
if ui.CurrentContact != nil && !ui.commandMode {
|
||||||
|
ui.CurrentContact.Conversation.SendMessage(line)
|
||||||
if ui.CurrentContact != nil {
|
return nil
|
||||||
if len(words[0]) > 0 && words[0][0] == '/' {
|
|
||||||
words[0] = words[0][1:]
|
|
||||||
} else {
|
|
||||||
ui.CurrentContact.Conversation.SendMessage(line)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
words := strings.SplitN(line, " ", 2)
|
||||||
if id, err := strconv.Atoi(words[0]); err == nil {
|
if id, err := strconv.Atoi(words[0]); err == nil {
|
||||||
contact := ui.Client.Contacts.ById(int32(id))
|
contact := ui.Client.Contacts.ById(int32(id))
|
||||||
if contact != nil {
|
if contact != nil {
|
||||||
|
@ -280,36 +276,55 @@ type conversationInputConfig struct {
|
||||||
BaseConfig *readline.Config
|
BaseConfig *readline.Config
|
||||||
PromptFmt string
|
PromptFmt string
|
||||||
|
|
||||||
|
CommandModeFlag *bool
|
||||||
|
editingLine []rune
|
||||||
|
|
||||||
usingConfig bool
|
usingConfig bool
|
||||||
stopPromptTimer chan struct{}
|
stopPromptTimer chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *conversationInputConfig) OnChange(line []rune, pos int, key rune) ([]rune, int, bool) {
|
func (cc *conversationInputConfig) OnChange(line []rune, pos int, key rune) ([]rune, int, bool) {
|
||||||
if len(line) == 0 && key != 0 && !cc.usingConfig {
|
cc.editingLine = line
|
||||||
cc.Install()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(line) > 0 && line[0] == '/' {
|
// Unset command mode at the beginning of a new read
|
||||||
if cc.usingConfig {
|
if line == nil && pos == 0 && key == 0 {
|
||||||
cc.stopPromptTimer <- struct{}{}
|
cc.Install()
|
||||||
cc.usingConfig = false
|
|
||||||
close(cc.stopPromptTimer)
|
|
||||||
cc.BaseConfig.Listener = cc.Config.Listener
|
|
||||||
cc.Input.SetConfig(cc.BaseConfig)
|
|
||||||
}
|
|
||||||
} else if !cc.usingConfig {
|
|
||||||
line = append([]rune{'/'}, line...)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return line, pos, true
|
return line, pos, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cc *conversationInputConfig) FilterInputRune(key rune) (rune, bool) {
|
||||||
|
if key == '/' && len(cc.editingLine) == 0 && cc.usingConfig {
|
||||||
|
// '/' at the beginning of the input triggers command mode
|
||||||
|
cc.stopPromptTimer <- struct{}{}
|
||||||
|
cc.usingConfig = false
|
||||||
|
close(cc.stopPromptTimer)
|
||||||
|
cc.BaseConfig.Listener = cc.Config.Listener
|
||||||
|
cc.BaseConfig.FuncFilterInputRune = cc.FilterInputRune
|
||||||
|
cc.Input.SetConfig(cc.BaseConfig)
|
||||||
|
*cc.CommandModeFlag = true
|
||||||
|
|
||||||
|
// The / is suppressed from the output
|
||||||
|
return key, false
|
||||||
|
} else if (key == readline.CharBackspace || key == readline.CharCtrlH) &&
|
||||||
|
len(cc.editingLine) == 0 && !cc.usingConfig {
|
||||||
|
// Backspace on an empty command mode line unsets command mode
|
||||||
|
cc.Install()
|
||||||
|
return key, false
|
||||||
|
} else {
|
||||||
|
return key, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (cc *conversationInputConfig) Install() {
|
func (cc *conversationInputConfig) Install() {
|
||||||
if !cc.usingConfig {
|
if !cc.usingConfig {
|
||||||
cc.usingConfig = true
|
cc.usingConfig = true
|
||||||
|
cc.Config.FuncFilterInputRune = cc.FilterInputRune
|
||||||
cc.Input.SetConfig(cc.Config)
|
cc.Input.SetConfig(cc.Config)
|
||||||
cc.stopPromptTimer = make(chan struct{})
|
cc.stopPromptTimer = make(chan struct{})
|
||||||
go cc.updatePromptTimer()
|
go cc.updatePromptTimer()
|
||||||
|
*cc.CommandModeFlag = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +335,9 @@ func (cc *conversationInputConfig) Remove() {
|
||||||
cc.stopPromptTimer <- struct{}{}
|
cc.stopPromptTimer <- struct{}{}
|
||||||
cc.usingConfig = false
|
cc.usingConfig = false
|
||||||
close(cc.stopPromptTimer)
|
close(cc.stopPromptTimer)
|
||||||
|
cc.BaseConfig.FuncFilterInputRune = nil
|
||||||
cc.Input.SetConfig(cc.BaseConfig)
|
cc.Input.SetConfig(cc.BaseConfig)
|
||||||
|
*cc.CommandModeFlag = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,10 +363,11 @@ func (ui *UI) setupConversationPrompt() {
|
||||||
}
|
}
|
||||||
|
|
||||||
listener := &conversationInputConfig{
|
listener := &conversationInputConfig{
|
||||||
Input: ui.Input,
|
Input: ui.Input,
|
||||||
Config: ui.baseChatConfig.Clone(),
|
Config: ui.baseChatConfig.Clone(),
|
||||||
BaseConfig: ui.baseConfig,
|
BaseConfig: ui.baseConfig,
|
||||||
PromptFmt: fmt.Sprintf(ui.baseChatConfig.Prompt, "%s", ui.CurrentContact.Data.Nickname),
|
PromptFmt: fmt.Sprintf(ui.baseChatConfig.Prompt, "%s", ui.CurrentContact.Data.Nickname),
|
||||||
|
CommandModeFlag: &ui.commandMode,
|
||||||
}
|
}
|
||||||
listener.Config.Listener = listener
|
listener.Config.Listener = listener
|
||||||
listener.Install()
|
listener.Install()
|
||||||
|
|
Loading…
Reference in New Issue