1515package main
1616
1717import (
18+ "errors"
1819 "flag"
1920 "fmt"
2021 "io"
2122 "os"
23+ "os/exec"
24+ "strings"
2225
2326 _ "embed"
2427
@@ -28,6 +31,7 @@ import (
2831var (
2932 outPath = flag .String ("o" , "" , "output file to use (defaults to stdout)" )
3033 assemble = flag .Bool ("s" , false , "whether to treat the input as a Protoscope source file" )
34+ spec = flag .Bool ("spec" , false , "opens the Protoscope spec in $PAGER" )
3135
3236 noQuotedStrings = flag .Bool ("no-quoted-strings" , false , "assume no fields in the input proto are strings" )
3337 allFieldsAreMessages = flag .Bool ("all-fields-are-messages" , false , "try really hard to disassemble all fields as messages" )
@@ -37,11 +41,18 @@ var (
3741)
3842
3943func main () {
44+ if err := Main (); err != nil {
45+ fmt .Fprintln (os .Stderr , "protoscope:" , err )
46+ os .Exit (1 )
47+ }
48+ }
49+
50+ func Main () error {
4051 flag .Usage = func () {
41- fmt .Fprintf (os .Stderr , "Usage: %s [OPTION...] [INPUT]\n " , os .Args [0 ])
42- fmt .Fprintf (os .Stderr , "Assemble a Protoscope file to binary, or inspect binary data as Protoscope text.\n \n " )
52+ fmt .Fprintf (os .Stderr , "Usage: %s [-s] [OPTION...] [INPUT]\n " , os .Args [0 ])
53+ fmt .Fprintf (os .Stderr , "Assemble a Protoscope file to binary, or inspect binary data as Protoscope text.\n " )
54+ fmt .Fprintf (os .Stderr , "Run with -spec to learn more about the Protoscope language.\n \n " )
4355 flag .PrintDefaults ()
44- fmt .Fprintf (os .Stderr , "\n %s\n " , protoscope .LanguageTxt )
4556 }
4657
4758 flag .Parse ()
@@ -51,23 +62,37 @@ func main() {
5162 os .Exit (1 )
5263 }
5364
65+ if * spec {
66+ pager := os .Getenv ("PAGER" )
67+ if pager == "" {
68+ return fmt .Errorf ("%s" , protoscope .LanguageTxt )
69+ return nil
70+ }
71+
72+ cmd := exec .Command (pager )
73+ cmd .Stdout = os .Stdout
74+ cmd .Stdin = strings .NewReader (protoscope .LanguageTxt )
75+ if err := cmd .Run (); err != nil {
76+ return err
77+ }
78+ return nil
79+ }
80+
5481 inPath := ""
5582 inFile := os .Stdin
5683 if flag .NArg () == 1 {
5784 inPath = flag .Arg (0 )
5885 var err error
5986 inFile , err = os .Open (inPath )
6087 if err != nil {
61- fmt .Fprintf (os .Stderr , "Error opening %s: %s\n " , inPath , err )
62- os .Exit (1 )
88+ return err
6389 }
6490 defer inFile .Close ()
6591 }
6692
6793 inBytes , err := io .ReadAll (inFile )
6894 if err != nil {
69- fmt .Fprintf (os .Stderr , "Error reading input: %s\n " , err )
70- os .Exit (1 )
95+ return err
7196 }
7297
7398 var outBytes []byte
@@ -77,7 +102,7 @@ func main() {
77102
78103 outBytes , err = scanner .Exec ()
79104 if err != nil {
80- fmt .Fprintf ( os . Stderr , "Syntax error: %s\n " , err )
105+ return fmt .Errorf ( "syntax error: %s\n " , err )
81106 os .Exit (1 )
82107 }
83108 } else {
@@ -95,14 +120,11 @@ func main() {
95120 var err error
96121 outFile , err = os .Create (* outPath )
97122 if err != nil {
98- fmt .Fprintf (os .Stderr , "Error opening %s: %s\n " , * outPath , err )
99- os .Exit (1 )
123+ return err
100124 }
101125 defer outFile .Close ()
102126 }
103127
104- if _ , err = outFile .Write (outBytes ); err != nil {
105- fmt .Fprintf (os .Stderr , "Error writing output: %s\n " , err )
106- os .Exit (1 )
107- }
128+ _ , err = outFile .Write (outBytes )
129+ return err
108130}
0 commit comments