fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

1// Copyright 2016 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package web 16 17import ( 18 "html/template" 19 "log" 20) 21 22// Top provides the standard templates in parsed form 23var Top = template.New("top").Funcs(Funcmap) 24 25// TemplateText contains the text of the standard templates. 26var TemplateText = map[string]string{ 27 "head": ` 28<head> 29<meta charset="utf-8"> 30<meta http-equiv="X-UA-Compatible" content="IE=edge"> 31<meta name="viewport" content="width=device-width, initial-scale=1"> 32<!-- Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) --> 33<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> 34<style> 35 #navsearchbox { width: 350px !important; } 36 #maxhits { width: 100px !important; } 37 #context { width: 70px !important; } 38 .label-dup { 39 border-width: 1px !important; 40 border-style: solid !important; 41 border-color: #aaa !important; 42 color: black; 43 } 44 .noselect { 45 color: #999; 46 user-select: none; 47 } 48 a.label-dup:hover { 49 color: black; 50 background: #ddd; 51 } 52 .result { 53 display: block; 54 content: " "; 55 visibility: hidden; 56 } 57 .container-results { 58 overflow: auto; 59 max-height: calc(100% - 72px); 60 } 61 .inline-pre { 62 border: unset; 63 background-color: unset; 64 margin: unset; 65 padding: unset; 66 overflow: unset; 67 } 68 :target { background-color: #ccf; } 69 table tbody tr td { border: none !important; padding: 2px !important; } 70</style> 71</head> 72 `, 73 74 "jsdep": ` 75<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> 76<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> 77`, 78 79 // the template for the search box. 80 "searchbox": ` 81<form action="search"> 82 <div class="form-group form-group-lg"> 83 <div class="input-group input-group-lg"> 84 <input class="form-control" placeholder="Search for some code..." autofocus 85 {{if .Query}} 86 value={{.Query}} 87 {{end}} 88 id="searchbox" type="text" name="q"> 89 <div class="input-group-btn"> 90 <button class="btn btn-primary">Search</button> 91 </div> 92 </div> 93 </div> 94</form> 95`, 96 97 "navbar": ` 98<nav class="navbar navbar-default"> 99 <div class="container-fluid"> 100 <div class="navbar-header"> 101 <a class="navbar-brand" href="/">Zoekt</a> 102 <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-collapse" aria-expanded="false"> 103 <span class="sr-only">Toggle navigation</span> 104 <span class="icon-bar"></span> 105 <span class="icon-bar"></span> 106 <span class="icon-bar"></span> 107 </button> 108 </div> 109 <div class="navbar-collapse collapse" id="navbar-collapse" aria-expanded="false" style="height: 1px;"> 110 <form class="navbar-form navbar-left" action="search"> 111 <div class="form-group"> 112 <input class="form-control" 113 placeholder="Search for some code..." role="search" 114 id="navsearchbox" type="text" name="q" autofocus 115 {{if .Query}} 116 value={{.Query}} 117 {{end}}> 118 <div class="input-group"> 119 <div class="input-group-addon">Max Results</div> 120 <input class="form-control" type="number" id="maxhits" name="num" value="{{.Num}}"> 121 </div> 122 <div class="input-group"> 123 <div class="input-group-addon">Context Lines</div> 124 <input class="form-control" id="context" name="ctx" type="number" value="{{.Ctx}}"> 125 </div> 126 <button class="btn btn-primary">Search</button> 127 <!--Hack: we use a hidden form field to keep track of the debug flag across searches--> 128 {{if .Debug}}<input id="debug" name="debug" type="hidden" value="{{.Debug}}">{{end}} 129 </div> 130 </form> 131 </div> 132 </div> 133</nav> 134<script> 135document.onkeydown=function(e){ 136 var e = e || window.event; 137 if (e.key == "/") { 138 var navbox = document.getElementById("navsearchbox"); 139 if (document.activeElement !== navbox) { 140 navbox.focus(); 141 return false; 142 } 143 } 144}; 145</script> 146`, 147 // search box for the entry page. 148 "search": ` 149<html> 150{{template "head"}} 151<title>Zoekt, en gij zult spinazie eten</title> 152<body> 153 <div class="jumbotron"> 154 <div class="container"> 155 {{template "searchbox" .Last}} 156 </div> 157 </div> 158 159 <div class="container"> 160 <div class="row"> 161 <div class="col-md-8"> 162 <h3>Search examples:</h3> 163 <dl class="dl-horizontal"> 164 <dt><a href="search?q=needle">needle</a></dt><dd>search for "needle"</dd> 165 <dt><a href="search?q=thread+or+needle">thread or needle</a></dt><dd>search for either "thread" or "needle"</dd> 166 <dt><a href="search?q=class+needle">class needle</a></span></dt><dd>search for files containing both "class" and "needle"</dd> 167 <dt><a href="search?q=class+Needle">class Needle</a></dt><dd>search for files containing both "class" (case insensitive) and "Needle" (case sensitive)</dd> 168 <dt><a href="search?q=class+Needle+case:yes">class Needle case:yes</a></dt><dd>search for files containing "class" and "Needle", both case sensitively</dd> 169 <dt><a href="search?q=%22class Needle%22">"class Needle"</a></dt><dd>search for files with the phrase "class Needle"</dd> 170 <dt><a href="search?q=needle+-hay">needle -hay</a></dt><dd>search for files with the word "needle" but not the word "hay"</dd> 171 <dt><a href="search?q=path+file:java">path file:java</a></dt><dd>search for the word "path" in files whose name contains "java"</dd> 172 <dt><a href="search?q=needle+lang%3Apython&num=50">needle lang:python</a></dt><dd>search for "needle" in Python source code</dd> 173 <dt><a href="search?q=f:%5C.c%24">f:\.c$</a></dt><dd>search for files whose name ends with ".c"</dd> 174 <dt><a href="search?q=path+-file:java">path -file:java</a></dt><dd>search for the word "path" excluding files whose name contains "java"</dd> 175 <dt><a href="search?q=foo.*bar">foo.*bar</a></dt><dd>search for the regular expression "foo.*bar"</dd> 176 <dt><a href="search?q=-%28Path File%29 Stream">-(Path File) Stream</a></dt><dd>search "Stream", but exclude files containing both "Path" and "File"</dd> 177 <dt><a href="search?q=-Path%5c+file+Stream">-Path\ file Stream</a></dt><dd>search "Stream", but exclude files containing "Path File"</dd> 178 <dt><a href="search?q=sym:data">sym:data</a></span></dt><dd>search for symbol definitions containing "data"</dd> 179 <dt><a href="search?q=phone+r:droid">phone r:droid</a></dt><dd>search for "phone" in repositories whose name contains "droid"</dd> 180 <dt><a href="search?q=phone+archived:no">phone archived:no</a></dt><dd>search for "phone" in repositories that are not archived</dd> 181 <dt><a href="search?q=phone+fork:no">phone fork:no</a></dt><dd>search for "phone" in repositories that are not forks</dd> 182 <dt><a href="search?q=phone+public:no">phone public:no</a></dt><dd>search for "phone" in repositories that are not public</dd> 183 <dt><a href="search?q=phone+b:master">phone b:master</a></dt><dd>for Git repos, find "phone" in files in branches whose name contains "master".</dd> 184 <dt><a href="search?q=phone+b:HEAD">phone b:HEAD</a></dt><dd>for Git repos, find "phone" in the default ('HEAD') branch.</dd> 185 </dl> 186 </div> 187 <div class="col-md-4"> 188 <h3>To list repositories, try:</h3> 189 <dl class="dl-horizontal"> 190 <dt><a href="search?q=r:droid">r:droid</a></dt><dd>list repositories whose name contains "droid".</dd> 191 <dt><a href="search?q=r:go+-r:google">r:go -r:google</a></dt><dd>list repositories whose name contains "go" but not "google".</dd> 192 </dl> 193 </div> 194 </div> 195 </div> 196 <nav class="navbar navbar-default navbar-bottom"> 197 <div class="container"> 198 {{template "footerBoilerplate"}} 199 <p class="navbar-text navbar-right"> 200 Used {{HumanUnit .Stats.IndexBytes}} mem for 201 {{.Stats.Documents}} documents ({{HumanUnit .Stats.ContentBytes}}) 202 from {{.Stats.Repos}} repositories. 203 </p> 204 </div> 205 </nav> 206</body> 207</html> 208`, 209 "footerBoilerplate": `<a class="navbar-text" href="about">About</a>`, 210 "results": ` 211<html> 212{{template "head"}} 213<title>Results for {{.QueryStr}}</title> 214<script> 215 function zoektAddQ(atom) { 216 window.location.href = "/search?q=" + encodeURIComponent("{{.QueryStr}}" + " " + atom) + 217 "&" + "num=" + {{.Last.Num}}; 218 } 219</script> 220<body id="results"> 221 {{template "navbar" .Last}} 222 <div class="container-fluid container-results"> 223 <h5> 224 {{if .Stats.Crashes}}<br><b>{{.Stats.Crashes}} shards crashed</b><br>{{end}} 225 {{ $fileCount := len .FileMatches }} 226 Found {{.Stats.MatchCount}} results in {{.Stats.FileCount}} files{{if or (lt $fileCount .Stats.FileCount) (or (gt .Stats.ShardsSkipped 0) (gt .Stats.FilesSkipped 0)) }}, 227 showing top {{ $fileCount }} files (<a rel="nofollow" 228 href="search?q={{.Last.Query}}&num={{More .Last.Num}}">show more</a>). 229 {{else}}.{{end}} 230 </h5> 231 {{range .FileMatches}} 232 <table class="table table-hover table-condensed"> 233 <thead> 234 <tr> 235 <th colspan="2"> 236 {{if .URL}}<a name="{{.ResultID}}" class="result"></a><a href="{{.URL}}" >{{else}}<a name="{{.ResultID}}">{{end}} 237 <small> 238 {{.Repo}}:{{.FileName}} {{if .ScoreDebug}}<i>({{.ScoreDebug}})</i>{{end}}</a>: 239 <span style="font-weight: normal">[ {{if .Branches}}{{range .Branches}}<span class="label label-default">{{.}}</span>,{{end}}{{end}} ]</span> 240 {{if .Language}}<button 241 title="restrict search to files written in {{.Language}}" 242 onclick="zoektAddQ('lang:&quot;{{.Language}}&quot;')" class="label label-primary">language {{.Language}}</button></span>{{end}} 243 {{if .DuplicateID}}<a class="label label-dup" href="#{{.DuplicateID}}">Duplicate result</a>{{end}} 244 </small> 245 </th> 246 </tr> 247 </thead> 248 {{if not .DuplicateID}} 249 <tbody> 250 {{range .Matches}} 251 {{if gt .LineNum 0}} 252 <tr> 253 <td style="width: 1%; white-space: nowrap; background-color: rgba(238, 238, 255, 0.6);"> 254<pre class="inline-pre"><p style="margin: 0px;">{{$beforeLines := AddLineNumbers .Before .LineNum true}}{{range $line := $beforeLines}}<span class="noselect"><u>{{$line.LineNum}}</u>:</span> 255{{end}}<span class="noselect">{{if .URL}}<a href="{{.URL}}">{{end}}<u>{{.LineNum}}</u>{{if .URL}}</a>{{end}}:</span> 256{{$afterLines := AddLineNumbers .After .LineNum false}}{{range $line := $afterLines}}<span class="noselect"><u>{{$line.LineNum}}</u>:</span> 257{{end}}</p></pre> 258 </td> 259 <td style="background-color: rgba(238, 238, 255, 0.6);"> 260<pre class="inline-pre"><p style="margin: 0px;">{{range $line := $beforeLines}} {{$line.Content}} 261{{end}}</p> {{range .Fragments}}{{LimitPre 100 .Pre}}<b>{{.Match}}</b>{{LimitPost 100 (TrimTrailingNewline .Post)}}{{end}}<p style="margin: 0px;">{{range $line := $afterLines}} {{$line.Content}} 262{{end}}</p>{{if .ScoreDebug}}<i>({{.ScoreDebug}})</i>{{end}}</pre> 263 </td> 264 </tr> 265 {{end}} 266 </tbody> 267 {{end}} 268 {{end}} 269 </table> 270 {{end}} 271 272 <nav class="navbar navbar-default navbar-bottom"> 273 <div class="container"> 274 {{template "footerBoilerplate"}} 275 <p class="navbar-text navbar-right"> 276 Took {{.Stats.Duration}}{{if .Stats.Wait}} (queued: {{.Stats.Wait}}){{end}} for 277 {{HumanUnit .Stats.IndexBytesLoaded}}B index data, 278 {{.Stats.NgramMatches}} ngram matches, 279 {{.Stats.FilesConsidered}} docs considered, 280 {{.Stats.FilesLoaded}} docs ({{HumanUnit .Stats.ContentBytesLoaded}}B) loaded, 281 {{.Stats.ShardsScanned}} shards scanned, 282 {{.Stats.ShardsSkippedFilter}} shards filtered 283 {{- if or .Stats.FilesSkipped .Stats.ShardsSkipped -}} 284 , {{.Stats.FilesSkipped}} docs skipped, {{.Stats.ShardsSkipped}} shards skipped 285 {{- end -}} 286 . 287 </p> 288 </div> 289 </nav> 290 </div> 291 {{ template "jsdep"}} 292</body> 293</html> 294`, 295 296 "repolist": ` 297<html> 298{{template "head"}} 299<body id="results"> 300 <div class="container"> 301 {{template "navbar" .Last}} 302 <div><b> 303 Found {{.Stats.Repos}} repositories ({{.Stats.Documents}} files, {{HumanUnit .Stats.ContentBytes}}B content) 304 </b></div> 305 <table class="table table-hover table-condensed"> 306 <thead> 307 <tr> 308 {{- define "q"}}q={{.Last.Query}}{{if (gt .Last.Num 0)}}&num={{.Last.Num}}{{end}}{{end}} 309 <th>Name <a href="/search?{{template "q" .}}&order=name">▼</a><a href="/search?{{template "q" .}}&order=revname">▲</a></th> 310 <th>Last updated <a href="/search?{{template "q" .}}&order=revtime">▼</a><a href="/search?{{template "q" .}}&order=time">▲</a></th> 311 <th>Branches</th> 312 <th>Size <a href="/search?{{template "q" .}}&order=revsize">▼</a><a href="/search?{{template "q" .}}&order=size">▲</a></th> 313 <th>RAM <a href="/search?{{template "q" .}}&order=revram">▼</a><a href="/search?{{template "q" .}}&order=ram">▲</a></th> 314 </tr> 315 </thead> 316 <tbody> 317 {{range .Repos -}} 318 <tr> 319 <td>{{if .URL}}<a href="{{.URL}}">{{end}}{{.Name}}{{if .URL}}</a>{{end}}</td> 320 <td><small>{{.IndexTime.Format "Jan 02, 2006 15:04"}}</small></td> 321 <td style="vertical-align: middle;"> 322 {{- range .Branches -}} 323 {{if .URL}}<tt><a class="label label-default small" href="{{.URL}}">{{end}}{{.Name}}{{if .URL}}</a> </tt>{{end}}&nbsp; 324 {{- end -}} 325 </td> 326 <td><small>{{HumanUnit .Files}} files ({{HumanUnit .Size}}B)</small></td> 327 <td><small>{{HumanUnit .MemorySize}}B</td> 328 </tr> 329 {{end}} 330 </tbody> 331 </table> 332 </div> 333 334 <nav class="navbar navbar-default navbar-bottom"> 335 <div class="container"> 336 {{template "footerBoilerplate"}} 337 <p class="navbar-text navbar-right"> 338 </p> 339 </div> 340 </nav> 341 342 {{ template "jsdep"}} 343</body> 344</html> 345`, 346 347 "print": ` 348<html> 349 {{template "head"}} 350 <title>{{.Repo}}:{{.Name}}</title> 351<body id="results"> 352 {{template "navbar" .Last}} 353 <div class="container-fluid container-results" > 354 <div><b>{{.Name}}</b></div> 355 <div class="table table-hover table-condensed" style="overflow:auto; background: #eef;"> 356 {{ range $index, $ln := .Lines}} 357 <pre id="l{{Inc $index}}" class="inline-pre"><span class="noselect"><a href="#l{{Inc $index}}">{{Inc $index}}</a>: </span>{{$ln}}</pre> 358 {{end}} 359 </div> 360 <nav class="navbar navbar-default navbar-bottom"> 361 <div class="container"> 362 {{template "footerBoilerplate"}} 363 <p class="navbar-text navbar-right"> 364 </p> 365 </div> 366 </nav> 367 </div> 368 {{ template "jsdep"}} 369</body> 370</html> 371`, 372 373 "about": ` 374 375<html> 376 {{template "head"}} 377 <title>About <em>zoekt</em></title> 378<body> 379 380 381 <div class="jumbotron"> 382 <div class="container"> 383 {{template "searchbox" .Last}} 384 </div> 385 </div> 386 387 <div class="container"> 388 <p> 389 This is <a href="http://github.com/sourcegraph/zoekt"><em>zoekt</em> (IPA: /zukt/)</a>, 390 an open-source full text search engine. It's pronounced roughly as you would 391 pronounce "zooked" in English. 392 </p> 393 <p> 394 {{if .Version}}<em>Zoekt</em> version {{.Version}}, uptime{{else}}Uptime{{end}} {{.Uptime}} 395 </p> 396 397 <p> 398 Used {{HumanUnit .Stats.IndexBytes}} memory for 399 {{.Stats.Documents}} documents ({{HumanUnit .Stats.ContentBytes}}) 400 from {{.Stats.Repos}} repositories. 401 </p> 402 </div> 403 404 <nav class="navbar navbar-default navbar-bottom"> 405 <div class="container"> 406 {{template "footerBoilerplate"}} 407 <p class="navbar-text navbar-right"> 408 </p> 409 </div> 410 </nav> 411`, 412 "robots": ` 413user-agent: * 414disallow: /search 415`, 416} 417 418func init() { 419 for k, v := range TemplateText { 420 _, err := Top.New(k).Parse(v) 421 if err != nil { 422 log.Panicf("parse(%s): %v:", k, err) 423 } 424 } 425}