# -*- coding: utf-8 -*-

import re
from uuid import uuid4
from urwid import (
    Text, Divider
)

def get_attribute(render_data, variable):
    levels = variable.split('.')
    r = render_data
    for level in levels:
        r = r[level]
    return r

variable_re = re.compile(r'({\s*.*\s*})')
def render_template(text, render_data):
    variables = variable_re.findall(text)
    variables = {var[1:-1].strip(): var for var in variables}
    for variable in variables:
        text = text.replace(variables[variable], get_attribute(render_data, variable))
    return text

def render_text_layout(attributes, text, opts, ref):
    class_ = attributes.get('class', '')
    classes = [] if not class_ else [class_]
    align = attributes.get('align', 'left')
    wrap = attributes.get('wrap', 'any')
    render_data = dict(ref)
    render_data['opts'] = opts
    if isinstance(text, str):
        markup = render_template(text, render_data)
    elif isinstance(text, list):
        markup = [render_template(tpl, render_data) for tpl in text if tpl]
    elif isinstance(text, tuple):
        markup = render_template(text[1], render_data)
    return Text(markup, align=align, wrap=wrap)

def render_div_layout(attributes, text, opts, ref):
    div_char = attributes.get('char', u' ')
    top = int(attributes.get('top', 0))
    bottom = int(attributes.get('bottom', 0))
    return Divider(div_char, top, bottom)

RENDERERS = {
    'text': render_text_layout,
    'div': render_div_layout,
}

def render_layout(layout, opts={}, ref={}):
    tag_name, attributes, children = layout
    el = RENDERERS[tag_name](attributes, children, opts, ref)
    el.uuid = uuid4()
    return el


@@ -28,16 +28,42 @@
 port re%0A
+from copy import deepcopy%0A
 from uui
@@ -255,15 +255,57 @@
  = r
-%5Blevel%5D
+.get(level) or %7B%7D%0A    if not r:%0A        return ''
 %0A   
@@ -693,94 +693,8 @@
 f):%0A
-    class_ = attributes.get('class', '')%0A    classes = %5B%5D if not class_ else %5Bclass_%5D%0A
     
@@ -712,19 +712,19 @@
 ributes.
-get
+pop
 ('align'
@@ -755,19 +755,19 @@
 ributes.
-get
+pop
 ('wrap',
@@ -772,11 +772,13 @@
 ', '
-any
+space
 ')%0A 
@@ -830,20 +830,73 @@
 pts'%5D = 
-opts
+deepcopy(opts)%0A    render_data%5B'opts'%5D.update(attributes)
 %0A    if 
@@ -1183,43 +1183,531 @@
 urn 
-Text(
+%5B%0A        'text',%0A        %7B%0A            'markup': markup,%0A            'align': align,%0A            'wrap': wrap,%0A        %7D%0A    %5D%0A%0Adef patch_text_layout(el1, el2):%0A    if el1%5B1%5D.get('
 markup
+'
 , 
-align=
+'') != el2%5B1%5D.get('markup', ''):%0A        yield ('set_text', el2%5B1%5D%5B'markup'%5D)%0A    if el1%5B1%5D.get('align', 'left') != el2%5B1%5D.get('
 align
+'
 , 
-wrap=wrap
+'left'):%0A        yield ('set_align_mode', el2%5B1%5D.get('align', 'left'))%0A    if el1%5B1%5D.get('wrap', 'space') != el2%5B1%5D.get('wrap', 'space'):%0A        yield ('set_wrap_mode', el2%5B1%5D.get('wrap', 'space')
 )%0A%0Ad
@@ -2009,16 +2009,63 @@
 out,%0A%7D%0A%0A
+PATCHERS = %7B%0A    'text': patch_text_layout,%0A%7D%0A%0A
 def rend
@@ -2152,12 +2152,14 @@
     
-el =
+return
  REN
@@ -2212,41 +2212,113 @@
 ef)%0A
-    el.uuid = uuid4()%0A    return el%0A
+%0Adef patch_layout(el1, el2):%0A    assert(el1%5B0%5D == el2%5B0%5D)%0A    return %5B_ for _ in PATCHERS%5Bel2%5B0%5D%5D(el1, el2)%5D
 %0A

Reimplement render_text_layout, patch_text_layout.