types.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. package query
  2. import (
  3. "fmt"
  4. "io"
  5. "strconv"
  6. "github.com/Jguer/aur"
  7. "github.com/Jguer/go-alpm/v2"
  8. "github.com/leonelquinteros/gotext"
  9. "github.com/Jguer/yay/v12/pkg/db"
  10. "github.com/Jguer/yay/v12/pkg/text"
  11. )
  12. type (
  13. aurQuery []aur.Pkg // Query is a collection of Results.
  14. repoQuery []alpm.IPackage // Query holds the results of a repository search.
  15. )
  16. type aurSortable struct {
  17. aurQuery
  18. sortBy string
  19. bottomUp bool
  20. }
  21. func (r repoQuery) Reverse() {
  22. for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
  23. r[i], r[j] = r[j], r[i]
  24. }
  25. }
  26. func (r repoQuery) Less(i, j int) bool {
  27. return text.LessRunes([]rune(r[i].Name()), []rune(r[j].Name()))
  28. }
  29. func (q aurSortable) Len() int {
  30. return len(q.aurQuery)
  31. }
  32. func (q aurSortable) Less(i, j int) bool {
  33. var result bool
  34. switch q.sortBy {
  35. case "votes":
  36. result = q.aurQuery[i].NumVotes > q.aurQuery[j].NumVotes
  37. case "popularity":
  38. result = q.aurQuery[i].Popularity > q.aurQuery[j].Popularity
  39. case "name":
  40. result = text.LessRunes([]rune(q.aurQuery[i].Name), []rune(q.aurQuery[j].Name))
  41. case "base":
  42. result = text.LessRunes([]rune(q.aurQuery[i].PackageBase), []rune(q.aurQuery[j].PackageBase))
  43. case "submitted":
  44. result = q.aurQuery[i].FirstSubmitted < q.aurQuery[j].FirstSubmitted
  45. case "modified":
  46. result = q.aurQuery[i].LastModified < q.aurQuery[j].LastModified
  47. case "id":
  48. result = q.aurQuery[i].ID < q.aurQuery[j].ID
  49. case "baseid":
  50. result = q.aurQuery[i].PackageBaseID < q.aurQuery[j].PackageBaseID
  51. }
  52. if q.bottomUp {
  53. return !result
  54. }
  55. return result
  56. }
  57. func (q aurSortable) Swap(i, j int) {
  58. q.aurQuery[i], q.aurQuery[j] = q.aurQuery[j], q.aurQuery[i]
  59. }
  60. func getSearchBy(value string) aur.By {
  61. switch value {
  62. case "name":
  63. return aur.Name
  64. case "maintainer":
  65. return aur.Maintainer
  66. case "submitter":
  67. return aur.Submitter
  68. case "depends":
  69. return aur.Depends
  70. case "makedepends":
  71. return aur.MakeDepends
  72. case "optdepends":
  73. return aur.OptDepends
  74. case "checkdepends":
  75. return aur.CheckDepends
  76. case "provides":
  77. return aur.Provides
  78. case "conflicts":
  79. return aur.Conflicts
  80. case "replaces":
  81. return aur.Replaces
  82. case "groups":
  83. return aur.Groups
  84. case "keywords":
  85. return aur.Keywords
  86. case "comaintainers":
  87. return aur.CoMaintainers
  88. default:
  89. return aur.NameDesc
  90. }
  91. }
  92. // PrintSearch handles printing search results in a given format.
  93. func (q aurQuery) printSearch(
  94. w io.Writer,
  95. start int,
  96. dbExecutor db.Executor,
  97. searchMode SearchVerbosity,
  98. bottomUp,
  99. singleLineResults bool,
  100. ) {
  101. for i := range q {
  102. if searchMode == Minimal {
  103. _, _ = fmt.Fprintln(w, q[i].Name)
  104. continue
  105. }
  106. var toprint string
  107. if searchMode == NumberMenu {
  108. if bottomUp {
  109. toprint += text.Magenta(strconv.Itoa(len(q)+start-i-1) + " ")
  110. } else {
  111. toprint += text.Magenta(strconv.Itoa(start+i) + " ")
  112. }
  113. }
  114. toprint += aurPkgSearchString(&q[i], dbExecutor, singleLineResults)
  115. _, _ = fmt.Fprintln(w, toprint)
  116. }
  117. }
  118. func aurPkgSearchString(
  119. pkg *aur.Pkg,
  120. dbExecutor db.Executor,
  121. singleLineResults bool,
  122. ) string {
  123. toPrint := text.Bold(text.ColorHash("aur")) + "/" + text.Bold(pkg.Name) +
  124. " " + text.Cyan(pkg.Version) +
  125. text.Bold(" (+"+strconv.Itoa(pkg.NumVotes)) +
  126. " " + text.Bold(strconv.FormatFloat(pkg.Popularity, 'f', 2, 64)+") ")
  127. if pkg.Maintainer == "" {
  128. toPrint += text.Bold(text.Red(gotext.Get("(Orphaned)"))) + " "
  129. }
  130. if pkg.OutOfDate != 0 {
  131. toPrint += text.Bold(text.Red(gotext.Get("(Out-of-date: %s)", text.FormatTime(pkg.OutOfDate)))) + " "
  132. }
  133. if localPkg := dbExecutor.LocalPackage(pkg.Name); localPkg != nil {
  134. if localPkg.Version() != pkg.Version {
  135. toPrint += text.Bold(text.Green(gotext.Get("(Installed: %s)", localPkg.Version())))
  136. } else {
  137. toPrint += text.Bold(text.Green(gotext.Get("(Installed)")))
  138. }
  139. }
  140. if singleLineResults {
  141. toPrint += "\t"
  142. } else {
  143. toPrint += "\n "
  144. }
  145. toPrint += pkg.Description
  146. return toPrint
  147. }
  148. // PrintSearch receives a RepoSearch type and outputs pretty text.
  149. func (r repoQuery) printSearch(w io.Writer, dbExecutor db.Executor, searchMode SearchVerbosity, bottomUp, singleLineResults bool) {
  150. for i, res := range r {
  151. if searchMode == Minimal {
  152. _, _ = fmt.Fprintln(w, res.Name())
  153. continue
  154. }
  155. var toprint string
  156. if searchMode == NumberMenu {
  157. if bottomUp {
  158. toprint += text.Magenta(strconv.Itoa(len(r)-i) + " ")
  159. } else {
  160. toprint += text.Magenta(strconv.Itoa(i+1) + " ")
  161. }
  162. }
  163. toprint += syncPkgSearchString(res, dbExecutor, singleLineResults)
  164. _, _ = fmt.Fprintln(w, toprint)
  165. }
  166. }
  167. // PrintSearch receives a RepoSearch type and outputs pretty text.
  168. func syncPkgSearchString(pkg alpm.IPackage, dbExecutor db.Executor, singleLineResults bool) string {
  169. toPrint := text.Bold(text.ColorHash(pkg.DB().Name())) + "/" + text.Bold(pkg.Name()) +
  170. " " + text.Cyan(pkg.Version()) +
  171. text.Bold(" ("+text.Human(pkg.Size())+
  172. " "+text.Human(pkg.ISize())+") ")
  173. packageGroups := dbExecutor.PackageGroups(pkg)
  174. if len(packageGroups) != 0 {
  175. toPrint += fmt.Sprint(packageGroups, " ")
  176. }
  177. if localPkg := dbExecutor.LocalPackage(pkg.Name()); localPkg != nil {
  178. if localPkg.Version() != pkg.Version() {
  179. toPrint += text.Bold(text.Green(gotext.Get("(Installed: %s)", localPkg.Version())))
  180. } else {
  181. toPrint += text.Bold(text.Green(gotext.Get("(Installed)")))
  182. }
  183. }
  184. if singleLineResults {
  185. toPrint += "\t"
  186. } else {
  187. toPrint += "\n "
  188. }
  189. toPrint += pkg.Description()
  190. return toPrint
  191. }