[Subversion] / PEAK / src / peak / util / IndentedStream.py  

View of /PEAK/src/peak/util/IndentedStream.py

Parent Directory | Revision Log
Revision: 1076 - (download) (as text)
Sat May 3 13:21:20 2003 UTC (20 years, 11 months ago) by pje
File size: 3906 byte(s)
Normalized whitespace.
"""Utility class for writing Python, XML, etc. w/easy indentation handling"""

class IndentedStream:

    """Adapter that adds indentation management to a write stream

        Basic Usage::

            >>> f = IndentedStream(sys.stdout)
            >>> f.write('{\n'); f.push(1); f.write('foo;\n'); f.pop(); \
                f.write('}\n');

        Outputs::

            {
                foo;
            }

        IndentedStreams have a indent level stack which keeps track of
        each new margin size; push sets a new margin (relative or absolute
        by spaces or tabs), and pop restores the last set margin.  Text written
        is split on line breaks and indented as needed.
    """

    tabwidth = 4
    maxdepth = 80
    needSpaces = 1
    spaces = ''

    def __init__(self,stream=None,tabwidth=4):

        """Create an indented stream from an existing stream"""

        if stream is None:
            from sys import stdout
            stream = stdout
        self.stream = stream
        self.tabwidth = tabwidth
        self.stack = [0]


    def setTabWidth(self,tabwidth):
        """Change current tab stop width"""
        self.tabwidth = tabwidth


    def setMargin(self,tabs=0,indent=0,outdent=0,absolute=None,absTabs=None):

        """Set current margin using relative or absolute spaces or tabs

            Examples::

                f=IndentedStream(sys.stdout,tabwidth=8)
                f.setMargin(1)           # indent by 8 spaces (current tab width)
                f.setMargin(-1)          # outdent by 8 spaces
                f.setMargin(indent=4)    # indent by 4 spaces (could outdent=-4)
                f.setMargin(outdent=4)   # outdent by 4 spaces (could indent=-4)
                f.setMargin(absolute=20) # set margin to 20 spaces
                f.setMargin(absTabs=3)   # set margin to 3 * current tab width

            Note that 'setMargin()' does not save the current margin; if you
            need it to be saved, use 'push()' instead, which will take the same
            arguments.
        """

        if absTabs is not None:
            absolute = absTabs * self.tabwidth

        if absolute is None:
            margin = self.stack[-1] + indent - outdent + tabs*self.tabwidth
        else:
            margin = absolute

        self.stack[-1] = max(min(margin,self.maxdepth),0)
        self._setspaces()







    def push(self,*args,**kw):
        """Save the current margin, and optionally set a new one

            This method optionally accepts all the same parameters as
            'setMargin()', so that you can save the current margin and set a new
            one all in one step.  If no arguments, just saves the current
            margin.
        """
        self.stack.append(self.stack[-1])
        if args or kw:
            apply(self.setMargin,args,kw)


    def pop(self):
        """Restore the most recently saved margin - underflow is ignored"""
        stack = self.stack
        if len(stack)>1:
            stack.pop()
            self._setspaces()


    def _indent(self):
        if self.needSpaces:
            self.stream.write(self.spaces)
            self.needSpaces=0


    def _setspaces(self):
        self.spaces = ' ' * self.stack[-1]


    def __getattr__(self,name):
        return getattr(self.stream,name)








    def write(self,data):

        """Write 'data' to stream, indenting as needed"""

        if '\n' in data:

            lines = data.split('\n')
            write = self.stream.write
            indent = self._indent

            for l in lines[:-1]:
                if l:
                    indent()
                    write(l)
                write('\n')
                self.needSpaces = 1

            if lines[-1]:
                indent()
                write(lines[-1])
        else:
            self._indent()
            self.stream.write(data)



















cvs-admin@eby-sarna.com

Powered by ViewCVS 1.0-dev

ViewCVS and CVS Help