root/livinglogic.python.xist/src/ll/xist/presenters.py @ 3808:167234390c1b

Revision 3808:167234390c1b, 21.4 KB (checked in by Walter Doerwald <walter@…>, 10 years ago)

Make reprtab a module level constant, so that it can be changed via code.

Line 
1# -*- coding: utf-8 -*-
2
3## Copyright 1999-2009 by LivingLogic AG, Bayreuth/Germany
4## Copyright 1999-2009 by Walter Dörwald
5##
6## All Rights Reserved
7##
8## See ll/__init__.py for the license
9
10
11"""
12This module contains presenter classes, which are used for displaying XIST
13nodes on screen (either on the terminal or via :mod:`ipipe` browsers).
14"""
15
16
17__docformat__ = "reStructuredText"
18
19
20import sys, os, keyword, codecs
21
22# IPython/ipipe support
23try:
24    import ipipe
25    table = ipipe.Table
26except ImportError:
27    table = object
28
29from ll import misc, url
30
31import xsc
32
33
34__docformat__ = "reStructuredText"
35
36
37###
38### Colors for output
39###
40
41try:
42    import astyle
43except ImportError:
44    from ll import astyle
45
46
47# style to be used for tabs
48s4tab = astyle.Style.fromenv("LL_XIST_STYLE_TAB", "blue:black")
49
50
51# style to be used for quotes (delimiters for text and attribute nodes)
52s4quote = astyle.Style.fromenv("LL_XIST_STYLE_QUOTE", "white:black:bold")
53
54
55# style to be used for text
56s4text = astyle.Style.fromenv("LL_XIST_STYLE_TEXT", "white:black")
57
58
59# style to be used for namespaces
60s4ns = astyle.Style.fromenv("LL_XIST_STYLE_NAMESPACE", "magenta:black")
61
62
63# style to be used for Null object
64s4null = astyle.Style.fromenv("LL_XIST_STYLE_NULL", "red:black")
65
66
67# style to be used for Null name
68s4nullname = astyle.Style.fromenv("LL_XIST_STYLE_NULLNAME", "red:black")
69
70
71# style to be used a Frag object
72s4frag = astyle.Style.fromenv("LL_XIST_STYLE_FRAG", "yellow:black")
73
74
75# style to be used for Frag name
76s4fragname = astyle.Style.fromenv("LL_XIST_STYLE_FRAGNAME", "yellow:black")
77
78
79# style to be used for elements (i.e. the <, > and / characters
80s4element = astyle.Style.fromenv("LL_XIST_STYLE_ELEMENT", "yellow:black")
81
82
83# style to be used for element names
84s4elementname = astyle.Style.fromenv("LL_XIST_STYLE_ELEMENTNAME", "yellow:black")
85
86
87# style to be used for processing instructions
88s4procinst = astyle.Style.fromenv("LL_XIST_STYLE_PROCINST", "magenta:black")
89
90
91# style to be used for processing instruction targets
92s4procinsttarget = astyle.Style.fromenv("LL_XIST_STYLE_PROCINSTTARGET", "magenta:black:bold")
93
94
95# style to be used for processing instruction content
96s4procinstcontent = astyle.Style.fromenv("LL_XIST_STYLE_PROCINSTCONTENT", "white:black")
97
98
99# style to be used for attributes (i.e. the quotes around their value)
100s4attr = astyle.Style.fromenv("LL_XIST_STYLE_ATTR", "yellow:black")
101
102
103# style to be used for attribute names
104s4attrname = astyle.Style.fromenv("LL_XIST_STYLE_ATTRNAME", "cyan:black")
105
106
107# style to be used for attrs class name
108s4attrs = astyle.Style.fromenv("LL_XIST_STYLE_ATTRS", "yellow:black")
109
110
111# style to be used for attrs class name
112s4attrsname = astyle.Style.fromenv("LL_XIST_STYLE_ATTRSNAME", "yellow:black:bold")
113
114
115# style to be used for entities
116s4entity = astyle.Style.fromenv("LL_XIST_STYLE_ENTITY", "magenta:black")
117
118
119# style to be used for entity names
120s4entityname = astyle.Style.fromenv("LL_XIST_STYLE_ENTITYNAME", "magenta:black:bold")
121
122
123# style to be used for charref names or codepoints
124s4charrefname = astyle.Style.fromenv("LL_XIST_STYLE_CHARREFNAME", "magenta:black")
125
126
127# style to be used for document types
128s4doctype = astyle.Style.fromenv("LL_XIST_STYLE_DOCTYPE", "white:black:bold")
129
130
131# style to be used for document types
132s4doctypetext = astyle.Style.fromenv("LL_XIST_STYLE_DOCTYPETEXT", "white:black:bold")
133
134
135# style to be used for comment (i.e. <!-- and -->)
136s4comment = astyle.Style.fromenv("LL_XIST_STYLE_COMMENT", "blue:black")
137
138
139# style to be used for comment text
140s4commenttext = astyle.Style.fromenv("LL_XIST_STYLE_COMMENTTEXT", "blue:black")
141
142
143# style to be used for attribute values
144s4attrvalue = astyle.Style.fromenv("LL_XIST_STYLE_ATTRVALUE", "green:black")
145
146
147# style to be used for URLs
148s4url = astyle.Style.fromenv("LL_XIST_STYLE_URL", "green:black")
149
150
151# style to be used for numbers in error messages etc.
152s4number = astyle.Style.fromenv("LL_XIST_STYLE_NUMBER", "blue:black")
153
154
155# style to be used for variable strings in error messages etc.
156s4string = astyle.Style.fromenv("LL_XIST_STYLE_STRING", "magenta:black")
157
158
159# style to be used for IDs in repr()
160s4id = astyle.Style.fromenv("LL_XIST_STYLE_ID", "yellow:black")
161
162
163reprtab = os.environ.get("LL_XIST_REPR_TAB", u"  ")
164
165
166def strtab(count):
167    # The environment variable ``LL_XIST_REPR_TAB`` specifies how to represent an indentation in the DOM tree
168    return s4tab(unicode(reprtab)*count)
169
170
171def strtext(text):
172    return s4text(s4quote(u'"'), text, s4quote(u'"'))
173
174
175class Presenter(table):
176    """
177    This class is the base of the presenter classes. It is abstract and only
178    serves as documentation for the methods.
179
180    A :class:`Presenter` generates a specific string representation of a node
181    to be printed on the screen.
182    """
183
184    def __init__(self, node):
185        self.node = node
186
187    @misc.notimplemented
188    def presentText(self, node):
189        """
190        Present a :class:`ll.xist.xsc.Text` node.
191        """
192
193    @misc.notimplemented
194    def presentFrag(self, node):
195        """
196        Present a :class:`ll.xist.xsc.Frag` node.
197        """
198
199    @misc.notimplemented
200    def presentComment(self, node):
201        """
202        Present a :class:`ll.xist.xsc.Comment` node.
203        """
204
205    @misc.notimplemented
206    def presentDocType(self, node):
207        """
208        Present a :class:`ll.xist.xsc.DocType` node.
209        """
210
211    @misc.notimplemented
212    def presentProcInst(self, node):
213        """
214        Present a :class:`ll.xist.xsc.ProcInst` node.
215        """
216
217    @misc.notimplemented
218    def presentAttrs(self, node):
219        """
220        Present an :class:`ll.xist.xsc.Attrs` node.
221        """
222
223    @misc.notimplemented
224    def presentElement(self, node):
225        """
226        Present an :class:`ll.xist.xsc.Element` node.
227        """
228
229    @misc.notimplemented
230    def presentEntity(self, node):
231        """
232        Present a :class:`ll.xist.xsc.Entity` node.
233        """
234
235    @misc.notimplemented
236    def presentNull(self, node):
237        """
238        Present the :data:`ll.xist.xsc.Null` node.
239        """
240
241    @misc.notimplemented
242    def presentAttr(self, node):
243        """
244        Present an :class:`ll.xist.xsc.Attr` node.
245        """
246
247
248class Line(object):
249    __slots__ = ("node", "loc", "path", "content")
250
251    def __init__(self, node, loc, path, content):
252        self.node = node
253        self.loc = loc
254        self.path = path
255        self.content = content
256
257    def __iter__(self):
258        return iter(defaultpresenter(self.node))
259
260    def __xattrs__(self, mode="default"):
261        if mode == "detail":
262            return ("node", "loc", "path", "content")
263        return ("loc", "path", "content")
264
265
266class TreePresenter(Presenter):
267    """
268    This presenter shows the object as a nested tree.
269    """
270
271    # When inside attributes the presenting methods yield astyle.Text objects
272    # Outside of attributes Line objects are yielded
273
274    def __init__(self, node, indent=None):
275        Presenter.__init__(self, node)
276        if indent is None:
277            indent = os.environ.get("LL_XIST_INDENT", "\t")
278        self.indent = indent
279
280    def __str__(self):
281        return "\n".join(str(line.content) for line in self)
282
283    def strindent(self, level):
284        indent = self.indent
285        if indent == "\t":
286            indent = "   "
287        return s4tab(level*indent)
288
289    def text(self, text):
290        return repr(text)[2:-1]
291
292    def __iter__(self):
293        self._inattr = 0
294        self._path = [] # numerical path
295
296        for line in self.node.present(self):
297            yield line
298
299        del self._inattr
300        del self._path
301
302    def _domultiline(self, node, lines, indent, formatter, head=None, tail=None):
303        loc = node.startloc
304        nest = len(self._path)
305        l = len(lines)
306        for i in xrange(max(1, l)): # at least one line
307            if loc is not None:
308                hereloc = loc.offset(i)
309            else:
310                hereloc = None
311            mynest = nest
312            if i<len(lines):
313                s = lines[i]
314            else:
315                s = u""
316            if indent:
317                oldlen = len(s)
318                s = s.lstrip(u"\t")
319                mynest += len(s)-oldlen
320            s = formatter(self.text(s))
321            if i == 0 and head is not None: # prepend head to first line
322                s = head + s
323            if i >= l-1 and tail is not None: # append tail to last line
324                s = s + tail
325            yield Line(node, hereloc, self._path[:], self.strindent(mynest) + s)
326
327    def presentFrag(self, node):
328        if self._inattr:
329            for child in node:
330                for text in child.present(self):
331                    yield text
332        else:
333            indent = self.strindent(len(self._path))
334            ns = s4ns(node.__class__.__module__)
335            name = s4fragname(node.__fullname__)
336            if len(node):
337                yield Line(
338                    node,
339                    node.startloc,
340                    self._path[:],
341                    s4frag(indent, "<", ns, ":", name, ">"),
342                )
343                self._path.append(0)
344                for child in node:
345                    for line in child.present(self):
346                        yield line
347                    self._path[-1] += 1
348                self._path.pop(-1)
349                yield Line(
350                    node,
351                    node.endloc,
352                    self._path[:],
353                    s4frag(indent, "</", ns, ":", name, ">"),
354                )
355            else:
356                yield Line(
357                    node,
358                    node.startloc,
359                    self._path[:],
360                    s4frag(indent, "<", ns, ":", name, "/>"),
361                )
362
363    def presentAttrs(self, node):
364        if self._inattr:
365            for (attrclass, attrvalue) in node.iteritems():
366                yield " "
367                if attrclass.xmlns is not None:
368                    yield s4attr(s4ns(self.text(unicode(attrclass.__module__))), ":", s4attrname(self.text(unicode(attrclass.__fullname__))))
369                else:
370                    yield s4attrname(self.text(unicode(attrclass.__name__)))
371                yield s4attr('="')
372                for text in attrvalue.present(self):
373                    yield text
374                yield s4attr('"')
375        else:
376            indent = self.strindent(len(self._path))
377            ns = s4ns(node.__class__.__module__)
378            name = s4attrsname(node.__fullname__)
379            yield Line(
380                node,
381                node.startloc,
382                self._path[:],
383                s4attrs(indent, "<", ns, ":", name, ">"),
384            )
385            self._path.append(None)
386            for (attrclass, attrvalue) in node.iteritems():
387                self._path[-1] = attrclass
388                for line in attrvalue.present(self):
389                    yield line
390            self._path.pop()
391            yield Line(
392                node,
393                node.endloc,
394                self._path[:],
395                s4attrs(indent, "</", ns, ":", name, ">"),
396            )
397
398    def presentElement(self, node):
399        ns = s4ns(node.__class__.__module__)
400        name = s4elementname(node.__fullname__)
401        if self._inattr:
402            yield s4element("<", ns, ":", name)
403            self._inattr += 1
404            for text in node.attrs.present(self):
405                yield text
406            self._inattr -= 1
407            if len(node):
408                yield s4element(">")
409                for text in node.content.present(self):
410                    yield text
411                yield s4element("</", ns, ":", name, ">")
412            else:
413                yield s4element("/>")
414        else:
415            firstline = s4element("<", ns, ":", name)
416            indent = self.strindent(len(self._path))
417
418            self._inattr += 1
419            for text in node.attrs.present(self):
420                firstline.append(text)
421            self._inattr -= 1
422            if len(node):
423                firstline.append(s4element(">"))
424                yield Line(
425                    node,
426                    node.startloc,
427                    self._path[:],
428                    indent + firstline,
429                )
430                self._path.append(0)
431                for child in node:
432                    for line in child.present(self):
433                        yield line
434                    self._path[-1] += 1
435                self._path.pop()
436                yield Line(
437                    node,
438                    node.endloc,
439                    self._path[:],
440                    s4element(indent, "</", ns, ":", name, ">"),
441                )
442            else:
443                firstline.append(s4element("/>"))
444                yield Line(
445                    node,
446                    node.startloc,
447                    self._path[:],
448                    indent + firstline,
449                )
450
451    def presentNull(self, node):
452        if not self._inattr:
453            indent = self.strindent(len(self._path))
454            ns = s4ns(node.__class__.__module__)
455            name = s4nullname(node.__fullname__)
456            yield Line(
457                node,
458                node.startloc,
459                self._path[:],
460                s4null(indent, "<", ns, ":", name, "/>"),
461            )
462
463    def presentText(self, node):
464        if self._inattr:
465            yield s4attrvalue(self.text(node.content))
466        else:
467            lines = node.content.splitlines(True)
468            for line in self._domultiline(node, lines, 0, strtext):
469                yield line
470
471    def presentEntity(self, node):
472        ns = s4ns(node.__class__.__module__)
473        name = s4entityname(node.__fullname__)
474        if self._inattr:
475            yield s4entity("&", ns, ":", name, ";")
476        else:
477            indent = self.strindent(len(self._path))
478            yield Line(
479                node,
480                node.startloc,
481                self._path[:],
482                s4entity(indent, "&", ns, ":", name, ";"),
483            )
484
485    def presentProcInst(self, node):
486        ns = s4ns(node.__class__.__module__)
487        name = s4procinsttarget(node.__fullname__)
488        if self._inattr:
489            yield s4procinst("<?", ns, ":", name, " ", s4procinstcontent(self.text(node.content)), "?>")
490        else:
491            head = s4procinst("<?", ns, ":", name, " ")
492            tail = s4procinst("?>")
493            lines = node.content.splitlines()
494            if len(lines)>1:
495                lines.insert(0, "")
496            for line in self._domultiline(node, lines, 1, s4procinstcontent, head, tail):
497                yield line
498
499    def presentComment(self, node):
500        if self._inattr:
501            yield s4comment("<!--", s4commenttext(self.text(node.content)), "-->")
502        else:
503            head = s4comment("<!--")
504            tail = s4comment("-->")
505            lines = node.content.splitlines()
506            for line in self._domultiline(node, lines, 1, s4commenttext, head, tail):
507                yield line
508
509    def presentDocType(self, node):
510        if self._inattr:
511            yield s4doctype("<!DOCTYPE ", s4doctypetext(self.text(node.content)), ">")
512        else:
513            head = s4doctype("<!DOCTYPE ")
514            tail = s4doctype(">")
515            lines = node.content.splitlines()
516            for line in self._domultiline(node, lines, 1, s4doctypetext, head, tail):
517                yield line
518
519    def presentAttr(self, node):
520        return self.presentFrag(node)
521
522
523class CodePresenter(Presenter):
524    """
525    This presenter formats the object as a nested Python object tree.
526
527    This makes it possible to quickly convert HTML/XML files to XIST constructor
528    calls.
529    """
530    def __init__(self, node, indent=None):
531        Presenter.__init__(self, node)
532        if indent is None:
533            indent = os.environ.get("LL_XIST_INDENT", "\t")
534        self.indent = indent
535
536    def __str__(self):
537        return "\n".join(str(line.content) for line in self)
538
539    def __iter__(self):
540        self._inattr = 0
541        self._level = 0
542        self._path = []
543        for line in self.node.present(self):
544            yield line
545        del self._path
546        del self._level
547        del self._inattr
548
549    def _indent(self):
550        if self._inattr:
551            return ""
552        else:
553            indent = self.indent
554            if indent == "\t":
555                indent = "   "
556            return s4tab(self.indent*self._level)
557
558    def _text(self, text):
559        # Find the simplest object to display
560        try:
561            s = text.encode("us-ascii")
562        except UnicodeError:
563            s = text
564        try:
565            i = int(s)
566        except ValueError:
567            pass
568        else:
569            if str(i) == s:
570                s = i
571        return s
572
573    def presentFrag(self, node):
574        name = s4frag(s4ns(node.__class__.__module__), ".", s4fragname(node.__fullname__))
575        if len(node):
576            if not self._inattr: # skip "(" for attributes, they will be added by presentElement()
577                yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "("))
578            self._level += 1
579            self._path.append(0)
580            for (i, child) in enumerate(node):
581                if i==len(node)-1:
582                    for line in child.present(self):
583                        yield line
584                else:
585                    lines = list(child.present(self))
586                    for (j, line) in enumerate(lines):
587                        if j==len(lines)-1:
588                            line.content += ","
589                        yield line
590                self._path[-1] += 1
591            self._level -= 1
592            self._path.pop()
593            if not self._inattr:
594                yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), ")"))
595        else:
596            if not self._inattr:
597                yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "()"))
598
599    def _formatattrvalue(self, attrvalue):
600        attrtext = astyle.Text()
601        if len(attrvalue)==1: # optimize away the tuple ()
602            for part in attrvalue[0].present(self):
603                if attrtext:
604                    attrtext.append(" ")
605                attrtext.append(part.content)
606        else:
607            for part in attrvalue.present(self):
608                if attrtext:
609                    attrtext.append(" ")
610                else:
611                    attrtext.append("(")
612                attrtext.append(part.content)
613            attrtext.append(")")
614        return attrtext
615
616    def presentAttrs(self, node):
617        name = s4attrs(s4ns(node.__class__.__module__), ".", s4attrsname(node.__fullname__))
618        if len(node):
619            globalattrs = {}
620            localattrs = {}
621            for (attrclass, attrvalue) in node.iteritems():
622                if attrclass.xmlns is not None:
623                    globalattrs[attrclass] = attrvalue
624                else:
625                    localattrs[attrclass] = attrvalue
626
627            yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "("))
628            self._level += 1
629            if globalattrs:
630                yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), "{"))
631                for (i, (attrclass, attrvalue)) in enumerate(globalattrs.iteritems()):
632                    self._path.append(attrclass)
633                    attrname = astyle.style_default(s4ns(attrclass.__module__), ".", s4attrname(attrclass.__fullname__))
634                    self._inattr += 1
635                    attrtext = self._formatattrvalue(attrvalue)
636                    self._inattr -= 1
637                    self._level += 1
638                    line = astyle.style_default(self._indent(), attrname, ": ", s4attrvalue(attrtext))
639                    if i != len(globalattrs) or not localattrs:
640                        line += ","
641                    yield Line(attrvalue, attrvalue.startloc, self._path[:], line)
642                    self._path.pop()
643                    self._level -= 1
644                line = astyle.style_default(self._indent(), "}")
645                if localattrs:
646                    line += ","
647                yield Line(node, node.startloc, self._path[:], line)
648            for (i, (attrclass, attrvalue)) in enumerate(localattrs.iteritems()):
649                self._path.append(attrclass.__name__)
650                self._inattr += 1
651                attrtext = self._formatattrvalue(attrvalue)
652                self._inattr -= 1
653                line = astyle.style_default(self._indent(), s4attrname(attrclass.__name__), "=", s4attrvalue(attrtext))
654                if i != len(localattrs)-1:
655                    line += ","
656                yield Line(attrvalue, attrvalue.startloc, self._path[:], line)
657                self._path.pop()
658            self._level -= 1
659            yield Line(node, node.endloc, self._path[:], astyle.style_default(self._indent(), ")"))
660        else:
661            yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "()"))
662
663    def presentElement(self, node):
664        name = s4element(s4ns(node.__class__.__module__), ".", s4elementname(node.__fullname__))
665        if len(node.content) or len(node.attrs):
666            yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "("))
667            self._level += 1
668            self._path.append(0)
669            for (i, child) in enumerate(node):
670                if i==len(node)-1 and not node.attrs:
671                    for line in child.present(self):
672                        yield line
673                else:
674                    lines = list(child.present(self))
675                    for (j, line) in enumerate(lines):
676                        if j == len(lines)-1:
677                            line.content += ","
678                        yield line
679                self._path[-1] += 1
680            self._path.pop()
681
682            globalattrs = {}
683            localattrs = {}
684            for (attrclass, attrvalue) in node.attrs.iteritems():
685                if attrclass.xmlns is not None:
686                    globalattrs[attrclass] = attrvalue
687                else:
688                    localattrs[attrclass] = attrvalue
689
690            if globalattrs:
691                yield Line(node.attrs, node.attrs.startloc, self._path[:], astyle.style_default(self._indent(), "{"))
692                for (i, (attrclass, attrvalue)) in enumerate(globalattrs.iteritems()):
693                    self._path.append(attrclass)
694                    attrname = astyle.style_default(s4ns(attrclass.__module__), ".", s4attrname(attrclass.__fullname__))
695                    self._inattr += 1
696                    attrtext = self._formatattrvalue(attrvalue)
697                    self._inattr -= 1
698                    self._level += 1
699                    line = astyle.style_default(self._indent(), attrname, ": ", s4attrvalue(attrtext))
700                    if i != len(globalattrs) or not localattrs:
701                        line += ","
702                    yield Line(attrvalue, attrvalue.startloc, self._path[:], line)
703                    self._path.pop()
704                    self._level -= 1
705                line = astyle.style_default(self._indent(), "}")
706                if localattrs:
707                    line += ","
708                yield Line(node.attrs, node.attrs.startloc, self._path[:], line)
709            for (i, (attrclass, attrvalue)) in enumerate(localattrs.iteritems()):
710                self._inattr += 1
711                attrtext = self._formatattrvalue(attrvalue)
712                self._inattr -= 1
713                line = astyle.style_default(self._indent(), s4attrname(attrclass.__name__), "=", s4attrvalue(attrtext))
714                if i != len(localattrs)-1:
715                    line += ","
716                self._path.append(attrclass.__name__)
717                yield Line(attrvalue, attrvalue.startloc, self._path[:], line)
718                self._path.pop()
719            self._level -= 1
720            yield Line(node, node.endloc, self._path[:], astyle.style_default(self._indent(), ")"))
721        else:
722            yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "()"))
723
724    def presentNull(self, node):
725        name = s4null(s4ns(node.__class__.__module__), ".", s4nullname(node.__fullname__))
726        yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name))
727
728    def presentText(self, node):
729        if self._inattr:
730            formatter = s4attrvalue
731        else:
732            formatter = s4text
733        yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), formatter(repr(self._text(node.content)))))
734
735    def presentEntity(self, node):
736        name = s4entity(s4ns(node.__class__.__module__), ".", s4entityname(node.__fullname__))
737        yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "()"))
738
739    def presentProcInst(self, node):
740        name = s4procinst(s4ns(node.__class__.__module__), ".", s4procinsttarget(node.__fullname__))
741        yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "(", s4procinstcontent(repr(self._text(node.content))), ")"))
742
743    def presentComment(self, node):
744        name = s4comment(s4ns(node.__class__.__module__), ".", node.__fullname__)
745        yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "(", s4commenttext(repr(self._text(node.content))), ")"))
746
747    def presentDocType(self, node):
748        name = s4doctype(s4ns(node.__class__.__module__), ".", node.__fullname__)
749        yield Line(node, node.startloc, self._path[:], astyle.style_default(self._indent(), name, "(", s4doctypetext(repr(self._text(node.content))), ")"))
750
751    def presentAttr(self, node):
752        return self.presentFrag(node)
753
754
755# used by the IPython displayhook below (set to :const:`None` to disable)
756defaultpresenter = TreePresenter
757
758try:
759    from IPython import ipapi, generics
760    import ipipe
761except Exception:
762    pass
763else:
764    if hasattr(ipipe, "display_tableobject"):
765        @generics.result_display.when_type(xsc.Node)
766        def displayhook(obj):
767            if defaultpresenter is not None:
768                return ipipe.display_tableobject(defaultpresenter(obj))
769            raise ipapi.TryNext
770    else:
771        @generics.result_display.when_type(xsc.Node)
772        def displayhook(obj):
773            if defaultpresenter is not None:
774                return ipipe.displayhook(None, defaultpresenter(obj))
775            raise ipapi.TryNext
Note: See TracBrowser for help on using the browser.