diff --git a/NOTES.md b/NOTES.md new file mode 100644 index 0000000000000000000000000000000000000000..9ce89dc3f071adfc4d3def1017b0a46515d48f69 --- /dev/null +++ b/NOTES.md @@ -0,0 +1,11 @@ +# Development notes + +These are the development notes for the Go version. + +The idea is to use the help files to implement BULLETIN. + +## Module links + + * cli ([docs](https://cli.urfave.org/v3/getting-started/), [github](https://pkg.go.dev/github.com/urfave/cli/v3)) + * readline ([docs](https://pkg.go.dev/github.com/chzyer/readline), [github](https://github.com/chzyer/readline)) + * xdg ([docs](https://pkg.go.dev/github.com/adrg/xdg), [github](https://github.com/adrg/xdg)) diff --git a/accounts/accounts.go b/accounts/accounts.go index 32412dd489ffa0b5714fbae70a4f63c2f17d24ac..beb1c48f95d204ccc73930ceb77c96dfdd57525a 100644 --- a/accounts/accounts.go +++ b/accounts/accounts.go @@ -10,3 +10,8 @@ func Verify(acc string) error { } return nil } + +// IsAdmin returns true if the user is an admin +func IsAdmin(acc string) bool { + return false +} diff --git a/go.mod b/go.mod index a82526a6e502dfec887a738223b22fb03a5595ff..a7c9849b48a2fcb5ed8f42bdcc3004683d46f4c7 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,8 @@ module git.lyda.ie/kevin/bulletin go 1.24.2 -require github.com/urfave/cli/v3 v3.3.2 // indirect +require ( + github.com/chzyer/readline v1.5.1 // indirect + github.com/urfave/cli/v3 v3.3.2 // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect +) diff --git a/go.sum b/go.sum index 80dc36d5fb7c9d6272c40569bcad852a0bb49e34..e3a5fccaaa4e63c632e27b59b7223a1c62204460 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,8 @@ +github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI= +github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= +github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/urfave/cli/v3 v3.3.2 h1:BYFVnhhZ8RqT38DxEYVFPPmGFTEf7tJwySTXsVRrS/o= github.com/urfave/cli/v3 v3.3.2/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/main.go b/main.go index 6df8ee6c8e51616777344a7807dc47ed67e98369..be02f5d8c5866eed92d45de4dc64730154836c59 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "os" "git.lyda.ie/kevin/bulletin/accounts" + "git.lyda.ie/kevin/bulletin/repl" "github.com/urfave/cli/v3" ) @@ -32,7 +33,10 @@ func main() { if err != nil { return err } - fmt.Println("Running as", user) + err = repl.Loop(user) + if err != nil { + return err + } return nil }, } diff --git a/repl/command.go b/repl/command.go new file mode 100644 index 0000000000000000000000000000000000000000..5567900ba7bf065af140e08863794346ad293653 --- /dev/null +++ b/repl/command.go @@ -0,0 +1,412 @@ +// Package repl implements the main event loop. +package repl + +type command struct { + command string + boolFlags []string + strFlags []string + args []string + commands []*command + action func(string, *command) error + } + +var commands = []*command{ + { + command: "ADD", + boolFlags: []string{ + "/ALL", + "/BELL", + "/BROADCAST", + "/CLUSTER", + "/EDIT", + "/EXPIRATION", + "/EXTRACT", + "/FOLDER", + "/LOCAL", + "/NODES", + "/NOINDENT", + "/PERMANENT", + "/SUBJECT", + "/SHUTDOWN", + "/SYSTEM", + "/USERNAME", + }, + }, + { + command: "ATTACH", + // 2 Parameters + // 2 Qualifiers + // 2 Examples + }, + { + command: "BACK", + }, + { + command: "BULLETIN", + }, + { + command: "CHANGE", + boolFlags: []string{ + "/ALL", + "/EDIT", + "/EXPIRATION", + "/GENERAL", + "/HEADER", + "/NEW", + "/NUMBER", + "/PERMANENT", + "/SHUTDOWN[=nodename]", + "/SUBJECT", + "/SYSTEM", + "/TEXT", + }, + }, + { + command: "COPY", + boolFlags: []string{ + "/ALL", + "/MERGE", + "/ORIGINAL", + }, + }, + { + command: "CREATE", + boolFlags: []string{ + "/BRIEF", + "/DESCRIPTION", + "/ID", + "/NODE", + "/NOTIFY", + "/OWNER", + "/PRIVATE", + "/READNEW", + "/REMOTENAME", + "/SHOWNEW", + "/SEMIPRIVATE", + "/SYSTEM", + }, + }, + { + command: "CURRENT", + boolFlags: []string{ + "/EDIT", + }, + }, + { + command: "DELETE", + boolFlags: []string{ + "/ALL", + "/IMMEDIATE", + "/NODES", + "/SUBJECT", + "/USERNAME", + }, + }, + { + command: "DIRECTORY", + boolFlags: []string{ + "/DESCRIBE", + "/EXPIRATION", + "/FOLDERS", + "/MARKED", + "/NEW", + "/REPLY", + "/SEARCH", + "/SINCE", + "/START", + "/SUBJECT", + }, + }, + { + command: "EXIT", + }, + { + command: "EXTRACT", + }, + { + command: "FILE", + boolFlags: []string{ + "/ALL", + "/FF", + "/HEADER", + "/NEW", + }, + }, + { + command: "Folders", + }, + { + command: "HELP", + }, + { + command: "INDEX", + boolFlags: []string{ + "/MARKED", + "/NEW", + "/RESTART", + }, + }, + { + command: "KEYPAD", + }, + { + command: "LAST", + }, + { + command: "MAIL", + boolFlags: []string{ + "/HEADER", + "/SUBJECT", + }, + }, + { + command: "MARK", + }, + { + command: "MODIFY", + boolFlags: []string{ + "/DESCRIPTION", + "/ID", + "/NAME", + "/OWNER", + }, + }, + { + command: "MOVE", + boolFlags: []string{ + "/ALL", + "/MERGE", + "/ORIGINAL", + }, + }, + { + command: "NEXT", + }, + { + command: "POST", + boolFlags: []string{ + "/CC", + "/EDIT", + "/EXTRACT", + "/NOINDENT", + "/SUBJECT", + }, + }, + { + command: "PRINT", + boolFlags: []string{ + "/ALL", + "/FORM", + "/HEADER", + "/NOTIFY", + "/QUEUE", + }, + }, + { + command: "READ", + boolFlags: []string{ + "/EDIT", + "/MARKED", + "/NEW", + "/PAGE", + "/SINCE", + }, + }, + { + command: "REMOVE", + }, + { + command: "REPLY", + boolFlags: []string{ + "/EXTRACT", + "/NOINDENT", + }, + }, + { + command: "RESPOND", + boolFlags: []string{ + "/CC", + "/EDIT", + "/EXTRACT", + "/LIST", + "/NOINDENT", + "/SUBJECT", + }, + }, + { + command: "QUIT", + }, + { + command: "SEARCH", + boolFlags: []string{ + "/REPLY", + "/REVERSE", + "/START", + "/SUBJECT", + }, + }, + { + command: "SELECT", + boolFlags: []string{ + "/MARKED", + }, + }, + { + command: "SET", + commands: []*command{ + { + command: "ACCESS", + boolFlags: []string{ + //3 id + "/ALL", + "/READ", + //3 Warning + }, + }, + { + command: "BBOARD", + boolFlags: []string{ + "/EXPIRATION", + "/SPECIAL", + "/VMSMAIL", + //3 More_information + }, + }, + { + command: "BRIEF", + boolFlags: []string{ + "/ALL", + "/DEFAULT", + "/FOLDER", + "/PERMANENT", + }, + }, + { + command: "CONTINUOUS_BRIEF", + }, + { + command: "DEFAULT_EXPIRE", + }, + { + command: "DIGEST", + }, + { + command: "DUMP", + }, + { + command: "EXPIRE_LIMIT", + }, + { + command: "FOLDER", + boolFlags: []string{ + "/MARKED", + }, + }, + { + command: "GENERIC", + boolFlags: []string{ + "/DAYS", + }, + }, + { + command: "KEYPAD", + }, + { + command: "LOGIN", + }, + { + command: "NODE", + boolFlags: []string{ + "/FOLDER", + }, + }, + { + command: "NOTIFY", + boolFlags: []string{ + "/ALL", + "/DEFAULT", + "/FOLDER", + "/PERMANENT", + }, + }, + { + command: "PAGE", + }, + { + command: "PRIVILEGES", + boolFlags: []string{ + "/ID", + }, + }, + { + command: "PROMPT_EXPIRE", + }, + { + command: "READNEW", + boolFlags: []string{ + "/ALL", + "/DEFAULT", + "/FOLDER", + "/PERMANENT", + }, + }, + { + command: "SHOWNEW", + boolFlags: []string{ + "/ALL", + "/DEFAULT", + "/FOLDER", + "/PERMANENT", + }, + }, + { + command: "STRIP", + }, + { + command: "SYSTEM", + }, + }, + }, + { + command: "SHOW", + commands: []*command{ + { + command: "FLAGS", + }, + { + command: "FOLDER", + boolFlags: []string{ + "/FULL", + }, + }, + { + command: "KEYPAD", + boolFlags: []string{ + "/PRINT", + }, + }, + { + command: "NEW", + }, + { + command: "PRIVILEGES", + }, + { + command: "USER", + boolFlags: []string{ + "/ALL", + "/LOGIN", + }, + }, + { + command: "VERSION", + }, + { + command: "SPAWN", + }, + { + command: "UNDELETE", + }, + }, + }, +} diff --git a/repl/repl.go b/repl/repl.go new file mode 100644 index 0000000000000000000000000000000000000000..ce2ecd2db47cb41cb60c7abbcc7d146c8993a198 --- /dev/null +++ b/repl/repl.go @@ -0,0 +1,36 @@ +// Package repl implements the main event loop. +package repl + +import ( + "fmt" + "strings" + + "github.com/chzyer/readline" +) + +// Loop is the main event loop. +func Loop(user string) error { + fmt.Printf("TODO: get config for user %s using xdg.", user) + rl, err := readline.New("BULLETIN> ") + if err != nil { + return err + } + defer rl.Close() + + for { + line, err := rl.Readline() + if err != nil { + return err + } + words := strings.Field(strings.ReplaceAll(line, "/", " /")) + if len(words) { + continue + } + switch strings.ToUpper(words[0]) { + case "ADD": + commandAdd() + } + } + + return nil +}