From 4279f9ff8b726ddbba498063b2f79b08511b6bbb Mon Sep 17 00:00:00 2001 From: Kevin Lyda <kevin@lyda.ie> Date: Sun, 18 May 2025 09:06:24 +0100 Subject: [PATCH] Make help work for compound commands --- NOTES.md | 5 ++-- repl/accounts.go | 11 ------- repl/command.go | 46 +++++++++++++++++++++++++---- repl/help.go | 77 +++++++++++++++++++++++++++++------------------- repl/set.go | 10 ------- repl/show.go | 5 ---- 6 files changed, 90 insertions(+), 64 deletions(-) diff --git a/NOTES.md b/NOTES.md index 4d60cce..332d091 100644 --- a/NOTES.md +++ b/NOTES.md @@ -26,8 +26,9 @@ Switch between MAIL and BULLETIN modes? MAIL commands are documented * Messages edit: CHANGE, REPLY * Moving messages: COPY, MOVE * Mark messages: MARK, UNMARK - * Compound commands: SET and SHOW - make HELP work for them. + * ~~Compound commands: SET and SHOW - make HELP work for them.~~ * Mail: MAIL, FORWARD, RESPOND + * Review each command and fully implement it. * Run this.Skew.Safe() before... each command? each write? * Handle broadcast messages - have bulletin watch a directory and display files from it. Then have them delete the file if it's older @@ -40,7 +41,6 @@ Switch between MAIL and BULLETIN modes? MAIL commands are documented * Commands for a local mail system? * Commands to connect to Mattermost or mastodon? * ~~Commands to manage users.~~ - * Handle MARK for SELECT and DIRECTORY. Done: @@ -66,6 +66,7 @@ Done: * ~~Remove the node/cluster/newsgroup/mailing-list related flags.~~ * ~~Remove BBOARD references.~~ * ~~format with `par w72j1`~~ + * ~~Handle MARK for SELECT and DIRECTORY.~~ ## Module links diff --git a/repl/accounts.go b/repl/accounts.go index ad85656..1a6fb88 100644 --- a/repl/accounts.go +++ b/repl/accounts.go @@ -15,12 +15,6 @@ import ( // ActionUser handles the `USER` command. func ActionUser(cmd *dclish.Command) error { fmt.Println(cmd.Description) - fmt.Println(` -The following commands are available: - - ADD ADMIN DELETE DISABLE ENABLE LIST - MOD NOADMIN NOMOD`) - fmt.Println() return nil } @@ -189,11 +183,6 @@ func ActionUserNomod(cmd *dclish.Command) error { // ActionSSH handles the `SSH` command. func ActionSSH(cmd *dclish.Command) error { fmt.Println(cmd.Description) - fmt.Println(` -The following commands are available: - - ADD DELETE LIST`) - fmt.Println() return nil } diff --git a/repl/command.go b/repl/command.go index 0dc244e..8dd6ded 100644 --- a/repl/command.go +++ b/repl/command.go @@ -554,7 +554,7 @@ place of an actual number, i.e. CURRENT-LAST, 1-CURRENT, etc.`, Description: `To obtain help on any topic, type: HELP topic`, - MaxArgs: 1, + MaxArgs: 2, Action: ActionHelp, }, "INDEX": { @@ -1102,8 +1102,17 @@ message.`, }, }, "USER": { - Description: `Commands for managing users.`, - Action: ActionUser, + Description: `Commands for managing users. + + Format: + USER action + +The following actions are available: + + ADD ADMIN DELETE DISABLE ENABLE LIST + MOD NOADMIN NOMOD +`, + Action: ActionUser, Commands: dclish.Commands{ "ADD": { Description: ` Creates a user.`, @@ -1160,8 +1169,16 @@ message.`, }, }, "SSH": { - Description: `The SSH command is used to manage SSH keys for users.`, - Action: ActionSSH, + Description: `The SSH command is used to manage SSH keys for users. + + Format: + SSH action + +The following commands are available: + + ADD DELETE LIST +`, + Action: ActionSSH, Commands: dclish.Commands{ "ADD": { Description: ` Adds an ssh key for a user. Only an admin can add an ssh key for @@ -1202,7 +1219,17 @@ message.`, characteristics of the BULLETIN Utility. Format: - SET option`, + SET option + +The following options are available: + + NOPROMPT_EXPIRE NOPROMPT_EXPIRE NOPROMPT_EXPIRE NOPROMPT_EXPIRE + ACCESS ALWAYS BRIEF DEFAULT_EXPIRE + EXPIRE_LIMIT FOLDER NOALWAYS NOBRIEF + NONOTIFY NOPROMPT_EXPIRE NOREADNEW NOSHOWNEW + NOSYSTEM NOTIFY PROMPT_EXPIRE READNEW + SHOWNEW SYSTEM +`, Action: ActionSet, Commands: dclish.Commands{ "ALWAYS": { @@ -1513,6 +1540,13 @@ that folder cannot be removed.`, }, "SHOW": { Description: `The SHOW command displays information about certain characteristics. + + Format: + SHOW option + +The following options are available: + + FLAGS FOLDER NEW PRIVILEGES USER VERSION `, Action: ActionShow, Commands: dclish.Commands{ diff --git a/repl/help.go b/repl/help.go index 0b39ea9..e2d9c81 100644 --- a/repl/help.go +++ b/repl/help.go @@ -92,30 +92,39 @@ in a state such that they would be inaccessible by other users.) +-----------------+--------+--------+`, } -func init() { - // Add all command help. - buf := &strings.Builder{} - for c := range commands { - fmt.Fprint(buf, commands[c].Description) - if len(commands[c].Flags) > 0 { - flgs := make([]string, len(commands[c].Flags)) +var subhelpmap = map[string]map[string]string{} + +func generateHelp(hmap map[string]string, cmds dclish.Commands) { + for c := range cmds { + buf := &strings.Builder{} + fmt.Fprint(buf, cmds[c].Description) + if len(cmds[c].Flags) > 0 { + flgs := make([]string, len(cmds[c].Flags)) i := 0 - for flg := range commands[c].Flags { + for flg := range cmds[c].Flags { flgs[i] = flg i++ } sort.Strings(flgs) for i := range flgs { - if strings.HasPrefix(commands[c].Flags[flgs[i]].Description, "/") { - fmt.Fprintf(buf, "\n\n%s", commands[c].Flags[flgs[i]].Description) + if strings.HasPrefix(cmds[c].Flags[flgs[i]].Description, "/") { + fmt.Fprintf(buf, "\n\n%s", cmds[c].Flags[flgs[i]].Description) } else { - fmt.Fprintf(buf, "\n\n%s\n\n%s", flgs[i], commands[c].Flags[flgs[i]].Description) + fmt.Fprintf(buf, "\n\n%s\n\n%s", flgs[i], cmds[c].Flags[flgs[i]].Description) } } } - helpmap[c] = buf.String() - buf.Reset() + hmap[c] = buf.String() + if cmds[c].Commands != nil { + subhelpmap[c] = map[string]string{} + generateHelp(subhelpmap[c], cmds[c].Commands) + } } +} + +func init() { + // Add all command help. + generateHelp(helpmap, commands) // Add a list of topics. topics := make([]string, len(helpmap)) @@ -129,7 +138,7 @@ func init() { maxlen = maxlen + 2 sort.Strings(topics) - buf.Reset() + buf := &strings.Builder{} linelen := 2 fmt.Fprint(buf, "\n\nThe following commands and topics are available for more help\n\n ") @@ -154,34 +163,42 @@ func init() { helpmap["HELP"] += buf.String() } -// ActionHelp handles the `HELP` command. -func ActionHelp(cmd *dclish.Command) error { - if len(cmd.Args) == 0 { - fmt.Printf("%s\n", helpmap["HELP"]) - return nil - } - wordup := strings.ToUpper(cmd.Args[0]) - helptext, ok := helpmap[wordup] +func findHelp(hmap map[string]string, args []string, fullcmd string) string { + wordup := strings.ToUpper(args[0]) + helptext, ok := hmap[wordup] if !ok { possibles := []string{} - for word := range helpmap { + for word := range hmap { if strings.HasPrefix(word, wordup) { possibles = append(possibles, word) } } switch len(possibles) { case 0: - fmt.Printf("ERROR: Topic not found: '%s'.\n", cmd.Args[0]) - return nil + return fmt.Sprintf("ERROR: Topic not found: '%s'.\n", fullcmd) case 1: - helptext = helpmap[possibles[0]] + if len(args) == 2 { + return findHelp(subhelpmap[possibles[0]], args[1:], strings.Join(args, " ")) + } + return hmap[possibles[0]] default: - fmt.Printf("ERROR: Ambiguous topic '%s' (matches %s)\n", - cmd.Args[0], strings.Join(possibles, ", ")) - return nil + return fmt.Sprintf("ERROR: Ambiguous topic '%s' (matches %s)\n", + args[0], strings.Join(possibles, ", ")) } + } + if len(args) == 2 { + return findHelp(subhelpmap[wordup], args[1:], strings.Join(args, " ")) + } + return helptext +} +// ActionHelp handles the `HELP` command. +func ActionHelp(cmd *dclish.Command) error { + if len(cmd.Args) == 0 { + fmt.Printf("%s\n", helpmap["HELP"]) + return nil } - pager.Pager(helptext) + + pager.Pager(findHelp(helpmap, cmd.Args, cmd.Args[0])) return nil } diff --git a/repl/set.go b/repl/set.go index 605d99e..51e674c 100644 --- a/repl/set.go +++ b/repl/set.go @@ -15,16 +15,6 @@ import ( // ActionSet handles the `SET` command. func ActionSet(cmd *dclish.Command) error { fmt.Println(cmd.Description) - fmt.Println(` -The following commands are available: - - NOPROMPT_EXPIRE NOPROMPT_EXPIRE NOPROMPT_EXPIRE NOPROMPT_EXPIRE - ACCESS ALWAYS BRIEF DEFAULT_EXPIRE - EXPIRE_LIMIT FOLDER NOALWAYS NOBRIEF - NONOTIFY NOPROMPT_EXPIRE NOREADNEW NOSHOWNEW - NOSYSTEM NOTIFY PROMPT_EXPIRE READNEW - SHOWNEW SYSTEM`) - fmt.Println() return nil } diff --git a/repl/show.go b/repl/show.go index a0ce307..a2d628d 100644 --- a/repl/show.go +++ b/repl/show.go @@ -16,11 +16,6 @@ import ( // ActionShow handles the `SHOW` command. func ActionShow(cmd *dclish.Command) error { fmt.Println(cmd.Description) - fmt.Println(` -The following commands are available: - - FLAGS FOLDER NEW PRIVILEGES USER VERSION`) - fmt.Println() return nil } -- GitLab