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

Proposed by Jake Peck on 2013-02-08
Status: Merged
Approved by: Jake Peck on 2013-05-02
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 on 2013-05-02
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 on 2013-02-08

Correction on comment definitions for md mode.

5604. By Jake Peck on 2013-02-08

Updated viewrendered docstring

5605. By Jake Peck on 2013-02-11

Merged revs 5601-5602 from mainline

5606. By Jake Peck on 2013-02-11

Fancier colorizer, based on https://github.com/peterlynch/jEdit-modes/blob/master/markdown.xml - run through jEdit2py

5607. By Jake Peck on 2013-02-11

Added configurable support for markdown extensions.

5608. By Jake Peck on 2013-02-17

Merge upstream revision 5603

5609. By Jake Peck on 2013-02-25

merge upstream rev 5605

5610. By Jake Peck on 2013-02-25

merge upstream rev 5606

5611. By Jake Peck on 2013-03-05

Merge upstream rev 5634

5612. By Jake Peck on 2013-03-28

Merged upstrem rev. 5644

5613. By Jake Peck on 2013-05-02

Merged upstream rev 5757

Jake Peck (gatesphere) wrote :

All unit tests pass, code looks good.

review: Approve
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: