~ubuntu-branches/ubuntu/natty/moin/natty-updates

« back to all changes in this revision

Viewing changes to MoinMoin/parser/highlight.py

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard
  • Date: 2008-06-22 21:17:13 UTC
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20080622211713-inlv5k4eifxckelr
ImportĀ upstreamĀ versionĀ 1.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- coding: iso-8859-1 -*-
2
 
"""
3
 
    MoinMoin - highlighting parser using the Pygments highlighting library
4
 
 
5
 
    @copyright: 2008 Radomir Dopieralski <moindev@sheep.art.pl>
6
 
    @license: GNU GPL, see COPYING for details.
7
 
"""
8
 
 
9
 
import re
10
 
 
11
 
import pygments
12
 
import pygments.util
13
 
import pygments.lexers
14
 
import pygments.formatter
15
 
from pygments.token import Token
16
 
 
17
 
from MoinMoin import config, wikiutil
18
 
from MoinMoin.parser import parse_start_step
19
 
from MoinMoin.support.python_compatibility import hash_new
20
 
from MoinMoin.Page import Page
21
 
 
22
 
Dependencies = ['user'] # the "Toggle line numbers link" depends on user's language
23
 
 
24
 
 
25
 
def extensions_from_lexer_filenames(filenames):
26
 
    # pygment's lexer.filenames is like ['*.py', 'Python'], but we only want
27
 
    # the filename extensions list (like ['.py', ]):
28
 
    return [filename[1:] for filename in filenames if filename.startswith('*.')]
29
 
 
30
 
def extensions_for_all_lexers():
31
 
    """
32
 
    get supported filename extensions for all pygments lexers
33
 
    """
34
 
    extensions = []
35
 
    for name, short, patterns, mime in pygments.lexers.get_all_lexers():
36
 
        extensions.extend(extensions_from_lexer_filenames(patterns))
37
 
    return extensions
38
 
 
39
 
 
40
 
class PygmentsFormatter(pygments.formatter.Formatter):
41
 
    """ a formatter for Pygments that uses the moin formatter for creating output """
42
 
    line_re = re.compile(r'(\n)')
43
 
 
44
 
    def __init__(self, formatter, **kw):
45
 
        pygments.formatter.Formatter.__init__(self)
46
 
        self.result = []
47
 
        self.formatter = formatter
48
 
        self.start_line = kw.get('start_line', 0)
49
 
 
50
 
    def get_class(self, ttype):
51
 
        if ttype in Token.Text:
52
 
            return None
53
 
        # Reuse existing MoinMoin css class names
54
 
        elif ttype in Token.Operator.Word:
55
 
            return 'ResWord'
56
 
        elif ttype in Token.Comment.Preproc:
57
 
            return 'Preprc'
58
 
        elif ttype in Token.Keyword.Constant:
59
 
            return 'ConsWord'
60
 
        elif ttype in Token.Keyword:
61
 
            return 'ResWord'
62
 
        elif ttype in Token.Name.Builtin:
63
 
            return 'ResWord'
64
 
        elif ttype in Token.Name.Constant:
65
 
            return 'ConsWord'
66
 
        elif ttype in Token.String.Char:
67
 
            return 'Char'
68
 
        elif ttype in Token.String.Escape:
69
 
            return 'SPChar'
70
 
        elif ttype in Token.String:
71
 
            return 'String'
72
 
        elif ttype in Token.Number:
73
 
            return 'Number'
74
 
        elif ttype in Token.Name:
75
 
            return 'ID'
76
 
        elif ttype in Token.Comment:
77
 
            return 'Comment'
78
 
        elif ttype in Token.Generic.Heading:
79
 
            return 'Comment'
80
 
        elif ttype in Token.Generic.Subheading:
81
 
            return 'DiffSeparator'
82
 
        elif ttype in Token.Generic.Inserted:
83
 
            return 'DiffAdded'
84
 
        elif ttype in Token.Generic.Deleted:
85
 
            return 'DiffRemoved'
86
 
        elif ttype in Token.Generic.Strong:
87
 
            return 'DiffChanged'
88
 
        elif ttype in Token.Generic.Output:
89
 
            return 'LineNumber'
90
 
        elif ttype in Token.Generic.Prompt:
91
 
            return 'ID'
92
 
        else:
93
 
            # skip tags that have no class defined
94
 
            return None
95
 
            # ... or use the token's name when nothing apropriate
96
 
            # return str(ttype).replace(".", " ")
