diff --git a/.gitignore b/.gitignore index cb9380e..6f40a17 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ bombadillo *.asciinema +*.swp diff --git a/DEVELOPING.md b/DEVELOPING.md index 4b05842..6ecdc8b 100644 --- a/DEVELOPING.md +++ b/DEVELOPING.md @@ -25,10 +25,10 @@ Changes are implemented to the default branch when: ### Process for introducing a new change -Please refer to our [notes on contributing](README.md#contributing) to get an understanding of how new changes are initiated, the type of changes accepted and the review process. +Before you begin, please refer to our [notes on contributing](README.md#contributing) to get an understanding of how new changes are initiated, the type of changes accepted and the review process. 1. Create a new feature branch based on the **develop** branch. -1. Raise a pull request (PR) targeting the **develop** branch. +1. Raise a pull request (PR) targeting the current release branch (confirm this in the issue comments before proceeding). 1. The PR is reviewed. 1. If the PR is approved, it is merged. 1. The version number is incremented, along with any other release activity. diff --git a/client.go b/client.go index 1765951..4b31efb 100644 --- a/client.go +++ b/client.go @@ -346,21 +346,16 @@ func (c *client) simpleCommand(action string) { case "HELP", "?": go c.Visit(helplocation) default: - c.SetMessage(fmt.Sprintf("Unknown action %q", action), true) + c.SetMessage(syntaxErrorMessage(action), true) c.DrawMessage() } } func (c *client) doCommand(action string, values []string) { - if length := len(values); length != 1 { - c.SetMessage(fmt.Sprintf("Expected 1 argument, received %d", len(values)), true) - c.DrawMessage() - return - } - switch action { - case "CHECK", "C": + case "C", "CHECK": c.displayConfigValue(values[0]) + c.DrawMessage() case "PURGE", "P": err := c.Certs.Purge(values[0]) if err != nil { @@ -405,24 +400,22 @@ func (c *client) doCommand(action string, values []string) { c.saveFile(u, fn) default: - c.SetMessage(fmt.Sprintf("Unknown action %q", action), true) + c.SetMessage(syntaxErrorMessage(action), true) c.DrawMessage() } } func (c *client) doCommandAs(action string, values []string) { - if len(values) < 2 { - c.SetMessage(fmt.Sprintf("Expected 2+ arguments, received %d", len(values)), true) - c.DrawMessage() - return - } - - if values[0] == "." { - values[0] = c.PageState.History[c.PageState.Position].Location.Full - } - switch action { case "ADD", "A": + if len(values) < 2 { + c.SetMessage(syntaxErrorMessage(action), true) + c.DrawMessage() + return + } + if values[0] == "." { + values[0] = c.PageState.History[c.PageState.Position].Location.Full + } msg, err := c.BookMarks.Add(values) if err != nil { c.SetMessage(err.Error(), true) @@ -441,8 +434,18 @@ func (c *client) doCommandAs(action string, values []string) { c.Draw() } case "SEARCH": + if len(values) < 2 { + c.SetMessage(syntaxErrorMessage(action), true) + c.DrawMessage() + return + } c.search(strings.Join(values, " "), "", "") case "SET", "S": + if len(values) < 2 { + c.SetMessage(syntaxErrorMessage(action), true) + c.DrawMessage() + return + } if _, ok := c.Options[values[0]]; ok { val := strings.Join(values[1:], " ") if !validateOpt(values[0], val) { @@ -473,7 +476,7 @@ func (c *client) doCommandAs(action string, values []string) { c.SetMessage(fmt.Sprintf("Unable to set %s, it does not exist", values[0]), true) c.DrawMessage() default: - c.SetMessage(fmt.Sprintf("Unknown command structure"), true) + c.SetMessage(syntaxErrorMessage(action), true) c.DrawMessage() } } @@ -523,7 +526,7 @@ func (c *client) doLinkCommandAs(action, target string, values []string) { out = append(out, values...) c.doCommandAs(action, out) default: - c.SetMessage(fmt.Sprintf("Unknown command structure"), true) + c.SetMessage(syntaxErrorMessage(action), true) c.DrawMessage() } } @@ -655,7 +658,7 @@ func (c *client) doLinkCommand(action, target string) { } c.saveFile(u, fn) default: - c.SetMessage("Unknown command structure", true) + c.SetMessage(syntaxErrorMessage(action), true) c.DrawMessage() } @@ -977,6 +980,7 @@ func (c *client) handleGemini(u Url) { case 2: // Success if capsule.MimeMaj == "text" || (c.Options["showimages"] == "true" && capsule.MimeMaj == "image") { + u.Mime = capsule.MimeMin pg := MakePage(u, capsule.Content, capsule.Links) pg.FileType = capsule.MimeMaj pg.WrapContent(c.Width-1, (c.Options["theme"] == "color")) @@ -1203,6 +1207,13 @@ func findAvailableFileName(fpath, fname string) (string, error) { return savePath, nil } +func syntaxErrorMessage(action string) string { + if val, ok := ERRS[action]; ok { + return fmt.Sprintf("Incorrect syntax. Try: %s", val) + } + return fmt.Sprintf("Unknown command %q", action) +} + func updateTimeouts(timeoutString string) error { sec, err := strconv.Atoi(timeoutString) if err != nil { diff --git a/cui/cui.go b/cui/cui.go index c3ee14a..1ed29d7 100644 --- a/cui/cui.go +++ b/cui/cui.go @@ -102,6 +102,7 @@ func Getch() rune { func GetLine(prefix string) (string, error) { termios.SetLineMode() + defer termios.SetCharMode() reader := bufio.NewReader(os.Stdin) fmt.Print(prefix) @@ -110,7 +111,6 @@ func GetLine(prefix string) (string, error) { return "", err } - termios.SetCharMode() return text[:len(text)-1], nil } diff --git a/gemini/gemini.go b/gemini/gemini.go index db02ca5..526aca6 100644 --- a/gemini/gemini.go +++ b/gemini/gemini.go @@ -361,6 +361,7 @@ func parseGemini(b, currentUrl string) (string, []string) { links := make([]string, 0, 10) inPreBlock := false + spacer := " " outputIndex := 0 for i, ln := range splitContent { @@ -371,7 +372,7 @@ func parseGemini(b, currentUrl string) (string, []string) { alt := strings.TrimSpace(ln) if len(alt) > 3 { alt = strings.TrimSpace(alt[3:]) - splitContent[outputIndex] = fmt.Sprintf("[ %s ]", alt) + splitContent[outputIndex] = fmt.Sprintf("%s[ALT][ %s ]", spacer, alt) outputIndex++ } } else if isPreBlockDeclaration { @@ -401,7 +402,12 @@ func parseGemini(b, currentUrl string) (string, []string) { if inPreBlock && (BlockBehavior == "alt" || BlockBehavior == "neither") { continue } - splitContent[outputIndex] = ln + var leader, tail string = "", "" + if len(ln) > 0 && ln[0] == '#' { + leader = "\033[1m" + tail = "\033[0m" + } + splitContent[outputIndex] = fmt.Sprintf("%s%s%s%s", spacer, leader, ln, tail) outputIndex++ } } diff --git a/gopher/gopher.go b/gopher/gopher.go index fbe579f..adf36e9 100644 --- a/gopher/gopher.go +++ b/gopher/gopher.go @@ -144,7 +144,8 @@ func parseMap(text string) (string, []string) { } else { link := buildLink(line[2], line[3], string(line[0][0]), line[1]) links = append(links, link) - linktext := fmt.Sprintf("(%s) %2d %s", getType(string(line[0][0])), len(links), title) + linkNum := fmt.Sprintf("[%d]",len(links)) + linktext := fmt.Sprintf("%s %5s %s", getType(string(line[0][0])), linkNum, title) splitContent[i] = linktext } } diff --git a/help.go b/help.go new file mode 100644 index 0000000..a9516f3 --- /dev/null +++ b/help.go @@ -0,0 +1,28 @@ +package main + +// ERRS maps commands to their syntax error message +var ERRS = map[string]string{ + "A": "`a [target] [name...]`", + "ADD": "`add [target] [name...]`", + "D": "`d [bookmark-id]`", + "DELETE": "`delete [bookmark-id]`", + "B": "`b [[bookmark-id]]`", + "BOOKMARKS": "`bookmarks [[bookmark-id]]`", + "C": "`c [link_id]` or `check [setting]`", + "CHECK": "`check [link_id]` or `check [setting]`", + "H": "`h`", + "HOME": "`home`", + "P": "`p [host]`", + "PURGE": "`purge [host]`", + "Q": "`q`", + "QUIT": "`quit`", + "R": "`r`", + "RELOAD": "`reload`", + "SEARCH": "`search [[keyword(s)...]]`", + "S": "`s [setting] [value]`", + "SET": "`set [setting] [value]`", + "W": "`w [target]`", + "WRITE": "`write [target]`", + "?": "`?`", + "HELP": "`help`", +} diff --git a/page.go b/page.go index ad44ab2..d4ed745 100644 --- a/page.go +++ b/page.go @@ -72,11 +72,17 @@ func (p *Page) WrapContent(width int, color bool) { } width = min(width, 100) counter := 0 - spacer := " " + spacer := "" var content strings.Builder var esc strings.Builder escape := false content.Grow(len(p.RawContent)) + + if p.Location.Mime == "1" { // gopher document + spacer = " " + } else if strings.HasSuffix(p.Location.Mime, "gemini") { //gemini document + spacer = " " + } for _, ch := range []rune(p.RawContent) { if escape { if color { @@ -125,10 +131,8 @@ func (p *Page) WrapContent(width int, color bool) { } else { content.WriteRune('\n') counter = 0 - if p.Location.Mime == "1" { - content.WriteString(spacer) - counter += len(spacer) - } + content.WriteString(spacer) + counter += len(spacer) content.WriteRune(ch) counter++ }