#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
**languages.py**
**Platform:**
Windows, Linux, Mac Os X.
**Description:**
Defines languages manipulation related objects.
**Others:**
"""
#**********************************************************************************************************************
#*** Future imports.
#**********************************************************************************************************************
from __future__ import unicode_literals
#**********************************************************************************************************************
#*** External imports.
#**********************************************************************************************************************
import os
from PyQt4.QtCore import QRegExp
#**********************************************************************************************************************
#*** Internal imports.
#**********************************************************************************************************************
import foundations.dataStructures
import foundations.parsers
import foundations.verbose
import umbra.ui.completers
import umbra.ui.highlighters
import umbra.ui.inputAccelerators
import umbra.ui.themes
import umbra.ui.visualAccelerators
from umbra.exceptions import LanguageGrammarError
from umbra.globals.uiConstants import UiConstants
#**********************************************************************************************************************
#*** Module attributes.
#**********************************************************************************************************************
__author__ = "Thomas Mansencal"
__copyright__ = "Copyright (C) 2008 - 2014 - Thomas Mansencal"
__license__ = "GPL V3.0 - http://www.gnu.org/licenses/"
__maintainer__ = "Thomas Mansencal"
__email__ = "[email protected]"
__status__ = "Production"
__all__ = ["LOGGER",
"PYTHON_GRAMMAR_FILE",
"LOGGING_GRAMMAR_FILE",
"TEXT_GRAMMAR_FILE",
"LANGUAGES_ACCELERATORS",
"DEFAULT_INDENT_MARKER",
"Language",
"getObjectFromLanguageAccelerators",
"getLanguageDescription",
"getPythonLanguage",
"getLoggingLanguage",
"PYTHON_LANGUAGE",
"LOGGING_LANGUAGE",
"TEXT_LANGUAGE", ]
LOGGER = foundations.verbose.installLogger()
PYTHON_GRAMMAR_FILE = umbra.ui.common.getResourcePath(UiConstants.pythonGrammarFile)
LOGGING_GRAMMAR_FILE = umbra.ui.common.getResourcePath(UiConstants.loggingGrammarFile)
TEXT_GRAMMAR_FILE = umbra.ui.common.getResourcePath(UiConstants.textGrammarFile)
LANGUAGES_ACCELERATORS = {"DefaultHighlighter" : umbra.ui.highlighters.DefaultHighlighter,
"DefaultCompleter" : umbra.ui.completers.DefaultCompleter,
"indentationPreEventInputAccelerators" :
umbra.ui.inputAccelerators.indentationPreEventInputAccelerators,
"indentationPostEventInputAccelerators" :
umbra.ui.inputAccelerators.indentationPostEventInputAccelerators,
"completionPreEventInputAccelerators" :
umbra.ui.inputAccelerators.completionPreEventInputAccelerators,
"completionPostEventInputAccelerators" :
umbra.ui.inputAccelerators.completionPostEventInputAccelerators,
"symbolsExpandingPreEventInputAccelerators" :
umbra.ui.inputAccelerators.symbolsExpandingPreEventInputAccelerators,
"highlightCurrentLine" :
umbra.ui.visualAccelerators.highlightCurrentLine,
"highlightOccurences" :
umbra.ui.visualAccelerators.highlightOccurences,
"highlightMatchingSymbolsPairs" :
umbra.ui.visualAccelerators.highlightMatchingSymbolsPairs,
"DefaultTheme" : umbra.ui.themes.DEFAULT_THEME,
"LoggingTheme" : umbra.ui.themes.LOGGING_THEME}
DEFAULT_INDENT_MARKER = "\t"
#**********************************************************************************************************************
#*** Module classes and definitions.
#**********************************************************************************************************************
[docs]class Language(foundations.dataStructures.Structure):
"""
Defines a storage object for the :class:`Editor` class language description.
"""
def __init__(self, **kwargs):
"""
Initializes the class.
:param \*\*kwargs: name, file, parser, extensions, highlighter, completer, preInputAccelerators,
postInputAccelerators, visualAccelerators, indentMarker, commentMarker, commentBlockMarkerStart, commentBlockMarkerEnd,
symbolsPairs, indentationSymbols, rules, tokens, theme. ( Key / Value pairs )
"""
LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))
foundations.dataStructures.Structure.__init__(self, **kwargs)
[docs]def getObjectFromLanguageAccelerators(accelerator):
"""
Returns the object associated to given accelerator.
:param accelerator: Accelerator.
:type accelerator: unicode
:return: Object.
:rtype: object
"""
return LANGUAGES_ACCELERATORS.get(accelerator)
# Oncilla: Statement commented by auto-documentation process:
# Oncilla: Statement commented by auto-documentation process: @foundations.exceptions.handleExceptions(LanguageGrammarError)
[docs]def getLanguageDescription(grammarfile):
"""
Gets the language description from given language grammar file.
:param grammarfile: Language grammar.
:type grammarfile: unicode
:return: Language description.
:rtype: Language
"""
LOGGER.debug("> Processing '{0}' grammar file.".format(grammarfile))
sectionsParser = foundations.parsers.SectionsFileParser(grammarfile)
sectionsParser.parse(stripQuotationMarkers=False)
name = sectionsParser.getValue("Name", "Language")
if not name:
raise LanguageGrammarError("{0} | '{1}' attribute not found in '{2}' file!".format(__name__,
"Language|Name",
grammarfile))
extensions = sectionsParser.getValue("Extensions", "Language")
if not extensions:
raise LanguageGrammarError("{0} | '{1}' attribute not found in '{2}' file!".format(__name__,
"Language|Extensions",
grammarfile))
highlighter = getObjectFromLanguageAccelerators(sectionsParser.getValue("Highlighter", "Accelerators"))
completer = getObjectFromLanguageAccelerators(sectionsParser.getValue("Completer", "Accelerators"))
preInputAccelerators = sectionsParser.getValue("PreInputAccelerators", "Accelerators")
preInputAccelerators = preInputAccelerators and [getObjectFromLanguageAccelerators(accelerator)
for accelerator in preInputAccelerators.split("|")] or ()
postInputAccelerators = sectionsParser.getValue("PostInputAccelerators", "Accelerators")
postInputAccelerators = postInputAccelerators and [getObjectFromLanguageAccelerators(accelerator)
for accelerator in postInputAccelerators.split("|")] or ()
visualAccelerators = sectionsParser.getValue("VisualAccelerators", "Accelerators")
visualAccelerators = visualAccelerators and [getObjectFromLanguageAccelerators(accelerator)
for accelerator in visualAccelerators.split("|")] or ()
indentMarker = sectionsParser.sectionExists("Syntax") and sectionsParser.getValue("IndentMarker", "Syntax") or \
DEFAULT_INDENT_MARKER
commentMarker = sectionsParser.sectionExists("Syntax") and \
sectionsParser.getValue("CommentMarker", "Syntax") or ""
commentBlockMarkerStart = sectionsParser.sectionExists("Syntax") and \
sectionsParser.getValue("CommentBlockMarkerStart", "Syntax") or ""
commentBlockMarkerEnd = sectionsParser.sectionExists("Syntax") and \
sectionsParser.getValue("CommentBlockMarkerEnd", "Syntax") or ""
symbolsPairs = sectionsParser.sectionExists("Syntax") and \
sectionsParser.getValue("SymbolsPairs", "Syntax") or {}
if symbolsPairs:
associatedPairs = foundations.dataStructures.Lookup()
for pair in symbolsPairs.split("|"):
associatedPairs[pair[0]] = pair[1]
symbolsPairs = associatedPairs
indentationSymbols = sectionsParser.sectionExists("Syntax") and \
sectionsParser.getValue("IndentationSymbols", "Syntax")
indentationSymbols = indentationSymbols and indentationSymbols.split("|") or ()
rules = []
attributes = sectionsParser.sections.get("Rules")
if attributes:
for attribute in sectionsParser.sections["Rules"]:
pattern = sectionsParser.getValue(attribute, "Rules")
rules.append(umbra.ui.highlighters.Rule(name=foundations.namespace.removeNamespace(attribute),
pattern=QRegExp(pattern)))
tokens = []
dictionary = sectionsParser.getValue("Dictionary", "Accelerators")
if dictionary:
dictionaryFile = os.path.join(os.path.dirname(grammarfile), dictionary)
if foundations.common.pathExists(dictionaryFile):
with open(dictionaryFile, "r") as file:
for line in iter(file):
line = line.strip()
line and tokens.append(line)
else:
LOGGER.warning(
"!> {0} | '{1}' language dictionary file doesn't exists and will be skipped!".format(__name__,
dictionaryFile))
theme = getObjectFromLanguageAccelerators(sectionsParser.getValue("Theme", "Accelerators")) or \
umbra.ui.highlighters.DEFAULT_THEME
attributes = {"name" : name,
"file" : grammarfile,
"parser" : sectionsParser,
"extensions" : extensions,
"highlighter" : highlighter,
"completer" : completer,
"preInputAccelerators" : preInputAccelerators,
"postInputAccelerators" : postInputAccelerators,
"visualAccelerators" : visualAccelerators,
"indentMarker" : indentMarker,
"commentMarker" : commentMarker,
"commentBlockMarkerStart" : commentBlockMarkerStart,
"commentBlockMarkerEnd" : commentBlockMarkerEnd,
"symbolsPairs" : symbolsPairs,
"indentationSymbols" : indentationSymbols,
"rules" : rules,
"tokens" : tokens,
"theme" : theme}
for attribute, value in sorted(attributes.iteritems()):
if attribute == "rules":
LOGGER.debug("> Registered '{0}' syntax rules.".format(len(value)))
elif attribute == "tokens":
LOGGER.debug("> Registered '{0}' completion tokens.".format(len(value)))
else:
LOGGER.debug("> Attribute: '{0}', Value: '{1}'.".format(attribute, value))
return Language(**attributes)
[docs]def getPythonLanguage():
"""
Returns the Python language description.
:return: Python language description.
:rtype: Language
"""
return getLanguageDescription(PYTHON_GRAMMAR_FILE)
[docs]def getLoggingLanguage():
"""
Returns the Logging language description.
:return: Logging language description.
:rtype: Language
"""
return getLanguageDescription(LOGGING_GRAMMAR_FILE)
[docs]def getTextLanguage():
"""
Returns the Text language description.
:return: Text language description.
:rtype: Language
"""
return getLanguageDescription(TEXT_GRAMMAR_FILE)
#**********************************************************************************************************************
#*** Module attributes.
#**********************************************************************************************************************
# Oncilla: Statement commented by auto-documentation process:
PYTHON_LANGUAGE = None
# Oncilla: Statement commented by auto-documentation process:
LOGGING_LANGUAGE = None
# Oncilla: Statement commented by auto-documentation process:
TEXT_LANGUAGE = None