97
 
 
98
 
    def add_next_line(self, line_parts):
99
 
        fmt = self.formatter
100
 
        self.lineno += 1
101
 
        self.result.append(fmt.code_line(1))
102
 
        self.result.append(fmt.line_anchordef(self.lineno))
103
 
        self.result += line_parts
104
 
        self.result.append(fmt.code_line(0))
105
 
 
106
 
    def format(self, tokensource, outfile):
107
 
        fmt = self.formatter
108
 
        self.lineno = self.start_line
109
 
        line_parts = []
110
 
        for ttype, value in tokensource:
111
 
            class_ = self.get_class(ttype)
112
 
            if value:
113
 
                for line in self.line_re.split(value):
114
 
                    if line == '\n':
115
 
                        self.add_next_line(line_parts)
116
 
                        line_parts = []
117
 
                        continue
118
 
                    if class_:
119
 
                        line_parts.append(fmt.code_token(1, class_))
120
 
                    line_parts.append(fmt.text(line))
121
 
                    if class_:
122
 
                        line_parts.append(fmt.code_token(0, class_))
123
 
        if line_parts and line_parts != [u'']: # Don't output an empty line at the end.
124
 
            self.add_next_line(line_parts)
125
 
 
126
 
 
127
 
class Parser:
128
 
    parsername = "highlight"  # compatibility wrappers override this with the pygments lexer name
129
 
    Dependencies = Dependencies
130
 
    extensions = extensions_for_all_lexers()
131
 
 
132
 
    def __init__(self, raw, request, filename=None, format_args='', **kw):
133
 
        self.request = request
134
 
        self.raw = raw
135
 
        self.filename = filename
136
 
        self.start_line = kw.get('start_line', 0)
137
 
 
138
 
        if self.parsername == 'highlight':
139
 
            # user is directly using the highlight parser
140
 
            parts = format_args.split(None)
141
 
            if parts:
142
 
                self.syntax = parts[0]
143
 
            else:
144
 
                self.syntax = 'text'
145
 
            if len(parts) > 1:
146
 
                params = ' '.join(parts[1:])
147
 
            else:
148
 
                params = ''
149
 
        else:
150
 
            # a compatibility wrapper inherited from this class
151
 
            self.syntax = self.parsername
152
 
            params = format_args
153
 
        self.show_nums, self.num_start, self.num_step, attrs = parse_start_step(request, params)
154
 
 
155
 
    def format(self, formatter):
156
 
        _ = self.request.getText
157
 
        fmt = PygmentsFormatter(formatter, start_line=self.start_line)
158
 
 
159
 
        # adding line number anchors for process instruction lines
160
 
        for lineno in range(1, self.num_start + 1):
161
 
            fmt.result.append(formatter.line_anchordef(lineno))
162
 
 
163
 
        fmt.result.append(formatter.div(1, css_class="highlight %s" % self.syntax))
164
 
        self._code_id = hash_new('sha1', self.raw.encode(config.charset)).hexdigest()
165
 
        msg = None
166
 
        if self.filename is not None:
167
 
            try:
168
 
                lexer = pygments.lexers.get_lexer_for_filename(self.filename)
169
 
            except pygments.util.ClassNotFound:
170
 
                fmt.result.append(formatter.text(self.filename))
171
 
                lexer = pygments.lexers.TextLexer()
172
 
        else:
173
 
            try:
174
 
                lexer = pygments.lexers.get_lexer_by_name(self.syntax)
175
 
            except pygments.util.ClassNotFound:
176
 
                f = self.request.formatter
177
 
                url = ''.join([
178
 
                               f.url(1, href=Page(self.request, _("HelpOnParsers")).url(self.request, escape=0)),
179
 
                               _("HelpOnParsers"),
180
 
                               f.url(0)])
181
 
                msg = _("Syntax highlighting not supported for '%(syntax)s', see %(highlight_help_page)s.") % {"syntax": wikiutil.escape(self.syntax),
182
 
                                                                                                               "highlight_help_page": url
183
 
                                                                                                              }
184
 
                lexer = pygments.lexers.TextLexer()
185
 
 
186
 
        fmt.result.append(formatter.code_area(1, self._code_id, self.parsername, self.show_nums, self.num_start, self.num_step, msg))
187
 
        pygments.highlight(self.raw, lexer, fmt)
188
 
        fmt.result.append(formatter.code_area(0, self._code_id))
189
 
        fmt.result.append(formatter.div(0))
190
 
        self.request.write("".join(fmt.result))
191