Merge lp:~gatesphere/leo-editor/markdown_support into lp:leo-editor

Proposed by Jake Peck
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
Reviewer Review Type Date Requested Status
Jake Peck Approve
Review via email: mp+147256@code.launchpad.net

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://pypi.python.org/pypi/Markdown).

To post a comment you must log in.
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

Revision history for this message
Jake Peck (gatesphere) wrote :

All unit tests pass, code looks good.

review: Approve
Revision history for this message
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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.

Subscribers

People subscribed via source and target branches

to all changes: