~ubuntu-branches/ubuntu/raring/wxwidgets2.8/raring

« back to all changes in this revision

Viewing changes to wxPython/wx/tools/Editra/plugins/Launch/launch/handlers.py

  • Committer: Package Import Robot
  • Author(s): Stéphane Graber
  • Date: 2012-01-07 13:59:25 UTC
  • mfrom: (1.1.9) (5.1.10 sid)
  • Revision ID: package-import@ubuntu.com-20120107135925-2601miy9ullcon9j
Tags: 2.8.12.1-6ubuntu1
* Resync from Debian, changes that were kept:
  - debian/rules: re-enable mediactrl. This allows libwx_gtk2u_media-2.8 to be
    built, as this is required by some applications (LP: #632984)
  - debian/control: Build-dep on libxt-dev for mediactrl.
  - Patches
    + fix-bashism-in-example
* Add conflict on python-wxgtk2.8 (<< 2.8.12.1-6ubuntu1~) to python-wxversion
  to guarantee upgrade ordering when moving from pycentral to dh_python2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
"""
32
32
 
33
33
__author__ = "Cody Precord <cprecord@editra.org>"
34
 
__svnid__ = "$Id: handlers.py 63822 2010-04-02 00:57:27Z CJP $"
35
 
__revision__ = "$Revision: 63822 $"
 
34
__svnid__ = "$Id: handlers.py 67779 2011-05-23 21:12:48Z CJP $"
 
35
__revision__ = "$Revision: 67779 $"
36
36
 
37
 
__all__ = ['GetHandlerById', 'GetHandlerByName', 'GetState',
38
 
           'SetState', 'DEFAULT_HANDLER']
 
37
__all__ = ['GetHandlerById', 'GetHandlerByName', 'GetState', 'DEFAULT_HANDLER']
39
38
 
40
39
#-----------------------------------------------------------------------------#
41
40
# Imports
42
41
import os
43
42
import sys
44
43
import re
 
44
import copy
45
45
 
46
46
# Editra Libraries
47
 
import eclib.outbuff as outbuff
 
47
import util
 
48
import ebmlib
 
49
import eclib
48
50
import syntax.synglob as synglob
 
51
from profiler import Profile_Get, Profile_Set
49
52
 
50
53
# Local Imports
51
54
import launchxml
53
56
#-----------------------------------------------------------------------------#
54
57
# Globals
55
58
DEFAULT_HANDLER = 'handler'
 
59
CONFIG_KEY = 'Launch.Config2'
56
60
 
57
61
# Ansi escape sequence color table
58
62
# For coloring shell script output
97
101
# Public Handler Api for use outside this module
98
102
def GetHandlerById(lang_id):
99
103
    """Get a handler for the specified language id"""
100
 
    if lang_id in HANDLERS:
101
 
        return HANDLERS[lang_id]
102
 
    else:
103
 
        return HANDLERS[0]
 
104
    return FileTypeHandler.FactoryCreate(lang_id)
104
105
 
105
106
def GetHandlerByName(name):
106
107
    """Get an output handler by name"""
107
 
    for handler in HANDLERS.values():
108
 
        if name.lower() == handler.GetName().lower():
109
 
            return handler
110
 
    else:
111
 
        return HANDLERS[0]
 
108
    lang_id = synglob.GetIdFromDescription(name)
 
109
    return GetHandlerById(lang_id)
 
110
 
 
111
def GetUserSettings(name):
 
112
    """Get the user settings for a given file type
 
113
    @param name: file type name
 
114
 
 
115
    """
 
116
    data = Profile_Get(CONFIG_KEY, default=dict())
 
117
    val = data.get(name, tuple())
 
118
    return val
112
119
 
113
120
def InitCustomHandlers(path):
114
121
    """Init the custom handlers defined in the launch.xml file
119
126
    loaded = False
120
127
    path = os.path.join(path, u'launch.xml')
121
128
    if os.path.exists(path):
122
 
        lxml = launchxml.LaunchXml()
123
 
        lxml.SetPath(path)
124
 
        loaded = lxml.LoadFromDisk()
 
129
        lxml = None
 
130
        try:
 
131
            lxml = launchxml.LaunchXml.Load(path)
 
132
        except Exception, msg:
 
133
            # XML Parsing error
 
134
            util.Log("[Launch][err] Failed to load custom Handlers")
 
135
            util.Log("[Launch][err] XML Parsing Error: %s" % msg)
125
136
 
126
 
        if loaded:
127
 
            for hndlr in lxml.GetHandlers().values():
128
 
                HANDLERS[hndlr.GetLangId()] = XmlHandlerDelegate(hndlr)
 
137
        if lxml:
 
138
            for hndlr in lxml.GetHandlers():
 
139
                try:
 
140
                    FileTypeHandler.RegisterClass(XmlHandlerDelegate(hndlr))
 
141
                except Exception, msg:
 
142
                    util.Log("[Launch][err] Unexpected error in creating xml delegate")
 
143
                    util.Log("[Launch][err] %s" % msg)
129
144
    return loaded
130
145
 
131
146
def LoadCustomHandler(xml_str):
136
151
    """
137
152
    try:
138
153
        lxml = launchxml.LaunchXml()
139
 
        lxml.LoadFromString(xml_str)
140
 
        for hndlr in lxml.GetHandlers().values():
141
 
            HANDLERS[hndlr.GetLangId()] = XmlHandlerDelegate(hndlr)
 
154
        lxml.Xml = xml_str
 
155
        for hndlr in lxml.GetHandlers():
 
156
            FileTypeHandler.RegisterClass(XmlHandlerDelegate(hndlr))
142
157
    except:
143
158
        return False
144
159
    else:
145
160
        return True
146
161
 
147
 
def GetState():
148
 
    """Get a dictionary capturing the current state of all handlers
149
 
    @return: dict { handlername : (default, [commands]) }
150
 
 
151
 
    """
152
 
    rdict = dict()
153
 
    for handler in HANDLERS.values():
154
 
        rdict[handler.GetName()] = (handler.GetDefault(), handler.GetCommands())
155
 
    return rdict
156
 
 
157
 
def SetState(state):
158
 
    """Set the state of all handlers based on a dictionary of values
159
 
    @param state: dict { handlername : (default, [(alias, command), ]) }
160
 
 
161
 
    """
162
 
    for ftype, vals in state.iteritems():
163
 
        handler = GetHandlerByName(ftype)
164
 
        handler.SetCommands(vals[1])
165
 
        handler.SetDefault(vals)
166
 
 
167
162
#-----------------------------------------------------------------------------#
168
163
# Handler Base Class and Handler implementations
169
164
#
 
165
 
 
166
class Meta:
 
167
    """Metadata namespace, acts as a container object for all FileTypeHandler
 
168
    meta attributes.
 
169
    @see: HandlerMeta
 
170
 
 
171
    """
 
172
    _defaults = {"typeid" : -1,            # Editra Language ID
 
173
                 "name" : DEFAULT_HANDLER, # Language Display Name (derived from ID)
 
174
                 "commands" : dict(),      # Commands alias -> commandline
 
175
                 "default" : u"",          # Default command alias
 
176
                 "error" : None,           # Error regular expression
 
177
                 "hotspot" : None,         # Hotspot expression (line, filename)
 
178
                 "transient" : False}      # Transient configuration (bool)
 
179
    def __init__(self, meta_attrs):
 
180
        for (attr,default) in self._defaults.items():
 
181
            attr_val = meta_attrs.get(attr, default)
 
182
            setattr(self, attr, copy.copy(attr_val))
 
183
 
 
184
class HandlerMeta(type):
 
185
    """Metaclass for manipulating a handler classes metadata converts
 
186
    all user defined 'meta' classes to a Meta class with all unset attributes
 
187
    initialized to the default setting.
 
188
 
 
189
    """
 
190
    def __new__(mcls,name,bases,attrs):
 
191
        cls = super(HandlerMeta,mcls).__new__(mcls,name,bases,attrs)
 
192
        meta_attrs = {}
 
193
        if hasattr(cls, 'meta'):
 
194
            for attr in dir(cls.meta):
 
195
                if not attr.startswith("_"):
 
196
                    meta_attrs[attr] = getattr(cls.meta,attr)
 
197
        cls.meta = Meta(meta_attrs)
 
198
        return cls
 
199
 
 
200
#-----------------------------------------------------------------------------#
 
201
 
170
202
class FileTypeHandler(object):
171
203
    """Base default Output handler all output handlers should derive from
172
204
    this class. This base class is used when an output handler is request
173
205
    but no special one exists.
174
206
 
175
207
    """
 
208
    __metaclass__ = HandlerMeta
 
209
    handler_cache = dict()
 
210
 
176
211
    def __init__(self):
177
 
        object.__init__(self)
178
 
        self.commands = dict()
179
 
        self.default = ''
180
 
 
181
 
    __name__ = DEFAULT_HANDLER
182
 
 
183
 
    def AppendCommand(self, cmd):
 
212
        super(FileTypeHandler, self).__init__()
 
213
 
 
214
        if self.meta.typeid != -1:
 
215
            self.meta.name = synglob.GetDescriptionFromId(self.meta.typeid)
 
216
 
 
217
    @staticmethod
 
218
    def __ClassFactory(ftype):
 
219
        """Generate a new class for ones that don't have a
 
220
        specialized implementation.
 
221
        @return: new FileTypeHandler class
 
222
 
 
223
        """
 
224
        class DynamicHandler(FileTypeHandler):
 
225
            class meta:
 
226
                langid = ftype
 
227
                name = synglob.GetDescriptionFromId(ftype)
 
228
        return DynamicHandler
 
229
 
 
230
    @classmethod
 
231
    def FactoryCreate(cls, ftype):
 
232
        """Create an instance of a FileTypeHandler for the given
 
233
        file type. One of the two arguments must be provided. If
 
234
        both are provided the ftype argument will take preference.
 
235
        @keyword ftype: Editra file type ID
 
236
        @keyword name: File type description string
 
237
 
 
238
        """
 
239
        obj = cls.handler_cache.get(ftype, None)
 
240
        if obj is None:
 
241
            # Check existing custom subclasses for a proper implementation
 
242
            for handler in cls.__subclasses__():
 
243
                if ftype != -1 and handler.meta.typeid == ftype:
 
244
                    obj = handler
 
245
                    break
 
246
            else:
 
247
                # Dynamically create a new class
 
248
                obj = cls.__ClassFactory(ftype)
 
249
            cls.RegisterClass(obj)
 
250
        obj = obj()
 
251
 
 
252
        # Load custom settings for non-transient filetypes
 
253
        if not obj.meta.transient:
 
254
            data = GetUserSettings(obj.GetName())
 
255
            if len(data):
 
256
                obj.SetCommands(data[1])
 
257
                obj.SetDefault(data)
 
258
        return obj
 
259
 
 
260
    @classmethod
 
261
    def AppendCommand(cls, cmd):
184
262
        """Add a command to the list of commands known to this handler
185
263
        @param cmd: Tuple of (Command alias, executable path or name)
186
264
 
187
265
        """
188
266
        if isinstance(cmd, tuple):
189
 
            self.commands[cmd[0]] = cmd[1]
190
 
        else:
191
 
            # Bad data
192
 
            pass
193
 
 
194
 
    def GetAliases(self):
 
267
            cls.meta.commands[cmd[0]] = cmd[1]
 
268
 
 
269
    @classmethod
 
270
    def RegisterClass(cls, handler):
 
271
        """Register a filetype handler in the handler
 
272
        chain cache.
 
273
        @param handler: FileTypeHandler
 
274
 
 
275
        """
 
276
        cls.handler_cache[handler.meta.typeid] = handler
 
277
 
 
278
    @classmethod
 
279
    def GetAliases(cls):
195
280
        """Get the list of command aliases"""
196
 
        return sorted(self.commands.keys())
 
281
        return sorted(cls.meta.commands.keys())
197
282
 
198
 
    def GetCommand(self, alias):
 
283
    @classmethod
 
284
    def GetCommand(cls, alias):
199
285
        """Get the command for a given alias"""
200
 
        return self.commands.get(alias, alias)
 
286
        return cls.meta.commands.get(alias, alias)
201
287
 
202
 
    def GetCommands(self):
 
288
    @classmethod
 
289
    def GetCommands(cls):
203
290
        """Get the set of commands available for this file type"""
204
 
        return sorted(self.commands.items())
 
291
        return sorted(cls.meta.commands.items())
205
292
 
206
 
    def GetDefault(self):
 
293
    @classmethod
 
294
    def GetDefault(cls):
207
295
        """Get the preferred default command
208
296
        @return: string
209
297
 
210
298
        """
211
 
        return self.default
 
299
        return cls.meta.default
212
300
 
213
301
    def GetEnvironment(self):
214
302
        """Get the dictionary of environmental variables to run the
217
305
        """
218
306
        return dict(os.environ)
219
307
 
220
 
    def GetName(self):
 
308
    @classmethod
 
309
    def GetName(cls):
221
310
        """Get the name of this handler"""
222
 
        return self.__name__
 
311
        return cls.meta.name
223
312
 
224
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
 
313
    @classmethod
 
314
    def HandleHotSpot(cls, mainw, outbuffer, line, fname):
225
315
        """Handle hotspot clicks. Called when a hotspot is clicked
226
316
        in an output buffer of this file type.
227
317
        @param mainw: MainWindow instance that created the launch instance
231
321
                      contains the hotspot.
232
322
 
233
323
        """
234
 
        pass
 
324
        if cls.meta.hotspot is not None:
 
325
            ifile, line = _FindFileLine(outbuffer, line, fname,
 
326
                                        cls.meta.hotspot)
 
327
            _OpenToLine(ifile, line, mainw)
235
328
 
236
329
    def FilterInput(self, text):
237
330
        """Filter incoming text return the text to be displayed
240
333
        """
241
334
        return text
242
335
 
243
 
    def SetCommands(self, cmds):
 
336
    @classmethod
 
337
    def SetCommands(cls, cmds):
244
338
        """Set the list of commands known by the handler
245
339
        @param cmds: list of command tuples
246
340
 
247
341
        """
248
342
        if not isinstance(cmds, list):
249
 
            raise TypeError, "SetCommands expects a list of tuples"
 
343
            raise TypeError("SetCommands expects a list of tuples: %s" % repr(cmds))
250
344
        else:
251
345
            sdict = dict()
252
346
            for cmd in cmds:
253
347
                if len(cmd) == 2:
254
348
                    sdict[cmd[0]] = cmd[1]
255
 
 
256
 
            if len(sdict.keys()):
257
 
                self.commands.clear()
258
 
                self.commands.update(sdict)
 
349
            cls.meta.commands.clear()
 
350
            cls.meta.commands.update(sdict)
259
351
 
260
352
            # Reset default if it has been removed
261
 
            if self.default not in self.commands:
262
 
                keys = self.commands.keys()
 
353
            if cls.meta.default not in cls.meta.commands:
 
354
                keys = cls.meta.commands.keys()
263
355
                if len(keys):
264
 
                    self.default = keys[0]
 
356
                    cls.meta.default = keys[0]
 
357
                else:
 
358
                    cls.meta.default = u""
265
359
 
266
 
    def SetDefault(self, cmd):
267
 
        """Set the prefered default command
 
360
    @classmethod
 
361
    def SetDefault(cls, cmd):
 
362
        """Set the preferred default command
268
363
        @param cmd: Command alias/path tuple to set as the preferred one
269
364
        @postcondition: if cmd is not in the saved command list it will be
270
365
                        added to that list.
271
366
 
272
367
        """
273
368
        cmd = [ cmd[0].strip(), cmd[1] ]
274
 
        if cmd[0] not in self.GetAliases():
275
 
            self.AppendCommand(cmd)
276
 
        self.default = cmd[0]
277
 
 
278
 
    def StyleText(self, stc, start, txt):
 
369
        if cmd[0] not in cls.GetAliases():
 
370
            cls.AppendCommand(cmd)
 
371
        cls.meta.default = cmd[0]
 
372
 
 
373
    @classmethod
 
374
    def StoreState(cls):
 
375
        """Store the state of this handler"""
 
376
        if cls.meta.transient:
 
377
            util.Log("[Launch][info] Transient XML handler: settings will not persist")
 
378
            # TODO: update XML configuration file?
 
379
            return
 
380
        data = Profile_Get(CONFIG_KEY, default=dict())
 
381
        cdata = data.get(cls.GetName(), None)
 
382
        if data != cdata:
 
383
            util.Log("[Launch][info] Store config: %s" % cls.GetName())
 
384
            data[cls.GetName()] = (cls.meta.default, cls.meta.commands.items())
 
385
            Profile_Set(CONFIG_KEY, data)
 
386
 
 
387
    @classmethod
 
388
    def StyleText(cls, stc, start, txt):
 
389
        """Style Information and Error messages from script output."""
 
390
        if cls.meta.error is not None:
 
391
            sty = STYLE_NORMAL
 
392
            err, more = _StyleError(stc, start, txt, cls.meta.error)
 
393
            if err:
 
394
                err = STYLE_ERROR
 
395
            if more:
 
396
                sty = cls._StyleText(stc, start, txt)[0]
 
397
            sty = max(err, sty)
 
398
        else:
 
399
            sty, more = cls._StyleText(stc, start, txt)
 
400
        return sty, more
 
401
 
 
402
    @classmethod
 
403
    def _StyleText(cls, stc, start, txt):
279
404
        """Style the text in the given buffer
280
405
        @param stc: stc based buffer to apply styling to
281
406
        @param start: start of text that was just added to buffer
288
413
            sty_s = start + info.start()
289
414
            sty_e = start + info.end()
290
415
            stc.StartStyling(sty_s, 0xff)
291
 
            stc.SetStyling(sty_e - sty_s, outbuff.OPB_STYLE_INFO)
 
416
            stc.SetStyling(sty_e - sty_s, eclib.OPB_STYLE_INFO)
292
417
            finfo = True
293
418
 
294
419
        if finfo:
300
425
 
301
426
class AdaHandler(FileTypeHandler):
302
427
    """FileTypeHandler for Ada"""
303
 
    def __init__(self):
304
 
        FileTypeHandler.__init__(self)
305
 
        self.commands = {'gcc -c' : 'gcc -c'}
306
 
        self.default = 'gcc -c'
307
 
 
308
 
    __name__ = 'ada'
 
428
    class meta:
 
429
        typeid = synglob.ID_LANG_ADA
 
430
        commands = {'gcc -c' : 'gcc -c'}
 
431
        default = 'gcc -c'
309
432
 
310
433
#-----------------------------------------------------------------------------#
311
434
 
312
435
class BashHandler(FileTypeHandler):
313
436
    """FileTypeHandler for Bash scripts"""
314
 
    RE_BASH_ERROR = re.compile('(.+): line ([0-9]+): .*' + os.linesep)
315
 
 
316
 
    def __init__(self):
317
 
        FileTypeHandler.__init__(self)
318
 
        self.commands = dict(bash='bash')
319
 
        self.default = 'bash'
320
 
 
321
 
    __name__ = 'bash shell'
 
437
    class meta:
 
438
        typeid = synglob.ID_LANG_BASH
 
439
        commands = dict(bash='bash')
 
440
        error = re.compile('(.+): line ([0-9]+): .*' + os.linesep)
 
441
        hotspot = re.compile('(.+): line ([0-9]+): .*' + os.linesep)
322
442
 
323
443
    def FilterInput(self, txt):
324
444
        """Filter out ansi escape sequences from input"""
325
445
        txt = RE_ANSI_START.sub('', txt)
326
446
        return RE_ANSI_END.sub('', txt)
327
447
 
328
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
 
448
    @classmethod
 
449
    def HandleHotSpot(cls, mainw, outbuffer, line, fname):
329
450
        """Hotspots are error messages, find the file/line of the
330
451
        error in question and open the file to that point in the buffer.
331
452
 
332
453
        """
333
454
        txt = outbuffer.GetLine(line)
334
 
        match = BashHandler.RE_BASH_ERROR.findall(txt)
 
455
        match = cls.meta.hotspot.findall(txt)
335
456
        ifile = None
336
457
        if len(match):
337
458
            ifile = match[0][0].split()[-1]
347
468
 
348
469
        _OpenToLine(ifile, line, mainw)
349
470
 
350
 
    def StyleText(self, stc, start, txt):
351
 
        """Style NSIS output messages"""
352
 
        sty = STYLE_NORMAL
353
 
        err, more = _StyleError(stc, start, txt, BashHandler.RE_BASH_ERROR)
354
 
        if err:
355
 
            err = STYLE_ERROR
356
 
        if more:
357
 
            sty = super(BashHandler, self).StyleText(stc, start, txt)[0]
358
 
        return max(err, sty)
359
 
 
360
471
#-----------------------------------------------------------------------------#
361
472
 
362
473
class BatchHandler(FileTypeHandler):
363
474
    """FileTypeHandler for Dos batch files"""
364
 
    def __init__(self):
365
 
        FileTypeHandler.__init__(self)
366
 
        self.commands = dict(cmd='cmd /c')
367
 
        self.default = 'cmd'
368
 
 
369
 
    __name__ = 'Batch'
 
475
    class meta:
 
476
        typeid = synglob.ID_LANG_BATCH
 
477
        commands = dict(cmd='cmd /c')
 
478
        default = 'cmd'
370
479
 
371
480
#-----------------------------------------------------------------------------#
372
481
 
373
482
class BooHandler(FileTypeHandler):
374
483
    """FileTypeHandler for Boo"""
375
 
    def __init__(self):
376
 
        FileTypeHandler.__init__(self)
377
 
        self.commands = dict(booi='booi')
378
 
        self.default = 'booi'
379
 
 
380
 
    __name__ = 'boo'
 
484
    class meta:
 
485
        typeid = synglob.ID_LANG_BOO
 
486
        commands = dict(booi='booi')
 
487
        default = 'booi'
 
488
 
 
489
#-----------------------------------------------------------------------------#
 
490
 
 
491
class CHandler(FileTypeHandler):
 
492
    """FileTypeHandler for C Files"""
 
493
    class meta:
 
494
        typeid = synglob.ID_LANG_C
 
495
        commands = {'gcc -c' : 'gcc -c'}
 
496
        default = 'gcc -c'
 
497
 
 
498
class CPPHandler(FileTypeHandler):
 
499
    """FileTypeHandler for C++ Files"""
 
500
    class meta:
 
501
        typeid = synglob.ID_LANG_CPP
 
502
        commands = {'g++ -c' : 'g++ -c'}
 
503
        default = 'g++ -c'
381
504
 
382
505
#-----------------------------------------------------------------------------#
383
506
 
384
507
class CamlHandler(FileTypeHandler):
385
508
    """FileTypeHandler for Caml"""
386
 
    RE_CAML_ERROR = re.compile(r'File "(.+)", line (.+), characters .+:')
387
 
 
388
 
    def __init__(self):
389
 
        FileTypeHandler.__init__(self)
390
 
        self.commands = dict(ocaml='ocaml')
391
 
        self.default = 'ocaml'
392
 
 
393
 
    __name__ = 'Caml'
394
 
 
395
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
396
 
        """Hotspots are error messages, find the file/line of the
397
 
        error in question and open the file to that point in the buffer.
398
 
 
399
 
        """
400
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
401
 
                                    CamlHandler.RE_CAML_ERROR)
402
 
        _OpenToLine(ifile, line, mainw)
403
 
 
404
 
    def StyleText(self, stc, start, txt):
405
 
        """Style OCaml Information and Error messages from script output."""
406
 
        sty = STYLE_NORMAL
407
 
        err, more = _StyleError(stc, start, txt, CamlHandler.RE_CAML_ERROR)
408
 
        if err:
409
 
            err = STYLE_ERROR
410
 
        if more:
411
 
            sty = super(CamlHandler, self).StyleText(stc, start, txt)[0]
412
 
        return max(err, sty)
 
509
    class meta:
 
510
        typeid = synglob.ID_LANG_CAML
 
511
        commands = dict(ocaml='ocaml')
 
512
        error = re.compile(r'File "(.+)", line (.+), characters .+:')
 
513
        hotspot = re.compile(r'File "(.+)", line (.+), characters .+:')
413
514
 
414
515
#-----------------------------------------------------------------------------#
415
516
 
416
517
class CSHHandler(FileTypeHandler):
417
518
    """FileTypeHandler for C-Shell"""
418
 
    def __init__(self):
419
 
        FileTypeHandler.__init__(self)
420
 
        self.commands = dict(csh='csh')
421
 
        self.default = 'csh'
422
 
 
423
 
    __name__ = 'c shell'
 
519
    class meta:
 
520
        typeid = synglob.ID_LANG_CSH
 
521
        commands = dict(csh='csh')
 
522
        default = 'csh'
424
523
 
425
524
#-----------------------------------------------------------------------------#
426
525
 
427
526
class DHandler(FileTypeHandler):
428
527
    """FileTypeHandler for D"""
429
 
    def __init__(self):
430
 
        FileTypeHandler.__init__(self)
431
 
        self.commands = dict(dmd='dmd -run')
432
 
        self.default = 'dmd'
433
 
 
434
 
    __name__ = 'd'
 
528
    class meta:
 
529
        typeid = synglob.ID_LANG_D
 
530
        commands = dict(dmd='dmd -run')
 
531
        default = 'dmd'
435
532
 
436
533
#-----------------------------------------------------------------------------#
437
534
 
438
535
class FeriteHandler(FileTypeHandler):
439
536
    """FileTypeHandler for Ferite"""
440
 
    def __init__(self):
441
 
        FileTypeHandler.__init__(self)
442
 
        self.commands = dict(ferite='ferite')
443
 
        self.default = 'ferite'
444
 
 
445
 
    __name__ = 'ferite'
 
537
    class meta:
 
538
        typeid = synglob.ID_LANG_FERITE
 
539
        commands = dict(ferite='ferite')
 
540
        default = 'ferite'
446
541
 
447
542
#-----------------------------------------------------------------------------#
448
543
 
449
544
class HaskellHandler(FileTypeHandler):
450
545
    """FileTypeHandler for Haskell"""
451
 
    RE_HASKELL_ERROR = re.compile('(.+):(.+):[0-9]+:.+ error .+')
452
 
 
453
 
    def __init__(self):
454
 
        FileTypeHandler.__init__(self)
455
 
        self.commands = {'ghc --make' : 'ghc --make'}
456
 
        self.default = 'ghc --make'
457
 
 
458
 
    __name__ = 'haskell'
459
 
 
460
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
461
 
        """Hotspots are error messages, find the file/line of the
462
 
        error in question and open the file to that point in the buffer.
463
 
 
464
 
        """
465
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
466
 
                                    HaskellHandler.RE_HASKELL_ERROR)
467
 
        _OpenToLine(ifile, line, mainw)
468
 
 
469
 
    def StyleText(self, stc, start, txt):
470
 
        """Style GHC Information and Error messages from script output."""
471
 
        sty = STYLE_NORMAL
472
 
        err, more = _StyleError(stc, start, txt, HaskellHandler.RE_HASKELL_ERROR)
473
 
        if err:
474
 
            err = STYLE_ERROR
475
 
        if more:
476
 
            sty = super(HaskellHandler, self).StyleText(stc, start, txt)[0]
477
 
        return max(err, sty)
 
546
    class meta:
 
547
        typeid = synglob.ID_LANG_HASKELL
 
548
        commands = {'ghc --make' : 'ghc --make'}
 
549
        default = 'ghc --make'
 
550
        error = re.compile('(.+):(.+):[0-9]+:.+ error .+')
 
551
        hotspot = re.compile('(.+):(.+):[0-9]+:.+ error .+')
478
552
 
479
553
#-----------------------------------------------------------------------------#
480
554
 
481
555
class HaxeHandler(FileTypeHandler):
482
556
    """FileTypeHandler for haXe"""
483
 
    RE_HAXE_ERROR = re.compile('([a-zA-Z_.]+)\(([0-9]+)\):.*')
484
 
 
485
 
    def __init__(self):
486
 
        FileTypeHandler.__init__(self)
487
 
        self.commands = dict(neko='neko', nekoc='nekoc')
488
 
        self.default = 'nekoc'
489
 
 
490
 
    __name__ = 'haxe'
491
 
 
492
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
493
 
        """Hotspots are error messages, find the file/line of the
494
 
        error in question and open the file to that point in the buffer.
495
 
 
496
 
        """
497
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
498
 
                                    HaxeHandler.RE_HAXE_ERROR)
499
 
        _OpenToLine(ifile, line, mainw)
500
 
 
501
 
    def StyleText(self, stc, start, txt):
502
 
        """Style haXe output messages"""
503
 
        sty = STYLE_NORMAL
504
 
        err, more = _StyleError(stc, start, txt, HaxeHandler.RE_HAXE_ERROR)
505
 
        if err:
506
 
            err = STYLE_ERROR
507
 
        if more:
508
 
            sty = super(HaxeHandler, self).StyleText(stc, start, txt)[0]
509
 
        return max(err, sty)
 
557
    class meta:
 
558
        typeid = synglob.ID_LANG_HAXE
 
559
        commands = dict(neko='neko', nekoc='nekoc')
 
560
        default = 'nekoc'
 
561
        error = re.compile('([a-zA-Z_.]+)\(([0-9]+)\):.*')
 
562
        hotspot = re.compile('([a-zA-Z_.]+)\(([0-9]+)\):.*')
510
563
 
511
564
#-----------------------------------------------------------------------------#
512
565
 
513
566
class HTMLHandler(FileTypeHandler):
514
567
    """FileTypeHandler for HTML"""
515
 
    def __init__(self):
516
 
        FileTypeHandler.__init__(self)
 
568
    class meta:
 
569
        typeid = synglob.ID_LANG_HTML
517
570
        if u'darwin' in sys.platform:
518
 
            self.commands = dict(Safari='open -a Safari.app',
519
 
                                 Camino='open -a Camino.app',
520
 
                                 Firefox='open -a Firefox.app',
521
 
                                 Opera='open -a Opera.app')
522
 
            self.default = 'Safari'
 
571
            commands = dict(Safari='open -a Safari.app',
 
572
                            Camino='open -a Camino.app',
 
573
                            Firefox='open -a Firefox.app',
 
574
                            Opera='open -a Opera.app')
 
575
            default = 'Safari'
523
576
        elif sys.platform.startswith('win'):
524
 
            self.commands = dict(ie='iexplorer.exe',
525
 
                                 firefox='firefox.exe',
526
 
                                 opera='opera.exe')
527
 
            self.default = 'ie'
 
577
            commands = dict(ie='iexplorer.exe',
 
578
                             firefox='firefox.exe',
 
579
                             opera='opera.exe')
 
580
            default = 'ie'
528
581
        else:
529
 
            self.commands = dict(firefox='firefox',
530
 
                                 opera='opera')
531
 
            self.default = 'firefox'
532
 
 
533
 
    __name__ = 'html'
 
582
            commands = dict(firefox='firefox', opera='opera')
 
583
            default = 'firefox'
534
584
 
535
585
#-----------------------------------------------------------------------------#
536
586
 
537
587
class InnoSetupHandler(FileTypeHandler):
538
588
    """FileTypeHandler for Inno Setup Scripts"""
539
 
    def __init__(self):
540
 
        FileTypeHandler.__init__(self)
541
 
        self.commands = dict(iscc='iscc.exe', Compil32='Compil32.exe /cc')
542
 
        self.default = 'iscc'
543
 
 
544
 
    __name__ = 'inno setup script'
 
589
    class meta:
 
590
        typeid = synglob.ID_LANG_INNO
 
591
        commands = dict(iscc='iscc.exe', Compil32='Compil32.exe /cc')
 
592
        default = 'iscc'
545
593
 
546
594
#-----------------------------------------------------------------------------#
547
595
 
548
596
class KornHandler(FileTypeHandler):
549
597
    """FileTypeHandler for Korn Shell scripts"""
550
 
    def __init__(self):
551
 
        FileTypeHandler.__init__(self)
552
 
        self.commands = dict(ksh='ksh')
553
 
        self.default = 'ksh'
554
 
 
555
 
    __name__ = 'korn shell'
 
598
    class meta:
 
599
        typeid = synglob.ID_LANG_KSH
 
600
        commands = dict(ksh='ksh')
 
601
        default = 'ksh'
556
602
 
557
603
#-----------------------------------------------------------------------------#
558
604
 
559
605
class STATAHandler(FileTypeHandler):
560
606
    """FileTypeHandler for Stata"""
561
 
    def __init__(self):
562
 
        FileTypeHandler.__init__(self)
563
 
        self.commands = dict(stata='stata', xstata='xstata')
564
 
        self.default = 'stata'
565
 
 
566
 
    __name__ = 'Stata'
 
607
    class meta:
 
608
        typeid = synglob.ID_LANG_STATA
 
609
        commands = dict(stata='stata', xstata='xstata')
 
610
        default = 'stata'
567
611
 
568
612
#-----------------------------------------------------------------------------#
569
613
 
570
614
class LatexHandler(FileTypeHandler):
571
615
    """FileTypeHandler for LaTex"""
572
 
    def __init__(self):
573
 
        FileTypeHandler.__init__(self)
574
 
        self.commands = dict(latex='latex', dvips='dvips',
575
 
                             pdflatex='pdflatex', ps2pdf='ps2pdf',
576
 
                             dvipng='dvipng', latex2html='latex2html')
577
 
        self.default = 'latex'
578
 
 
579
 
    __name__ = 'LaTex'
 
616
    class meta:
 
617
        typeid = synglob.ID_LANG_LATEX
 
618
        commands = dict(latex='latex', dvips='dvips',
 
619
                        pdflatex='pdflatex', ps2pdf='ps2pdf',
 
620
                        dvipng='dvipng', latex2html='latex2html')
 
621
        default = 'latex'
580
622
 
581
623
#-----------------------------------------------------------------------------#
582
624
 
583
625
class LuaHandler(FileTypeHandler):
584
626
    """FileTypeHandler for Lua"""
585
 
    RE_LUA_ERROR = re.compile('.*: (.+):([0-9]+):.*')
586
 
 
587
 
    def __init__(self):
588
 
        FileTypeHandler.__init__(self)
589
 
        self.commands = dict(lua='lua', luac='luac')
590
 
        self.default = 'lua'
591
 
 
592
 
    __name__ = 'lua'
593
 
 
594
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
595
 
        """Hotspots are error messages, find the file/line of the
596
 
        error in question and open the file to that point in the buffer.
597
 
 
598
 
        """
599
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
600
 
                                    LuaHandler.RE_LUA_ERROR)
601
 
        _OpenToLine(ifile, line, mainw)
602
 
 
603
 
    def StyleText(self, stc, start, txt):
604
 
        """Style NSIS output messages"""
605
 
        sty = STYLE_NORMAL
606
 
        err, more = _StyleError(stc, start, txt, LuaHandler.RE_LUA_ERROR)
607
 
        if err:
608
 
            err = STYLE_ERROR
609
 
        if more:
610
 
            sty = super(LuaHandler, self).StyleText(stc, start, txt)[0]
611
 
        return max(err, sty)
 
627
    class meta:
 
628
        typeid = synglob.ID_LANG_LUA
 
629
        commands = dict(lua='lua', luac='luac')
 
630
        default = 'lua'
 
631
        error = re.compile('.*: (.+):([0-9]+):.*')
 
632
        hotspot = re.compile('.*: (.+):([0-9]+):.*')
612
633
 
613
634
#-----------------------------------------------------------------------------#
614
635
 
615
636
class NewLispHandler(FileTypeHandler):
616
637
    """FileTypeHandler for newLisp"""
617
 
 
618
 
    def __init__(self):
619
 
        FileTypeHandler.__init__(self)
620
 
        self.commands = dict(newlisp='newlisp')
621
 
        self.default = 'newlisp'
622
 
 
623
 
    __name__ = 'newlisp'
 
638
    class meta:
 
639
        typeid = synglob.ID_LANG_NEWLISP
 
640
        commands = dict(newlisp='newlisp')
 
641
        default = 'newlisp'
624
642
 
625
643
#-----------------------------------------------------------------------------#
626
644
 
627
645
class NSISHandler(FileTypeHandler):
628
646
    """FileTypeHandler for NSIS scripts"""
629
 
    RE_NSIS_ERROR = re.compile(r'Error .* "(.+)" on line ([0-9]+) ')
630
 
 
631
 
    def __init__(self):
632
 
        FileTypeHandler.__init__(self)
633
 
        self.commands = dict(makensis='makensis')
634
 
        self.default = 'makensis'
635
 
 
636
 
    __name__ = 'nsis'
637
 
 
638
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
639
 
        """Hotspots are error messages, find the file/line of the
640
 
        error in question and open the file to that point in the buffer.
641
 
 
642
 
        """
643
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
644
 
                                    NSISHandler.RE_NSIS_ERROR)
645
 
        _OpenToLine(ifile, line, mainw)
646
 
 
647
 
    def StyleText(self, stc, start, txt):
648
 
        """Style NSIS output messages"""
649
 
        sty = STYLE_NORMAL
650
 
        err, more = _StyleError(stc, start, txt, NSISHandler.RE_NSIS_ERROR)
651
 
        if err:
652
 
            err = STYLE_ERROR
653
 
        if more:
654
 
            sty = super(NSISHandler, self).StyleText(stc, start, txt)[0]
655
 
        return max(err, sty)
 
647
    class meta:
 
648
        typeid = synglob.ID_LANG_NSIS
 
649
        commands = dict(makensis='makensis')
 
650
        default = 'makensis'
 
651
        error = re.compile(r'Error .* "(.+)" on line ([0-9]+) ')
 
652
        hotspot = re.compile(r'Error .* "(.+)" on line ([0-9]+) ')
656
653
 
657
654
#-----------------------------------------------------------------------------#
658
655
 
659
656
class PhpHandler(FileTypeHandler):
660
657
    """FileTypeHandler for Php"""
661
 
    RE_PHP_ERROR = re.compile(r'[a-zA-Z]+ error: .* in (.+) on line ([0-9]+).*')
662
 
 
663
 
    def __init__(self):
664
 
        FileTypeHandler.__init__(self)
665
 
        self.commands = dict(php='php -f')
666
 
        self.default = 'php'
667
 
 
668
 
    __name__ = 'php'
669
 
 
670
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
671
 
        """Hotspots are error messages, find the file/line of the
672
 
        error in question and open the file to that point in the buffer.
673
 
 
674
 
        """
675
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
676
 
                                    PhpHandler.RE_PHP_ERROR)
677
 
        _OpenToLine(ifile, line, mainw)
678
 
 
679
 
    def StyleText(self, stc, start, txt):
680
 
        """Style php Information and Error messages from script
681
 
        output.
682
 
 
683
 
        """
684
 
        sty = STYLE_NORMAL
685
 
        err, more = _StyleError(stc, start, txt, PhpHandler.RE_PHP_ERROR)
686
 
        if err:
687
 
            err = STYLE_ERROR
688
 
        if more:
689
 
            sty = super(PhpHandler, self).StyleText(stc, start, txt)[0]
690
 
        return max(sty, err)
 
658
    class meta:
 
659
        typeid = synglob.ID_LANG_PHP
 
660
        commands = dict(php='php -f')
 
661
        default = 'php'
 
662
        error = re.compile(r'[a-zA-Z]+ error: .* in (.+) on line ([0-9]+).*')
 
663
        hotspot = re.compile(r'[a-zA-Z]+ error: .* in (.+) on line ([0-9]+).*')
691
664
 
692
665
#-----------------------------------------------------------------------------#
693
666
 
694
667
class PikeHandler(FileTypeHandler):
695
668
    """FileTypeHandler for Pike"""
696
 
    def __init__(self):
697
 
        FileTypeHandler.__init__(self)
698
 
        self.commands = dict(pike='pike')
699
 
        self.default = 'pike'
700
 
 
701
 
    __name__ = 'pike'
 
669
    class meta:
 
670
        typeid = synglob.ID_LANG_PIKE
 
671
        commands = dict(pike='pike')
 
672
        default = 'pike'
702
673
 
703
674
#-----------------------------------------------------------------------------#
704
675
 
705
676
class PerlHandler(FileTypeHandler):
706
677
    """FileTypeHandler for Perl scripts"""
707
 
    RE_PERL_ERROR = re.compile(r'.+ at (.+) line ([0-9]+)[,\.].*')
708
 
 
709
 
    def __init__(self):
710
 
        FileTypeHandler.__init__(self)
711
 
        self.commands = dict(perl='perl')
712
 
        self.default = 'perl'
713
 
 
714
 
    __name__ = 'perl'
715
 
 
716
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
717
 
        """Hotspots are error messages, find the file/line of the
718
 
        error in question and open the file to that point in the buffer.
719
 
 
720
 
        """
721
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
722
 
                                    PerlHandler.RE_PERL_ERROR)
723
 
        _OpenToLine(ifile, line, mainw)
724
 
 
725
 
    def StyleText(self, stc, start, txt):
726
 
        """Style perl Information and Error messages from script
727
 
        output.
728
 
 
729
 
        """
730
 
        sty = STYLE_NORMAL
731
 
        err, more = _StyleError(stc, start, txt, PerlHandler.RE_PERL_ERROR)
732
 
        if err:
733
 
            err = STYLE_ERROR
734
 
        if more:
735
 
            sty = super(PerlHandler, self).StyleText(stc, start, txt)[0]
736
 
        return max(err, sty)
 
678
    class meta:
 
679
        typeid = synglob.ID_LANG_PERL
 
680
        commands = dict(perl='perl')
 
681
        default = 'perl'
 
682
        hotspot = re.compile(r'.+ at (.+) line ([0-9]+)[,\.].*')
737
683
 
738
684
#-----------------------------------------------------------------------------#
739
685
 
740
686
class PostScriptHandler(FileTypeHandler):
741
687
    """FileTypeHandler for Post/GhostScript"""
742
 
    def __init__(self):
743
 
        FileTypeHandler.__init__(self)
 
688
    class meta:
 
689
        typeid = synglob.ID_LANG_PS
744
690
        if sys.platform.startswith('win'):
745
 
            self.commands = dict(gswin32c='gswin32c')
746
 
            self.default = 'gs2in32c'
 
691
            commands = dict(gswin32c='gswin32c')
 
692
            default = 'gs2in32c'
747
693
        elif 'darwin' in sys.platform:
748
 
            self.commands = dict(pstopdf='pstopdf')
749
 
            self.default = 'pstopdf'
 
694
            commands = dict(pstopdf='pstopdf')
 
695
            default = 'pstopdf'
750
696
        else:
751
 
            self.commands = dict(gs='gs')
752
 
            self.default = 'gs'
753
 
 
754
 
    __name__ = 'postscript'
 
697
            commands = dict(gs='gs')
 
698
            default = 'gs'
755
699
 
756
700
#-----------------------------------------------------------------------------#
757
701
 
758
702
class PythonHandler(FileTypeHandler):
759
703
    """FileTypeHandler for Python"""
760
 
    RE_PY_ERROR = re.compile('File "(.+)", line ([0-9]+)') # Python Exceptions
761
704
    RE_PL_ERR = re.compile(r'\s*([REWCF]):\s*([0-9]+):.*') # Pylint Output
762
705
 
763
 
    def __init__(self):
764
 
        FileTypeHandler.__init__(self)
765
 
        self.commands = dict(python='python -u', pylint='pylint',
 
706
    class meta:
 
707
        typeid = synglob.ID_LANG_PYTHON
 
708
        commands = dict(python='python -u', pylint='pylint',
766
709
                             pylinterr='pylint -e')
767
 
        self.default = 'python'
768
 
 
769
 
    __name__ = 'python'
 
710
        default = 'python'
 
711
        error = re.compile('File "(.+)", line ([0-9]+)')
 
712
        hotspot = re.compile('File "(.+)", line ([0-9]+)')
770
713
 
771
714
    def GetEnvironment(self):
772
715
        """Get the environment to run the python script in"""
778
721
        proc_env['PYTHONUNBUFFERED'] = '1'
779
722
        return proc_env
780
723
 
781
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
 
724
    @classmethod
 
725
    def HandleHotSpot(cls, mainw, outbuffer, line, fname):
782
726
        """Hotspots are error messages, find the file/line of the
783
727
        error in question and open the file to that point in the buffer.
784
728
 
788
732
            eline = max(0, int(match.group(2)) - 1)
789
733
            _OpenToLine(fname, eline, mainw)
790
734
        else:
791
 
            ifile, line = _FindFileLine(outbuffer, line, fname,
792
 
                                        PythonHandler.RE_PY_ERROR)
793
 
            _OpenToLine(ifile, line, mainw)
794
 
 
795
 
    def StyleText(self, stc, start, txt):
796
 
        """Style python Information and Error messages from script
797
 
        output.
798
 
 
799
 
        """
800
 
        sty = STYLE_NORMAL
801
 
        err, more = _StyleError(stc, start, txt, PythonHandler.RE_PY_ERROR)
802
 
        if more:
803
 
            sty, more = _StyleError(stc, start, txt, PythonHandler.RE_PL_ERR)
804
 
 
805
 
        if not err:
806
 
            err = sty
807
 
 
808
 
        if err:
809
 
            err = STYLE_ERROR
810
 
        if more:
811
 
            sty = super(PythonHandler, self).StyleText(stc, start, txt)[0]
812
 
        return max(err, sty)
 
735
            super(PythonHandler, cls).HandleHotSpot(mainw, outbuffer, line, fname)
813
736
 
814
737
#-----------------------------------------------------------------------------#
815
738
 
816
739
class RHandler(FileTypeHandler):
817
740
    """FileTypeHandler for R"""
818
 
    def __init__(self):
819
 
        FileTypeHandler.__init__(self)
820
 
        self.commands = {'r' : 'R',
821
 
                         'Rterm' : 'Rterm',
822
 
                         'Rgui' : 'Rgui',
823
 
                         'Rscript' : 'Rscript'}
824
 
        self.default = 'Rscript'
825
 
 
826
 
    __name__ = 'R'
 
741
    class meta:
 
742
        typeid = synglob.ID_LANG_R
 
743
        commands = {'r' : 'R', 'Rterm' : 'Rterm', 
 
744
                    'Rgui' : 'Rgui', 'Rscript' : 'Rscript'}
 
745
        default = 'Rscript'
827
746
 
828
747
#-----------------------------------------------------------------------------#
829
748
 
830
749
class RubyHandler(FileTypeHandler):
831
750
    """FileTypeHandler for Ruby scripts"""
832
 
    RE_RUBY_ERROR = re.compile('(.+):([0-9]+)[:]{0,1}.*')
833
 
 
834
 
    def __init__(self):
835
 
        FileTypeHandler.__init__(self)
836
 
        self.commands = dict(ruby='ruby')
837
 
        self.default = 'ruby'
838
 
 
839
 
    __name__ = 'ruby'
840
 
 
841
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
842
 
        """Hotspots are error messages, find the file/line of the
843
 
        error in question and open the file to that point in the buffer.
844
 
 
845
 
        """
846
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
847
 
                                    RubyHandler.RE_RUBY_ERROR)
