bug.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Data and interface definitions for bugs
  2. package buggo
  3. import (
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "github.com/charmbracelet/lipgloss"
  9. )
  10. // Bug Definitions ------------------------------------------------------------
  11. // ----------------------------------------------------------------------------
  12. type Bug struct {
  13. Title string // The title of the bug in human readable format
  14. Description Field // The description of the bug
  15. Status Field // The status of the bug
  16. Tags VariadicField // A slice of VariadicFields
  17. Blockedby VariadicField // A slice of VariadicFields
  18. Path string // The path to the bug
  19. // machineTitle string // The machine parseable bug title
  20. }
  21. // Renders a bug as text
  22. // DEPRECATED
  23. func (b Bug) View() string {
  24. headerStyle := lipgloss.NewStyle().
  25. Width(120).
  26. Foreground(lipgloss.Color("#00FF00"))
  27. subtitleStyle := lipgloss.NewStyle().
  28. Width(120).
  29. Faint(true).
  30. Underline(true).
  31. Italic(true)
  32. tagsStyle := lipgloss.NewStyle().
  33. Width(50).
  34. Italic(true)
  35. var tags string
  36. for _, tag := range b.Tags.Fields {
  37. tags = tags + string(tag.Data) + ", "
  38. }
  39. var blockers string
  40. for _, blocker := range b.Blockedby.Fields {
  41. blockers = blockers + string(blocker.Data) + ", "
  42. }
  43. return fmt.Sprintf("%s\n%s\n---\nTags:\t%s\nBlockedby:\t%s\n---\n%s",
  44. headerStyle.Render(b.Title),
  45. subtitleStyle.Render("status:\t"+b.Status.Data),
  46. tagsStyle.Render(tags),
  47. tagsStyle.Render(blockers),
  48. b.Description.Data,
  49. )
  50. }
  51. // Constrcutor for Bugs
  52. func (b Bug) New(title string, status Field, tags VariadicField, blockedby VariadicField, path string) (bug Bug, err error) { // TODO Implement
  53. return Bug{}, err
  54. }
  55. // Constrcutor for Bugs that loads relevant data from disk
  56. func (b Bug) NewFromPath(path string) (bug Bug, err error) {
  57. // Required Fields
  58. description := &Field{Path: "/description"}
  59. status := &Field{Path: "/status"}
  60. requiredFields := []*Field{description, status}
  61. for _, field := range requiredFields {
  62. data, err := readPath(path + field.Path)
  63. if err != nil {
  64. return Bug{}, err
  65. }
  66. field.Data = data
  67. }
  68. // Variadic Fields
  69. tags := VariadicField{Path: "/tags"}
  70. blockers := VariadicField{Path: "/blockedby"}
  71. tags, _ = VariadicField.NewFromPath(tags, path)
  72. blockers, _ = VariadicField.NewFromPath(blockers, path)
  73. // we can ignore the errors, as loadVariadicField already gracefully handles
  74. //them.
  75. // title from path
  76. title := parsePathToHuman(path)
  77. return Bug{
  78. Title: title,
  79. Description: *description,
  80. Status: *status,
  81. Tags: tags,
  82. Blockedby: blockers,
  83. Path: path,
  84. }, err
  85. }
  86. // Field Definitions ----------------------------------------------------------
  87. // ----------------------------------------------------------------------------
  88. // A struct representing data that is tied to data on disk
  89. type Field struct {
  90. Path string
  91. Data string
  92. }
  93. // Constructor for Fields
  94. func (f Field) New(data string, path string) Field { return Field{Data: data, Path: path} }
  95. // VariadicField Definitions --------------------------------------------------
  96. // ----------------------------------------------------------------------------
  97. // VariadicFields hold lists of Field objects.
  98. type VariadicField struct {
  99. Path string // The associated path on disk of Fields represented by Variadic Field
  100. Fields []Field // The underlying slice of Field objects
  101. }
  102. // Constructor for VariadicFields
  103. func (vf VariadicField) New(fields []Field, path string) VariadicField {
  104. return VariadicField{Fields: fields, Path: path}
  105. }
  106. // Constructor for VariadicFields that loads relevant data from disk
  107. func (vf VariadicField) NewFromPath(pathOnDisk string) (v VariadicField, err error) {
  108. rootPath := pathOnDisk + "/" + vf.Path
  109. files, err := os.ReadDir(rootPath)
  110. if err != nil {
  111. return vf, err
  112. }
  113. for _, file := range files {
  114. data, err := readPath(rootPath + "/" + file.Name())
  115. if err != nil {
  116. return vf, err
  117. }
  118. vf.Fields = append(vf.Fields, Field{Data: data, Path: file.Name()})
  119. }
  120. return vf, err
  121. }
  122. // Util Definitions -----------------------------------------------------------
  123. // ----------------------------------------------------------------------------
  124. // Parses human readable strings as path strings
  125. func parseHumanToPath(humanReadable string) string {
  126. var out string
  127. out = strings.ReplaceAll(humanReadable, "-", "\\replace/")
  128. out = strings.ReplaceAll(out, " ", "-")
  129. out = strings.ReplaceAll(out, "\\replace/", "--")
  130. return out
  131. }
  132. // Parses machine parseable paths as human readable strings
  133. func parsePathToHuman(path string) string {
  134. _, last := filepath.Split(filepath.Clean(path))
  135. last = strings.ReplaceAll(last, "--", "\\replace/")
  136. last = strings.ReplaceAll(last, "-", " ")
  137. last = strings.ReplaceAll(last, "\\replace/", "-")
  138. return last
  139. }