gm

an extremely simple gemini browser/formatter
git clone git://bvnf.space/gm.git
Log | Files | Refs | LICENSE

commit 18fa794d2a12a83c96fe0f53aec076fc887d83fe
parent 76b39705e851467317f08bd204607d5f26f251f3
Author: phoebos <ben@bvnf.space>
Date:   Sat, 28 Aug 2021 18:18:57 +0100

s/^I/    /g

Diffstat:
Mgemtext.go | 98++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mgm.go | 147+++++++++++++++++++++++++++++++++++++++----------------------------------------
2 files changed, 122 insertions(+), 123 deletions(-)

diff --git a/gemtext.go b/gemtext.go @@ -1,60 +1,60 @@ package main import ( - "strings" + "strings" ) // Prettify formats gemtext nicely with escape sequences. func Prettify(plain *string) *string { - lines := strings.Split(*plain, "\n") - outlines := make([]string, 0, len(lines)) - preform := false - for _, line := range lines { - outline := line - line = strings.TrimSpace(line) - fwspace := strings.Index(line, " ") - var firstword string - if fwspace == -1 { - firstword = line - } else { - firstword = line[:fwspace] - } - if preform && firstword != "```" { - outlines = append(outlines, outline) - continue - } - if len(firstword) > 3 { - firstword = firstword[:3] - } + lines := strings.Split(*plain, "\n") + outlines := make([]string, 0, len(lines)) + preform := false + for _, line := range lines { + outline := line + line = strings.TrimSpace(line) + fwspace := strings.Index(line, " ") + var firstword string + if fwspace == -1 { + firstword = line + } else { + firstword = line[:fwspace] + } + if preform && firstword != "```" { + outlines = append(outlines, outline) + continue + } + if len(firstword) > 3 { + firstword = firstword[:3] + } - switch firstword { - case "```": - // preformatted - preform = !preform - continue - case "#": - // heading - outline = "\033[1;31m" + outline + "\033[m" - case "##": - // subheading - outline = "\033[1;32m" + outline + "\033[m" - case "###": - // sub-subheading - outline = "\033[1;33m" + outline + "\033[m" - case "*": - // list - outline = " •" + line[1:] - case ">": - // quote - outline = "\t\033[3;37m" + outline + "\033[m" - case "=>": - // link - outline = "\033[4;34m" + outline + "\033[m" - } + switch firstword { + case "```": + // preformatted + preform = !preform + continue + case "#": + // heading + outline = "\033[1;31m" + outline + "\033[m" + case "##": + // subheading + outline = "\033[1;32m" + outline + "\033[m" + case "###": + // sub-subheading + outline = "\033[1;33m" + outline + "\033[m" + case "*": + // list + outline = " •" + line[1:] + case ">": + // quote + outline = "\t\033[3;37m" + outline + "\033[m" + case "=>": + // link + outline = "\033[4;34m" + outline + "\033[m" + } - outlines = append(outlines, outline) - } + outlines = append(outlines, outline) + } - pretty := strings.Join(outlines, "\n") - return &pretty + pretty := strings.Join(outlines, "\n") + return &pretty } diff --git a/gm.go b/gm.go @@ -1,99 +1,98 @@ package main import ( - "bufio" - "crypto/tls" - "flag" - "fmt" - "io/ioutil" - golog "log" - "net/url" - "os" - "strings" + "bufio" + "crypto/tls" + "flag" + "fmt" + "io/ioutil" + golog "log" + "net/url" + "os" + "strings" ) - var ( - v *bool + v *bool ) // log prints timestamped diagnosis messages to stderr if verbose output is turned on. func log(msg ...interface{}) { - if *v { - fmt.Fprint(os.Stderr, "\033[32m") - golog.Println(msg...) - fmt.Fprint(os.Stderr, "\033[m") - } + if *v { + fmt.Fprint(os.Stderr, "\033[32m") + golog.Println(msg...) + fmt.Fprint(os.Stderr, "\033[m") + } } func die(msg ...interface{}) { - fmt.Fprintf(os.Stderr, "\033[31m%s\033[m\n", fmt.Sprint(msg...)) - os.Exit(1) + fmt.Fprintf(os.Stderr, "\033[31m%s\033[m\n", fmt.Sprint(msg...)) + os.Exit(1) } func main() { - port := flag.Int("p", 1965, "port number") - plain := flag.Bool("plain", false, "print raw header and response (no formatting)") - v = flag.Bool("v", false, "print more information to stderr") - flag.Parse() - // only accept one url - if flag.NArg() != 1 { - die("give one url") - } + port := flag.Int("p", 1965, "port number") + plain := flag.Bool("plain", false, "print raw header and response (no formatting)") + v = flag.Bool("v", false, "print more information to stderr") + flag.Parse() + // only accept one url + if flag.NArg() != 1 { + die("give one url") + } - u := flag.Args()[0] + u := flag.Args()[0] - if !strings.HasPrefix(u, "gemini://") { - u = "gemini://" + u - } + if !strings.HasPrefix(u, "gemini://") { + u = "gemini://" + u + } - parsed, err := url.Parse(u) - if err != nil { - die(fmt.Sprintf("error parsing url (%s): %s", u, err.Error())) - } + parsed, err := url.Parse(u) + if err != nil { + die(fmt.Sprintf("error parsing url (%s): %s", u, err.Error())) + } - conn, err := tls.Dial("tcp", parsed.Host+fmt.Sprintf(":%d", *port), &tls.Config{InsecureSkipVerify: true}) - if err != nil { - die("tls error: ", err) - } - defer conn.Close() - conn.Write([]byte(u + "\r\n")) + conn, err := tls.Dial("tcp", parsed.Host+fmt.Sprintf(":%d", *port), &tls.Config{InsecureSkipVerify: true}) + if err != nil { + die("tls error: ", err) + } + defer conn.Close() + conn.Write([]byte(u + "\r\n")) - // just dump the response if we want - if *plain { - resp, err := ioutil.ReadAll(bufio.NewReader(conn)) - if err != nil { - die(err) - } - fmt.Println(string(resp)) - os.Exit(0) - } + // just dump the response if we want + if *plain { + resp, err := ioutil.ReadAll(bufio.NewReader(conn)) + if err != nil { + die(err) + } + fmt.Println(string(resp)) + os.Exit(0) + } - scanner := bufio.NewScanner(conn) + scanner := bufio.NewScanner(conn) - // read first line (status) - scanner.Scan() - statusline := scanner.Text() - switch statusline[0] { - case '1': - // INPUT - case '2': - // SUCCESS - case '3': - // REDIRECT - log("redirecting to", statusline[3:]) - case '6': - // CLIENT CERTIFICATE REQUIRED - default: - // reponse 4x or 5x - // FAILURE - die("error: ", statusline) - } + // read first line (status) + scanner.Scan() + statusline := scanner.Text() + switch statusline[0] { + case '1': + // INPUT + case '2': + // SUCCESS + case '3': + // REDIRECT + log("redirecting to", statusline[3:]) + case '6': + // CLIENT CERTIFICATE REQUIRED + default: + // reponse 4x or 5x + // FAILURE + die("error: ", statusline) + } - resp, err := ioutil.ReadAll(bufio.NewReader(conn)) - if err != nil { - die("error: ", err.Error()) - } - s := string(resp) - fmt.Println(*Prettify(&s)) + resp, err := ioutil.ReadAll(bufio.NewReader(conn)) + if err != nil { + die("error: ", err.Error()) + } + s := string(resp) + fmt.Println(*Prettify(&s)) }