848
 
        _OpenToLine(ifile, line, mainw)
849
 
 
850
 
    def StyleText(self, stc, start, txt):
851
 
        """Style NSIS output messages"""
852
 
        sty = STYLE_NORMAL
853
 
        err, more = _StyleError(stc, start, txt, RubyHandler.RE_RUBY_ERROR)
854
 
        if err:
855
 
            err = STYLE_ERROR
856
 
        if more:
857
 
            sty = super(RubyHandler, self).StyleText(stc, start, txt)[0]
858
 
        return max(err, sty)
 
751
    class meta:
 
752
        typeid = synglob.ID_LANG_RUBY
 
753
        commands = dict(ruby='ruby')
 
754
        default = 'ruby'
 
755
        error = re.compile('(.+):([0-9]+)[:]{0,1}.*')
 
756
        hotspot = re.compile('(.+):([0-9]+)[:]{0,1}.*')
859
757
 
860
758
#-----------------------------------------------------------------------------#
861
759
 
862
760
class TCLHandler(FileTypeHandler):
863
761
    """FileTypeHandler for TCL/TK"""
864
 
    RE_TCL_ERROR = re.compile('\(file "(.+)" line ([0-9]+)\)')
865
 
 
866
 
    def __init__(self):
867
 
        FileTypeHandler.__init__(self)
