present: record info in AST for reproducing present inputs

Commands like .code now have a TemplateCmd method
that returns the original command.

The Text struct now has a Raw field set when Pre==true.
It contains the original indented text, without the tab "fixing".

This helps building tooling that reformats or rewrites present files.

For golang/go#33955.

Change-Id: Ieb036e8b509a4531d120c597b19f2158306a5352
Reviewed-on: https://go-review.googlesource.com/c/tools/+/222845
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rob Pike <r@golang.org>
This commit is contained in:
Russ Cox 2020-03-09 22:20:35 -04:00
Родитель 1775515697
Коммит 657575a564
8 изменённых файлов: 25 добавлений и 7 удалений

Просмотреть файл

@ -11,12 +11,14 @@ func init() {
}
type Caption struct {
Cmd string // original command from present source
Text string
}
func (c Caption) PresentCmd() string { return c.Cmd }
func (c Caption) TemplateName() string { return "caption" }
func parseCaption(_ *Context, _ string, _ int, text string) (Elem, error) {
text = strings.TrimSpace(strings.TrimPrefix(text, ".caption"))
return Caption{text}, nil
return Caption{text, text}, nil
}

Просмотреть файл

@ -34,6 +34,7 @@ func init() {
}
type Code struct {
Cmd string // original command from present source
Text template.HTML
Play bool // runnable code
Edit bool // editable code
@ -42,6 +43,7 @@ type Code struct {
Raw []byte // content of the file
}
func (c Code) PresentCmd() string { return c.Cmd }
func (c Code) TemplateName() string { return "code" }
// The input line is a .code or .play entry with a file name and an optional HLfoo marker on the end.
@ -58,6 +60,7 @@ var (
// The directive may also be ".play" if the snippet is executable.
func parseCode(ctx *Context, sourceFile string, sourceLine int, cmd string) (Elem, error) {
cmd = strings.TrimSpace(cmd)
origCmd := cmd
// Pull off the HL, if any, from the end of the input line.
highlight := ""
@ -129,6 +132,7 @@ func parseCode(ctx *Context, sourceFile string, sourceLine int, cmd string) (Ele
return nil, err
}
return Code{
Cmd: origCmd,
Text: template.HTML(buf.String()),
Play: play,
Edit: data.Edit,

Просмотреть файл

@ -21,11 +21,13 @@ func parseHTML(ctx *Context, fileName string, lineno int, text string) (Elem, er
if err != nil {
return nil, err
}
return HTML{template.HTML(b)}, nil
return HTML{text, template.HTML(b)}, nil
}
type HTML struct {
Cmd string // original command from present source
template.HTML
}
func (s HTML) PresentCmd() string { return s.Cmd }
func (s HTML) TemplateName() string { return "html" }

Просмотреть файл

@ -14,11 +14,13 @@ func init() {
}
type Iframe struct {
Cmd string // original command from present source
URL string
Width int
Height int
}
func (i Iframe) PresentCmd() string { return i.Cmd }
func (i Iframe) TemplateName() string { return "iframe" }
func parseIframe(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
@ -26,7 +28,7 @@ func parseIframe(ctx *Context, fileName string, lineno int, text string) (Elem,
if len(args) < 2 {
return nil, fmt.Errorf("incorrect iframe invocation: %q", text)
}
i := Iframe{URL: args[1]}
i := Iframe{Cmd: text, URL: args[1]}
a, err := parseArgs(fileName, lineno, args[2:])
if err != nil {
return nil, err

Просмотреть файл

@ -14,11 +14,13 @@ func init() {
}
type Image struct {
Cmd string // original command from present source
URL string
Width int
Height int
}
func (i Image) PresentCmd() string { return i.Cmd }
func (i Image) TemplateName() string { return "image" }
func parseImage(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
@ -26,7 +28,7 @@ func parseImage(ctx *Context, fileName string, lineno int, text string) (Elem, e
if len(args) < 2 {
return nil, fmt.Errorf("incorrect image invocation: %q", text)
}
img := Image{URL: args[1]}
img := Image{Cmd: text, URL: args[1]}
a, err := parseArgs(fileName, lineno, args[2:])
if err != nil {
return nil, err

Просмотреть файл

@ -16,10 +16,12 @@ func init() {
}
type Link struct {
Cmd string // original command from present source
URL *url.URL
Label string
}
func (l Link) PresentCmd() string { return l.Cmd }
func (l Link) TemplateName() string { return "link" }
func parseLink(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
@ -41,7 +43,7 @@ func parseLink(ctx *Context, fileName string, lineno int, text string) (Elem, er
}
label = strings.Replace(url.String(), scheme, "", 1)
}
return Link{url, label}, nil
return Link{text, url, label}, nil
}
func renderLink(href, text string) string {

Просмотреть файл

@ -196,6 +196,7 @@ func execTemplate(t *template.Template, name string, data interface{}) (template
type Text struct {
Lines []string
Pre bool
Raw string // original text, for Pre==true
}
func (t Text) TemplateName() string { return "text" }
@ -371,9 +372,10 @@ func parseSections(ctx *Context, name string, lines *Lines, number []int) ([]Sec
}
lines.back()
pre := strings.Join(s, "\n")
raw := pre
pre = strings.Replace(pre, "\t", " ", -1) // browsers treat tabs badly
pre = strings.TrimRightFunc(pre, unicode.IsSpace)
e = Text{Lines: []string{pre}, Pre: true}
e = Text{Lines: []string{pre}, Pre: true, Raw: raw}
case strings.HasPrefix(text, "- "):
var b []string
for {

Просмотреть файл

@ -14,12 +14,14 @@ func init() {
}
type Video struct {
Cmd string // original command from present source
URL string
SourceType string
Width int
Height int
}
func (v Video) PresentCmd() string { return v.Cmd }
func (v Video) TemplateName() string { return "video" }
func parseVideo(ctx *Context, fileName string, lineno int, text string) (Elem, error) {
@ -27,7 +29,7 @@ func parseVideo(ctx *Context, fileName string, lineno int, text string) (Elem, e
if len(args) < 3 {
return nil, fmt.Errorf("incorrect video invocation: %q", text)
}
vid := Video{URL: args[1], SourceType: args[2]}
vid := Video{Cmd: text, URL: args[1], SourceType: args[2]}
a, err := parseArgs(fileName, lineno, args[3:])
if err != nil {
return nil, err