CommandLib more or less finished
This commit is contained in:
parent
1b0564b39a
commit
82082b128f
14 changed files with 203 additions and 323 deletions
|
@ -1,86 +0,0 @@
|
||||||
package commandlib
|
|
||||||
|
|
||||||
type ArgType byte
|
|
||||||
|
|
||||||
const (
|
|
||||||
StringArg = iota
|
|
||||||
IntArg
|
|
||||||
FloatArg
|
|
||||||
)
|
|
||||||
|
|
||||||
func (a ArgType) String() string {
|
|
||||||
switch a {
|
|
||||||
case StringArg:
|
|
||||||
return "word"
|
|
||||||
case IntArg:
|
|
||||||
return "number"
|
|
||||||
case FloatArg:
|
|
||||||
return "decimal number"
|
|
||||||
default:
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type arg struct {
|
|
||||||
name string
|
|
||||||
help string
|
|
||||||
optional bool
|
|
||||||
|
|
||||||
argType ArgType
|
|
||||||
validators []ArgValidator
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateArg(
|
|
||||||
name string,
|
|
||||||
help string,
|
|
||||||
optional bool,
|
|
||||||
argType ArgType,
|
|
||||||
validators ...ArgValidator,
|
|
||||||
) (res *arg, err error) {
|
|
||||||
res = &arg{
|
|
||||||
name: name,
|
|
||||||
help: help,
|
|
||||||
argType: argType,
|
|
||||||
validators: validators,
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateStringArg(name string, help string, validators ...ArgValidator) (res *arg) {
|
|
||||||
res = &arg{
|
|
||||||
name: name,
|
|
||||||
help: help,
|
|
||||||
argType: StringArg,
|
|
||||||
validators: append([]ArgValidator{StringArgTypeValidator}, validators...),
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (arg *arg) ArgType() ArgType {
|
|
||||||
return arg.argType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (arg *arg) Name() string {
|
|
||||||
return arg.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (arg *arg) IsOptional() bool {
|
|
||||||
return arg.optional
|
|
||||||
}
|
|
||||||
|
|
||||||
func (arg *arg) Validate(value any) (valid bool, feedback []error) {
|
|
||||||
feedback = []error{}
|
|
||||||
|
|
||||||
for _, validate := range arg.validators {
|
|
||||||
err := validate(value)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
valid = false
|
|
||||||
feedback = append(feedback, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
package commandlib
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
type ArgValidator = func(value any) (err error)
|
|
||||||
|
|
||||||
type argValidationError struct {
|
|
||||||
message string
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateArgValidationError(template string, args ...any) *argValidationError {
|
|
||||||
return &argValidationError{
|
|
||||||
message: fmt.Sprintf(template, args...),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (err *argValidationError) Error() string {
|
|
||||||
return err.message
|
|
||||||
}
|
|
||||||
|
|
||||||
func StringArgTypeValidator(value any) (err error) {
|
|
||||||
_, valid := value.(string)
|
|
||||||
|
|
||||||
if !valid {
|
|
||||||
err = CreateArgValidationError("Invalid argument type, expected %v", StringArg)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func IntArgTypeValidator(value any) (err error) {
|
|
||||||
_, valid := value.(int32)
|
|
||||||
|
|
||||||
if !valid {
|
|
||||||
err = CreateArgValidationError("Invalid type, expected %v", IntArg)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func FloatArgTypeValidator(value any) (err error) {
|
|
||||||
_, valid := value.(float32)
|
|
||||||
|
|
||||||
if !valid {
|
|
||||||
err = CreateArgValidationError("Invalid type, expected %v", FloatArg)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package commandlib
|
|
||||||
|
|
||||||
type argValue struct {
|
|
||||||
value any
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateArgValue(val any) *argValue {
|
|
||||||
return &argValue{
|
|
||||||
value: val,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (aVal *argValue) Value() any {
|
|
||||||
return aVal.value
|
|
||||||
}
|
|
|
@ -1,71 +1,70 @@
|
||||||
package commandlib
|
package commandlib
|
||||||
|
|
||||||
type ArgumentBase interface {
|
type Command struct {
|
||||||
Name() string
|
commandDefinition CommandDefinition
|
||||||
ArgType() ArgType
|
params []Parameter
|
||||||
IsOptional() bool
|
|
||||||
Validate(value any) (valid bool, feedback []error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ArgumentValue interface {
|
func CreateCommand(cmdDef CommandDefinition, parameters []Parameter) Command {
|
||||||
Value() any
|
return Command{
|
||||||
|
commandDefinition: cmdDef,
|
||||||
|
params: parameters,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type command struct {
|
func (cmd Command) Execute() (err error) {
|
||||||
name string
|
return cmd.commandDefinition.work(cmd.params...)
|
||||||
altname string
|
|
||||||
|
|
||||||
args []ArgumentBase
|
|
||||||
|
|
||||||
work func(argValues []ArgumentValue) (err error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateCommand(
|
type commandContextError struct {
|
||||||
name string,
|
err string
|
||||||
altname string,
|
}
|
||||||
work func(argValues []ArgumentValue) (err error),
|
|
||||||
arguments ...ArgumentBase,
|
|
||||||
) (cmd *command, err error) {
|
|
||||||
var onlyAcceptingOptionals = false
|
|
||||||
|
|
||||||
for _, v := range arguments {
|
func createCommandContextError(err string) *commandContextError {
|
||||||
if !v.IsOptional() && onlyAcceptingOptionals {
|
return &commandContextError{
|
||||||
// Optional arguments can only be placed after non-optional ones
|
err: err,
|
||||||
err = CreateCommandLibError(name, "Cannot define non-optional arguments after optional ones.")
|
}
|
||||||
cmd = nil
|
}
|
||||||
|
|
||||||
|
func (cce *commandContextError) Error() string {
|
||||||
|
return cce.err
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommandContext struct {
|
||||||
|
commandString string
|
||||||
|
tokens []Token
|
||||||
|
|
||||||
|
command Command
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateCommandContext(commandRegistry *CommandRegistry, commandString string) (ctx *CommandContext, err error) {
|
||||||
|
tokenizer := CreateTokenizer()
|
||||||
|
|
||||||
|
tokens, tokenizerError := tokenizer.Tokenize(commandString)
|
||||||
|
|
||||||
|
if tokenizerError != nil {
|
||||||
|
err = tokenizerError
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.IsOptional() {
|
commandDef := commandRegistry.Match(tokens)
|
||||||
onlyAcceptingOptionals = true
|
|
||||||
}
|
if commandDef == nil {
|
||||||
|
err = createCommandContextError("Unknown command")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd = new(command)
|
params := commandDef.ParseParameters(tokens)
|
||||||
|
|
||||||
cmd.name = name
|
ctx = &CommandContext{
|
||||||
cmd.altname = altname
|
commandString: commandString,
|
||||||
cmd.work = work
|
tokens: tokens,
|
||||||
|
command: CreateCommand(*commandDef, params),
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *command) Name() string {
|
func (ctx *CommandContext) ExecuteCommand() (err error) {
|
||||||
return cmd.name
|
return ctx.command.Execute()
|
||||||
}
|
|
||||||
|
|
||||||
func (cmd *command) Execute(argValues []ArgumentValue) (err error) {
|
|
||||||
|
|
||||||
for i, v := range cmd.args {
|
|
||||||
if i > len(argValues)-1 {
|
|
||||||
if !v.IsOptional() {
|
|
||||||
return CreateCommandLibError(cmd.name, "Not enough arguments, found %d, expected more", len(argValues))
|
|
||||||
} else {
|
|
||||||
break // There are no more arg values to process, and the remaining arguments are all optional anyway
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cmd.work(argValues)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
package commandlib
|
|
||||||
|
|
||||||
type commandContext struct {
|
|
||||||
commandString string
|
|
||||||
tokens []Token
|
|
||||||
|
|
||||||
command Command
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateCommandContext(commandString string) (ctx *commandContext, err error) {
|
|
||||||
tokenizer := CreateTokenizer()
|
|
||||||
|
|
||||||
tokens, tokenizerError := tokenizer.Tokenize(commandString)
|
|
||||||
|
|
||||||
if tokenizerError != nil {
|
|
||||||
err = tokenizerError
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = &commandContext{
|
|
||||||
commandString: commandString,
|
|
||||||
tokens: tokens,
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *commandContext) Execute() (err error) {
|
|
||||||
ctx.command.Execute()
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
package commandlib
|
|
||||||
|
|
||||||
type CommandDefinition struct {
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package commandlib
|
|
||||||
|
|
||||||
type Command interface {
|
|
||||||
Name() string
|
|
||||||
DoWork(argValues []ArgumentValue) (err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type commandRegistry struct {
|
|
||||||
commands []Command
|
|
||||||
}
|
|
|
@ -2,18 +2,18 @@ package commandlib
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
type commandLibError struct {
|
type commandError struct {
|
||||||
cmdName string
|
cmdName string
|
||||||
message string
|
message string
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateCommandLibError(cmdName string, msg string, msgArgs ...any) *commandLibError {
|
func createCommandError(cmdName string, msg string, msgArgs ...any) *commandError {
|
||||||
return &commandLibError{
|
return &commandError{
|
||||||
cmdName: cmdName,
|
cmdName: cmdName,
|
||||||
message: fmt.Sprintf(msg, msgArgs...),
|
message: fmt.Sprintf(msg, msgArgs...),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmdErr *commandLibError) Error() string {
|
func (cmdErr *commandError) Error() string {
|
||||||
return "Error with command '" + cmdErr.cmdName + "': " + cmdErr.message
|
return "Error with command '" + cmdErr.cmdName + "': " + cmdErr.message
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
package commandlib
|
|
||||||
|
|
||||||
type Parameter interface {
|
|
||||||
Value() any
|
|
||||||
}
|
|
||||||
|
|
||||||
type Command interface {
|
|
||||||
Name() string
|
|
||||||
Parameters() []Parameter
|
|
||||||
}
|
|
|
@ -45,7 +45,7 @@ look ::= "look" [ "around" | direction | "at" identifier ] ;
|
||||||
|
|
||||||
move ::= "move" direction | "go" direction ;
|
move ::= "move" direction | "go" direction ;
|
||||||
|
|
||||||
// [Player Name], [Item Name], [Place Name] or just Played Name, Item Name, Place Name
|
// [Player Name], [Item Name], [Place Name] or just Player Name, Item Name, Place Name
|
||||||
// brackets may be useful in situations where there are multiple identifiers
|
// brackets may be useful in situations where there are multiple identifiers
|
||||||
identifier ::= "[" name "]" | name ;
|
identifier ::= "[" name "]" | name ;
|
||||||
|
|
||||||
|
@ -57,12 +57,10 @@ number ::= digit ( digit )* ; // 123, 12, 97401, etc.
|
||||||
|
|
||||||
word ::= letter+;
|
word ::= letter+;
|
||||||
|
|
||||||
chatMessage ::= ( letter | punctuation | digit | space )+ ;
|
chatMessage ::= ( letter | digit | space )+ ;
|
||||||
|
|
||||||
direction ::= "east" | "west" | "north" | "up" | "down" ;
|
direction ::= "east" | "west" | "north" | "up" | "down" ;
|
||||||
|
|
||||||
punctuation ::= "," | "." | "!" | "?" | "'" | "/" | '"' | ":" | ";" | "-" | "(" | ")" | "[" | "]" ;
|
|
||||||
|
|
||||||
letter ::= "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"
|
letter ::= "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"
|
||||||
| "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t"
|
| "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t"
|
||||||
| "u" | "v" | "w" | "x" | "y" | "z" ;
|
| "u" | "v" | "w" | "x" | "y" | "z" ;
|
||||||
|
|
25
src/CommandLib/parameter.go
Normal file
25
src/CommandLib/parameter.go
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package commandlib
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
type Parameter struct {
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateParameter(value string) Parameter {
|
||||||
|
return Parameter{
|
||||||
|
value: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Parameter) AsString() (res string, err error) {
|
||||||
|
return p.value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Parameter) AsInteger() (res int, err error) {
|
||||||
|
return strconv.Atoi(p.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Parameter) AsDecimal() (res float64, err error) {
|
||||||
|
return strconv.ParseFloat(p.value, 32)
|
||||||
|
}
|
71
src/CommandLib/registry.go
Normal file
71
src/CommandLib/registry.go
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
package commandlib
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
|
||||||
|
type TokenMatcher func(tokens []Token) bool
|
||||||
|
|
||||||
|
type ParameterParser func(tokens []Token) []Parameter
|
||||||
|
|
||||||
|
type CommandWork func(parameters ...Parameter) (err error)
|
||||||
|
|
||||||
|
type CommandDefinition struct {
|
||||||
|
name string
|
||||||
|
tokenMatcher TokenMatcher
|
||||||
|
parameterParser ParameterParser
|
||||||
|
work CommandWork
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateCommandDefinition(
|
||||||
|
name string,
|
||||||
|
tokenMatcher TokenMatcher,
|
||||||
|
parameterParser ParameterParser,
|
||||||
|
work CommandWork,
|
||||||
|
) CommandDefinition {
|
||||||
|
return CommandDefinition{
|
||||||
|
name: name,
|
||||||
|
tokenMatcher: tokenMatcher,
|
||||||
|
parameterParser: parameterParser,
|
||||||
|
work: work,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (def CommandDefinition) Name() string {
|
||||||
|
return def.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (def CommandDefinition) Match(tokens []Token) bool {
|
||||||
|
return def.tokenMatcher(tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (def CommandDefinition) ParseParameters(tokens []Token) []Parameter {
|
||||||
|
return def.parameterParser(tokens)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (def CommandDefinition) ExecuteFunc() CommandWork {
|
||||||
|
return def.work
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommandRegistry struct {
|
||||||
|
commandDefinitions []CommandDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateCommandRegistry(commandDefinitions ...CommandDefinition) *CommandRegistry {
|
||||||
|
return &CommandRegistry{
|
||||||
|
commandDefinitions: commandDefinitions,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (comReg *CommandRegistry) Register(newCommandDefinitions ...CommandDefinition) {
|
||||||
|
comReg.commandDefinitions = append(comReg.commandDefinitions, newCommandDefinitions...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (comReg *CommandRegistry) Match(tokens []Token) (comDef *CommandDefinition) {
|
||||||
|
for _, v := range comReg.commandDefinitions {
|
||||||
|
if v.Match(tokens) {
|
||||||
|
log.Println("Found match", v.Name())
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
|
@ -20,7 +20,6 @@ const (
|
||||||
|
|
||||||
TokenDirection
|
TokenDirection
|
||||||
TokenCommand
|
TokenCommand
|
||||||
TokenSayCommand
|
|
||||||
TokenSelf
|
TokenSelf
|
||||||
|
|
||||||
TokenWhitespace
|
TokenWhitespace
|
||||||
|
@ -46,8 +45,6 @@ func (tt TokenType) String() string {
|
||||||
return "Direction"
|
return "Direction"
|
||||||
case TokenCommand:
|
case TokenCommand:
|
||||||
return "Command"
|
return "Command"
|
||||||
case TokenSayCommand:
|
|
||||||
return "SayCommand"
|
|
||||||
case TokenSelf:
|
case TokenSelf:
|
||||||
return "Self"
|
return "Self"
|
||||||
case TokenWhitespace:
|
case TokenWhitespace:
|
||||||
|
@ -92,12 +89,15 @@ type tokenPattern struct {
|
||||||
pattern string
|
pattern string
|
||||||
}
|
}
|
||||||
|
|
||||||
type tokenizer struct {
|
// Used to tokenize a string input.
|
||||||
|
// This is the starting point for parsing a command string.
|
||||||
|
// Create with [CreateTokenizer]
|
||||||
|
type Tokenizer struct {
|
||||||
tokenPatterns []tokenPattern
|
tokenPatterns []tokenPattern
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateTokenizer() *tokenizer {
|
func CreateTokenizer() *Tokenizer {
|
||||||
return &tokenizer{
|
return &Tokenizer{
|
||||||
tokenPatterns: []tokenPattern{
|
tokenPatterns: []tokenPattern{
|
||||||
{tokenType: TokenDecimal, pattern: `\b\d+\.\d+\b`},
|
{tokenType: TokenDecimal, pattern: `\b\d+\.\d+\b`},
|
||||||
{tokenType: TokenNumber, pattern: `\b\d+\b`},
|
{tokenType: TokenNumber, pattern: `\b\d+\b`},
|
||||||
|
@ -111,15 +111,16 @@ func CreateTokenizer() *tokenizer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tokenizer) Tokenize(commandMsg string) (tokens []Token, err error) {
|
// Tokenize a command string
|
||||||
|
func (t *Tokenizer) Tokenize(commandString string) (tokens []Token, err error) {
|
||||||
tokens = []Token{}
|
tokens = []Token{}
|
||||||
pos := 0
|
pos := 0
|
||||||
inputLen := len(commandMsg)
|
inputLen := len(commandString)
|
||||||
|
|
||||||
// Continue iterating until we reach the end of the input
|
// Continue iterating until we reach the end of the input
|
||||||
for pos < inputLen {
|
for pos < inputLen {
|
||||||
matched := false
|
matched := false
|
||||||
remaining := commandMsg[pos:]
|
remaining := commandString[pos:]
|
||||||
|
|
||||||
// Iterate through each token type and test its pattern
|
// Iterate through each token type and test its pattern
|
||||||
for _, pattern := range t.tokenPatterns {
|
for _, pattern := range t.tokenPatterns {
|
||||||
|
@ -133,7 +134,7 @@ func (t *tokenizer) Tokenize(commandMsg string) (tokens []Token, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the loc isn't nil, that means we've found a match
|
// If the location of the match isn't nil, that means we've found a match
|
||||||
if loc := re.FindStringIndex(remaining); loc != nil {
|
if loc := re.FindStringIndex(remaining); loc != nil {
|
||||||
lexeme := remaining[loc[0]:loc[1]]
|
lexeme := remaining[loc[0]:loc[1]]
|
||||||
|
|
||||||
|
@ -145,9 +146,9 @@ func (t *tokenizer) Tokenize(commandMsg string) (tokens []Token, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unknown tokens are still added, except carriage return (\r) and newline (\n)
|
// Unknown tokens are still added
|
||||||
if !matched {
|
if !matched {
|
||||||
tokens = append(tokens, CreateToken(TokenUnknown, commandMsg[pos:pos+1], pos))
|
tokens = append(tokens, CreateToken(TokenUnknown, commandString[pos:pos+1], pos))
|
||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
|
||||||
|
|
||||||
commandlib "code.haedhutner.dev/mvv/LastMUD/CommandLib"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Command interface {
|
type Command interface {
|
||||||
|
@ -15,18 +12,6 @@ type Command interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// testcmd, err := commandlib.CreateCommand(
|
|
||||||
// "test",
|
|
||||||
// "t",
|
|
||||||
// func(argValues []commandlib.ArgumentValue) (err error) {
|
|
||||||
// err = nil
|
|
||||||
// return
|
|
||||||
// },
|
|
||||||
// commandlib.CreateStringArg("test", "test message"),
|
|
||||||
// )
|
|
||||||
|
|
||||||
tokenizer := commandlib.CreateTokenizer()
|
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", ":8000")
|
ln, err := net.Listen("tcp", ":8000")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -41,47 +26,52 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cmdRegistry := commandlib.CreateCommandRegistry(
|
||||||
|
// commandlib.CreateCommandDefinition(
|
||||||
|
// "exit",
|
||||||
|
// func(tokens []commandlib.Token) bool {
|
||||||
|
// return tokens[0].Lexeme() == "exit"
|
||||||
|
// },
|
||||||
|
// func(tokens []commandlib.Token) []commandlib.Parameter {
|
||||||
|
// return nil
|
||||||
|
// },
|
||||||
|
// func(parameters ...commandlib.Parameter) (err error) {
|
||||||
|
// err = conn.Close()
|
||||||
|
// return
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
// )
|
||||||
|
|
||||||
for {
|
for {
|
||||||
message, err := bufio.NewReader(conn).ReadString('\n')
|
message, _ := bufio.NewReader(conn).ReadString('\n')
|
||||||
response := ""
|
response := ""
|
||||||
|
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Fatal(err)
|
|
||||||
}
|
// if err == io.EOF {
|
||||||
|
// fmt.Println("Client disconnected")
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
|
||||||
|
// log.Println("Read error:", err)
|
||||||
|
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
|
||||||
conn.Write([]byte(message + "\n"))
|
conn.Write([]byte(message + "\n"))
|
||||||
|
|
||||||
tokens, err := tokenizer.Tokenize(message)
|
// cmdContext, err := commandlib.CreateCommandContext(cmdRegistry, message)
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
response = err.Error()
|
|
||||||
} else {
|
|
||||||
lines := make([]string, len(tokens))
|
|
||||||
|
|
||||||
for i, tok := range tokens {
|
|
||||||
lines[i] = tok.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
response = strings.Join(lines, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
// if strings.HasPrefix(message, testcmd.Name()) {
|
|
||||||
// tokens := commandlib.Tokenize(message)
|
|
||||||
// args := []commandlib.ArgumentValue{}
|
|
||||||
|
|
||||||
// for _, v := range tokens[1:] {
|
|
||||||
// args = append(args, commandlib.CreateArgValue(v))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// err := testcmd.DoWork(args)
|
|
||||||
|
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// fmt.Print(err.Error())
|
// log.Println(err)
|
||||||
// }
|
// response = err.Error()
|
||||||
// } else {
|
// } else {
|
||||||
// fmt.Print("Message Received: ", string(message))
|
// // err = cmdContext.ExecuteCommand()
|
||||||
|
|
||||||
// response = strings.ToUpper(message)
|
// // if err != nil {
|
||||||
|
// // log.Println(err)
|
||||||
|
// // response = err.Error()
|
||||||
|
// // }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
conn.Write([]byte(response + "\n> "))
|
conn.Write([]byte(response + "\n> "))
|
||||||
|
|
Loading…
Add table
Reference in a new issue