line.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package ace
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. const unicodeSpace = 32
  7. const indentTop = 0
  8. // line represents a line of codes.
  9. type line struct {
  10. no int
  11. str string
  12. indent int
  13. tokens []string
  14. opts *Options
  15. file *File
  16. }
  17. // isEmpty returns true if the line is empty.
  18. func (l *line) isEmpty() bool {
  19. return strings.TrimSpace(l.str) == ""
  20. }
  21. // isTopIndent returns true if the line's indent is the top level.
  22. func (l *line) isTopIndent() bool {
  23. return l.indent == indentTop
  24. }
  25. // isHelperMethod returns true if the line is a helper method.
  26. func (l *line) isHelperMethod() bool {
  27. return len(l.tokens) > 1 && l.tokens[0] == equal
  28. }
  29. // isHelperMethodOf returns true if the line is a specified helper method.
  30. func (l *line) isHelperMethodOf(name string) bool {
  31. return l.isHelperMethod() && l.tokens[1] == name
  32. }
  33. // isPlainText returns true if the line is a plain text.
  34. func (l *line) isPlainText() bool {
  35. return len(l.tokens) > 0 && (l.tokens[0] == pipe || l.tokens[0] == doublePipe)
  36. }
  37. // isComment returns true if the line is a comment.
  38. func (l *line) isComment() bool {
  39. return len(l.tokens) > 0 && l.tokens[0] == slash
  40. }
  41. // isHTMLComment returns true if the line is an HTML comment.
  42. func (l *line) isHTMLComment() bool {
  43. return len(l.tokens) > 0 && l.tokens[0] == slash+slash
  44. }
  45. // isAction returns true if the line is an action.
  46. func (l *line) isAction() bool {
  47. str := strings.TrimSpace(l.str)
  48. return strings.HasPrefix(str, l.opts.DelimLeft) && strings.HasSuffix(str, l.opts.DelimRight)
  49. }
  50. // fileName returns the file name.
  51. func (l *line) fileName() string {
  52. return l.file.path + dot + l.opts.Extension
  53. }
  54. // childOf returns true if the line is a child of the element.
  55. func (l *line) childOf(parent element) (bool, error) {
  56. var ok bool
  57. var err error
  58. switch {
  59. case l.isEmpty():
  60. ok = true
  61. case parent.ContainPlainText():
  62. switch {
  63. case parent.Base().ln.indent < l.indent:
  64. ok = true
  65. }
  66. default:
  67. switch {
  68. case l.indent == parent.Base().ln.indent+1:
  69. ok = true
  70. case l.indent > parent.Base().ln.indent+1:
  71. err = fmt.Errorf("the indent is invalid [file: %s][line: %d]", l.fileName(), l.no)
  72. }
  73. }
  74. return ok, err
  75. }
  76. // newLine creates and returns a line.
  77. func newLine(no int, str string, opts *Options, f *File) *line {
  78. return &line{
  79. no: no,
  80. str: str,
  81. indent: indent(str),
  82. tokens: strings.Split(strings.TrimLeft(str, space), space),
  83. opts: opts,
  84. file: f,
  85. }
  86. }
  87. // indent returns the line's indent.
  88. func indent(str string) int {
  89. var i int
  90. for _, b := range str {
  91. if b != unicodeSpace {
  92. break
  93. }
  94. i++
  95. }
  96. return i / 2
  97. }