vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Add repository code search
aef992843b95fd107327b103c12d135cd708c11e · Keenan Nemetz · 15d ago · parent 5cab7b18
Add repository code search The Code tab now searches file names and plain-text contents at the selected branch. Contents go through git grep with fixed strings, case-insensitive matching, binary skipping, and a capped result set; there is no second index to drift. Results group by file and link to line anchors in the blob view. Also highlights a targeted line and adds the remaining polish notes to the UI plan.
server/web/templates/code_search.html +72
| @@ -0,0 +1,72 @@ | |||
| 1 | {{define "code_search"}} | ||
| 2 | {{template "header" .}} | ||
| 3 | {{template "repohead" (nav .Name "code" .CanAdmin)}} | ||
| 4 | |||
| 5 | <div class="page-head"> | ||
| 6 | <div class="page-head-main"> | ||
| 7 | <h1>Search code</h1> | ||
| 8 | <p class="page-sub">File names and contents on <code>{{.Ref}}</code>. Content search is case-insensitive and treats the query as plain text.</p> | ||
| 9 | </div> | ||
| 10 | <div class="page-head-actions"> | ||
| 11 | <a class="button secondary" href="/r/{{.Name}}/code?ref={{esc .Ref}}">{{icon "code"}}Browse</a> | ||
| 12 | </div> | ||
| 13 | </div> | ||
| 14 | |||
| 15 | <form class="filters" method="get" action="/r/{{.Name}}/search" role="search"> | ||
| 16 | <input type="hidden" name="ref" value="{{.Ref}}"> | ||
| 17 | <input type="search" name="q" value="{{.Query}}" placeholder="Find in files" aria-label="Find in files" autofocus> | ||
| 18 | <button type="submit">{{icon "search"}}Search</button> | ||
| 19 | </form> | ||
| 20 | |||
| 21 | {{if .Error}}<div class="flash bad">{{.Error}}</div>{{end}} | ||
| 22 | |||
| 23 | {{if not .Commit}} | ||
| 24 | <div class="empty-state"> | ||
| 25 | <p>There is no commit on <code>{{.Ref}}</code> to search.</p> | ||
| 26 | </div> | ||
| 27 | {{else if not .Query}} | ||
| 28 | <div class="empty-state"> | ||
| 29 | <p>Search this repository.</p> | ||
| 30 | <p class="muted">Names and file contents are searched at the selected branch. Binary files are skipped.</p> | ||
| 31 | </div> | ||
| 32 | {{else}} | ||
| 33 | <p class="muted">{{.Hits}} content match(es){{if .FileHits}} · {{len .FileHits}} file name match(es){{end}} for “{{.Query}}”{{if .Truncated}} · showing a partial result set{{end}}</p> | ||
| 34 | |||
| 35 | <h2>Files</h2> | ||
| 36 | {{if .FileHits}} | ||
| 37 | <div class="panel"> | ||
| 38 | <table class="search-files"> | ||
| 39 | <tbody> | ||
| 40 | {{range .FileHits}} | ||
| 41 | <tr><td><a href="/r/{{$.Name}}/blob/{{esc $.Ref}}/{{pathurl .}}" hx-get="/r/{{$.Name}}/blob/{{esc $.Ref}}/{{pathurl .}}" hx-target="#code-main" hx-swap="outerHTML" hx-push-url="true">{{icon "file"}}{{.}}</a></td></tr> | ||
| 42 | {{end}} | ||
| 43 | </tbody> | ||
| 44 | </table> | ||
| 45 | </div> | ||
| 46 | {{else}} | ||
| 47 | <p class="muted">No file names match.</p> | ||
| 48 | {{end}} | ||
| 49 | |||
| 50 | <h2>Content</h2> | ||
| 51 | {{if .Groups}} | ||
| 52 | {{range .Groups}}{{$g := .}} | ||
| 53 | <section class="search-group"> | ||
| 54 | <h3><a href="/r/{{$.Name}}/blob/{{esc $.Ref}}/{{pathurl .Path}}">{{.Path}}</a></h3> | ||
| 55 | <table class="search-lines"> | ||
| 56 | <tbody> | ||
| 57 | {{range .Lines}} | ||
| 58 | <tr id="L{{.Line}}"> | ||
| 59 | <td class="ln"><a href="/r/{{$.Name}}/blob/{{esc $.Ref}}/{{pathurl $g.Path}}#L{{.Line}}">{{.Line}}</a></td> | ||
| 60 | <td class="code">{{.Text}}</td> | ||
| 61 | </tr> | ||
| 62 | {{end}} | ||
| 63 | </tbody> | ||
| 64 | </table> | ||
| 65 | </section> | ||
| 66 | {{end}} | ||
| 67 | {{else}} | ||
| 68 | <p class="muted">No file content matches.</p> | ||
| 69 | {{end}} | ||
| 70 | {{end}} | ||
| 71 | {{template "footer" .}} | ||
| 72 | {{end}} | ||