src/eric7/QScintilla/MarkupProviders/RestructuredTextProvider.py

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

eric ide

mercurial