summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/tools/present/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/tools/present/parse.go')
-rw-r--r--vendor/golang.org/x/tools/present/parse.go559
1 files changed, 0 insertions, 559 deletions
diff --git a/vendor/golang.org/x/tools/present/parse.go b/vendor/golang.org/x/tools/present/parse.go
deleted file mode 100644
index d7289db..0000000
--- a/vendor/golang.org/x/tools/present/parse.go
+++ /dev/null
@@ -1,559 +0,0 @@
-// Copyright 2011 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package present
-
-import (
- "bufio"
- "bytes"
- "errors"
- "fmt"
- "html/template"
- "io"
- "io/ioutil"
- "log"
- "net/url"
- "regexp"
- "strings"
- "time"
- "unicode"
- "unicode/utf8"
-)
-
-var (
- parsers = make(map[string]ParseFunc)
- funcs = template.FuncMap{}
-)
-
-// Template returns an empty template with the action functions in its FuncMap.
-func Template() *template.Template {
- return template.New("").Funcs(funcs)
-}
-
-// Render renders the doc to the given writer using the provided template.
-func (d *Doc) Render(w io.Writer, t *template.Template) error {
- data := struct {
- *Doc
- Template *template.Template
- PlayEnabled bool
- NotesEnabled bool
- }{d, t, PlayEnabled, NotesEnabled}
- return t.ExecuteTemplate(w, "root", data)
-}
-
-// Render renders the section to the given writer using the provided template.
-func (s *Section) Render(w io.Writer, t *template.Template) error {
- data := struct {
- *Section
- Template *template.Template
- PlayEnabled bool
- }{s, t, PlayEnabled}
- return t.ExecuteTemplate(w, "section", data)
-}
-
-type ParseFunc func(ctx *Context, fileName string, lineNumber int, inputLine string) (Elem, error)
-
-// Register binds the named action, which does not begin with a period, to the
-// specified parser to be invoked when the name, with a period, appears in the
-// present input text.
-func Register(name string, parser ParseFunc) {
- if len(name) == 0 || name[0] == ';' {
- panic("bad name in Register: " + name)
- }
- parsers["."+name] = parser
-}
-
-// Doc represents an entire document.
-type Doc struct {
- Title string
- Subtitle string
- Time time.Time
- Authors []Author
- TitleNotes []string
- Sections []Section
- Tags []string
-}
-
-// Author represents the person who wrote and/or is presenting the document.
-type Author struct {
- Elem []Elem
-}
-
-// TextElem returns the first text elements of the author details.
-// This is used to display the author' name, job title, and company
-// without the contact details.
-func (p *Author) TextElem() (elems []Elem) {
- for _, el := range p.Elem {
- if _, ok := el.(Text); !ok {
- break
- }
- elems = append(elems, el)
- }
- return
-}
-
-// Section represents a section of a document (such as a presentation slide)
-// comprising a title and a list of elements.
-type Section struct {
- Number []int
- Title string
- Elem []Elem
- Notes []string
- Classes []string
- Styles []string
-}
-
-// HTMLAttributes for the section
-func (s Section) HTMLAttributes() template.HTMLAttr {
- if len(s.Classes) == 0 && len(s.Styles) == 0 {
- return ""
- }
-
- var class string
- if len(s.Classes) > 0 {
- class = fmt.Sprintf(`class=%q`, strings.Join(s.Classes, " "))
- }
- var style string
- if len(s.Styles) > 0 {
- style = fmt.Sprintf(`style=%q`, strings.Join(s.Styles, " "))
- }
- return template.HTMLAttr(strings.Join([]string{class, style}, " "))
-}
-
-// Sections contained within the section.
-func (s Section) Sections() (sections []Section) {
- for _, e := range s.Elem {
- if section, ok := e.(Section); ok {
- sections = append(sections, section)
- }
- }
- return
-}
-
-// Level returns the level of the given section.
-// The document title is level 1, main section 2, etc.
-func (s Section) Level() int {
- return len(s.Number) + 1
-}
-
-// FormattedNumber returns a string containing the concatenation of the
-// numbers identifying a Section.
-func (s Section) FormattedNumber() string {
- b := &bytes.Buffer{}
- for _, n := range s.Number {
- fmt.Fprintf(b, "%v.", n)
- }
- return b.String()
-}
-
-func (s Section) TemplateName() string { return "section" }
-
-// Elem defines the interface for a present element. That is, something that
-// can provide the name of the template used to render the element.
-type Elem interface {
- TemplateName() string
-}
-
-// renderElem implements the elem template function, used to render
-// sub-templates.
-func renderElem(t *template.Template, e Elem) (template.HTML, error) {
- var data interface{} = e
- if s, ok := e.(Section); ok {
- data = struct {
- Section
- Template *template.Template
- }{s, t}
- }
- return execTemplate(t, e.TemplateName(), data)
-}
-
-func init() {
- funcs["elem"] = renderElem
-}
-
-// execTemplate is a helper to execute a template and return the output as a
-// template.HTML value.
-func execTemplate(t *template.Template, name string, data interface{}) (template.HTML, error) {
- b := new(bytes.Buffer)
- err := t.ExecuteTemplate(b, name, data)
- if err != nil {
- return "", err
- }
- return template.HTML(b.String()), nil
-}
-
-// Text represents an optionally preformatted paragraph.
-type Text struct {
- Lines []string
- Pre bool
-}
-
-func (t Text) TemplateName() string { return "text" }
-
-// List represents a bulleted list.
-type List struct {
- Bullet []string
-}
-
-func (l List) TemplateName() string { return "list" }
-
-// Lines is a helper for parsing line-based input.
-type Lines struct {
- line int // 0 indexed, so has 1-indexed number of last line returned
- text []string
-}
-
-func readLines(r io.Reader) (*Lines, error) {
- var lines []string
- s := bufio.NewScanner(r)
- for s.Scan() {
- lines = append(lines, s.Text())
- }
- if err := s.Err(); err != nil {
- return nil, err
- }
- return &Lines{0, lines}, nil
-}
-
-func (l *Lines) next() (text string, ok bool) {
- for {
- current := l.line
- l.line++
- if current >= len(l.text) {
- return "", false
- }
- text = l.text[current]
- // Lines starting with # are comments.
- if len(text) == 0 || text[0] != '#' {
- ok = true
- break
- }
- }
- return
-}
-
-func (l *Lines) back() {
- l.line--
-}
-
-func (l *Lines) nextNonEmpty() (text string, ok bool) {
- for {
- text, ok = l.next()
- if !ok {
- return
- }
- if len(text) > 0 {
- break
- }
- }
- return
-}
-
-// A Context specifies the supporting context for parsing a presentation.
-type Context struct {
- // ReadFile reads the file named by filename and returns the contents.
- ReadFile func(filename string) ([]byte, error)
-}
-
-// ParseMode represents flags for the Parse function.
-type ParseMode int
-
-const (
- // If set, parse only the title and subtitle.
- TitlesOnly ParseMode = 1
-)
-
-// Parse parses a document from r.
-func (ctx *Context) Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {
- doc := new(Doc)
- lines, err := readLines(r)
- if err != nil {
- return nil, err
- }
-
- for i := lines.line; i < len(lines.text); i++ {
- if strings.HasPrefix(lines.text[i], "*") {
- break
- }
-
- if isSpeakerNote(lines.text[i]) {
- doc.TitleNotes = append(doc.TitleNotes, lines.text[i][2:])
- }
- }
-
- err = parseHeader(doc, lines)
- if err != nil {
- return nil, err
- }
- if mode&TitlesOnly != 0 {
- return doc, nil
- }
-
- // Authors
- if doc.Authors, err = parseAuthors(lines); err != nil {
- return nil, err
- }
- // Sections
- if doc.Sections, err = parseSections(ctx, name, lines, []int{}); err != nil {
- return nil, err
- }
- return doc, nil
-}
-
-// Parse parses a document from r. Parse reads assets used by the presentation
-// from the file system using ioutil.ReadFile.
-func Parse(r io.Reader, name string, mode ParseMode) (*Doc, error) {
- ctx := Context{ReadFile: ioutil.ReadFile}
- return ctx.Parse(r, name, mode)
-}
-
-// isHeading matches any section heading.
-var isHeading = regexp.MustCompile(`^\*+ `)
-
-// lesserHeading returns true if text is a heading of a lesser or equal level
-// than that denoted by prefix.
-func lesserHeading(text, prefix string) bool {
- return isHeading.MatchString(text) && !strings.HasPrefix(text, prefix+"*")
-}
-
-// parseSections parses Sections from lines for the section level indicated by
-// number (a nil number indicates the top level).
-func parseSections(ctx *Context, name string, lines *Lines, number []int) ([]Section, error) {
- var sections []Section
- for i := 1; ; i++ {
- // Next non-empty line is title.
- text, ok := lines.nextNonEmpty()
- for ok && text == "" {
- text, ok = lines.next()
- }
- if !ok {
- break
- }
- prefix := strings.Repeat("*", len(number)+1)
- if !strings.HasPrefix(text, prefix+" ") {
- lines.back()
- break
- }
- section := Section{
- Number: append(append([]int{}, number...), i),
- Title: text[len(prefix)+1:],
- }
- text, ok = lines.nextNonEmpty()
- for ok && !lesserHeading(text, prefix) {
- var e Elem
- r, _ := utf8.DecodeRuneInString(text)
- switch {
- case unicode.IsSpace(r):
- i := strings.IndexFunc(text, func(r rune) bool {
- return !unicode.IsSpace(r)
- })
- if i < 0 {
- break
- }
- indent := text[:i]
- var s []string
- for ok && (strings.HasPrefix(text, indent) || text == "") {
- if text != "" {
- text = text[i:]
- }
- s = append(s, text)
- text, ok = lines.next()
- }
- lines.back()
- pre := strings.Join(s, "\n")
- pre = strings.Replace(pre, "\t", " ", -1) // browsers treat tabs badly
- pre = strings.TrimRightFunc(pre, unicode.IsSpace)
- e = Text{Lines: []string{pre}, Pre: true}
- case strings.HasPrefix(text, "- "):
- var b []string
- for ok && strings.HasPrefix(text, "- ") {
- b = append(b, text[2:])
- text, ok = lines.next()
- }
- lines.back()
- e = List{Bullet: b}
- case isSpeakerNote(text):
- section.Notes = append(section.Notes, text[2:])
- case strings.HasPrefix(text, prefix+"* "):
- lines.back()
- subsecs, err := parseSections(ctx, name, lines, section.Number)
- if err != nil {
- return nil, err
- }
- for _, ss := range subsecs {
- section.Elem = append(section.Elem, ss)
- }
- case strings.HasPrefix(text, "."):
- args := strings.Fields(text)
- if args[0] == ".background" {
- section.Classes = append(section.Classes, "background")
- section.Styles = append(section.Styles, "background-image: url('"+args[1]+"')")
- break
- }
- parser := parsers[args[0]]
- if parser == nil {
- return nil, fmt.Errorf("%s:%d: unknown command %q\n", name, lines.line, text)
- }
- t, err := parser(ctx, name, lines.line, text)
- if err != nil {
- return nil, err
- }
- e = t
- default:
- var l []string
- for ok && strings.TrimSpace(text) != "" {
- if text[0] == '.' { // Command breaks text block.
- lines.back()
- break
- }
- if strings.HasPrefix(text, `\.`) { // Backslash escapes initial period.
- text = text[1:]
- }
- l = append(l, text)
- text, ok = lines.next()
- }
- if len(l) > 0 {
- e = Text{Lines: l}
- }
- }
- if e != nil {
- section.Elem = append(section.Elem, e)
- }
- text, ok = lines.nextNonEmpty()
- }
- if isHeading.MatchString(text) {
- lines.back()
- }
- sections = append(sections, section)
- }
- return sections, nil
-}
-
-func parseHeader(doc *Doc, lines *Lines) error {
- var ok bool
- // First non-empty line starts header.
- doc.Title, ok = lines.nextNonEmpty()
- if !ok {
- return errors.New("unexpected EOF; expected title")
- }
- for {
- text, ok := lines.next()
- if !ok {
- return errors.New("unexpected EOF")
- }
- if text == "" {
- break
- }
- if isSpeakerNote(text) {
- continue
- }
- const tagPrefix = "Tags:"
- if strings.HasPrefix(text, tagPrefix) {
- tags := strings.Split(text[len(tagPrefix):], ",")
- for i := range tags {
- tags[i] = strings.TrimSpace(tags[i])
- }
- doc.Tags = append(doc.Tags, tags...)
- } else if t, ok := parseTime(text); ok {
- doc.Time = t
- } else if doc.Subtitle == "" {
- doc.Subtitle = text
- } else {
- return fmt.Errorf("unexpected header line: %q", text)
- }
- }
- return nil
-}
-
-func parseAuthors(lines *Lines) (authors []Author, err error) {
- // This grammar demarcates authors with blanks.
-
- // Skip blank lines.
- if _, ok := lines.nextNonEmpty(); !ok {
- return nil, errors.New("unexpected EOF")
- }
- lines.back()
-
- var a *Author
- for {
- text, ok := lines.next()
- if !ok {
- return nil, errors.New("unexpected EOF")
- }
-
- // If we find a section heading, we're done.
- if strings.HasPrefix(text, "* ") {
- lines.back()
- break
- }
-
- if isSpeakerNote(text) {
- continue
- }
-
- // If we encounter a blank we're done with this author.
- if a != nil && len(text) == 0 {
- authors = append(authors, *a)
- a = nil
- continue
- }
- if a == nil {
- a = new(Author)
- }
-
- // Parse the line. Those that
- // - begin with @ are twitter names,
- // - contain slashes are links, or
- // - contain an @ symbol are an email address.
- // The rest is just text.
- var el Elem
- switch {
- case strings.HasPrefix(text, "@"):
- el = parseURL("http://twitter.com/" + text[1:])
- case strings.Contains(text, ":"):
- el = parseURL(text)
- case strings.Contains(text, "@"):
- el = parseURL("mailto:" + text)
- }
- if l, ok := el.(Link); ok {
- l.Label = text
- el = l
- }
- if el == nil {
- el = Text{Lines: []string{text}}
- }
- a.Elem = append(a.Elem, el)
- }
- if a != nil {
- authors = append(authors, *a)
- }
- return authors, nil
-}
-
-func parseURL(text string) Elem {
- u, err := url.Parse(text)
- if err != nil {
- log.Printf("Parse(%q): %v", text, err)
- return nil
- }
- return Link{URL: u}
-}
-
-func parseTime(text string) (t time.Time, ok bool) {
- t, err := time.Parse("15:04 2 Jan 2006", text)
- if err == nil {
- return t, true
- }
- t, err = time.Parse("2 Jan 2006", text)
- if err == nil {
- // at 11am UTC it is the same date everywhere
- t = t.Add(time.Hour * 11)
- return t, true
- }
- return time.Time{}, false
-}
-
-func isSpeakerNote(s string) bool {
- return strings.HasPrefix(s, ": ")
-}