1 package exec 2 3 /* Incomplete: 4 ----------- 5 6 verbatim (only the "name" argument is missing for verbatim) 7 8 Reconsideration: 9 ---------------- 10 11 debug (reason: not sure what to output yet) 12 regroup / Grouping on other properties (reason: maybe too python-specific; not sure how useful this would be in Go) 13 14 Following built-in tags wont be added: 15 -------------------------------------- 16 17 csrf_token (reason: web-framework specific) 18 load (reason: python-specific) 19 url (reason: web-framework specific) 20 */ 21 22 import ( 23 // "fmt" 24 25 "github.com/pkg/errors" 26 27 "github.com/noirbizarre/gonja/nodes" 28 "github.com/noirbizarre/gonja/parser" 29 // "github.com/noirbizarre/gonja/tokens" 30 ) 31 32 // type NodeStatement interface { 33 // astNode 34 // } 35 36 // This is the function signature of the tag's parser you will have 37 // to implement in order to create a new tag. 38 // 39 // 'doc' is providing access to the whole document while 'arguments' 40 // is providing access to the user's arguments to the tag: 41 // 42 // {% your_tag_name some "arguments" 123 %} 43 // 44 // start_token will be the *Token with the tag's name in it (here: your_tag_name). 45 // 46 // Please see the Parser documentation on how to use the parser. 47 // See RegisterTag()'s documentation for more information about 48 // writing a tag as well. 49 50 // type StatementExecutor func(*nodes.Node, *ExecutionContext) *Value 51 52 type Statement interface { 53 nodes.Statement 54 Execute(*Renderer, *nodes.StatementBlock) error 55 } 56 57 type StatementSet map[string]parser.StatementParser 58 59 // Exists returns true if the given test is already registered 60 func (ss StatementSet) Exists(name string) bool { 61 _, existing := ss[name] 62 return existing 63 } 64 65 // Registers a new tag. You usually want to call this 66 // function in the tag's init() function: 67 // http://golang.org/doc/effective_go.html#init 68 // 69 // See http://www.florian-schlachter.de/post/gonja/ for more about 70 // writing filters and tags. 71 func (ss *StatementSet) Register(name string, parser parser.StatementParser) error { 72 if ss.Exists(name) { 73 return errors.Errorf("Statement '%s' is already registered", name) 74 } 75 (*ss)[name] = parser 76 // &statement{ 77 // name: name, 78 // parser: parserFn, 79 // } 80 return nil 81 } 82 83 // Replaces an already registered tag with a new implementation. Use this 84 // function with caution since it allows you to change existing tag behaviour. 85 func (ss *StatementSet) Replace(name string, parser parser.StatementParser) error { 86 if !ss.Exists(name) { 87 return errors.Errorf("Statement '%s' does not exist (therefore cannot be overridden)", name) 88 } 89 (*ss)[name] = parser 90 // statements[name] = &statement{ 91 // name: name, 92 // parser: parserFn, 93 // } 94 return nil 95 } 96 97 func (ss *StatementSet) Update(other StatementSet) StatementSet { 98 for name, parser := range other { 99 (*ss)[name] = parser 100 } 101 return *ss 102 } 103 104 // func (ss StatementSet) Parsers() map[string]parser.StatementParser { 105 // parsers := map[string]parser.StatementParser{} 106 // for key, specs := range ss { 107 // parsers[key] = specs.Parse 108 // } 109 // return parsers 110 // } 111 112 // // Tag = "{%" IDENT ARGS "%}" 113 // func (p *Parser) ParseStatement() (ast.Statement, *Error) { 114 // p.Consume() // consume "{%" 115 // tokenName := p.MatchType(TokenIdentifier) 116 117 // // Check for identifier 118 // if tokenName == nil { 119 // return nil, p.Error("Statement name must be an identifier.", nil) 120 // } 121 122 // // Check for the existing statement 123 // stmt, exists := statements[tokenName.Val] 124 // if !exists { 125 // // Does not exists 126 // return nil, p.Error(fmt.Sprintf("Statement '%s' not found (or beginning not provided)", tokenName.Val), tokenName) 127 // } 128 129 // // Check sandbox tag restriction 130 // if _, isBanned := p.bannedStmts[tokenName.Val]; isBanned { 131 // return nil, p.Error(fmt.Sprintf("Usage of statement '%s' is not allowed (sandbox restriction active).", tokenName.Val), tokenName) 132 // } 133 134 // var argsToken []*Token 135 // for p.Peek(TokenSymbol, "%}") == nil && p.Remaining() > 0 { 136 // // Add token to args 137 // argsToken = append(argsToken, p.Current()) 138 // p.Consume() // next token 139 // } 140 141 // // EOF? 142 // if p.Remaining() == 0 { 143 // return nil, p.Error("Unexpectedly reached EOF, no statement end found.", p.lastToken) 144 // } 145 146 // p.Match(TokenSymbol, "%}") 147 148 // argParser := newParser(p.name, argsToken, p.template) 149 // if len(argsToken) == 0 { 150 // // This is done to have nice EOF error messages 151 // argParser.lastToken = tokenName 152 // } 153 154 // p.template.level++ 155 // defer func() { p.template.level-- }() 156 // return stmt.parser(p, tokenName, argParser) 157 // } 158