2017-10-27 09:10:54 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2019-12-23 15:31:16 +03:00
package code
2017-10-27 09:10:54 +03:00
import (
"bytes"
"strings"
"code.gitea.io/gitea/modules/highlight"
2020-02-20 22:53:55 +03:00
"code.gitea.io/gitea/modules/timeutil"
2017-10-27 09:10:54 +03:00
"code.gitea.io/gitea/modules/util"
)
// Result a search result to display
type Result struct {
2018-03-16 17:04:33 +03:00
RepoID int64
2017-10-27 09:10:54 +03:00
Filename string
2020-02-20 22:53:55 +03:00
CommitID string
UpdatedUnix timeutil . TimeStamp
Language string
Color string
2017-10-27 09:10:54 +03:00
LineNumbers [ ] int
2020-07-01 00:34:03 +03:00
FormattedLines string
2017-10-27 09:10:54 +03:00
}
func indices ( content string , selectionStartIndex , selectionEndIndex int ) ( int , int ) {
startIndex := selectionStartIndex
numLinesBefore := 0
for ; startIndex > 0 ; startIndex -- {
if content [ startIndex - 1 ] == '\n' {
if numLinesBefore == 1 {
break
}
numLinesBefore ++
}
}
endIndex := selectionEndIndex
numLinesAfter := 0
for ; endIndex < len ( content ) ; endIndex ++ {
if content [ endIndex ] == '\n' {
if numLinesAfter == 1 {
break
}
numLinesAfter ++
}
}
return startIndex , endIndex
}
func writeStrings ( buf * bytes . Buffer , strs ... string ) error {
for _ , s := range strs {
_ , err := buf . WriteString ( s )
if err != nil {
return err
}
}
return nil
}
2019-12-23 15:31:16 +03:00
func searchResult ( result * SearchResult , startIndex , endIndex int ) ( * Result , error ) {
2017-10-27 09:10:54 +03:00
startLineNum := 1 + strings . Count ( result . Content [ : startIndex ] , "\n" )
var formattedLinesBuffer bytes . Buffer
contentLines := strings . SplitAfter ( result . Content [ startIndex : endIndex ] , "\n" )
lineNumbers := make ( [ ] int , len ( contentLines ) )
index := startIndex
for i , line := range contentLines {
var err error
if index < result . EndIndex &&
result . StartIndex < index + len ( line ) &&
result . StartIndex < result . EndIndex {
openActiveIndex := util . Max ( result . StartIndex - index , 0 )
closeActiveIndex := util . Min ( result . EndIndex - index , len ( line ) )
err = writeStrings ( & formattedLinesBuffer ,
2020-07-01 00:34:03 +03:00
line [ : openActiveIndex ] ,
line [ openActiveIndex : closeActiveIndex ] ,
line [ closeActiveIndex : ] ,
2017-10-27 09:10:54 +03:00
)
} else {
err = writeStrings ( & formattedLinesBuffer ,
2020-07-01 00:34:03 +03:00
line ,
2017-10-27 09:10:54 +03:00
)
}
if err != nil {
return nil , err
}
lineNumbers [ i ] = startLineNum + i
index += len ( line )
}
return & Result {
2018-03-16 17:04:33 +03:00
RepoID : result . RepoID ,
2017-10-27 09:10:54 +03:00
Filename : result . Filename ,
2020-02-20 22:53:55 +03:00
CommitID : result . CommitID ,
UpdatedUnix : result . UpdatedUnix ,
Language : result . Language ,
Color : result . Color ,
2017-10-27 09:10:54 +03:00
LineNumbers : lineNumbers ,
2020-07-01 00:34:03 +03:00
FormattedLines : highlight . Code ( result . Filename , formattedLinesBuffer . String ( ) ) ,
2017-10-27 09:10:54 +03:00
} , nil
}
// PerformSearch perform a search on a repository
2020-02-20 22:53:55 +03:00
func PerformSearch ( repoIDs [ ] int64 , language , keyword string , page , pageSize int ) ( int , [ ] * Result , [ ] * SearchResultLanguages , error ) {
2017-10-27 09:10:54 +03:00
if len ( keyword ) == 0 {
2020-02-20 22:53:55 +03:00
return 0 , nil , nil , nil
2017-10-27 09:10:54 +03:00
}
2020-02-20 22:53:55 +03:00
total , results , resultLanguages , err := indexer . Search ( repoIDs , language , keyword , page , pageSize )
2017-10-27 09:10:54 +03:00
if err != nil {
2020-02-20 22:53:55 +03:00
return 0 , nil , nil , err
2017-10-27 09:10:54 +03:00
}
displayResults := make ( [ ] * Result , len ( results ) )
for i , result := range results {
startIndex , endIndex := indices ( result . Content , result . StartIndex , result . EndIndex )
displayResults [ i ] , err = searchResult ( result , startIndex , endIndex )
if err != nil {
2020-02-20 22:53:55 +03:00
return 0 , nil , nil , err
2017-10-27 09:10:54 +03:00
}
}
2020-02-20 22:53:55 +03:00
return int ( total ) , displayResults , resultLanguages , nil
2017-10-27 09:10:54 +03:00
}