mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-25 18:53:09 +00:00
[PORT] Fix wrong line number in code search result (gitea#29260) (#2619)
Port [Fix wrong line number in code search result (gitea#29260)](https://github.com/go-gitea/gitea/pull/29260) PS: also added [`-e`](https://git-scm.com/docs/git-grep#Documentation/git-grep.txt--e) before passing the keyword (my bad) Co-authored-by: yp05327 <576951401@qq.com> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2619 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: Shiny Nematoda <snematoda.751k2@aleeas.com> Co-committed-by: Shiny Nematoda <snematoda.751k2@aleeas.com>
This commit is contained in:
parent
79f8339c74
commit
3b2f28ff1c
6 changed files with 90 additions and 67 deletions
|
@ -16,14 +16,18 @@ import (
|
||||||
|
|
||||||
// Result a search result to display
|
// Result a search result to display
|
||||||
type Result struct {
|
type Result struct {
|
||||||
RepoID int64
|
RepoID int64
|
||||||
Filename string
|
Filename string
|
||||||
CommitID string
|
CommitID string
|
||||||
UpdatedUnix timeutil.TimeStamp
|
UpdatedUnix timeutil.TimeStamp
|
||||||
Language string
|
Language string
|
||||||
Color string
|
Color string
|
||||||
LineNumbers []int
|
Lines []ResultLine
|
||||||
FormattedLines template.HTML
|
}
|
||||||
|
|
||||||
|
type ResultLine struct {
|
||||||
|
Num int
|
||||||
|
FormattedContent template.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
type SearchResultLanguages = internal.SearchResultLanguages
|
type SearchResultLanguages = internal.SearchResultLanguages
|
||||||
|
@ -70,7 +74,7 @@ func searchResult(result *internal.SearchResult, startIndex, endIndex int) (*Res
|
||||||
var formattedLinesBuffer bytes.Buffer
|
var formattedLinesBuffer bytes.Buffer
|
||||||
|
|
||||||
contentLines := strings.SplitAfter(result.Content[startIndex:endIndex], "\n")
|
contentLines := strings.SplitAfter(result.Content[startIndex:endIndex], "\n")
|
||||||
lineNumbers := make([]int, len(contentLines))
|
lines := make([]ResultLine, 0, len(contentLines))
|
||||||
index := startIndex
|
index := startIndex
|
||||||
for i, line := range contentLines {
|
for i, line := range contentLines {
|
||||||
var err error
|
var err error
|
||||||
|
@ -93,21 +97,29 @@ func searchResult(result *internal.SearchResult, startIndex, endIndex int) (*Res
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lineNumbers[i] = startLineNum + i
|
lines = append(lines, ResultLine{Num: startLineNum + i})
|
||||||
index += len(line)
|
index += len(line)
|
||||||
}
|
}
|
||||||
|
|
||||||
highlighted, _ := highlight.Code(result.Filename, "", formattedLinesBuffer.String())
|
// we should highlight the whole code block first, otherwise it doesn't work well with multiple line highlighting
|
||||||
|
hl, _ := highlight.Code(result.Filename, "", formattedLinesBuffer.String())
|
||||||
|
highlightedLines := strings.Split(string(hl), "\n")
|
||||||
|
|
||||||
|
// The lines outputted by highlight.Code might not match the original lines, because "highlight" removes the last `\n`
|
||||||
|
lines = lines[:min(len(highlightedLines), len(lines))]
|
||||||
|
highlightedLines = highlightedLines[:len(lines)]
|
||||||
|
for i := 0; i < len(lines); i++ {
|
||||||
|
lines[i].FormattedContent = template.HTML(highlightedLines[i])
|
||||||
|
}
|
||||||
|
|
||||||
return &Result{
|
return &Result{
|
||||||
RepoID: result.RepoID,
|
RepoID: result.RepoID,
|
||||||
Filename: result.Filename,
|
Filename: result.Filename,
|
||||||
CommitID: result.CommitID,
|
CommitID: result.CommitID,
|
||||||
UpdatedUnix: result.UpdatedUnix,
|
UpdatedUnix: result.UpdatedUnix,
|
||||||
Language: result.Language,
|
Language: result.Language,
|
||||||
Color: result.Color,
|
Color: result.Color,
|
||||||
LineNumbers: lineNumbers,
|
Lines: lines,
|
||||||
FormattedLines: highlighted,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,14 +16,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
RepoID int64 // ignored
|
RepoID int64 // ignored
|
||||||
Filename string
|
Filename string
|
||||||
CommitID string // branch
|
CommitID string // branch
|
||||||
UpdatedUnix timeutil.TimeStamp // ignored
|
UpdatedUnix timeutil.TimeStamp // ignored
|
||||||
Language string
|
Language string
|
||||||
Color string
|
Color string
|
||||||
LineNumbers []int64
|
Lines []ResultLine
|
||||||
FormattedLines template.HTML
|
}
|
||||||
|
|
||||||
|
type ResultLine struct {
|
||||||
|
Num int64
|
||||||
|
FormattedContent template.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
const pHEAD = "HEAD:"
|
const pHEAD = "HEAD:"
|
||||||
|
@ -46,7 +50,8 @@ func NewRepoGrep(ctx context.Context, repo *repo_model.Repository, keyword strin
|
||||||
"-n", // line nums
|
"-n", // line nums
|
||||||
"-i", // ignore case
|
"-i", // ignore case
|
||||||
"--full-name", // full file path, rel to repo
|
"--full-name", // full file path, rel to repo
|
||||||
//"--column", // for adding better highlighting support
|
//"--column", // for adding better highlighting support
|
||||||
|
"-e", // for queries starting with "-"
|
||||||
).
|
).
|
||||||
AddDynamicArguments(keyword).
|
AddDynamicArguments(keyword).
|
||||||
AddArguments("HEAD").
|
AddArguments("HEAD").
|
||||||
|
@ -57,6 +62,8 @@ func NewRepoGrep(ctx context.Context, repo *repo_model.Repository, keyword strin
|
||||||
|
|
||||||
for _, block := range strings.Split(stdout, "\n\n") {
|
for _, block := range strings.Split(stdout, "\n\n") {
|
||||||
res := Result{CommitID: repo.DefaultBranch}
|
res := Result{CommitID: repo.DefaultBranch}
|
||||||
|
|
||||||
|
linenum := []int64{}
|
||||||
code := []string{}
|
code := []string{}
|
||||||
|
|
||||||
for _, line := range strings.Split(block, "\n") {
|
for _, line := range strings.Split(block, "\n") {
|
||||||
|
@ -71,18 +78,32 @@ func NewRepoGrep(ctx context.Context, repo *repo_model.Repository, keyword strin
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
res.LineNumbers = append(res.LineNumbers, i)
|
linenum = append(linenum, i)
|
||||||
code = append(code, after)
|
code = append(code, after)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.Filename == "" || len(code) == 0 || len(res.LineNumbers) == 0 {
|
if res.Filename == "" || len(code) == 0 || len(linenum) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
res.FormattedLines, res.Language = highlight.Code(res.Filename, "", strings.Join(code, "\n"))
|
var hl template.HTML
|
||||||
|
|
||||||
|
hl, res.Language = highlight.Code(res.Filename, "", strings.Join(code, "\n"))
|
||||||
res.Color = enry.GetColor(res.Language)
|
res.Color = enry.GetColor(res.Language)
|
||||||
|
|
||||||
|
hlCode := strings.Split(string(hl), "\n")
|
||||||
|
n := min(len(hlCode), len(linenum))
|
||||||
|
|
||||||
|
res.Lines = make([]ResultLine, n)
|
||||||
|
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
res.Lines[i] = ResultLine{
|
||||||
|
Num: linenum[i],
|
||||||
|
FormattedContent: template.HTML(hlCode[i]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data = append(data, &res)
|
data = append(data, &res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,14 +25,16 @@ func TestNewRepoGrep(t *testing.T) {
|
||||||
|
|
||||||
expected := []*Result{
|
expected := []*Result{
|
||||||
{
|
{
|
||||||
RepoID: 0,
|
RepoID: 0,
|
||||||
Filename: "README.md",
|
Filename: "README.md",
|
||||||
CommitID: "master",
|
CommitID: "master",
|
||||||
UpdatedUnix: 0,
|
UpdatedUnix: 0,
|
||||||
Language: "Markdown",
|
Language: "Markdown",
|
||||||
Color: "#083fa1",
|
Color: "#083fa1",
|
||||||
LineNumbers: []int64{2, 3},
|
Lines: []ResultLine{
|
||||||
FormattedLines: "\nDescription for repo1",
|
{Num: 2, FormattedContent: ""},
|
||||||
|
{Num: 3, FormattedContent: "Description for repo1"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,20 +22,7 @@
|
||||||
<a role="button" class="ui basic tiny button" rel="nofollow" href="{{$repo.Link}}/src/commit/{{$result.CommitID | PathEscape}}/{{.Filename | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.diff.view_file"}}</a>
|
<a role="button" class="ui basic tiny button" rel="nofollow" href="{{$repo.Link}}/src/commit/{{$result.CommitID | PathEscape}}/{{.Filename | PathEscapeSegments}}">{{ctx.Locale.Tr "repo.diff.view_file"}}</a>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
<div class="file-body file-code code-view">
|
{{template "shared/searchfile" dict "RepoLink" $repo.Link "IsIndexer" true "SearchResult" .}}
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="lines-num">
|
|
||||||
{{range .LineNumbers}}
|
|
||||||
<a href="{{$repo.Link}}/src/commit/{{$result.CommitID | PathEscape}}/{{$result.Filename | PathEscapeSegments}}#L{{.}}"><span>{{.}}</span></a>
|
|
||||||
{{end}}
|
|
||||||
</td>
|
|
||||||
<td class="lines-code chroma"><code class="code-inner">{{.FormattedLines}}</code></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{template "shared/searchbottom" dict "root" $ "result" .}}
|
{{template "shared/searchbottom" dict "root" $ "result" .}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -46,20 +46,7 @@
|
||||||
<a role="button" class="ui basic tiny button" rel="nofollow" href="{{$.SourcePath}}/src/{{if $.CodeIndexerEnabled}}commit{{else}}branch{{end}}/{{PathEscape $result.CommitID}}/{{PathEscapeSegments .Filename}}">{{ctx.Locale.Tr "repo.diff.view_file"}}</a>
|
<a role="button" class="ui basic tiny button" rel="nofollow" href="{{$.SourcePath}}/src/{{if $.CodeIndexerEnabled}}commit{{else}}branch{{end}}/{{PathEscape $result.CommitID}}/{{PathEscapeSegments .Filename}}">{{ctx.Locale.Tr "repo.diff.view_file"}}</a>
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
<div class="file-body file-code code-view">
|
{{template "shared/searchfile" dict "RepoLink" $.SourcePath "IsIndexer" $.CodeIndexerEnabled "SearchResult" .}}
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td class="lines-num">
|
|
||||||
{{range .LineNumbers}}
|
|
||||||
<a href="{{$.SourcePath}}/src/{{if $.CodeIndexerEnabled}}commit{{else}}branch{{end}}/{{PathEscape $result.CommitID}}/{{PathEscapeSegments $result.Filename}}#L{{.}}"><span>{{.}}</span></a>
|
|
||||||
{{end}}
|
|
||||||
</td>
|
|
||||||
<td class="lines-code chroma"><code class="code-inner">{{.FormattedLines}}</code></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{template "shared/searchbottom" dict "root" $ "result" .}}
|
{{template "shared/searchbottom" dict "root" $ "result" .}}
|
||||||
</div>
|
</div>
|
||||||
|
|
14
templates/shared/searchfile.tmpl
Normal file
14
templates/shared/searchfile.tmpl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<div class="file-body file-code code-view">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{{range .SearchResult.Lines}}
|
||||||
|
<tr>
|
||||||
|
<td class="lines-num">
|
||||||
|
<a href="{{$.RepoLink}}/src/{{if not $.IsIndexer}}branch{{else}}commit{{end}}/{{PathEscape $.SearchResult.CommitID}}/{{PathEscapeSegments $.SearchResult.Filename}}#L{{.Num}}"><span>{{.Num}}</span></a>
|
||||||
|
</td>
|
||||||
|
<td class="lines-code chroma"><code class="code-inner">{{.FormattedContent}}</code></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
Loading…
Reference in a new issue