summaryrefslogtreecommitdiffstats
path: root/cobbler/Cheetah/Utils/Indenter.py
blob: abdb0dde686b1a42f06f2a903233acf566a1c0c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python
# $Id: Indenter.py,v 1.7 2006/01/08 01:09:30 tavis_rudd Exp $
"""Indentation maker.
@@TR: this code is unsupported and largely undocumented ...

This version is based directly on code by Robert Kuzelj
<robert_kuzelj@yahoo.com> and uses his directive syntax.  Some classes and
attributes have been renamed.  Indentation is output via
$self._CHEETAH__indenter.indent() to prevent '_indenter' being looked up on the
searchList and another one being found.  The directive syntax will
soon be changed somewhat.

Meta-Data
================================================================================
Author: Mike Orr <iron@mso.oz.net>
License: This software is released for unlimited distribution under the
         terms of the MIT license.  See the LICENSE file.
Version: $Revision: 1.7 $
Start Date: 2001/11/07
Last Revision Date: $Date: 2006/01/08 01:09:30 $
""" 
__author__ = "Mike Orr <iron@mso.oz.net>"
__revision__ = "$Revision: 1.7 $"[11:-2]

import re
import sys

def indentize(source):
    return IndentProcessor().process(source)

class IndentProcessor:
    """Preprocess #indent tags."""
    LINE_SEP = '\n'
    ARGS = "args"
    INDENT_DIR = re.compile(r'[ \t]*#indent[ \t]*(?P<args>.*)')
    DIRECTIVE = re.compile(r"[ \t]*#")
    WS = "ws"
    WHITESPACES = re.compile(r"(?P<ws>[ \t]*)")

    INC = "++"
    DEC = "--"
    
    SET = "="
    CHAR = "char"
    
    ON = "on"
    OFF = "off"

    PUSH = "push"
    POP = "pop"
    
    def process(self, _txt):
        result = []

        for line in _txt.splitlines():
            match = self.INDENT_DIR.match(line)
            if match:
                #is indention directive
                args = match.group(self.ARGS).strip()
                if args == self.ON:
                    line = "#silent $self._CHEETAH__indenter.on()"
                elif args == self.OFF:
                    line = "#silent $self._CHEETAH__indenter.off()"
                elif args == self.INC:
                    line = "#silent $self._CHEETAH__indenter.inc()"
                elif args == self.DEC:
                    line = "#silent $self._CHEETAH__indenter.dec()"
                elif args.startswith(self.SET):
                    level = int(args[1:])
                    line = "#silent $self._CHEETAH__indenter.setLevel(%(level)d)" % {"level":level}
                elif args.startswith('chars'):
                    self.indentChars = eval(args.split('=')[1])
                    line = "#silent $self._CHEETAH__indenter.setChars(%(level)d)" % {"level":level}
                elif args.startswith(self.PUSH):
                    line = "#silent $self._CHEETAH__indenter.push()"
                elif args.startswith(self.POP):
                    line = "#silent $self._CHEETAH__indenter.pop()"
            else:
                match = self.DIRECTIVE.match(line)
                if not match:
                    #is not another directive
                    match = self.WHITESPACES.match(line)
                    if match:
                        size = len(match.group("ws").expandtabs(4))
                        line = ("${self._CHEETAH__indenter.indent(%(size)d)}" % {"size":size}) + line.lstrip()
                    else:
                        line = "${self._CHEETAH__indenter.indent(0)}" + line
            result.append(line)

        return self.LINE_SEP.join(result)

class Indenter:
    """A class that keeps track of the current indentation level.
    .indent() returns the appropriate amount of indentation.
    """
    def __init__(self):
        self.On = 1
        self.Level = 0
        self.Chars = " "*4
        self.LevelStack = []
    def on(self):
        self.On = 1
    def off(self):
        self.On = 0
    def inc(self):
        self.Level += 1
    def dec(self):
        """decrement can only be applied to values greater zero
            values below zero don't make any sense at all!"""
        if self.Level > 0:
            self.Level -= 1
    def push(self):
        self.LevelStack.append(self.Level)
    def pop(self):
        """the levestack can not become -1. any attempt to do so
           sets the level to 0!"""
        if len(self.LevelStack) > 0:
            self.Level = self.LevelStack.pop()
        else:
            self.Level = 0
    def setLevel(self, _level):
        """the leve can't be less than zero. any attempt to do so
           sets the level automatically to zero!"""
        if _level < 0:
            self.Level = 0
        else:
            self.Level = _level
    def setChar(self, _chars):
        self.Chars = _chars
    def indent(self, _default=0):
        if self.On:
            return self.Chars * self.Level
        else:
            return " " * _default