868
 
        self.commands = dict(wish='wish')
869
 
        self.default = 'wish'
870
 
 
871
 
    __name__ = 'tcl/tk'
872
 
 
873
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
 
762
    class meta:
 
763
        typeid = synglob.ID_LANG_TCL
 
764
        commands = dict(wish='wish')
 
765
        default = 'wish'
 
766
        error = re.compile('\(file "(.+)" line ([0-9]+)\)')
 
767
        hotspot = re.compile('\(file "(.+)" line ([0-9]+)\)')
 
768
 
 
769
    @classmethod
 
770
    def HandleHotSpot(cls, mainw, outbuffer, line, fname):
874
771
        """Hotspots are error messages, find the file/line of the
875
772
        error in question and open the file to that point in the buffer.
876
773
 
877
774
        """
878
775
        txt = outbuffer.GetLine(line)
879
 
        match = TCLHandler.RE_TCL_ERROR.findall(txt)
 
776
        match = cls.meta.hotspot.findall(txt)
880
777
        ifile = None
881
778
        if len(match):
882
779
            ifile = match[0][0]
892
789
 
893
790
        _OpenToLine(ifile, line, mainw)
894
791
 
895
 
    def StyleText(self, stc, start, txt):
896
 
        """Style TCL output messages"""
897
 
        sty = STYLE_NORMAL
