diff options
author | Ondřej Surý <ondrej@sury.org> | 2011-02-14 13:23:51 +0100 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2011-02-14 13:23:51 +0100 |
commit | 758ff64c69e34965f8af5b2d6ffd65e8d7ab2150 (patch) | |
tree | 6d6b34f8c678862fe9b56c945a7b63f68502c245 /src/cmd/godoc/godoc.go | |
parent | 3e45412327a2654a77944249962b3652e6142299 (diff) | |
download | golang-upstream/2011-02-01.1.tar.gz |
Imported Upstream version 2011-02-01.1upstream/2011-02-01.1
Diffstat (limited to 'src/cmd/godoc/godoc.go')
-rw-r--r-- | src/cmd/godoc/godoc.go | 120 |
1 files changed, 39 insertions, 81 deletions
diff --git a/src/cmd/godoc/godoc.go b/src/cmd/godoc/godoc.go index d6054ab9d..6a00a3e70 100644 --- a/src/cmd/godoc/godoc.go +++ b/src/cmd/godoc/godoc.go @@ -25,7 +25,6 @@ import ( "strings" "template" "time" - "utf8" ) @@ -56,7 +55,7 @@ var ( // TODO(gri) consider the invariant that goroot always end in '/' goroot = flag.String("goroot", runtime.GOROOT(), "Go root directory") testDir = flag.String("testdir", "", "Go root subdirectory - for testing only (faster startups)") - path = flag.String("path", "", "additional package directories (colon-separated)") + pkgPath = flag.String("path", "", "additional package directories (colon-separated)") filter = flag.String("filter", "", "filter file containing permitted package directory paths") filterMin = flag.Int("filter_minutes", 0, "filter file update interval in minutes; disabled if <= 0") filterDelay delayTime // actual filter update interval in minutes; usually filterDelay == filterMin, but filterDelay may back off exponentially @@ -64,7 +63,7 @@ var ( // layout control tabwidth = flag.Int("tabwidth", 4, "tab width") showTimestamps = flag.Bool("timestamps", true, "show timestamps with directory listings") - fulltextIndex = flag.Bool("fulltext", false, "build full text index for regular expression queries") + maxResults = flag.Int("maxresults", 10000, "maximum number of full text search results shown") // file system mapping fsMap Mapping // user-defined mapping @@ -80,7 +79,7 @@ var ( func initHandlers() { - fsMap.Init(*path) + fsMap.Init(*pkgPath) fileServer = http.FileServer(*goroot, "") cmdHandler = httpHandler{"/cmd/", pathutil.Join(*goroot, "src/cmd"), false} pkgHandler = httpHandler{"/pkg/", pathutil.Join(*goroot, "src/pkg"), true} @@ -626,11 +625,11 @@ func readTemplate(name string) *template.Template { path := pathutil.Join(*goroot, "lib/godoc/"+name) data, err := ioutil.ReadFile(path) if err != nil { - log.Exitf("ReadFile %s: %v", path, err) + log.Fatalf("ReadFile %s: %v", path, err) } t, err := template.Parse(string(data), fmap) if err != nil { - log.Exitf("%s: %v", name, err) + log.Fatalf("%s: %v", name, err) } return t } @@ -768,53 +767,6 @@ func redirect(w http.ResponseWriter, r *http.Request) (redirected bool) { } -// TODO(gri): Should have a mapping from extension to handler, eventually. - -// textExt[x] is true if the extension x indicates a text file, and false otherwise. -var textExt = map[string]bool{ - ".css": false, // must be served raw - ".js": false, // must be served raw -} - - -func isTextFile(path string) bool { - // if the extension is known, use it for decision making - if isText, found := textExt[pathutil.Ext(path)]; found { - return isText - } - - // the extension is not known; read an initial chunk of - // file and check if it looks like correct UTF-8; if it - // does, it's probably a text file - f, err := os.Open(path, os.O_RDONLY, 0) - if err != nil { - return false - } - defer f.Close() - - var buf [1024]byte - n, err := f.Read(buf[0:]) - if err != nil { - return false - } - - s := string(buf[0:n]) - n -= utf8.UTFMax // make sure there's enough bytes for a complete unicode char - for i, c := range s { - if i > n { - break - } - if c == 0xFFFD || c < ' ' && c != '\n' && c != '\t' { - // decoding error or control character - not a text file - return false - } - } - - // likely a text file - return true -} - - func serveTextFile(w http.ResponseWriter, r *http.Request, abspath, relpath, title string) { src, err := ioutil.ReadFile(abspath) if err != nil { @@ -1159,41 +1111,47 @@ type SearchResult struct { func lookup(query string) (result SearchResult) { result.Query = query - // determine identifier lookup string and full text regexp - lookupStr := "" - lookupRx, err := regexp.Compile(query) - if err != nil { - result.Alert = "Error in query regular expression: " + err.String() - return - } - if prefix, complete := lookupRx.LiteralPrefix(); complete { - // otherwise we lookup "" (with no result) because - // identifier lookup doesn't support regexp search - lookupStr = prefix - } + index, timestamp := searchIndex.get() + if index != nil { + index := index.(*Index) - if index, timestamp := searchIndex.get(); index != nil { // identifier search - index := index.(*Index) - result.Hit, result.Alt, err = index.Lookup(lookupStr) - if err != nil && !*fulltextIndex { - // ignore the error if there is full text search - // since it accepts that query regular expression + var err os.Error + result.Hit, result.Alt, err = index.Lookup(query) + if err != nil && *maxResults <= 0 { + // ignore the error if full text search is enabled + // since the query may be a valid regular expression result.Alert = "Error in query string: " + err.String() return } - // textual search - // TODO(gri) should max be a flag? - const max = 10000 // show at most this many fulltext results - result.Found, result.Textual = index.LookupRegexp(lookupRx, max+1) - result.Complete = result.Found <= max - - // is the result accurate? - if _, ts := fsModified.get(); timestamp < ts { - result.Alert = "Indexing in progress: result may be inaccurate" + // full text search + if *maxResults > 0 && query != "" { + rx, err := regexp.Compile(query) + if err != nil { + result.Alert = "Error in query regular expression: " + err.String() + return + } + // If we get maxResults+1 results we know that there are more than + // maxResults results and thus the result may be incomplete (to be + // precise, we should remove one result from the result set, but + // nobody is going to count the results on the result page). + result.Found, result.Textual = index.LookupRegexp(rx, *maxResults+1) + result.Complete = result.Found <= *maxResults + if !result.Complete { + result.Found-- // since we looked for maxResults+1 + } } } + + // is the result accurate? + if _, ts := fsModified.get(); timestamp < ts { + // The index is older than the latest file system change + // under godoc's observation. Indexing may be in progress + // or start shortly (see indexer()). + result.Alert = "Indexing in progress: result may be inaccurate" + } + return } @@ -1278,7 +1236,7 @@ func indexer() { log.Printf("updating index...") } start := time.Nanoseconds() - index := NewIndex(fsDirnames(), *fulltextIndex) + index := NewIndex(fsDirnames(), *maxResults > 0) stop := time.Nanoseconds() searchIndex.set(index) if *verbose { |