...

Source file src/github.com/noirbizarre/gonja/ext/django/statements/ifchanged.go

Documentation: github.com/noirbizarre/gonja/ext/django/statements

     1  package statements
     2  
     3  import (
     4  	// "bytes"
     5  
     6  	"fmt"
     7  	"strings"
     8  
     9  	"github.com/noirbizarre/gonja/exec"
    10  	"github.com/noirbizarre/gonja/nodes"
    11  	"github.com/noirbizarre/gonja/parser"
    12  	"github.com/noirbizarre/gonja/tokens"
    13  )
    14  
    15  type IfChangedStmt struct {
    16  	Location    *tokens.Token
    17  	watchedExpr []nodes.Expression
    18  	lastValues  []*exec.Value
    19  	lastContent string
    20  	thenWrapper *nodes.Wrapper
    21  	elseWrapper *nodes.Wrapper
    22  }
    23  
    24  func (stmt *IfChangedStmt) Position() *tokens.Token { return stmt.Location }
    25  func (stmt *IfChangedStmt) String() string {
    26  	t := stmt.Position()
    27  	return fmt.Sprintf("IfChangedStmt(Line=%d Col=%d)", t.Line, t.Col)
    28  }
    29  
    30  func (stmt *IfChangedStmt) Execute(r *exec.Renderer, tag *nodes.StatementBlock) error {
    31  	if len(stmt.watchedExpr) == 0 {
    32  		// Check against own rendered body
    33  		var out strings.Builder
    34  		sub := r.Inherit()
    35  		sub.Out = &out
    36  		err := sub.ExecuteWrapper(stmt.thenWrapper)
    37  		if err != nil {
    38  			return err
    39  		}
    40  
    41  		str := out.String()
    42  		if stmt.lastContent != str {
    43  			// Rendered content changed, output it
    44  			r.WriteString(str)
    45  			stmt.lastContent = str
    46  		}
    47  	} else {
    48  		nowValues := make([]*exec.Value, 0, len(stmt.watchedExpr))
    49  		for _, expr := range stmt.watchedExpr {
    50  			val := r.Eval(expr)
    51  			if val.IsError() {
    52  				return val
    53  			}
    54  			nowValues = append(nowValues, val)
    55  		}
    56  
    57  		// Compare old to new values now
    58  		changed := len(stmt.lastValues) == 0
    59  
    60  		for idx, oldVal := range stmt.lastValues {
    61  			if !oldVal.EqualValueTo(nowValues[idx]) {
    62  				changed = true
    63  				break // we can stop here because ONE value changed
    64  			}
    65  		}
    66  
    67  		stmt.lastValues = nowValues
    68  
    69  		if changed {
    70  			// Render thenWrapper
    71  			err := r.ExecuteWrapper(stmt.thenWrapper)
    72  			if err != nil {
    73  				return err
    74  			}
    75  		} else {
    76  			// Render elseWrapper
    77  			err := r.ExecuteWrapper(stmt.elseWrapper)
    78  			if err != nil {
    79  				return err
    80  			}
    81  		}
    82  	}
    83  
    84  	return nil
    85  }
    86  
    87  func ifchangedParser(p *parser.Parser, args *parser.Parser) (nodes.Statement, error) {
    88  	stmt := &IfChangedStmt{
    89  		Location: p.Current(),
    90  	}
    91  
    92  	for !args.End() {
    93  		// Parse condition
    94  		expr, err := args.ParseExpression()
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  		stmt.watchedExpr = append(stmt.watchedExpr, expr)
    99  	}
   100  
   101  	if !args.End() {
   102  		return nil, args.Error("Ifchanged-arguments are malformed.", nil)
   103  	}
   104  
   105  	// Wrap then/else-blocks
   106  	wrapper, endargs, err := p.WrapUntil("else", "endifchanged")
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	stmt.thenWrapper = wrapper
   111  
   112  	if !endargs.End() {
   113  		return nil, endargs.Error("Arguments not allowed here.", nil)
   114  	}
   115  
   116  	if wrapper.EndTag == "else" {
   117  		// if there's an else in the if-statement, we need the else-Block as well
   118  		wrapper, endargs, err = p.WrapUntil("endifchanged")
   119  		if err != nil {
   120  			return nil, err
   121  		}
   122  		stmt.elseWrapper = wrapper
   123  
   124  		if !endargs.End() {
   125  			return nil, endargs.Error("Arguments not allowed here.", nil)
   126  		}
   127  	}
   128  
   129  	return stmt, nil
   130  }
   131  
   132  func init() {
   133  	All.Register("ifchanged", ifchangedParser)
   134  }
   135  

View as plain text