error.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package pongo2
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. // This Error type is being used to address an error during lexing, parsing or
  8. // execution. If you want to return an error object (for example in your own
  9. // tag or filter) fill this object with as much information as you have.
  10. // Make sure "Sender" is always given (if you're returning an error within
  11. // a filter, make Sender equals 'filter:yourfilter'; same goes for tags: 'tag:mytag').
  12. // It's okay if you only fill in ErrorMsg if you don't have any other details at hand.
  13. type Error struct {
  14. Template *Template
  15. Filename string
  16. Line int
  17. Column int
  18. Token *Token
  19. Sender string
  20. ErrorMsg string
  21. }
  22. func (e *Error) updateFromTokenIfNeeded(template *Template, t *Token) *Error {
  23. if e.Template == nil {
  24. e.Template = template
  25. }
  26. if e.Token == nil {
  27. e.Token = t
  28. if e.Line <= 0 {
  29. e.Line = t.Line
  30. e.Column = t.Col
  31. }
  32. }
  33. return e
  34. }
  35. // Returns a nice formatted error string.
  36. func (e *Error) Error() string {
  37. s := "[Error"
  38. if e.Sender != "" {
  39. s += " (where: " + e.Sender + ")"
  40. }
  41. if e.Filename != "" {
  42. s += " in " + e.Filename
  43. }
  44. if e.Line > 0 {
  45. s += fmt.Sprintf(" | Line %d Col %d", e.Line, e.Column)
  46. if e.Token != nil {
  47. s += fmt.Sprintf(" near '%s'", e.Token.Val)
  48. }
  49. }
  50. s += "] "
  51. s += e.ErrorMsg
  52. return s
  53. }
  54. // Returns the affected line from the original template, if available.
  55. func (e *Error) RawLine() (line string, available bool) {
  56. if e.Line <= 0 || e.Filename == "<string>" {
  57. return "", false
  58. }
  59. filename := e.Filename
  60. if e.Template != nil {
  61. filename = e.Template.set.resolveFilename(e.Template, e.Filename)
  62. }
  63. file, err := os.Open(filename)
  64. if err != nil {
  65. panic(err)
  66. }
  67. defer file.Close()
  68. scanner := bufio.NewScanner(file)
  69. l := 0
  70. for scanner.Scan() {
  71. l++
  72. if l == e.Line {
  73. return scanner.Text(), true
  74. }
  75. }
  76. return "", false
  77. }