Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions lib/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{} }
Expand All @@ -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 {
Expand Down
15 changes: 15 additions & 0 deletions lib/outline.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Doc struct {
Description string
Functions Functions
Types Types
Constants Constants
}

// Sort sorts all sortable fields in the document
Expand All @@ -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
Expand Down Expand Up @@ -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] }
31 changes: 31 additions & 0 deletions lib/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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...)
}
15 changes: 15 additions & 0 deletions lib/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down
2 changes: 2 additions & 0 deletions lib/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(':')
}
Expand Down
2 changes: 2 additions & 0 deletions lib/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down