90 lines
2.8 KiB
Go
90 lines
2.8 KiB
Go
package main
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
interactiveCommandHelp = "help"
|
|
interactiveCommandQuit = "quit"
|
|
interactiveCommandText = "text"
|
|
interactiveCommandFile = "file"
|
|
)
|
|
|
|
// 交互式命令行界面,允许用户在连接建立后反复发送文本或文件消息。
|
|
var errEmptyInteractiveCommand = errors.New("interactive command is empty")
|
|
|
|
type interactiveCommand struct {
|
|
name string
|
|
to string
|
|
value string
|
|
}
|
|
|
|
// 解析用户输入的交互式命令,支持发送文本或文件消息,以及查看帮助和退出。
|
|
func parseInteractiveCommand(line string) (interactiveCommand, error) {
|
|
commandName, rest, ok := cutInteractiveField(strings.TrimSpace(line))
|
|
if !ok {
|
|
return interactiveCommand{}, errEmptyInteractiveCommand
|
|
}
|
|
|
|
switch strings.ToLower(commandName) {
|
|
case "help", "h", "?":
|
|
return interactiveCommand{name: interactiveCommandHelp}, nil
|
|
case "quit", "exit":
|
|
return interactiveCommand{name: interactiveCommandQuit}, nil
|
|
case interactiveCommandText:
|
|
to, body, err := parseInteractiveTargetValue(rest, interactiveCommandText)
|
|
if err != nil {
|
|
return interactiveCommand{}, err
|
|
}
|
|
return interactiveCommand{name: interactiveCommandText, to: to, value: body}, nil
|
|
case interactiveCommandFile:
|
|
to, path, err := parseInteractiveTargetValue(rest, interactiveCommandFile)
|
|
if err != nil {
|
|
return interactiveCommand{}, err
|
|
}
|
|
return interactiveCommand{name: interactiveCommandFile, to: to, value: path}, nil
|
|
default:
|
|
return interactiveCommand{}, fmt.Errorf("unknown command %q; type help for usage", commandName)
|
|
}
|
|
}
|
|
|
|
func parseInteractiveTargetValue(rest, commandName string) (string, string, error) {
|
|
to, value, ok := cutInteractiveField(strings.TrimSpace(rest))
|
|
if !ok {
|
|
return "", "", fmt.Errorf("%s command requires a target peer and payload", commandName)
|
|
}
|
|
if strings.TrimSpace(value) == "" {
|
|
return "", "", fmt.Errorf("%s command requires a non-empty payload", commandName)
|
|
}
|
|
|
|
return to, strings.TrimSpace(value), nil
|
|
}
|
|
|
|
func cutInteractiveField(input string) (string, string, bool) {
|
|
trimmed := strings.TrimSpace(input)
|
|
if trimmed == "" {
|
|
return "", "", false
|
|
}
|
|
|
|
for i, r := range trimmed {
|
|
if r == ' ' || r == '\t' {
|
|
return trimmed[:i], strings.TrimSpace(trimmed[i+1:]), true
|
|
}
|
|
}
|
|
|
|
return trimmed, "", true
|
|
}
|
|
|
|
// 打印交互式命令帮助信息,列出可用的命令和用法说明。
|
|
func printInteractiveHelp(w io.Writer) {
|
|
_, _ = fmt.Fprintln(w, "interactive mode commands:")
|
|
_, _ = fmt.Fprintln(w, " help show this help")
|
|
_, _ = fmt.Fprintln(w, " text <peer> <message> send one text message over the existing connection")
|
|
_, _ = fmt.Fprintln(w, " file <peer> <path> send one file over the existing connection")
|
|
_, _ = fmt.Fprintln(w, " quit exit this peer process")
|
|
}
|