summaryrefslogtreecommitdiff
path: root/src/cmd/godoc/snippet.go
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
committerOndřej Surý <ondrej@sury.org>2011-09-13 13:13:40 +0200
commit5ff4c17907d5b19510a62e08fd8d3b11e62b431d (patch)
treec0650497e988f47be9c6f2324fa692a52dea82e1 /src/cmd/godoc/snippet.go
parent80f18fc933cf3f3e829c5455a1023d69f7b86e52 (diff)
downloadgolang-5ff4c17907d5b19510a62e08fd8d3b11e62b431d.tar.gz
Imported Upstream version 60upstream/60
Diffstat (limited to 'src/cmd/godoc/snippet.go')
-rwxr-xr-xsrc/cmd/godoc/snippet.go100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/cmd/godoc/snippet.go b/src/cmd/godoc/snippet.go
new file mode 100755
index 000000000..68e27d9a0
--- /dev/null
+++ b/src/cmd/godoc/snippet.go
@@ -0,0 +1,100 @@
+// Copyright 2009 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.
+
+// This file contains the infrastructure to create a code
+// snippet for search results.
+//
+// Note: At the moment, this only creates HTML snippets.
+
+package main
+
+import (
+ "bytes"
+ "go/ast"
+ "go/token"
+ "fmt"
+)
+
+type Snippet struct {
+ Line int
+ Text string // HTML-escaped
+}
+
+func newSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) *Snippet {
+ // TODO instead of pretty-printing the node, should use the original source instead
+ var buf1 bytes.Buffer
+ writeNode(&buf1, fset, decl)
+ // wrap text with <pre> tag
+ var buf2 bytes.Buffer
+ buf2.WriteString("<pre>")
+ FormatText(&buf2, buf1.Bytes(), -1, true, id.Name, nil)
+ buf2.WriteString("</pre>")
+ return &Snippet{fset.Position(id.Pos()).Line, buf2.String()}
+}
+
+func findSpec(list []ast.Spec, id *ast.Ident) ast.Spec {
+ for _, spec := range list {
+ switch s := spec.(type) {
+ case *ast.ImportSpec:
+ if s.Name == id {
+ return s
+ }
+ case *ast.ValueSpec:
+ for _, n := range s.Names {
+ if n == id {
+ return s
+ }
+ }
+ case *ast.TypeSpec:
+ if s.Name == id {
+ return s
+ }
+ }
+ }
+ return nil
+}
+
+func genSnippet(fset *token.FileSet, d *ast.GenDecl, id *ast.Ident) *Snippet {
+ s := findSpec(d.Specs, id)
+ if s == nil {
+ return nil // declaration doesn't contain id - exit gracefully
+ }
+
+ // only use the spec containing the id for the snippet
+ dd := &ast.GenDecl{d.Doc, d.Pos(), d.Tok, d.Lparen, []ast.Spec{s}, d.Rparen}
+
+ return newSnippet(fset, dd, id)
+}
+
+func funcSnippet(fset *token.FileSet, d *ast.FuncDecl, id *ast.Ident) *Snippet {
+ if d.Name != id {
+ return nil // declaration doesn't contain id - exit gracefully
+ }
+
+ // only use the function signature for the snippet
+ dd := &ast.FuncDecl{d.Doc, d.Recv, d.Name, d.Type, nil}
+
+ return newSnippet(fset, dd, id)
+}
+
+// NewSnippet creates a text snippet from a declaration decl containing an
+// identifier id. Parts of the declaration not containing the identifier
+// may be removed for a more compact snippet.
+//
+func NewSnippet(fset *token.FileSet, decl ast.Decl, id *ast.Ident) (s *Snippet) {
+ switch d := decl.(type) {
+ case *ast.GenDecl:
+ s = genSnippet(fset, d, id)
+ case *ast.FuncDecl:
+ s = funcSnippet(fset, d, id)
+ }
+
+ // handle failure gracefully
+ if s == nil {
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, `<span class="alert">could not generate a snippet for <span class="highlight">%s</span></span>`, id.Name)
+ s = &Snippet{fset.Position(id.Pos()).Line, buf.String()}
+ }
+ return
+}