diff --git a/lib/options.go b/lib/options.go index 2b65c30..d6c19df 100644 --- a/lib/options.go +++ b/lib/options.go @@ -5,8 +5,9 @@ type Option interface { } type config struct { - alphaSortTypes bool - alphaSortFuncs bool + alphaSortTypes bool + alphaSortFuncs bool + alphaSortConstants bool } func AlphaSortTypes() Option { return alphaSortTypes{} } @@ -27,6 +28,15 @@ func (o alphaSortFuncs) apply(cfg *config) error { return nil } +func AlphaSortConstants() Option { return alphaSortConstants{} } + +type alphaSortConstants struct{} + +func (o alphaSortConstants) apply(cfg *config) error { + cfg.alphaSortConstants = true + return nil +} + func parseOptions(opts []Option) (config, error) { cfg := config{} for _, opt := range opts { diff --git a/lib/outline.go b/lib/outline.go index 20f9706..ed36176 100644 --- a/lib/outline.go +++ b/lib/outline.go @@ -36,6 +36,7 @@ type Doc struct { Description string Functions Functions Types Types + Constants Constants } // Sort sorts all sortable fields in the document @@ -46,6 +47,9 @@ func (d *Doc) Sort() { if d.cfg.alphaSortTypes { sort.Sort(d.Types) } + if d.cfg.alphaSortConstants { + sort.Sort(d.Constants) + } } // Examples returns a slice of all examples defined in the document @@ -208,3 +212,14 @@ type Example struct { Description string Code string } + +type Constant struct { + Name string + Description string +} + +type Constants []*Constant + +func (c Constants) Len() int { return len(c) } +func (c Constants) Less(i, j int) bool { return c[i].Name < c[j].Name } +func (c Constants) Swap(i, j int) { c[i], c[j] = c[j], c[i] } diff --git a/lib/parser.go b/lib/parser.go index c55a62f..a514f99 100644 --- a/lib/parser.go +++ b/lib/parser.go @@ -146,6 +146,10 @@ func (p *parser) readDocument(baseIndent int) (doc *Doc, err error) { if doc.Types, err = p.readTypes(p.indent); err != nil { return } + case ConstantsTok: + if doc.Constants, err = p.readConstants(p.indent); err != nil { + return + } case TextTok: // only read descriptions when indented if p.indent > baseIndent { @@ -431,6 +435,33 @@ func (p *parser) readExample(baseIndent int) (eg *Example, err error) { } } +func (p *parser) readConstants(baseIndent int) (consts []*Constant, err error) { + for { + var c *Constant + if c, err = p.readConstant(baseIndent + 1); err != nil || c == nil { + return + } + consts = append(consts, c) + } +} + +func (p *parser) readConstant(baseIndent int) (c *Constant, err error) { + tok := p.scan() + if p.indent < baseIndent || tok.Type != TextTok { + p.unscan() + return + } + + // Split the token text into name and description based on the first colon. + parts := strings.SplitN(tok.Text, ":", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("failed to parse constant: %s", tok.Text) + } + + c = &Constant{Name: strings.TrimSpace(parts[0]), Description: strings.TrimSpace(parts[1])} + return +} + func (p *parser) errorf(format string, args ...interface{}) error { return fmt.Errorf(format, args...) } diff --git a/lib/parser_test.go b/lib/parser_test.go index 4f7a860..1102fb3 100644 --- a/lib/parser_test.go +++ b/lib/parser_test.go @@ -270,6 +270,20 @@ var withExamples = &Doc{ }, } +const withConstantsText = `outline: string + constants: + ascii_letters: A string containing all the characters that are considered letters. + digits: A string containing all characters considered decimal digits: '0123456789' +` + +var withConstants = &Doc{ + Name: "string", + Constants: []*Constant{ + {Name: "ascii_letters", Description: "A string containing all the characters that are considered letters."}, + {Name: "digits", Description: "A string containing all characters considered decimal digits: '0123456789'"}, + }, +} + func TestParse(t *testing.T) { cases := []struct { name string @@ -286,6 +300,7 @@ func TestParse(t *testing.T) { {"dataframe", dataframeTabs, dataframe, ""}, {"leading_and_trailing", ignoreOuterText, ignoreOuter, ""}, {"examples", withExamplesText, withExamples, ""}, + {"constants", withConstantsText, withConstants, ""}, } for _, c := range cases { diff --git a/lib/scanner.go b/lib/scanner.go index 37e6203..343513f 100644 --- a/lib/scanner.go +++ b/lib/scanner.go @@ -80,6 +80,8 @@ func (s *scanner) Scan() Token { return s.newTok(CodeTok) case "examples": return s.newTok(ExamplesTok) + case "constants": + return s.newTok(ConstantsTok) default: s.text.WriteRune(':') } diff --git a/lib/token.go b/lib/token.go index 8e07105..16d2af6 100644 --- a/lib/token.go +++ b/lib/token.go @@ -60,6 +60,8 @@ const ( MethodsTok // OperatorsTok is the "operators:" token OperatorsTok + // ConstantsTok is the "constants:" token + ConstantsTok // KeywordEnd marks the end of keyword tokens in the token enumeration KeywordEnd )