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

drawer.go 2.5KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. package org
  2. import (
  3. "regexp"
  4. "strings"
  5. )
  6. type Drawer struct {
  7. Name string
  8. Children []Node
  9. }
  10. type PropertyDrawer struct {
  11. Properties [][]string
  12. }
  13. var beginDrawerRegexp = regexp.MustCompile(`^(\s*):(\S+):\s*$`)
  14. var endDrawerRegexp = regexp.MustCompile(`^(\s*):END:\s*$`)
  15. var propertyRegexp = regexp.MustCompile(`^(\s*):(\S+):(\s+(.*)$|$)`)
  16. func lexDrawer(line string) (token, bool) {
  17. if m := endDrawerRegexp.FindStringSubmatch(line); m != nil {
  18. return token{"endDrawer", len(m[1]), "", m}, true
  19. } else if m := beginDrawerRegexp.FindStringSubmatch(line); m != nil {
  20. return token{"beginDrawer", len(m[1]), strings.ToUpper(m[2]), m}, true
  21. }
  22. return nilToken, false
  23. }
  24. func (d *Document) parseDrawer(i int, parentStop stopFn) (int, Node) {
  25. name := strings.ToUpper(d.tokens[i].content)
  26. if name == "PROPERTIES" {
  27. return d.parsePropertyDrawer(i, parentStop)
  28. }
  29. drawer, start := Drawer{Name: name}, i
  30. i++
  31. stop := func(d *Document, i int) bool {
  32. if parentStop(d, i) {
  33. return true
  34. }
  35. kind := d.tokens[i].kind
  36. return kind == "beginDrawer" || kind == "endDrawer" || kind == "headline"
  37. }
  38. for {
  39. consumed, nodes := d.parseMany(i, stop)
  40. i += consumed
  41. drawer.Children = append(drawer.Children, nodes...)
  42. if i < len(d.tokens) && d.tokens[i].kind == "beginDrawer" {
  43. p := Paragraph{[]Node{Text{":" + d.tokens[i].content + ":", false}}}
  44. drawer.Children = append(drawer.Children, p)
  45. i++
  46. } else {
  47. break
  48. }
  49. }
  50. if i < len(d.tokens) && d.tokens[i].kind == "endDrawer" {
  51. i++
  52. }
  53. return i - start, drawer
  54. }
  55. func (d *Document) parsePropertyDrawer(i int, parentStop stopFn) (int, Node) {
  56. drawer, start := PropertyDrawer{}, i
  57. i++
  58. stop := func(d *Document, i int) bool {
  59. return parentStop(d, i) || (d.tokens[i].kind != "text" && d.tokens[i].kind != "beginDrawer")
  60. }
  61. for ; !stop(d, i); i++ {
  62. m := propertyRegexp.FindStringSubmatch(d.tokens[i].matches[0])
  63. if m == nil {
  64. return 0, nil
  65. }
  66. k, v := strings.ToUpper(m[2]), strings.TrimSpace(m[4])
  67. drawer.Properties = append(drawer.Properties, []string{k, v})
  68. }
  69. if i < len(d.tokens) && d.tokens[i].kind == "endDrawer" {
  70. i++
  71. } else {
  72. return 0, nil
  73. }
  74. return i - start, drawer
  75. }
  76. func (d *PropertyDrawer) Get(key string) (string, bool) {
  77. if d == nil {
  78. return "", false
  79. }
  80. for _, kvPair := range d.Properties {
  81. if kvPair[0] == key {
  82. return kvPair[1], true
  83. }
  84. }
  85. return "", false
  86. }
  87. func (n Drawer) String() string { return orgWriter.WriteNodesAsString(n) }
  88. func (n PropertyDrawer) String() string { return orgWriter.WriteNodesAsString(n) }