898
 
        err, more = _StyleError(stc, start, txt, TCLHandler.RE_TCL_ERROR)
899
 
        if err:
900
 
            err = STYLE_ERROR
901
 
        if more:
902
 
            sty = super(TCLHandler, self).StyleText(stc, start, txt)[0]
903
 
        return max(err, sty)
904
 
 
905
792
#-----------------------------------------------------------------------------#
906
793
 
907
794
class VBScriptHandler(FileTypeHandler):
908
795
    """FileTypeHandler for VBScript"""
909
 
    RE_VBS_ERROR = re.compile('(.+)\(([0-9]+).*' + os.linesep)
910
 
 
911
 
    def __init__(self):
912
 
        FileTypeHandler.__init__(self)
913
 
        self.commands = dict(cscript='CSCRIPT.exe', wscript='WSCRIPT.exe')
914
 
        self.default = 'cscript'
915
 
 
916
 
    __name__ = 'VBScript'
917
 
 
918
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
919
 
        """Hotspots are error messages, find the file/line of the
920
 
        error in question and open the file to that point in the
921
 
        buffer.
922
 
 
923
 
        """
924
 
        ifile, line = _FindFileLine(outbuffer, line, fname,
925
 
                                    VBScriptHandler.RE_VBS_ERROR)
926
 
        _OpenToLine(ifile, line, mainw)
