You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

search.go 3.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package code
  5. import (
  6. "bytes"
  7. "html"
  8. gotemplate "html/template"
  9. "strings"
  10. "code.gitea.io/gitea/modules/highlight"
  11. "code.gitea.io/gitea/modules/util"
  12. )
  13. // Result a search result to display
  14. type Result struct {
  15. RepoID int64
  16. Filename string
  17. HighlightClass string
  18. LineNumbers []int
  19. FormattedLines gotemplate.HTML
  20. }
  21. func indices(content string, selectionStartIndex, selectionEndIndex int) (int, int) {
  22. startIndex := selectionStartIndex
  23. numLinesBefore := 0
  24. for ; startIndex > 0; startIndex-- {
  25. if content[startIndex-1] == '\n' {
  26. if numLinesBefore == 1 {
  27. break
  28. }
  29. numLinesBefore++
  30. }
  31. }
  32. endIndex := selectionEndIndex
  33. numLinesAfter := 0
  34. for ; endIndex < len(content); endIndex++ {
  35. if content[endIndex] == '\n' {
  36. if numLinesAfter == 1 {
  37. break
  38. }
  39. numLinesAfter++
  40. }
  41. }
  42. return startIndex, endIndex
  43. }
  44. func writeStrings(buf *bytes.Buffer, strs ...string) error {
  45. for _, s := range strs {
  46. _, err := buf.WriteString(s)
  47. if err != nil {
  48. return err
  49. }
  50. }
  51. return nil
  52. }
  53. func searchResult(result *SearchResult, startIndex, endIndex int) (*Result, error) {
  54. startLineNum := 1 + strings.Count(result.Content[:startIndex], "\n")
  55. var formattedLinesBuffer bytes.Buffer
  56. contentLines := strings.SplitAfter(result.Content[startIndex:endIndex], "\n")
  57. lineNumbers := make([]int, len(contentLines))
  58. index := startIndex
  59. for i, line := range contentLines {
  60. var err error
  61. if index < result.EndIndex &&
  62. result.StartIndex < index+len(line) &&
  63. result.StartIndex < result.EndIndex {
  64. openActiveIndex := util.Max(result.StartIndex-index, 0)
  65. closeActiveIndex := util.Min(result.EndIndex-index, len(line))
  66. err = writeStrings(&formattedLinesBuffer,
  67. `<li>`,
  68. html.EscapeString(line[:openActiveIndex]),
  69. `<span class='active'>`,
  70. html.EscapeString(line[openActiveIndex:closeActiveIndex]),
  71. `</span>`,
  72. html.EscapeString(line[closeActiveIndex:]),
  73. `</li>`,
  74. )
  75. } else {
  76. err = writeStrings(&formattedLinesBuffer,
  77. `<li>`,
  78. html.EscapeString(line),
  79. `</li>`,
  80. )
  81. }
  82. if err != nil {
  83. return nil, err
  84. }
  85. lineNumbers[i] = startLineNum + i
  86. index += len(line)
  87. }
  88. return &Result{
  89. RepoID: result.RepoID,
  90. Filename: result.Filename,
  91. HighlightClass: highlight.FileNameToHighlightClass(result.Filename),
  92. LineNumbers: lineNumbers,
  93. FormattedLines: gotemplate.HTML(formattedLinesBuffer.String()),
  94. }, nil
  95. }
  96. // PerformSearch perform a search on a repository
  97. func PerformSearch(repoIDs []int64, keyword string, page, pageSize int) (int, []*Result, error) {
  98. if len(keyword) == 0 {
  99. return 0, nil, nil
  100. }
  101. total, results, err := indexer.Search(repoIDs, keyword, page, pageSize)
  102. if err != nil {
  103. return 0, nil, err
  104. }
  105. displayResults := make([]*Result, len(results))
  106. for i, result := range results {
  107. startIndex, endIndex := indices(result.Content, result.StartIndex, result.EndIndex)
  108. displayResults[i], err = searchResult(result, startIndex, endIndex)
  109. if err != nil {
  110. return 0, nil, err
  111. }
  112. }
  113. return int(total), displayResults, nil
  114. }