Merge lp:~gatesphere/leo-editor/markdown_support into lp:leo-editor
- markdown_support
- Merge into trunk3
Status: | Merged |
---|---|
Approved by: | Jake Peck |
Approved revision: | 5613 |
Merged at revision: | 5758 |
Proposed branch: | lp:~gatesphere/leo-editor/markdown_support |
Merge into: | lp:leo-editor |
Diff against target: |
739 lines (+644/-3) 3 files modified
leo/core/leoApp.py (+3/-0) leo/modes/md.py (+543/-0) leo/plugins/viewrendered.py (+98/-3) |
To merge this branch: | bzr merge lp:~gatesphere/leo-editor/markdown_support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jake Peck | Approve | ||
Review via email: mp+147256@code.launchpad.net |
Commit message
Description of the change
Adds support for markdown (.md) files to colorizer, as well as rendering support for .md files in viewrendered (requires the python module "markdown" from http://
- 5603. By Jake Peck
-
Correction on comment definitions for md mode.
- 5604. By Jake Peck
-
Updated viewrendered docstring
- 5605. By Jake Peck
-
Merged revs 5601-5602 from mainline
- 5606. By Jake Peck
-
Fancier colorizer, based on https:/
/github. com/peterlynch/ jEdit-modes/ blob/master/ markdown. xml - run through jEdit2py - 5607. By Jake Peck
-
Added configurable support for markdown extensions.
- 5608. By Jake Peck
-
Merge upstream revision 5603
- 5609. By Jake Peck
-
merge upstream rev 5605
- 5610. By Jake Peck
-
merge upstream rev 5606
- 5611. By Jake Peck
-
Merge upstream rev 5634
- 5612. By Jake Peck
-
Merged upstrem rev. 5644
- 5613. By Jake Peck
-
Merged upstream rev 5757
Edward K. Ream (edreamleo) wrote : | # |
On Thu, May 2, 2013 at 1:00 PM, <email address hidden> wrote:
> The proposal to merge lp:~gatesphere/leo-editor/markdown_support into
> lp:leo-editor has been updated.
>
> Status: Approved => Merged
>
Looks good. All unit tests pass here.
EKR
Preview Diff
1 | === modified file 'leo/core/leoApp.py' |
2 | --- leo/core/leoApp.py 2013-03-02 17:50:17 +0000 |
3 | +++ leo/core/leoApp.py 2013-05-02 13:27:25 +0000 |
4 | @@ -265,6 +265,7 @@ |
5 | "makefile" : "#", |
6 | "maple" : "//", |
7 | "matlab" : "%", # EKR: 2011/10/21 |
8 | + "md" : "<!-- -->", # PeckJ: 2013/02/08 |
9 | "ml" : "(* *)", |
10 | "modula3" : "(* *)", |
11 | "moin" : "##", |
12 | @@ -428,6 +429,7 @@ |
13 | "makefile" : "mak", |
14 | "maple" : "mpl", |
15 | "matlab" : "m", |
16 | + "md" : "md", # PeckJ: 2013/02/07 |
17 | "ml" : "ml", |
18 | "modula3" : "mod", |
19 | "moin" : "wiki", |
20 | @@ -573,6 +575,7 @@ |
21 | "ly": "lilypond", |
22 | "m": "matlab", # EKR: 2011/10/21 |
23 | "mak": "makefile", |
24 | + "md": "md", # PeckJ 2013/02/07 |
25 | "ml": "ml", |
26 | "mm": "objective_c", # Only one extension is valid: .m |
27 | "mod": "modula3", |
28 | |
29 | === added file 'leo/modes/md.py' |
30 | --- leo/modes/md.py 1970-01-01 00:00:00 +0000 |
31 | +++ leo/modes/md.py 2013-05-02 13:27:25 +0000 |
32 | @@ -0,0 +1,543 @@ |
33 | +# Leo colorizer control file for md mode. |
34 | +# This file is in the public domain. |
35 | + |
36 | +# Properties for md mode. |
37 | +properties = { |
38 | + "commentEnd": "-->", |
39 | + "commentStart": "<!--", |
40 | + "indentSize": "4", |
41 | + "maxLineLen": "120", |
42 | + "tabSize": "4", |
43 | +} |
44 | + |
45 | +# Attributes dict for md_main ruleset. |
46 | +md_main_attributes_dict = { |
47 | + "default": "null", |
48 | + "digit_re": "", |
49 | + "escape": "", |
50 | + "highlight_digits": "true", |
51 | + "ignore_case": "true", |
52 | + "no_word_sep": "", |
53 | +} |
54 | + |
55 | +# Attributes dict for md_inline_markup ruleset. |
56 | +md_inline_markup_attributes_dict = { |
57 | + "default": "MARKUP", |
58 | + "digit_re": "", |
59 | + "escape": "", |
60 | + "highlight_digits": "true", |
61 | + "ignore_case": "true", |
62 | + "no_word_sep": "", |
63 | +} |
64 | + |
65 | +# Attributes dict for md_block_html_tags ruleset. |
66 | +md_block_html_tags_attributes_dict = { |
67 | + "default": "MARKUP", |
68 | + "digit_re": "", |
69 | + "escape": "", |
70 | + "highlight_digits": "true", |
71 | + "ignore_case": "true", |
72 | + "no_word_sep": "", |
73 | +} |
74 | + |
75 | +# Attributes dict for md_markdown ruleset. |
76 | +md_markdown_attributes_dict = { |
77 | + "default": "MARKUP", |
78 | + "digit_re": "", |
79 | + "escape": "", |
80 | + "highlight_digits": "true", |
81 | + "ignore_case": "false", |
82 | + "no_word_sep": "", |
83 | +} |
84 | + |
85 | +# Attributes dict for md_link_label_definition ruleset. |
86 | +md_link_label_definition_attributes_dict = { |
87 | + "default": "KEYWORD3", |
88 | + "digit_re": "", |
89 | + "escape": "", |
90 | + "highlight_digits": "true", |
91 | + "ignore_case": "false", |
92 | + "no_word_sep": "", |
93 | +} |
94 | + |
95 | +# Attributes dict for md_link_inline_url_title ruleset. |
96 | +md_link_inline_url_title_attributes_dict = { |
97 | + "default": "KEYWORD3", |
98 | + "digit_re": "", |
99 | + "escape": "", |
100 | + "highlight_digits": "true", |
101 | + "ignore_case": "false", |
102 | + "no_word_sep": "", |
103 | +} |
104 | + |
105 | +# Attributes dict for md_link_inline_url_title_close ruleset. |
106 | +md_link_inline_url_title_close_attributes_dict = { |
107 | + "default": "KEYWORD3", |
108 | + "digit_re": "", |
109 | + "escape": "", |
110 | + "highlight_digits": "true", |
111 | + "ignore_case": "false", |
112 | + "no_word_sep": "", |
113 | +} |
114 | + |
115 | +# Attributes dict for md_link_inline_label_close ruleset. |
116 | +md_link_inline_label_close_attributes_dict = { |
117 | + "default": "LABEL", |
118 | + "digit_re": "", |
119 | + "escape": "", |
120 | + "highlight_digits": "true", |
121 | + "ignore_case": "false", |
122 | + "no_word_sep": "", |
123 | +} |
124 | + |
125 | +# Attributes dict for md_markdown_blockquote ruleset. |
126 | +md_markdown_blockquote_attributes_dict = { |
127 | + "default": "LABEL", |
128 | + "digit_re": "", |
129 | + "escape": "", |
130 | + "highlight_digits": "true", |
131 | + "ignore_case": "false", |
132 | + "no_word_sep": "", |
133 | +} |
134 | + |
135 | +# Dictionary of attributes dictionaries for md mode. |
136 | +attributesDictDict = { |
137 | + "md_block_html_tags": md_block_html_tags_attributes_dict, |
138 | + "md_inline_markup": md_inline_markup_attributes_dict, |
139 | + "md_link_inline_label_close": md_link_inline_label_close_attributes_dict, |
140 | + "md_link_inline_url_title": md_link_inline_url_title_attributes_dict, |
141 | + "md_link_inline_url_title_close": md_link_inline_url_title_close_attributes_dict, |
142 | + "md_link_label_definition": md_link_label_definition_attributes_dict, |
143 | + "md_main": md_main_attributes_dict, |
144 | + "md_markdown": md_markdown_attributes_dict, |
145 | + "md_markdown_blockquote": md_markdown_blockquote_attributes_dict, |
146 | +} |
147 | + |
148 | +# Keywords dict for md_main ruleset. |
149 | +md_main_keywords_dict = {} |
150 | + |
151 | +# Keywords dict for md_inline_markup ruleset. |
152 | +md_inline_markup_keywords_dict = {} |
153 | + |
154 | +# Keywords dict for md_block_html_tags ruleset. |
155 | +md_block_html_tags_keywords_dict = {} |
156 | + |
157 | +# Keywords dict for md_markdown ruleset. |
158 | +md_markdown_keywords_dict = {} |
159 | + |
160 | +# Keywords dict for md_link_label_definition ruleset. |
161 | +md_link_label_definition_keywords_dict = {} |
162 | + |
163 | +# Keywords dict for md_link_inline_url_title ruleset. |
164 | +md_link_inline_url_title_keywords_dict = {} |
165 | + |
166 | +# Keywords dict for md_link_inline_url_title_close ruleset. |
167 | +md_link_inline_url_title_close_keywords_dict = {} |
168 | + |
169 | +# Keywords dict for md_link_inline_label_close ruleset. |
170 | +md_link_inline_label_close_keywords_dict = {} |
171 | + |
172 | +# Keywords dict for md_markdown_blockquote ruleset. |
173 | +md_markdown_blockquote_keywords_dict = {} |
174 | + |
175 | +# Dictionary of keywords dictionaries for md mode. |
176 | +keywordsDictDict = { |
177 | + "md_block_html_tags": md_block_html_tags_keywords_dict, |
178 | + "md_inline_markup": md_inline_markup_keywords_dict, |
179 | + "md_link_inline_label_close": md_link_inline_label_close_keywords_dict, |
180 | + "md_link_inline_url_title": md_link_inline_url_title_keywords_dict, |
181 | + "md_link_inline_url_title_close": md_link_inline_url_title_close_keywords_dict, |
182 | + "md_link_label_definition": md_link_label_definition_keywords_dict, |
183 | + "md_main": md_main_keywords_dict, |
184 | + "md_markdown": md_markdown_keywords_dict, |
185 | + "md_markdown_blockquote": md_markdown_blockquote_keywords_dict, |
186 | +} |
187 | + |
188 | +# Rules for md_main ruleset. |
189 | + |
190 | +def md_rule0(colorer, s, i): |
191 | + return colorer.match_span(s, i, kind="comment1", begin="<!--", end="-->", |
192 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
193 | + delegate="",exclude_match=False, |
194 | + no_escape=False, no_line_break=False, no_word_break=False) |
195 | + |
196 | +def md_rule1(colorer, s, i): |
197 | + return colorer.match_span(s, i, kind="markup", begin="<script", end="</script>", |
198 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
199 | + delegate="html::javascript",exclude_match=False, |
200 | + no_escape=False, no_line_break=False, no_word_break=False) |
201 | + |
202 | +def md_rule2(colorer, s, i): |
203 | + return colorer.match_seq_regexp(s, i, kind="markup", regexp="<hr\\b([^<>])*?/?>", |
204 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, delegate="") |
205 | + |
206 | +def md_rule3(colorer, s, i): |
207 | + return colorer.match_span_regexp(s, i, kind="markup", begin="<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|noscript|form|fieldset|iframe|math|ins|del)\\b", end="</$1>", |
208 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
209 | + delegate="md::block_html_tags",exclude_match=False, |
210 | + no_escape=False, no_line_break=False, no_word_break=False) |
211 | + |
212 | +def md_rule4(colorer, s, i): |
213 | + return colorer.match_seq(s, i, kind="null", seq=" < ", |
214 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
215 | + |
216 | +def md_rule5(colorer, s, i): |
217 | + return colorer.match_span(s, i, kind="markup", begin="<", end=">", |
218 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
219 | + delegate="md::inline_markup",exclude_match=False, |
220 | + no_escape=False, no_line_break=False, no_word_break=False) |
221 | + |
222 | + |
223 | +# Rules dict for md_main ruleset. |
224 | +rulesDict1 = { |
225 | + " ": [md_rule4,], |
226 | + "<": [md_rule0,md_rule1,md_rule2,md_rule3,md_rule5,], |
227 | +} |
228 | + |
229 | +# Rules for md_inline_markup ruleset. |
230 | + |
231 | + |
232 | +# Rules dict for md_inline_markup ruleset. |
233 | +rulesDict2 = {} |
234 | + |
235 | +# Rules for md_block_html_tags ruleset. |
236 | + |
237 | +def md_rule6(colorer, s, i): |
238 | + return colorer.match_eol_span_regexp(s, i, kind="invalid", regexp="[\\S]+", |
239 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
240 | + delegate="", exclude_match=False) |
241 | + |
242 | +def md_rule7(colorer, s, i): |
243 | + return colorer.match_eol_span_regexp(s, i, kind="invalid", regexp="{1,3}[\\S]+", |
244 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
245 | + delegate="", exclude_match=False) |
246 | + |
247 | +def md_rule8(colorer, s, i): |
248 | + return colorer.match_eol_span_regexp(s, i, kind="", regexp="( {4}|\\t)", |
249 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
250 | + delegate="html::main", exclude_match=False) |
251 | + |
252 | +def md_rule9(colorer, s, i): |
253 | + return colorer.match_span(s, i, kind="literal1", begin="\"", end="\"", |
254 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
255 | + delegate="",exclude_match=False, |
256 | + no_escape=False, no_line_break=False, no_word_break=False) |
257 | + |
258 | +def md_rule10(colorer, s, i): |
259 | + return colorer.match_span(s, i, kind="literal1", begin="'", end="'", |
260 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
261 | + delegate="",exclude_match=False, |
262 | + no_escape=False, no_line_break=False, no_word_break=False) |
263 | + |
264 | +def md_rule11(colorer, s, i): |
265 | + return colorer.match_seq(s, i, kind="operator", seq="=", |
266 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
267 | + |
268 | +# Rules dict for md_block_html_tags ruleset. |
269 | +rulesDict3 = { |
270 | + "\"": [md_rule9,], |
271 | + "'": [md_rule10,], |
272 | + "(": [md_rule8,], |
273 | + "=": [md_rule11,], |
274 | + "[": [md_rule6,], |
275 | + "{": [md_rule7,], |
276 | +} |
277 | + |
278 | +# Rules for md_markdown ruleset. |
279 | + |
280 | +def md_rule12(colorer, s, i): |
281 | + return colorer.match_eol_span_regexp(s, i, kind="", regexp="[ \\t]*(>[ \\t]{1})+", |
282 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
283 | + delegate="md::markdown_blockquote", exclude_match=False) |
284 | + |
285 | +def md_rule13(colorer, s, i): |
286 | + return colorer.match_seq(s, i, kind="null", seq="*", |
287 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
288 | + |
289 | +def md_rule14(colorer, s, i): |
290 | + return colorer.match_seq(s, i, kind="null", seq="_", |
291 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
292 | + |
293 | +def md_rule15(colorer, s, i): |
294 | + return colorer.match_seq(s, i, kind="null", seq="\\][", |
295 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
296 | + |
297 | +def md_rule16(colorer, s, i): |
298 | + return colorer.match_seq_regexp(s, i, kind="null", regexp="\\\\[\\Q*_\\`[](){}#+.!-\\E]", |
299 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
300 | + |
301 | +def md_rule17(colorer, s, i): |
302 | + return colorer.match_span(s, i, kind="literal2", begin="``` ruby", end="```", |
303 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
304 | + delegate="ruby::main",exclude_match=False, |
305 | + no_escape=False, no_line_break=False, no_word_break=False) |
306 | + |
307 | +def md_rule18(colorer, s, i): |
308 | + return colorer.match_span(s, i, kind="literal2", begin="```", end="```", |
309 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
310 | + delegate="",exclude_match=False, |
311 | + no_escape=False, no_line_break=False, no_word_break=False) |
312 | + |
313 | +def md_rule19(colorer, s, i): |
314 | + return colorer.match_span_regexp(s, i, kind="literal2", begin="(`{1,2})", end="$1", |
315 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
316 | + delegate="",exclude_match=False, |
317 | + no_escape=False, no_line_break=False, no_word_break=False) |
318 | + |
319 | +def md_rule20(colorer, s, i): |
320 | + return colorer.match_eol_span_regexp(s, i, kind="literal2", regexp="( {4,}|\\t+)\\S", |
321 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
322 | + delegate="", exclude_match=False) |
323 | + |
324 | +def md_rule21(colorer, s, i): |
325 | + return colorer.match_eol_span_regexp(s, i, kind="keyword1", regexp="[=-]+", |
326 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
327 | + delegate="", exclude_match=False) |
328 | + |
329 | +def md_rule22(colorer, s, i): |
330 | + return colorer.match_eol_span_regexp(s, i, kind="keyword1", regexp="#{1,6}[ \\t]*(.+?)", |
331 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
332 | + delegate="", exclude_match=False) |
333 | + |
334 | +def md_rule23(colorer, s, i): |
335 | + return colorer.match_eol_span_regexp(s, i, kind="keyword1", regexp="[ ]{0,2}([ ]?[-_*][ ]?){3,}[ \\t]*", |
336 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, |
337 | + delegate="", exclude_match=False) |
338 | + |
339 | +def md_rule24(colorer, s, i): |
340 | + return colorer.match_seq_regexp(s, i, kind="keyword2", regexp="[ \\t]{0,}[*+-][ \\t]+", |
341 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, delegate="") |
342 | + |
343 | +def md_rule25(colorer, s, i): |
344 | + return colorer.match_seq_regexp(s, i, kind="keyword2", regexp="[ \\t]{0,}\\d+\\.[ \\t]+", |
345 | + at_line_start=True, at_whitespace_end=False, at_word_start=False, delegate="") |
346 | + |
347 | +def md_rule26(colorer, s, i): |
348 | + return colorer.match_eol_span_regexp(s, i, kind="label", regexp="\\[(.*?)\\]\\:", |
349 | + at_line_start=False, at_whitespace_end=True, at_word_start=False, |
350 | + delegate="md::link_label_definition", exclude_match=False) |
351 | + |
352 | +def md_rule27(colorer, s, i): |
353 | + return colorer.match_span_regexp(s, i, kind="keyword4", begin="!?\\[[\\p{Alnum}\\p{Blank}]*", end="\\]", |
354 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
355 | + delegate="md::link_inline_url_title",exclude_match=False, |
356 | + no_escape=False, no_line_break=True, no_word_break=False) |
357 | + |
358 | +def md_rule28(colorer, s, i): |
359 | + return colorer.match_span_regexp(s, i, kind="literal3", begin="(\\*\\*|__)", end="$1", |
360 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
361 | + delegate="",exclude_match=False, |
362 | + no_escape=False, no_line_break=True, no_word_break=False) |
363 | + |
364 | +def md_rule29(colorer, s, i): |
365 | + return colorer.match_span_regexp(s, i, kind="literal4", begin="(\\*|_)", end="$1", |
366 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
367 | + delegate="",exclude_match=False, |
368 | + no_escape=False, no_line_break=True, no_word_break=False) |
369 | + |
370 | +# Rules dict for md_markdown ruleset. |
371 | +rulesDict4 = { |
372 | + "!": [md_rule27,], |
373 | + "#": [md_rule22,], |
374 | + "(": [md_rule19,md_rule20,md_rule28,md_rule29,], |
375 | + "*": [md_rule13,], |
376 | + "[": [md_rule12,md_rule21,md_rule23,md_rule24,md_rule25,], |
377 | + "\\": [md_rule15,md_rule16,md_rule26,], |
378 | + "_": [md_rule14,], |
379 | + "`": [md_rule17,md_rule18,], |
380 | +} |
381 | + |
382 | +# Rules for md_link_label_definition ruleset. |
383 | + |
384 | +def md_rule30(colorer, s, i): |
385 | + return colorer.match_seq_regexp(s, i, kind="null", regexp="\\\\[\\Q*_\\`[](){}#+.!-\\E]", |
386 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
387 | + |
388 | +def md_rule31(colorer, s, i): |
389 | + return colorer.match_seq(s, i, kind="operator", seq="\"", |
390 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
391 | + |
392 | +def md_rule32(colorer, s, i): |
393 | + return colorer.match_seq(s, i, kind="operator", seq="(", |
394 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
395 | + |
396 | +def md_rule33(colorer, s, i): |
397 | + return colorer.match_seq(s, i, kind="operator", seq=")", |
398 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
399 | + |
400 | + |
401 | +# Rules dict for md_link_label_definition ruleset. |
402 | +rulesDict5 = { |
403 | + "\"": [md_rule31,], |
404 | + "(": [md_rule32,], |
405 | + ")": [md_rule33,], |
406 | + "\\": [md_rule30,], |
407 | +} |
408 | + |
409 | +# Rules for md_link_inline_url_title ruleset. |
410 | + |
411 | +def md_rule34(colorer, s, i): |
412 | + return colorer.match_seq(s, i, kind="operator", seq="]", |
413 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
414 | + |
415 | +def md_rule35(colorer, s, i): |
416 | + return colorer.match_span_regexp(s, i, kind="keyword4", begin="\\[", end="\\]", |
417 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
418 | + delegate="md::link_inline_label_close",exclude_match=False, |
419 | + no_escape=False, no_line_break=True, no_word_break=False) |
420 | + |
421 | +def md_rule36(colorer, s, i): |
422 | + return colorer.match_span_regexp(s, i, kind="keyword4", begin="\\(", end="\\)", |
423 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
424 | + delegate="md::link_inline_url_title_close",exclude_match=False, |
425 | + no_escape=False, no_line_break=True, no_word_break=False) |
426 | + |
427 | +# Rules dict for md_link_inline_url_title ruleset. |
428 | +rulesDict6 = { |
429 | + "(": [md_rule36,], |
430 | + "[": [md_rule35,], |
431 | + "]": [md_rule34,], |
432 | +} |
433 | + |
434 | +# Rules for md_link_inline_url_title_close ruleset. |
435 | + |
436 | +def md_rule37(colorer, s, i): |
437 | + return colorer.match_eol_span(s, i, kind="null", seq=")", |
438 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
439 | + delegate="md::main", exclude_match=False) |
440 | + |
441 | +# Rules dict for md_link_inline_url_title_close ruleset. |
442 | +rulesDict7 = { |
443 | + ")": [md_rule37,], |
444 | +} |
445 | + |
446 | +# Rules for md_link_inline_label_close ruleset. |
447 | + |
448 | +def md_rule38(colorer, s, i): |
449 | + return colorer.match_eol_span(s, i, kind="null", seq="]", |
450 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
451 | + delegate="md::main", exclude_match=False) |
452 | + |
453 | +# Rules dict for md_link_inline_label_close ruleset. |
454 | +rulesDict8 = { |
455 | + "]": [md_rule38,], |
456 | +} |
457 | + |
458 | +# Rules for md_markdown_blockquote ruleset. |
459 | + |
460 | +def md_rule39(colorer, s, i): |
461 | + return colorer.match_seq(s, i, kind="null", seq=" < ", |
462 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
463 | + |
464 | +def md_rule40(colorer, s, i): |
465 | + return colorer.match_span(s, i, kind="markup", begin="<", end=">", |
466 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
467 | + delegate="md::inline_markup",exclude_match=False, |
468 | + no_escape=False, no_line_break=False, no_word_break=False) |
469 | + |
470 | +def md_rule41(colorer, s, i): |
471 | + return colorer.match_seq(s, i, kind="null", seq="*", |
472 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
473 | + |
474 | +def md_rule42(colorer, s, i): |
475 | + return colorer.match_seq(s, i, kind="null", seq="_", |
476 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
477 | + |
478 | +def md_rule43(colorer, s, i): |
479 | + return colorer.match_seq(s, i, kind="null", seq="\\][", |
480 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
481 | + |
482 | +def md_rule44(colorer, s, i): |
483 | + return colorer.match_seq_regexp(s, i, kind="null", regexp="\\\\[\\Q*_\\`[](){}#+.!-\\E]", |
484 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
485 | + |
486 | +def md_rule45(colorer, s, i): |
487 | + return colorer.match_span_regexp(s, i, kind="literal2", begin="(`{1,2})", end="$1", |
488 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
489 | + delegate="",exclude_match=False, |
490 | + no_escape=False, no_line_break=False, no_word_break=False) |
491 | + |
492 | +def md_rule46(colorer, s, i): |
493 | + return colorer.match_eol_span_regexp(s, i, kind="literal2", regexp="( {4,}|\\t+)\\S", |
494 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
495 | + delegate="", exclude_match=False) |
496 | + |
497 | +def md_rule47(colorer, s, i): |
498 | + return colorer.match_eol_span_regexp(s, i, kind="keyword1", regexp="[=-]+", |
499 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
500 | + delegate="", exclude_match=False) |
501 | + |
502 | +def md_rule48(colorer, s, i): |
503 | + return colorer.match_eol_span_regexp(s, i, kind="keyword1", regexp="#{1,6}[ \\t]*(.+?)", |
504 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
505 | + delegate="", exclude_match=False) |
506 | + |
507 | +def md_rule49(colorer, s, i): |
508 | + return colorer.match_eol_span_regexp(s, i, kind="keyword1", regexp="[ ]{0,2}([ ]?[-_*][ ]?){3,}[ \\t]*", |
509 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
510 | + delegate="", exclude_match=False) |
511 | + |
512 | +def md_rule50(colorer, s, i): |
513 | + return colorer.match_seq_regexp(s, i, kind="keyword2", regexp="[ \\t]{0,}[*+-][ \\t]+", |
514 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
515 | + |
516 | +def md_rule51(colorer, s, i): |
517 | + return colorer.match_seq_regexp(s, i, kind="keyword2", regexp="[ \\t]{0,}\\d+\\.[ \\t]+", |
518 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="") |
519 | + |
520 | +def md_rule52(colorer, s, i): |
521 | + return colorer.match_eol_span_regexp(s, i, kind="label", regexp="\\[(.*?)\\]\\:", |
522 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
523 | + delegate="md::link_label_definition", exclude_match=False) |
524 | + |
525 | +def md_rule53(colorer, s, i): |
526 | + return colorer.match_span_regexp(s, i, kind="keyword4", begin="!?\\[[\\p{Alnum}\\p{Blank}]*", end="\\]", |
527 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
528 | + delegate="md::link_inline_url_title",exclude_match=False, |
529 | + no_escape=False, no_line_break=True, no_word_break=False) |
530 | + |
531 | +def md_rule54(colorer, s, i): |
532 | + return colorer.match_span_regexp(s, i, kind="literal3", begin="(\\*\\*|__)", end="$1", |
533 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
534 | + delegate="",exclude_match=False, |
535 | + no_escape=False, no_line_break=False, no_word_break=False) |
536 | + |
537 | +def md_rule55(colorer, s, i): |
538 | + return colorer.match_span_regexp(s, i, kind="literal4", begin="(\\*|_)", end="$1", |
539 | + at_line_start=False, at_whitespace_end=False, at_word_start=False, |
540 | + delegate="",exclude_match=False, |
541 | + no_escape=False, no_line_break=False, no_word_break=False) |
542 | + |
543 | +# Rules dict for md_markdown_blockquote ruleset. |
544 | +rulesDict9 = { |
545 | + " ": [md_rule39,], |
546 | + "!": [md_rule53,], |
547 | + "#": [md_rule48,], |
548 | + "(": [md_rule45,md_rule46,md_rule54,md_rule55,], |
549 | + "*": [md_rule41,], |
550 | + "<": [md_rule40,], |
551 | + "[": [md_rule47,md_rule49,md_rule50,md_rule51,], |
552 | + "\\": [md_rule43,md_rule44,md_rule52,], |
553 | + "_": [md_rule42,], |
554 | +} |
555 | + |
556 | +# x.rulesDictDict for md mode. |
557 | +rulesDictDict = { |
558 | + "md_block_html_tags": rulesDict3, |
559 | + "md_inline_markup": rulesDict2, |
560 | + "md_link_inline_label_close": rulesDict8, |
561 | + "md_link_inline_url_title": rulesDict6, |
562 | + "md_link_inline_url_title_close": rulesDict7, |
563 | + "md_link_label_definition": rulesDict5, |
564 | + "md_main": rulesDict1, |
565 | + "md_markdown": rulesDict4, |
566 | + "md_markdown_blockquote": rulesDict9, |
567 | +} |
568 | + |
569 | +# Import dict for md mode. |
570 | +importDict = { |
571 | + "md_inline_markup": ["html::tags",], |
572 | + "md_link_label_definition": ["md_link_label_definition::markdown",], |
573 | + "md_main": ["md_main::markdown",], |
574 | +} |
575 | + |
576 | |
577 | === modified file 'leo/plugins/viewrendered.py' (properties changed: -x to +x) |
578 | --- leo/plugins/viewrendered.py 2013-04-26 12:06:51 +0000 |
579 | +++ leo/plugins/viewrendered.py 2013-05-02 13:27:25 +0000 |
580 | @@ -9,9 +9,12 @@ |
581 | Dependencies |
582 | ============ |
583 | |
584 | -This plugin uses docutils,http://docutils.sourceforge.net/, to render reStructuredText, |
585 | +This plugin uses docutils, http://docutils.sourceforge.net/, to render reStructuredText, |
586 | so installing docutils is highly recommended when using this plugin. |
587 | |
588 | +This plugin uses markdown, http://http://pypi.python.org/pypi/Markdown, to render Markdown, |
589 | +so installing markdown is highly recommended when using this plugin. |
590 | + |
591 | Commands |
592 | ======== |
593 | |
594 | @@ -88,6 +91,14 @@ |
595 | |
596 | **Important**: reStructuredText errors and warnings will appear in red in the rendering pane. |
597 | |
598 | +Rendering markdown |
599 | +================== |
600 | +Please see the markdown syntax document at http://daringfireball.net/projects/markdown/syntax |
601 | +for more information on markdown. |
602 | + |
603 | +Unless ``@string view-rendered-default-kind`` is set to ``md``, markdown rendering must be |
604 | +specified by putting it in a ``@md`` node. |
605 | + |
606 | Special Renderings |
607 | =================== |
608 | |
609 | @@ -137,8 +148,13 @@ |
610 | When True, hide the rendering pane for text-only renderings. |
611 | |
612 | - ``@string view-rendered-default-kind = rst`` |
613 | - The default kind of rendering. One of (big,rst,html) |
614 | + The default kind of rendering. One of (big,rst,md,html) |
615 | |
616 | +- ``@string view-rendered-md-extensions = extra`` |
617 | + A comma-delineated list of markdown extensions to use. |
618 | + Suitable extensions can be seen here: |
619 | + http://pythonhosted.org/Markdown/extensions/index.html |
620 | + |
621 | Acknowledgments |
622 | ================ |
623 | |
624 | @@ -148,6 +164,8 @@ |
625 | Edward K. Ream generalized this plugin and added communication |
626 | and coordination between the free_layout, NestedSplitter and viewrendered plugins. |
627 | |
628 | +Jacob Peck added markdown support to this plugin. |
629 | + |
630 | ''' |
631 | #@-<< docstring >> |
632 | |
633 | @@ -176,6 +194,13 @@ |
634 | g.es_exception() |
635 | else: |
636 | got_docutils = False |
637 | + |
638 | +## markdown support, non-vital |
639 | +try: |
640 | + from markdown import markdown |
641 | + got_markdown = True |
642 | +except ImportError: |
643 | + got_markdown = False |
644 | |
645 | try: |
646 | import PyQt4.phonon as phonon |
647 | @@ -486,6 +511,7 @@ |
648 | 'html': pc.update_html, |
649 | 'graphics-script': pc.update_graphics_script, |
650 | 'image': pc.update_image, |
651 | + 'md': pc.update_md, |
652 | 'movie': pc.update_movie, |
653 | 'networkx': pc.update_networkx, |
654 | 'rst': pc.update_rst, |
655 | @@ -752,6 +778,74 @@ |
656 | w.setHtml(template) |
657 | w.setReadOnly(True) |
658 | |
659 | + #@+node:peckj.20130207132858.3671: *4* update_md |
660 | + def update_md (self,s,keywords): |
661 | + |
662 | + trace = False and not g.unitTesting |
663 | + pc = self ; c = pc.c ; p = c.p |
664 | + s = s.strip().strip('"""').strip("'''").strip() |
665 | + isHtml = s.startswith('<') and not s.startswith('<<') |
666 | + |
667 | + if trace: g.trace('isHtml',isHtml) |
668 | + |
669 | + # Do this regardless of whether we show the widget or not. |
670 | + w = pc.ensure_text_widget() |
671 | + assert pc.w |
672 | + |
673 | + if s: |
674 | + pc.show() |
675 | + else: |
676 | + if pc.auto_hide: |
677 | + pass # needs review |
678 | + # pc.hide() |
679 | + return |
680 | + |
681 | + if got_markdown and not isHtml: |
682 | + # Not html: convert to html. |
683 | + path = g.scanAllAtPathDirectives(c,p) or c.getNodePath(p) |
684 | + if not os.path.isdir(path): |
685 | + path = os.path.dirname(path) |
686 | + if os.path.isdir(path): |
687 | + os.chdir(path) |
688 | + |
689 | + try: |
690 | + msg = '' # The error message from docutils. |
691 | + if pc.title: |
692 | + s = pc.underline(pc.title) + s |
693 | + pc.title = None |
694 | + mdext = c.config.getString('view-rendered-md-extensions') or 'extra' |
695 | + mdext = [x.strip() for x in mdext.split(',')] |
696 | + s = markdown(s, mdext) |
697 | + s = g.toUnicode(s) # 2011/03/15 |
698 | + show = True |
699 | + except SystemMessage as sm: |
700 | + # g.trace(sm,sm.args) |
701 | + msg = sm.args[0] |
702 | + if 'SEVERE' in msg or 'FATAL' in msg: |
703 | + s = 'MD error:\n%s\n\n%s' % (msg,s) |
704 | + |
705 | + sb = w.verticalScrollBar() |
706 | + |
707 | + if sb: |
708 | + d = pc.scrollbar_pos_dict |
709 | + if pc.node_changed: |
710 | + # Set the scrollbar. |
711 | + pos = d.get(p.v,sb.sliderPosition()) |
712 | + sb.setSliderPosition(pos) |
713 | + else: |
714 | + # Save the scrollbars |
715 | + d[p.v] = pos = sb.sliderPosition() |
716 | + |
717 | + if pc.kind in ('big','rst','html', 'md'): |
718 | + w.setHtml(s) |
719 | + if pc.kind == 'big': |
720 | + w.zoomIn(4) # Doesn't work. |
721 | + else: |
722 | + w.setPlainText(s) |
723 | + |
724 | + if sb and pos: |
725 | + # Restore the scrollbars |
726 | + sb.setSliderPosition(pos) |
727 | #@+node:ekr.20110320120020.14481: *4* update_movie |
728 | def update_movie (self,s,keywords): |
729 | |
730 | @@ -852,7 +946,8 @@ |
731 | else: |
732 | # Save the scrollbars |
733 | d[p.v] = pos = sb.sliderPosition() |
734 | - if pc.kind in ('big','rst','html'): |
735 | + |
736 | + if pc.kind in ('big','rst','html', 'md'): |
737 | w.setHtml(s) |
738 | if pc.kind == 'big': |
739 | w.zoomIn(4) # Doesn't work. |
All unit tests pass, code looks good.