927
 
 
928
 
    def StyleText(self, stc, start, txt):
929
 
        """Style VBScript Information and Error messages from script output."""
930
 
        sty = STYLE_NORMAL
931
 
        err, more = _StyleError(stc, start, txt, VBScriptHandler.RE_VBS_ERROR)
932
 
        if err:
933
 
            err = STYLE_ERROR
934
 
        if more:
935
 
            sty = super(VBScriptHandler, self).StyleText(stc, start, txt)[0]
936
 
        return max(err, sty)
 
796
    class meta:
 
797
        typeid = synglob.ID_LANG_VBSCRIPT
 
798
        commands = dict(cscript='CSCRIPT.exe', wscript='WSCRIPT.exe')
 
799
        default = 'cscript'
 
800
        error = re.compile('(.+)\(([0-9]+).*' + os.linesep)
 
801
        hotspot = re.compile('(.+)\(([0-9]+).*' + os.linesep)
937
802
 
938
803
#-----------------------------------------------------------------------------#
939
804
 
940
 
class XmlHandlerDelegate(FileTypeHandler):
941
 
    """Delegate class for creating new filetype handlers from a Launch
 
805
def XmlHandlerDelegate(xmlobj):
 
806
    """Create delegate class for creating new filetype handlers from a Launch
942
807
    Xml object.
 
