godoc: remove the last of the global variables, unexport Server
The exported Server becomes handlerServer, and part of Presentation now. Presentation is also now an http.Handler with its own internal mux (a detail, which might go away). main.go becomes ever simpler. R=golang-dev, adg CC=golang-dev https://golang.org/cl/11505043
This commit is contained in:
parent
40a278e5ee
commit
705bb7ffce
|
@ -110,14 +110,12 @@ func registerPublicHandlers(mux *http.ServeMux) {
|
||||||
if pres == nil {
|
if pres == nil {
|
||||||
panic("nil Presentation")
|
panic("nil Presentation")
|
||||||
}
|
}
|
||||||
godoc.CmdHandler.RegisterWithMux(mux)
|
|
||||||
godoc.PkgHandler.RegisterWithMux(mux)
|
|
||||||
mux.HandleFunc("/doc/codewalk/", codewalk)
|
mux.HandleFunc("/doc/codewalk/", codewalk)
|
||||||
mux.Handle("/doc/play/", godoc.FileServer)
|
mux.Handle("/doc/play/", pres.FileServer())
|
||||||
mux.HandleFunc("/search", pres.HandleSearch)
|
mux.HandleFunc("/search", pres.HandleSearch)
|
||||||
mux.Handle("/robots.txt", godoc.FileServer)
|
mux.Handle("/robots.txt", pres.FileServer())
|
||||||
mux.HandleFunc("/opensearch.xml", serveSearchDesc)
|
mux.HandleFunc("/opensearch.xml", serveSearchDesc)
|
||||||
mux.HandleFunc("/", pres.ServeFile)
|
mux.Handle("/", pres)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -298,6 +296,7 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
corpus := godoc.NewCorpus(fs)
|
corpus := godoc.NewCorpus(fs)
|
||||||
|
corpus.Verbose = *verbose
|
||||||
corpus.IndexEnabled = *indexEnabled
|
corpus.IndexEnabled = *indexEnabled
|
||||||
corpus.IndexFiles = *indexFiles
|
corpus.IndexFiles = *indexFiles
|
||||||
if *writeIndex {
|
if *writeIndex {
|
||||||
|
@ -319,8 +318,6 @@ func main() {
|
||||||
|
|
||||||
readTemplates(pres)
|
readTemplates(pres)
|
||||||
|
|
||||||
godoc.InitHandlers(pres)
|
|
||||||
|
|
||||||
if *writeIndex {
|
if *writeIndex {
|
||||||
// Write search index and exit.
|
// Write search index and exit.
|
||||||
if *indexFiles == "" {
|
if *indexFiles == "" {
|
||||||
|
@ -429,14 +426,14 @@ func main() {
|
||||||
abspath = target
|
abspath = target
|
||||||
relpath = bp.ImportPath
|
relpath = bp.ImportPath
|
||||||
} else {
|
} else {
|
||||||
abspath = pathpkg.Join(godoc.PkgHandler.FSRoot(), path)
|
abspath = pathpkg.Join(pres.PkgFSRoot(), path)
|
||||||
}
|
}
|
||||||
if relpath == "" {
|
if relpath == "" {
|
||||||
relpath = abspath
|
relpath = abspath
|
||||||
}
|
}
|
||||||
|
|
||||||
var mode godoc.PageInfoMode
|
var mode godoc.PageInfoMode
|
||||||
if relpath == godoc.BuiltinPkgPath {
|
if relpath == "builtin" {
|
||||||
// the fake built-in package contains unexported identifiers
|
// the fake built-in package contains unexported identifiers
|
||||||
mode = godoc.NoFiltering
|
mode = godoc.NoFiltering
|
||||||
}
|
}
|
||||||
|
@ -451,15 +448,15 @@ func main() {
|
||||||
// first, try as package unless forced as command
|
// first, try as package unless forced as command
|
||||||
var info *godoc.PageInfo
|
var info *godoc.PageInfo
|
||||||
if !forceCmd {
|
if !forceCmd {
|
||||||
info = godoc.PkgHandler.GetPageInfo(abspath, relpath, mode)
|
info = pres.GetPkgPageInfo(abspath, relpath, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// second, try as command unless the path is absolute
|
// second, try as command unless the path is absolute
|
||||||
// (the go command invokes godoc w/ absolute paths; don't override)
|
// (the go command invokes godoc w/ absolute paths; don't override)
|
||||||
var cinfo *godoc.PageInfo
|
var cinfo *godoc.PageInfo
|
||||||
if !filepath.IsAbs(path) {
|
if !filepath.IsAbs(path) {
|
||||||
abspath = pathpkg.Join(godoc.CmdHandler.FSRoot(), path)
|
abspath = pathpkg.Join(pres.CmdFSRoot(), path)
|
||||||
cinfo = godoc.CmdHandler.GetPageInfo(abspath, relpath, mode)
|
cinfo = pres.GetCmdPageInfo(abspath, relpath, mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine what to use
|
// determine what to use
|
||||||
|
|
|
@ -21,6 +21,9 @@ import (
|
||||||
type Corpus struct {
|
type Corpus struct {
|
||||||
fs vfs.FileSystem
|
fs vfs.FileSystem
|
||||||
|
|
||||||
|
// Verbose logging.
|
||||||
|
Verbose bool
|
||||||
|
|
||||||
// IndexEnabled controls whether indexing is enabled.
|
// IndexEnabled controls whether indexing is enabled.
|
||||||
IndexEnabled bool
|
IndexEnabled bool
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,9 @@ import (
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Verbose controls logging verbosity.
|
|
||||||
var Verbose = false
|
|
||||||
|
|
||||||
// Fake relative package path for built-ins. Documentation for all globals
|
// Fake relative package path for built-ins. Documentation for all globals
|
||||||
// (not just exported ones) will be shown for packages in this directory.
|
// (not just exported ones) will be shown for packages in this directory.
|
||||||
const BuiltinPkgPath = "builtin"
|
const builtinPkgPath = "builtin"
|
||||||
|
|
||||||
// FuncMap defines template functions used in godoc templates.
|
// FuncMap defines template functions used in godoc templates.
|
||||||
//
|
//
|
||||||
|
@ -232,7 +229,7 @@ func pkgLinkFunc(path string) string {
|
||||||
// because of the irregular mapping under goroot
|
// because of the irregular mapping under goroot
|
||||||
// we need to correct certain relative paths
|
// we need to correct certain relative paths
|
||||||
relpath = strings.TrimPrefix(relpath, "src/pkg/")
|
relpath = strings.TrimPrefix(relpath, "src/pkg/")
|
||||||
return PkgHandler.pattern[1:] + relpath // remove trailing '/' for relative URL
|
return "pkg/" + relpath // remove trailing '/' for relative URL
|
||||||
}
|
}
|
||||||
|
|
||||||
// n must be an ast.Node or a *doc.Note
|
// n must be an ast.Node or a *doc.Note
|
||||||
|
|
|
@ -1090,14 +1090,14 @@ func (c *Corpus) readIndex(filenames string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Corpus) UpdateIndex() {
|
func (c *Corpus) UpdateIndex() {
|
||||||
if Verbose {
|
if c.Verbose {
|
||||||
log.Printf("updating index...")
|
log.Printf("updating index...")
|
||||||
}
|
}
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
index := NewIndex(c, c.fsDirnames(), c.MaxResults > 0, c.IndexThrottle)
|
index := NewIndex(c, c.fsDirnames(), c.MaxResults > 0, c.IndexThrottle)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
c.searchIndex.Set(index)
|
c.searchIndex.Set(index)
|
||||||
if Verbose {
|
if c.Verbose {
|
||||||
secs := stop.Sub(start).Seconds()
|
secs := stop.Sub(start).Seconds()
|
||||||
stats := index.Stats()
|
stats := index.Stats()
|
||||||
log.Printf("index updated (%gs, %d bytes of source, %d files, %d lines, %d unique words, %d spots)",
|
log.Printf("index updated (%gs, %d bytes of source, %d files, %d lines, %d unique words, %d spots)",
|
||||||
|
|
|
@ -94,7 +94,7 @@ func linksFor(node ast.Node) (list []link) {
|
||||||
switch m {
|
switch m {
|
||||||
case identUse:
|
case identUse:
|
||||||
if n.Obj == nil && predeclared[n.Name] {
|
if n.Obj == nil && predeclared[n.Name] {
|
||||||
info.path = BuiltinPkgPath
|
info.path = builtinPkgPath
|
||||||
}
|
}
|
||||||
info.name = n.Name
|
info.name = n.Name
|
||||||
case identDef:
|
case identDef:
|
||||||
|
|
|
@ -5,15 +5,23 @@
|
||||||
package godoc
|
package godoc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sync"
|
"sync"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
|
"code.google.com/p/go.tools/godoc/vfs/httpfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Presentation generates output from a corpus.
|
// Presentation generates output from a corpus.
|
||||||
type Presentation struct {
|
type Presentation struct {
|
||||||
Corpus *Corpus
|
Corpus *Corpus
|
||||||
|
|
||||||
|
mux *http.ServeMux
|
||||||
|
fileServer http.Handler
|
||||||
|
cmdHandler handlerServer
|
||||||
|
pkgHandler handlerServer
|
||||||
|
|
||||||
DirlistHTML,
|
DirlistHTML,
|
||||||
ErrorHTML,
|
ErrorHTML,
|
||||||
ExampleHTML,
|
ExampleHTML,
|
||||||
|
@ -36,6 +44,11 @@ type Presentation struct {
|
||||||
// notes to render in the output.
|
// notes to render in the output.
|
||||||
NotesRx *regexp.Regexp
|
NotesRx *regexp.Regexp
|
||||||
|
|
||||||
|
// AdjustPageInfoMode optionally specifies a function to
|
||||||
|
// modify the PageInfoMode of a request. The default chosen
|
||||||
|
// value is provided.
|
||||||
|
AdjustPageInfoMode func(req *http.Request, mode PageInfoMode) PageInfoMode
|
||||||
|
|
||||||
initFuncMapOnce sync.Once
|
initFuncMapOnce sync.Once
|
||||||
funcMap template.FuncMap
|
funcMap template.FuncMap
|
||||||
templateFuncs template.FuncMap
|
templateFuncs template.FuncMap
|
||||||
|
@ -46,10 +59,47 @@ func NewPresentation(c *Corpus) *Presentation {
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic("nil Corpus")
|
panic("nil Corpus")
|
||||||
}
|
}
|
||||||
return &Presentation{
|
p := &Presentation{
|
||||||
Corpus: c,
|
Corpus: c,
|
||||||
|
mux: http.NewServeMux(),
|
||||||
|
fileServer: http.FileServer(httpfs.New(c.fs)),
|
||||||
|
|
||||||
TabWidth: 4,
|
TabWidth: 4,
|
||||||
ShowExamples: true,
|
ShowExamples: true,
|
||||||
DeclLinks: true,
|
DeclLinks: true,
|
||||||
}
|
}
|
||||||
|
p.cmdHandler = handlerServer{p, c, "/cmd/", "/src/cmd"}
|
||||||
|
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src/pkg"}
|
||||||
|
p.cmdHandler.registerWithMux(p.mux)
|
||||||
|
p.pkgHandler.registerWithMux(p.mux)
|
||||||
|
p.mux.HandleFunc("/", p.ServeFile)
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Presentation) FileServer() http.Handler {
|
||||||
|
return p.fileServer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Presentation) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
p.mux.ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Presentation) PkgFSRoot() string {
|
||||||
|
return p.pkgHandler.fsRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Presentation) CmdFSRoot() string {
|
||||||
|
return p.cmdHandler.fsRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
|
||||||
|
// but this doesn't feel right.
|
||||||
|
func (p *Presentation) GetPkgPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
|
||||||
|
return p.pkgHandler.GetPageInfo(abspath, relpath, mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(bradfitz): move this to be a method on Corpus. Just moving code around for now,
|
||||||
|
// but this doesn't feel right.
|
||||||
|
func (p *Presentation) GetCmdPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
|
||||||
|
return p.cmdHandler.GetPageInfo(abspath, relpath, mode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ func (p *Presentation) HandleSearch(w http.ResponseWriter, r *http.Request) {
|
||||||
query := strings.TrimSpace(r.FormValue("q"))
|
query := strings.TrimSpace(r.FormValue("q"))
|
||||||
result := p.Corpus.Lookup(query)
|
result := p.Corpus.Lookup(query)
|
||||||
|
|
||||||
if GetPageInfoMode(r)&NoHTML != 0 {
|
if p.GetPageInfoMode(r)&NoHTML != 0 {
|
||||||
p.ServeText(w, applyTemplate(p.SearchText, "searchText", result))
|
p.ServeText(w, applyTemplate(p.SearchText, "searchText", result))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,35 +25,18 @@ import (
|
||||||
|
|
||||||
"code.google.com/p/go.tools/godoc/util"
|
"code.google.com/p/go.tools/godoc/util"
|
||||||
"code.google.com/p/go.tools/godoc/vfs"
|
"code.google.com/p/go.tools/godoc/vfs"
|
||||||
"code.google.com/p/go.tools/godoc/vfs/httpfs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO(bradfitz,adg): these are moved from godoc.go globals.
|
// handlerServer is a migration from an old godoc http Handler type.
|
||||||
// Clean this up.
|
// This should probably merge into something else.
|
||||||
var (
|
type handlerServer struct {
|
||||||
FileServer http.Handler // default file server
|
|
||||||
CmdHandler Server
|
|
||||||
PkgHandler Server
|
|
||||||
)
|
|
||||||
|
|
||||||
func InitHandlers(p *Presentation) {
|
|
||||||
c := p.Corpus
|
|
||||||
FileServer = http.FileServer(httpfs.New(c.fs))
|
|
||||||
CmdHandler = Server{p, c, "/cmd/", "/src/cmd"}
|
|
||||||
PkgHandler = Server{p, c, "/pkg/", "/src/pkg"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server is a godoc server.
|
|
||||||
type Server struct {
|
|
||||||
p *Presentation
|
p *Presentation
|
||||||
c *Corpus // copy of p.Corpus
|
c *Corpus // copy of p.Corpus
|
||||||
pattern string // url pattern; e.g. "/pkg/"
|
pattern string // url pattern; e.g. "/pkg/"
|
||||||
fsRoot string // file system root to which the pattern is mapped
|
fsRoot string // file system root to which the pattern is mapped
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) FSRoot() string { return s.fsRoot }
|
func (s *handlerServer) registerWithMux(mux *http.ServeMux) {
|
||||||
|
|
||||||
func (s *Server) RegisterWithMux(mux *http.ServeMux) {
|
|
||||||
mux.Handle(s.pattern, s)
|
mux.Handle(s.pattern, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +48,7 @@ func (s *Server) RegisterWithMux(mux *http.ServeMux) {
|
||||||
// directories, PageInfo.Dirs is nil. If an error occurred, PageInfo.Err is
|
// directories, PageInfo.Dirs is nil. If an error occurred, PageInfo.Err is
|
||||||
// set to the respective error but the error is not logged.
|
// set to the respective error but the error is not logged.
|
||||||
//
|
//
|
||||||
func (h *Server) GetPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
|
func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode) *PageInfo {
|
||||||
info := &PageInfo{Dirname: abspath}
|
info := &PageInfo{Dirname: abspath}
|
||||||
|
|
||||||
// Restrict to the package files that would be used when building
|
// Restrict to the package files that would be used when building
|
||||||
|
@ -194,15 +177,15 @@ func (h *Server) GetPageInfo(abspath, relpath string, mode PageInfoMode) *PageIn
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (h *handlerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
if redirect(w, r) {
|
if redirect(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
relpath := pathpkg.Clean(r.URL.Path[len(h.pattern):])
|
relpath := pathpkg.Clean(r.URL.Path[len(h.pattern):])
|
||||||
abspath := pathpkg.Join(h.fsRoot, relpath)
|
abspath := pathpkg.Join(h.fsRoot, relpath)
|
||||||
mode := GetPageInfoMode(r)
|
mode := h.p.GetPageInfoMode(r)
|
||||||
if relpath == BuiltinPkgPath {
|
if relpath == builtinPkgPath {
|
||||||
mode = NoFiltering
|
mode = NoFiltering
|
||||||
}
|
}
|
||||||
info := h.GetPageInfo(abspath, relpath, mode)
|
info := h.GetPageInfo(abspath, relpath, mode)
|
||||||
|
@ -279,19 +262,16 @@ var modeNames = map[string]PageInfoMode{
|
||||||
// GetPageInfoMode computes the PageInfoMode flags by analyzing the request
|
// GetPageInfoMode computes the PageInfoMode flags by analyzing the request
|
||||||
// URL form value "m". It is value is a comma-separated list of mode names
|
// URL form value "m". It is value is a comma-separated list of mode names
|
||||||
// as defined by modeNames (e.g.: m=src,text).
|
// as defined by modeNames (e.g.: m=src,text).
|
||||||
func GetPageInfoMode(r *http.Request) PageInfoMode {
|
func (p *Presentation) GetPageInfoMode(r *http.Request) PageInfoMode {
|
||||||
var mode PageInfoMode
|
var mode PageInfoMode
|
||||||
for _, k := range strings.Split(r.FormValue("m"), ",") {
|
for _, k := range strings.Split(r.FormValue("m"), ",") {
|
||||||
if m, found := modeNames[strings.TrimSpace(k)]; found {
|
if m, found := modeNames[strings.TrimSpace(k)]; found {
|
||||||
mode |= m
|
mode |= m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return AdjustPageInfoMode(r, mode)
|
if p.AdjustPageInfoMode != nil {
|
||||||
}
|
mode = p.AdjustPageInfoMode(r, mode)
|
||||||
|
}
|
||||||
// AdjustPageInfoMode allows specialized versions of godoc to adjust
|
|
||||||
// PageInfoMode by overriding this variable.
|
|
||||||
var AdjustPageInfoMode = func(_ *http.Request, mode PageInfoMode) PageInfoMode {
|
|
||||||
return mode
|
return mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +564,7 @@ func (p *Presentation) serveFile(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
FileServer.ServeHTTP(w, r)
|
p.fileServer.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Presentation) serveSearchDesc(w http.ResponseWriter, r *http.Request) {
|
func (p *Presentation) serveSearchDesc(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
Loading…
Reference in New Issue