src/eric7/QScintilla/MarkupProviders/MarkdownProvider.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2017 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Markdown markup provider.
8 """
9
10 from PyQt6.QtCore import QCoreApplication
11 from PyQt6.QtWidgets import QDialog, QInputDialog
12
13 from .MarkupBase import MarkupBase
14
15
16 class MarkdownProvider(MarkupBase):
17 """
18 Class implementing the Markdown markup provider.
19 """
20 def __init__(self):
21 """
22 Constructor
23 """
24 super().__init__()
25
26 def kind(self):
27 """
28 Public method to get the markup kind.
29
30 @return string with markup kind
31 @rtype str
32 """
33 return "markdown"
34
35 def hasBold(self):
36 """
37 Public method to indicate the availability of bold markup.
38
39 @return flag indicating the availability of bold markup
40 @rtype bool
41 """
42 return True
43
44 def bold(self, editor):
45 """
46 Public method to generate bold text.
47
48 @param editor reference to the editor to work on
49 @type Editor
50 """
51 self.__insertMarkup("**", editor)
52
53 def hasItalic(self):
54 """
55 Public method to indicate the availability of italic markup.
56
57 @return flag indicating the availability of italic markup
58 @rtype bool
59 """
60 return True
61
62 def italic(self, editor):
63 """
64 Public method to generate italic text.
65
66 @param editor reference to the editor to work on
67 @type Editor
68 """
69 self.__insertMarkup("_", editor)
70
71 def hasStrikethrough(self):
72 """
73 Public method to indicate the availability of strikethrough markup.
74
75 @return flag indicating the availability of strikethrough markup
76 @rtype bool
77 """
78 return True
79
80 def strikethrough(self, editor):
81 """
82 Public method to generate strikethrough text.
83
84 @param editor reference to the editor to work on
85 @type Editor
86 """
87 self.__insertMarkup("~~", editor)
88
89 def headerLevels(self):
90 """
91 Public method to determine the available header levels.
92
93 @return supported header levels
94 @rtype int
95 """
96 return 6
97
98 def header(self, editor, level):
99 """
100 Public method to generate a header.
101
102 @param editor reference to the editor to work on
103 @type Editor
104 @param level header level
105 @type int
106 """
107 if editor is None or level > self.headerLevels():
108 return
109
110 editor.beginUndoAction()
111 cline, cindex = editor.getCursorPosition()
112 editor.insertAt(level * "#" + " ", cline, 0)
113 editor.setCursorPosition(cline, level + 1)
114 editor.endUndoAction()
115
116 def hasCode(self):
117 """
118 Public method to indicate the availability of inline code markup.
119
120 @return flag indicating the availability of inline code markup
121 @rtype bool
122 """
123 return True
124
125 def code(self, editor):
126 """
127 Public method to generate inline code text.
128
129 @param editor reference to the editor to work on
130 @type Editor
131 """
132 self.__insertMarkup("`", editor)
133
134 def hasCodeBlock(self):
135 """
136 Public method to indicate the availability of code block markup.
137
138 @return flag indicating the availability of code block markup
139 @rtype bool
140 """
141 return True
142
143 def codeBlock(self, editor):
144 """
145 Public method to generate code block text.
146
147 @param editor reference to the editor to work on
148 @type Editor
149 """
150 if editor is None:
151 return
152
153 lineSeparator = editor.getLineSeparator()
154 editor.beginUndoAction()
155 if editor.hasSelectedText():
156 newText = "```{0}{1}```{0}".format(
157 lineSeparator, editor.selectedText())
158 editor.replaceSelectedText(newText)
159 else:
160 editor.insert("```{0}{0}```{0}".format(lineSeparator))
161 cline, cindex = editor.getCursorPosition()
162 editor.setCursorPosition(cline + 1, 0)
163 editor.endUndoAction()
164
165 def __insertMarkup(self, markup, editor):
166 """
167 Private method to insert the specified markup.
168
169 If the editor has selected text, this text is enclosed by the given
170 markup. If no text is selected, the markup is inserted at the cursor
171 position and the cursor is positioned in between.
172
173 @param markup markup string to be inserted
174 @type str
175 @param editor reference to the editor to work on
176 @type Editor
177 """
178 if editor is None:
179 return
180
181 editor.beginUndoAction()
182 if editor.hasSelectedText():
183 newText = "{0}{1}{0}".format(markup, editor.selectedText())
184 editor.replaceSelectedText(newText)
185 else:
186 editor.insert(2 * markup)
187 cline, cindex = editor.getCursorPosition()
188 editor.setCursorPosition(cline, cindex + len(markup))
189 editor.endUndoAction()
190
191 def hasHyperlink(self):
192 """
193 Public method to indicate the availability of hyperlink markup.
194
195 @return flag indicating the availability of hyperlink markup
196 @rtype bool
197 """
198 return True
199
200 def hyperlink(self, editor):
201 """
202 Public method to generate hyperlink text.
203
204 @param editor reference to the editor to work on
205 @type Editor
206 """
207 if editor is None:
208 return
209
210 from .HyperlinkMarkupDialog import HyperlinkMarkupDialog
211 dlg = HyperlinkMarkupDialog(False, True)
212 if dlg.exec() == QDialog.DialogCode.Accepted:
213 text, target, title = dlg.getData()
214
215 link = "[{0}]".format(text)
216 if target and title:
217 link = '{0}({1} "{2}")'.format(link, target, title)
218 elif target:
219 link = '{0}({1})'.format(link, target)
220 elif title:
221 link = '{0}("{1}")'.format(link, title)
222
223 editor.beginUndoAction()
224 cline, cindex = editor.getCursorPosition()
225 editor.insert(link)
226 editor.setCursorPosition(cline, cindex + len(link))
227 editor.endUndoAction()
228
229 def hasLine(self):
230 """
231 Public method to indicate the availability of a horizontal line markup.
232
233 @return flag indicating the availability of a horizontal line markup
234 @rtype bool
235 """
236 return True
237
238 def line(self, editor):
239 """
240 Public method to generate a horizontal line text.
241
242 @param editor reference to the editor to work on
243 @type Editor
244 """
245 if editor is None:
246 return
247
248 lineSeparator = editor.getLineSeparator()
249 editor.beginUndoAction()
250 markup = "{0}-----{0}{0}".format(lineSeparator)
251 editor.insert(markup)
252 cline, cindex = editor.getCursorPosition()
253 editor.setCursorPosition(cline + 3, 0)
254 editor.endUndoAction()
255
256 def hasQuote(self):
257 """
258 Public method to indicate the availability of block quote markup.
259
260 @return flag indicating the availability of block quote markup
261 @rtype bool
262 """
263 return True
264
265 def quote(self, editor):
266 """
267 Public method to generate block quote text.
268
269 @param editor reference to the editor to work on
270 @type Editor
271 """
272 if editor is None:
273 return
274
275 editor.beginUndoAction()
276 markup = "> "
277 sline, sindex, eline, eindex = editor.getSelection()
278 for line in range(sline, eline + 1 if eindex > 0 else eline):
279 editor.insertAt(markup, line, 0)
280 editor.endUndoAction()
281
282 def hasImage(self):
283 """
284 Public method to indicate the availability of image markup.
285
286 @return flag indicating the availability of image markup
287 @rtype bool
288 """
289 return True
290
291 def image(self, editor):
292 """
293 Public method to generate image text.
294
295 @param editor reference to the editor to work on
296 @type Editor
297 """
298 if editor is None:
299 return
300
301 from .ImageMarkupDialog import ImageMarkupDialog
302 dlg = ImageMarkupDialog(ImageMarkupDialog.MarkDownMode)
303 if dlg.exec() == QDialog.DialogCode.Accepted:
304 address, altText, title, originalSize, width, height = (
305 dlg.getData()
306 )
307
308 if title:
309 markup = '![{0}]({1} "{2}")'.format(altText, address, title)
310 else:
311 markup = '![{0}]({1})'.format(altText, address)
312
313 editor.beginUndoAction()
314 editor.insert(markup)
315 cline, cindex = editor.getCursorPosition()
316 editor.setCursorPosition(cline, cindex + len(markup))
317 editor.endUndoAction()
318
319 def hasBulletedList(self):
320 """
321 Public method to indicate the availability of bulleted list markup.
322
323 @return flag indicating the availability of bulleted list markup
324 @rtype bool
325 """
326 return True
327
328 def bulletedList(self, editor):
329 """
330 Public method to generate bulleted list text.
331
332 @param editor reference to the editor to work on
333 @type Editor
334 """
335 self.__makeList(editor, False)
336
337 def hasNumberedList(self):
338 """
339 Public method to indicate the availability of numbered list markup.
340
341 @return flag indicating the availability of numbered list markup
342 @rtype bool
343 """
344 return True
345
346 def numberedList(self, editor):
347 """
348 Public method to generate numbered list text.
349
350 @param editor reference to the editor to work on
351 @type Editor
352 """
353 self.__makeList(editor, True)
354
355 def __makeList(self, editor, numberedList):
356 """
357 Private method to generate the desired list markup.
358
359 @param editor reference to the editor to work on
360 @type Editor
361 @param numberedList flag indicating the generation of a numbered list
362 @type bool
363 """
364 if editor is None:
365 return
366
367 markup = " 1. " if numberedList else " * "
368 lineSeparator = editor.getLineSeparator()
369 editor.beginUndoAction()
370 if editor.hasSelectedText():
371 startLine, startIndex, endLine, endIndex = (
372 editor.getSelection()
373 )
374 if endIndex == 0:
375 endLine -= 1
376 for line in range(startLine, endLine + 1):
377 editor.insertAt(markup, line, 0)
378 editor.setCursorPosition(endLine + 1, 0)
379 else:
380 listElements, ok = QInputDialog.getInt(
381 None,
382 QCoreApplication.translate(
383 "MarkdownProvider", "Create List"),
384 QCoreApplication.translate(
385 "MarkdownProvider",
386 "Enter desired number of list elements:"),
387 0, 0, 99, 1)
388 if ok:
389 if listElements == 0:
390 listElements = 1
391 cline, cindex = editor.getCursorPosition()
392 listBody = (
393 listElements * "{1}{0}".format(lineSeparator, markup)
394 )
395 if cindex == 0:
396 editor.insertAt(listBody, cline, cindex)
397 editor.setCursorPosition(cline, len(markup))
398 else:
399 if cline == editor.lines() - 1:
400 editor.insertAt(lineSeparator, cline, 1000)
401 editor.insertAt(listBody, cline + 1, 0)
402 editor.setCursorPosition(cline + 1, len(markup))
403 editor.endUndoAction()

eric ide

mercurial