808
    @param xmlobj: launchxml.Handler
943
809
 
944
810
    """
945
 
    def __init__(self, xmlobj):
946
 
        """Create the object from the Launch XML Object"""
947
 
        FileTypeHandler.__init__(self)
948
 
 
949
 
        # Attributes
950
 
        self._xml = xmlobj
951
 
        self._errpat = self._xml.GetErrorPattern()
952
 
        self._hotspot = self._xml.GetHotSpotPattern()
953
 
 
954
 
        # FileTypeHandler implementation
955
 
        self.commands = self._xml.GetCommands()
956
 
        self.default = self._xml.GetDefaultCommand()
957
 
        self._name = self._xml.GetLang()
958
 
 
959
 
    @property
960
 
    def __name__(self):
961
 
        return self._name
962
 
 
963
 
    def HandleHotSpot(self, mainw, outbuffer, line, fname):
964
 
        """Handle hotspot navigation if it has been defined by the custom
965
 
        handler.
966
 
 
967
 
        """
968
 
        if self._hotspot is not None:
969
 
            ifile, line = _FindFileLine(outbuffer, line, fname, self._hotspot)
970
 
            _OpenToLine(ifile, line, mainw)
971
 
        else:
972
 
            return None
973
 
 
974
 
    def StyleText(self, stc, start, txt):
975
 
        """Highlight text if an error pattern was defined."""
976
 
        sty = STYLE_NORMAL
977
 
        err = STYLE_NORMAL
978
 
        if self._errpat is not None:
979
 
            err, more = _StyleError(stc, start, txt, self._errpat)
980
 
            if err:
981
 
                err = STYLE_ERROR
982
 
            if more:
983
 
                sty = super(XmlHandlerDelegate, self).StyleText(stc, start, txt)[0]
984
 
        return max(err, sty)
985
 
 
986
 
#-----------------------------------------------------------------------------#
987
 
# Handler Object Dictionary
988
 
# Create an instance of each Handler to use as a persistent object
989
 
HANDLERS = { 0                      : FileTypeHandler(), # Null Handler
990
 
            synglob.ID_LANG_ADA     : AdaHandler(),
991
 
            synglob.ID_LANG_BASH    : BashHandler(),
992
 
            synglob.ID_LANG_BATCH   : BatchHandler(),
993
 
            synglob.ID_LANG_BOO     : BooHandler(),
994
 
            synglob.ID_LANG_CAML    : CamlHandler(),
995
 
            synglob.ID_LANG_CSH     : CSHHandler(),
996
 
            synglob.ID_LANG_D       : DHandler(),
997
 
            synglob.ID_LANG_FERITE  : FeriteHandler(),
998
 
            synglob.ID_LANG_KSH     : KornHandler(),
999
 
            synglob.ID_LANG_HASKELL : HaskellHandler(),
1000
 
            synglob.ID_LANG_HAXE    : HaxeHandler(),
1001
 
            synglob.ID_LANG_HTML    : HTMLHandler(),
1002
 
            synglob.ID_LANG_INNO    : InnoSetupHandler(),
1003
 
            synglob.ID_LANG_LATEX   : LatexHandler(),
1004
 
            synglob.ID_LANG_STATA   : STATAHandler(),
1005
 
            synglob.ID_LANG_LUA     : LuaHandler(),
1006
 
            synglob.ID_LANG_NEWLISP : NewLispHandler(),
1007
 
            synglob.ID_LANG_NSIS    : NSISHandler(),
1008
 
            synglob.ID_LANG_PERL    : PerlHandler(),
1009
 
            synglob.ID_LANG_PHP     : PhpHandler(),
1010
 
            synglob.ID_LANG_PIKE    : PikeHandler(),
1011
 
            synglob.ID_LANG_PS      : PostScriptHandler(),
1012
 
            synglob.ID_LANG_PYTHON  : PythonHandler(),
1013
 
            synglob.ID_LANG_R       : RHandler(),
1014
 
            synglob.ID_LANG_RUBY    : RubyHandler(),
1015
 
            synglob.ID_LANG_TCL     : TCLHandler(),
1016
 
            synglob.ID_LANG_VBSCRIPT : VBScriptHandler() }
 
811
    class XmlDelegateClass(FileTypeHandler):
 
812
        class meta:
 
813
            typeid = getattr(synglob, xmlobj.id, -1)
 
814
            name = xmlobj.name
 
815
            commands = xmlobj.GetCommands()
 
816
            default = xmlobj.GetDefaultCommand()
 
817
            error = xmlobj.GetErrorPattern()
 
818
            hotspot = xmlobj.GetHotspotPattern()
 
819
            transient = True
 
820
    return XmlDelegateClass
1017
821
 
1018
822
#-----------------------------------------------------------------------------#
1019
823
# Local utility functions
1055
859
    @param mainw: MainWindow instance to open the file in
1056
860
 
1057
861
    """
 
862
    fname = os.path.abspath(fname) # Normalize path
1058
863
    nbook = mainw.GetNotebook()
1059
864
    buffers = [ page.GetFileName() for page in nbook.GetTextControls() ]
1060
 
    if fname in buffers:
1061
 
        page = buffers.index(fname)
1062
 
        nbook.ChangePage(page)
1063
 
        nbook.GetPage(page).GotoLine(line)
 
865
    for page, name in enumerate(buffers):
 
866
        if ebmlib.ComparePaths(fname, name):
 
867
            nbook.ChangePage(page)
 
868
            nbook.GetPage(page).GotoLine(line)
 
869
            break
1064
870
    else:
1065
871
        nbook.OnDrop([fname])
1066
872
        nbook.GetPage(nbook.GetSelection()).GotoLine(line)
1067
873
 
1068
874
def _StyleError(stc, start, txt, regex):
1069
875
    """Style Error message groups
1070
 
    @param stc: outputbuffer reference
 
876
    @param stc: OutputBuffer reference
1071
877
    @param start: start of text just added to buffer
1072
878
    @param txt: text that was just added
1073
879
    @param regex: regular expression object for matching the errors
1081
887
        sty_s = start + group.start()
1082
888
        sty_e = start + group.end()
1083
889
        stc.StartStyling(sty_s, 0xff)
1084
 
        stc.SetStyling(sty_e - sty_s, outbuff.OPB_STYLE_ERROR)
 
890
        stc.SetStyling(sty_e - sty_s, eclib.OPB_STYLE_ERROR)
1085
891
        found_err = True
1086
892
 
1087
893
    if sty_e != start + len(txt):