20 from pygments.plugin import find_plugin_lexers |
20 from pygments.plugin import find_plugin_lexers |
21 from pygments.util import ClassNotFound, itervalues, guess_decode |
21 from pygments.util import ClassNotFound, itervalues, guess_decode |
22 |
22 |
23 |
23 |
24 __all__ = ['get_lexer_by_name', 'get_lexer_for_filename', 'find_lexer_class', |
24 __all__ = ['get_lexer_by_name', 'get_lexer_for_filename', 'find_lexer_class', |
25 'guess_lexer'] + list(LEXERS) |
25 'guess_lexer', 'load_lexer_from_file'] + list(LEXERS) |
26 |
26 |
27 _lexer_cache = {} |
27 _lexer_cache = {} |
28 _pattern_cache = {} |
28 _pattern_cache = {} |
29 |
29 |
30 |
30 |
70 for cls in find_plugin_lexers(): |
70 for cls in find_plugin_lexers(): |
71 if cls.name == name: |
71 if cls.name == name: |
72 return cls |
72 return cls |
73 |
73 |
74 |
74 |
|
75 def find_lexer_class_by_name(_alias): |
|
76 """Lookup a lexer class by alias. |
|
77 |
|
78 Like `get_lexer_by_name`, but does not instantiate the class. |
|
79 |
|
80 .. versionadded:: 2.2 |
|
81 """ |
|
82 if not _alias: |
|
83 raise ClassNotFound('no lexer for alias %r found' % _alias) |
|
84 # lookup builtin lexers |
|
85 for module_name, name, aliases, _, _ in itervalues(LEXERS): |
|
86 if _alias.lower() in aliases: |
|
87 if name not in _lexer_cache: |
|
88 _load_lexers(module_name) |
|
89 return _lexer_cache[name] |
|
90 # continue with lexers from setuptools entrypoints |
|
91 for cls in find_plugin_lexers(): |
|
92 if _alias.lower() in cls.aliases: |
|
93 return cls |
|
94 raise ClassNotFound('no lexer for alias %r found' % _alias) |
|
95 |
|
96 |
75 def get_lexer_by_name(_alias, **options): |
97 def get_lexer_by_name(_alias, **options): |
76 """Get a lexer by an alias. |
98 """Get a lexer by an alias. |
77 |
99 |
78 Raises ClassNotFound if not found. |
100 Raises ClassNotFound if not found. |
79 """ |
101 """ |
89 # continue with lexers from setuptools entrypoints |
111 # continue with lexers from setuptools entrypoints |
90 for cls in find_plugin_lexers(): |
112 for cls in find_plugin_lexers(): |
91 if _alias.lower() in cls.aliases: |
113 if _alias.lower() in cls.aliases: |
92 return cls(**options) |
114 return cls(**options) |
93 raise ClassNotFound('no lexer for alias %r found' % _alias) |
115 raise ClassNotFound('no lexer for alias %r found' % _alias) |
|
116 |
|
117 |
|
118 def load_lexer_from_file(filename, lexername="CustomLexer", **options): |
|
119 """Load a lexer from a file. |
|
120 |
|
121 This method expects a file located relative to the current working |
|
122 directory, which contains a Lexer class. By default, it expects the |
|
123 Lexer to be name CustomLexer; you can specify your own class name |
|
124 as the second argument to this function. |
|
125 |
|
126 Users should be very careful with the input, because this method |
|
127 is equivalent to running eval on the input file. |
|
128 |
|
129 Raises ClassNotFound if there are any problems importing the Lexer. |
|
130 |
|
131 .. versionadded:: 2.2 |
|
132 """ |
|
133 try: |
|
134 # This empty dict will contain the namespace for the exec'd file |
|
135 custom_namespace = {} |
|
136 exec(open(filename, 'rb').read(), custom_namespace) |
|
137 # Retrieve the class `lexername` from that namespace |
|
138 if lexername not in custom_namespace: |
|
139 raise ClassNotFound('no valid %s class found in %s' % |
|
140 (lexername, filename)) |
|
141 lexer_class = custom_namespace[lexername] |
|
142 # And finally instantiate it with the options |
|
143 return lexer_class(**options) |
|
144 except IOError as err: |
|
145 raise ClassNotFound('cannot read %s' % filename) |
|
146 except ClassNotFound as err: |
|
147 raise |
|
148 except Exception as err: |
|
149 raise ClassNotFound('error when loading custom lexer: %s' % err) |
94 |
150 |
95 |
151 |
96 def find_lexer_class_for_filename(_fn, code=None): |
152 def find_lexer_class_for_filename(_fn, code=None): |
97 """Get a lexer for a filename. |
153 """Get a lexer for a filename. |
98 |
154 |
125 # The class _always_ defines analyse_text because it's included in |
181 # The class _always_ defines analyse_text because it's included in |
126 # the Lexer class. The default implementation returns None which |
182 # the Lexer class. The default implementation returns None which |
127 # gets turned into 0.0. Run scripts/detect_missing_analyse_text.py |
183 # gets turned into 0.0. Run scripts/detect_missing_analyse_text.py |
128 # to find lexers which need it overridden. |
184 # to find lexers which need it overridden. |
129 if code: |
185 if code: |
130 return cls.analyse_text(code) + bonus |
186 return cls.analyse_text(code) + bonus, cls.__name__ |
131 return cls.priority + bonus |
187 return cls.priority + bonus, cls.__name__ |
132 |
188 |
133 if matches: |
189 if matches: |
134 matches.sort(key=get_rating) |
190 matches.sort(key=get_rating) |
135 # print "Possible lexers, after sort:", matches |
191 # print "Possible lexers, after sort:", matches |
136 return matches[-1][0] |
192 return matches[-1][0] |