src/pyams_utils/pygments.py
branchdev-tf
changeset 408 cf2304af0fab
parent 318 12e519cc367c
equal deleted inserted replaced
407:0037199881fb 408:cf2304af0fab
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
    10 # FOR A PARTICULAR PURPOSE.
    10 # FOR A PARTICULAR PURPOSE.
    11 #
    11 #
    12 
    12 
    13 __docformat__ = 'restructuredtext'
    13 """PyAMS_utils.pygments module
       
    14 
       
    15 This module is used to provide an URL which allows you to load Pygments CSS files.
       
    16 It also provides two vocabularies of available lexers and styles.
       
    17 """
    14 
    18 
    15 from fanstatic import get_library_registry
    19 from fanstatic import get_library_registry
    16 from persistent import Persistent
    20 from persistent import Persistent
    17 from pygments import highlight
    21 from pygments import highlight
    18 from pygments.formatters.html import HtmlFormatter
    22 from pygments.formatters.html import HtmlFormatter
    19 from pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer
    23 from pygments.lexers import get_all_lexers, get_lexer_by_name, guess_lexer
    20 from pygments.styles import get_all_styles
    24 from pygments.styles import get_all_styles
    21 from pyramid.response import Response
    25 from pyramid.response import Response
    22 from pyramid.view import view_config
    26 from pyramid.view import view_config
    23 from zope.container.contained import Contained
    27 from zope.container.contained import Contained
    24 from zope.interface import Interface, implementer
       
    25 from zope.schema import Bool, Choice
       
    26 from zope.schema.fieldproperty import FieldProperty
    28 from zope.schema.fieldproperty import FieldProperty
    27 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
    29 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
    28 
    30 
    29 from pyams_utils.factory import factory_config
    31 from pyams_utils.factory import factory_config
    30 from pyams_utils.fanstatic import ExternalResource
    32 from pyams_utils.fanstatic import ExternalResource
       
    33 from pyams_utils.interfaces.pygments import IPygmentsCodeConfiguration, \
       
    34     PYGMENTS_LEXERS_VOCABULARY, PYGMENTS_STYLES_VOCABULARY
    31 from pyams_utils.list import unique_iter
    35 from pyams_utils.list import unique_iter
    32 from pyams_utils.vocabulary import vocabulary_config
    36 from pyams_utils.vocabulary import vocabulary_config
       
    37 
       
    38 
       
    39 __docformat__ = 'restructuredtext'
    33 
    40 
    34 from pyams_utils import _
    41 from pyams_utils import _
    35 
    42 
    36 
    43 
    37 #
    44 #
    45         from pyams_skin import library
    52         from pyams_skin import library
    46     except ImportError:
    53     except ImportError:
    47         from pyams_default_theme import library
    54         from pyams_default_theme import library
    48 
    55 
    49 
    56 
       
    57 # pylint: disable=invalid-name
    50 pygments_css = ExternalResource(library, 'get-pygments-style.css', resource_type='css')
    58 pygments_css = ExternalResource(library, 'get-pygments-style.css', resource_type='css')
    51 
    59 
    52 
    60 
    53 @view_config(name='get-pygments-style.css')
    61 @view_config(name='get-pygments-style.css')
    54 def get_pygments_style_view(request):
    62 def get_pygments_style_view(request):
       
    63     """View used to download Pygments style"""
    55     style = request.params.get('style', 'default')
    64     style = request.params.get('style', 'default')
    56     styles = HtmlFormatter(linenos='inline',
    65     styles = HtmlFormatter(linenos='inline',
    57                            nowrap=False,
    66                            nowrap=False,
    58                            cssclass='source',
    67                            cssclass='source',
    59                            style=style).get_style_defs()
    68                            style=style).get_style_defs()
    62 
    71 
    63 #
    72 #
    64 # Pygments lexers
    73 # Pygments lexers
    65 #
    74 #
    66 
    75 
    67 PYGMENTS_LEXERS_VOCABULARY = 'Pygments lexers vocabulary'
       
    68 
       
    69 
       
    70 @vocabulary_config(name=PYGMENTS_LEXERS_VOCABULARY)
    76 @vocabulary_config(name=PYGMENTS_LEXERS_VOCABULARY)
    71 class PygmentsLexersVocabulary(SimpleVocabulary):
    77 class PygmentsLexersVocabulary(SimpleVocabulary):
    72     """Pygments lexers vocabulary"""
    78     """Pygments lexers vocabulary"""
    73 
    79 
    74     def __init__(self, context):
    80     def __init__(self, context):  # pylint: disable=unused-argument
    75         terms = [SimpleTerm('auto', title=_("Automatic detection"))]
    81         terms = [SimpleTerm('auto', title=_("Automatic detection"))]
       
    82         # pylint: disable=unused-variable
    76         for name, aliases, filetypes, mimetypes in sorted(unique_iter(get_all_lexers(),
    83         for name, aliases, filetypes, mimetypes in sorted(unique_iter(get_all_lexers(),
    77                                                                       key=lambda x: x[0].lower()),
    84                                                                       key=lambda x: x[0].lower()),
    78                                                           key=lambda x: x[0].lower()):
    85                                                           key=lambda x: x[0].lower()):
    79             terms.append(SimpleTerm(aliases[0] if len(aliases) > 0 else name,
    86             terms.append(SimpleTerm(aliases[0] if len(aliases) > 0 else name,
    80                                     title='{0}{1}'.format(name,
    87                                     title='{0}{1}'.format(name,
    81                                                           ' ({})'.format(', '.join(filetypes)) if filetypes else '')))
    88                                                           ' ({})'.format(', '.join(filetypes))
       
    89                                                           if filetypes else '')))
    82         super(PygmentsLexersVocabulary, self).__init__(terms)
    90         super(PygmentsLexersVocabulary, self).__init__(terms)
    83 
       
    84 
       
    85 PYGMENTS_STYLES_VOCABULARY = 'Pygments styles vocabulary'
       
    86 
    91 
    87 
    92 
    88 @vocabulary_config(name=PYGMENTS_STYLES_VOCABULARY)
    93 @vocabulary_config(name=PYGMENTS_STYLES_VOCABULARY)
    89 class PygmentsStylesVocabulary(SimpleVocabulary):
    94 class PygmentsStylesVocabulary(SimpleVocabulary):
    90     """Pygments styles vocabulary"""
    95     """Pygments styles vocabulary"""
    91 
    96 
    92     def __init__(self, context):
    97     def __init__(self, context):  # pylint: disable=unused-argument
    93         terms = []
    98         terms = []
    94         for name in sorted(get_all_styles()):
    99         for name in sorted(get_all_styles()):
    95             terms.append(SimpleTerm(name))
   100             terms.append(SimpleTerm(name))
    96         super(PygmentsStylesVocabulary, self).__init__(terms)
   101         super(PygmentsStylesVocabulary, self).__init__(terms)
    97 
   102 
    98 
   103 
    99 #
   104 #
   100 # Pygments configuration
   105 # Pygments configuration
   101 #
   106 #
   102 
       
   103 class IPygmentsCodeConfiguration(Interface):
       
   104     """Pygments html formatter options"""
       
   105 
       
   106     lexer = Choice(title=_("Selected lexer"),
       
   107                    description=_("Lexer used to format source code"),
       
   108                    required=True,
       
   109                    vocabulary=PYGMENTS_LEXERS_VOCABULARY,
       
   110                    default='auto')
       
   111 
       
   112     display_linenos = Bool(title=_("Display line numbers?"),
       
   113                            description=_("If 'no', line numbers will be hidden"),
       
   114                            required=True,
       
   115                            default=True)
       
   116 
       
   117     disable_wrap = Bool(title=_("Lines wrap?"),
       
   118                         description=_("If 'yes', lines wraps will be enabled; line numbers will not be "
       
   119                                       "displayed if lines wrap is enabled..."),
       
   120                         required=True,
       
   121                         default=False)
       
   122 
       
   123     style = Choice(title=_("Color style"),
       
   124                    description=_("Selected color style"),
       
   125                    required=True,
       
   126                    vocabulary=PYGMENTS_STYLES_VOCABULARY,
       
   127                    default='default')
       
   128 
       
   129 
   107 
   130 @factory_config(IPygmentsCodeConfiguration)
   108 @factory_config(IPygmentsCodeConfiguration)
   131 class PygmentsCodeRendererSettings(Persistent, Contained):
   109 class PygmentsCodeRendererSettings(Persistent, Contained):
   132     """Pygments code renderer settings"""
   110     """Pygments code renderer settings"""
   133 
   111 
   147         formatter = HtmlFormatter(linenos='inline' if settings.display_linenos else None,
   125         formatter = HtmlFormatter(linenos='inline' if settings.display_linenos else None,
   148                                   nowrap=settings.disable_wrap,
   126                                   nowrap=settings.disable_wrap,
   149                                   cssclass='source',
   127                                   cssclass='source',
   150                                   style=settings.style)
   128                                   style=settings.style)
   151         return highlight(code, lexer, formatter)
   129         return highlight(code, lexer, formatter)
       
   130     return None