src/eric7/QScintilla/MarkupProviders/MarkdownProvider.py

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

eric ide

mercurial