Package docs :: Package latex :: Module fetch_docstrings
[hide private]
[frames] | no frames]

Source Code for Module docs.latex.fetch_docstrings

   1  ############################################################################### 
   2  #                                                                             # 
   3  # Copyright (C) 2005-2012 Edward d'Auvergne                                   # 
   4  #                                                                             # 
   5  # This file is part of the program relax.                                     # 
   6  #                                                                             # 
   7  # relax is free software; you can redistribute it and/or modify               # 
   8  # it under the terms of the GNU General Public License as published by        # 
   9  # the Free Software Foundation; either version 2 of the License, or           # 
  10  # (at your option) any later version.                                         # 
  11  #                                                                             # 
  12  # relax is distributed in the hope that it will be useful,                    # 
  13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
  14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
  15  # GNU General Public License for more details.                                # 
  16  #                                                                             # 
  17  # You should have received a copy of the GNU General Public License           # 
  18  # along with relax; if not, write to the Free Software                        # 
  19  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   # 
  20  #                                                                             # 
  21  ############################################################################### 
  22   
  23  # Python module imports. 
  24  from re import search 
  25  from string import letters, lowercase, punctuation, replace, split, upper, whitespace 
  26  import sys 
  27   
  28  # Add the path to the relax base directory. 
  29  sys.path.append(sys.path[0]) 
  30  sys.path[0] = '../..' 
  31   
  32  # Import the program relax. 
  33  from user_functions.data import Uf_info; uf_info = Uf_info() 
  34  from user_functions.data import Uf_tables; uf_tables = Uf_tables() 
  35   
  36   
37 -class Fetch_docstrings:
38 - def __init__(self, file='docstring.tex'):
39 """Fetch all the docstrings of the user functions and format them LaTeX style.""" 40 41 # Initialise some variables. 42 self.in_quote = False 43 self.table_count = 1 44 self.uf_table_labels = [] 45 46 # Set up the words to index. 47 self.index_entries() 48 49 # Open the LaTeX file. 50 self.file = open(file, 'w') 51 52 # Loop over the user functions. 53 for self.uf_name, self.uf in uf_info.uf_loop(): 54 # Reset the table count for each user function. 55 self.uf_table_count = 1 56 57 # Printout. 58 sys.stdout.write("User function: %s().\n" % self.uf_name) 59 60 # Build and write out the various sections, as needed. 61 self.build_uf() 62 self.build_synopsis() 63 self.build_arg_defaults() 64 self.build_kargs() 65 self.build_description() 66 67 # Close the LaTeX file. 68 self.file.close()
69 70
71 - def break_functions(self, text):
72 """Allow the function text to be broken nicely across lines. 73 74 The '\' character will be added later by the latex_special_chars() method. 75 """ 76 77 # Allow line breaks after the opening bracket. 78 text = replace(text, "(", "(\linebreak[0]") 79 80 # Allow line breaks after periods (but not in numbers). 81 for char in letters: 82 text = replace(text, ".%s" % char, ".\linebreak[0]%s" % char) 83 84 # Allow line breaks after equal signs. 85 text = replace(text, "=", "=\linebreak[0]") 86 87 # Remove the backslash to prevent is processing. 88 text = replace(text, "\linebreak", "linebreak") 89 90 # Return the modified text. 91 return text
92 93
94 - def build_arg_defaults(self):
95 """Create the user function argument default section.""" 96 97 # The section heading. 98 self.file.write("\subsubsection{Defaults}\n\n") 99 100 # Initialise the text. 101 text = "(" 102 103 # The keyword args. 104 for i in range(len(self.uf.kargs)): 105 # Comma separation. 106 if i >= 1: 107 text += ", " 108 109 # Add the arg. 110 text += "%s=%s" % (self.uf.kargs[i]['name'], repr(self.uf.kargs[i]['default'])) 111 112 # The end. 113 text += ")" 114 115 # LaTeX formatting. 116 text = self.break_functions(text) 117 text = self.latex_quotes(text) 118 text = self.latex_special_chars(text) 119 120 # Write to file. 121 self.file.write("\\begin{flushleft}\n") 122 self.file.write("\\textsf{\\textbf{%s}%s}\n" % (self.latex_special_chars(self.break_functions(self.uf_name)), text)) 123 self.file.write("\\end{flushleft}\n\n\n")
124 125
126 - def build_description(self):
127 """Create the user function argument default section.""" 128 129 # Loop over the sections. 130 for i in range(len(self.uf.desc)): 131 # Alias the description. 132 desc = self.uf.desc[i] 133 134 # The section heading. 135 self.file.write("\subsubsection{%s}\n\n" % desc.get_title()) 136 137 # Loop over the documentation elements. 138 for type, element in desc.element_loop(): 139 # A paragraph. 140 if type == 'paragraph': 141 self.write_paragraph(element) 142 143 # Verbatim text. 144 elif type == 'verbatim': 145 self.write_verbatim(element) 146 147 # A list. 148 elif type == 'list': 149 self.write_list(element) 150 151 # An itemised list. 152 elif type == 'item list': 153 self.write_item_list(element) 154 155 # A table. 156 elif type == 'table': 157 self.write_table(element) 158 159 # A prompt example. 160 elif type == 'prompt': 161 self.write_prompt_example(element)
162 163 164
165 - def build_kargs(self):
166 """Create the user function keyword argument section.""" 167 168 # No keyword args, so do nothing. 169 if not len(self.uf.kargs): 170 return 171 172 # The section heading. 173 self.file.write("\subsubsection{Keyword arguments}\n\n") 174 175 # The keyword args. 176 for i in range(len(self.uf.kargs)): 177 # LaTeX formatting. 178 arg = self.latex_special_chars(self.uf.kargs[i]['name']) 179 text = self.latex_special_chars(self.uf.kargs[i]['desc']) 180 text = self.latex_formatting(text) 181 text = self.word_formatting(text, bold=False) 182 183 # Write to file. 184 self.file.write("\\hspace{3 mm}\\keyword{%s:} %s\n\n" % (arg, text)) 185 186 # Empty line to end with. 187 self.file.write("\n")
188 189
190 - def build_synopsis(self):
191 """Create the user function synopsis.""" 192 193 # The section heading. 194 self.file.write("\subsubsection{Synposis}\n\n") 195 196 # The text. 197 text = self.uf.title 198 199 # LaTeX formatting. 200 text = self.latex_special_chars(text) 201 text = self.latex_formatting(text) 202 text = self.word_formatting(text, bold=False) 203 204 # Write to file. 205 self.file.write(text + '\n\n\n')
206 207
208 - def build_uf(self):
209 """Create the user function sectioning.""" 210 211 # Some whitespace. 212 self.file.write("\n\n") 213 214 # Add a spaced out rule. 215 self.file.write("\\vspace{20pt}\n") 216 self.file.write("\\rule{\columnwidth}{2pt}\n") 217 self.file.write("\\vspace{-30pt}\n") 218 219 # The title. 220 self.uf_name_latex = self.uf_name 221 222 # LaTeX formatting. 223 self.uf_name_latex = self.latex_special_chars(self.uf_name_latex) 224 self.uf_name_latex = self.word_formatting(self.uf_name_latex, bold=True) 225 226 # Allow for hyphenation. 227 self.uf_name_latex = replace(self.uf_name_latex, '.', '\-.') 228 self.uf_name_latex = replace(self.uf_name_latex, '\_', '\-\_') 229 230 # Write out the title. 231 self.file.write("\subsection{%s}\n\n" % self.uf_name_latex)
232 233
234 - def indexing(self, index, bold=False):
235 """Insert index marks into the text, word by word. 236 237 @param index: The index of the word in the self.words data structure. 238 @type index: int 239 @keyword bold: A flag which if True will cause the index entries to be in bold font. 240 @type bold: bool 241 """ 242 243 # End string. 244 if bold: 245 end_string = '|textbf}' 246 else: 247 end_string = '}' 248 249 # Loop over the indices. 250 for i in xrange(len(self.entries)): 251 # Find triple word entries. 252 if index+2 < len(self.words) and self.entries[i][2] == 3 and search(self.entries[i][0], self.words[index] + ' ' + self.words[index+1] + ' ' + self.words[index+2]): 253 self.words[index] = self.words[index] + '\\index{' + self.entries[i][1] + end_string 254 255 # Find double word entries. 256 elif index+1 < len(self.words) and self.entries[i][2] == 2 and search(self.entries[i][0], self.words[index] + ' ' + self.words[index+1]): 257 self.words[index] = self.words[index] + '\\index{' + self.entries[i][1] + end_string 258 259 # Find single word entries. 260 elif self.entries[i][2] == 1 and search(self.entries[i][0], self.words[index]): 261 self.words[index] = self.words[index] + '\\index{' + self.entries[i][1] + end_string
262 263
264 - def index_entries(self):
265 """Function for returning a data structure containing all words which should be indexed.""" 266 267 # Initialise. 268 self.entries = [] 269 270 # The index entries (where to index and the index name). 271 ######################################################## 272 273 self.entries.append(['AIC', 'model selection!AIC']) 274 self.entries.append(['AICc', 'model selection!AICc']) 275 self.entries.append(['angle', 'angles']) 276 self.entries.append(['anisotropic', 'diffusion!anisotropic']) 277 self.entries.append(['ANOVA', 'model selection!ANOVA']) 278 self.entries.append(['asymmetric', 'diffusion!ellipsoid (asymmetric)']) 279 self.entries.append(['axially symmetric', 'diffusion!spheroid (axially symmetric)']) 280 281 self.entries.append(['BIC', 'model selection!BIC']) 282 self.entries.append(['BFGS', 'minimisation techniques!BFGS']) 283 self.entries.append(['bond length', 'bond length']) 284 self.entries.append(['bootstrap', 'model selection!bootstrap']) 285 self.entries.append(['bound', 'parameter!bounds']) 286 self.entries.append(['Brownian', 'diffusion!Brownian']) 287 self.entries.append(['bzip2', 'compression!bzip2']) 288 289 self.entries.append(['cauchy', 'minimisation techniques!Cauchy point']) 290 self.entries.append(['CG-Steihaug', 'minimisation techniques!CG-Steihaug']) 291 self.entries.append(['chemical exchange', 'chemical exchange']) 292 self.entries.append(['chi-squared', 'chi-squared']) 293 self.entries.append(['compression', 'compression']) 294 self.entries.append(['conjugate gradient', 'minimisation techniques!conjugate gradient']) 295 self.entries.append(['constraint', 'constraint']) 296 self.entries.append(['copy', 'copy']) 297 self.entries.append(['correlation time', 'correlation time']) 298 self.entries.append(['cross-validation', 'model selection!cross-validation']) 299 300 self.entries.append(['dasha', 'software!Dasha']) 301 self.entries.append(['Dasha', 'software!Dasha']) 302 self.entries.append(['delete', 'delete']) 303 self.entries.append(['diffusion tensor', 'diffusion!tensor']) 304 self.entries.append(['display', 'display']) 305 self.entries.append(['dogleg', 'minimisation techniques!dogleg']) 306 307 self.entries.append(['eigenvalue', 'eigenvalues']) 308 self.entries.append(['elimination', 'model elimination']) 309 self.entries.append(['ellipsoid', 'diffusion!ellipsoid (asymmetric)']) 310 self.entries.append(['Euler angle', 'Euler angles']) 311 self.entries.append(['exact trust region', 'minimisation techniques!exact trust region']) 312 313 self.entries.append(['Fletcher-Reeves', 'minimisation techniques!Fletcher-Reeves']) 314 self.entries.append(['floating point', 'floating point number']) 315 316 self.entries.append(['grace', 'software!Grace']) 317 self.entries.append(['Grace', 'software!Grace']) 318 self.entries.append(['gzip', 'compression!gzip']) 319 320 self.entries.append(['Hestenes-Stiefel', 'minimisation techniques!Hestenes-Stiefel']) 321 self.entries.append(['hypothesis testing', 'model selection!hypothesis testing']) 322 323 self.entries.append(['isotropic', 'diffusion!sphere (isotropic)']) 324 325 self.entries.append(['Levenberg-Marquardt', 'minimisation techniques!Levenberg-Marquardt']) 326 self.entries.append(['limit', 'parameter!limit']) 327 328 self.entries.append(['map', 'map']) 329 self.entries.append(['method of [Mm]ultipliers', 'minimisation techniques!Method of Multipliers']) 330 self.entries.append(['minimise', 'minimisation']) 331 self.entries.append(['minimisation', 'minimisation']) 332 self.entries.append(['model elimination', 'model elimination']) 333 self.entries.append(['modelfree4', 'software!Modelfree']) 334 self.entries.append(['Modelfree4', 'software!Modelfree']) 335 self.entries.append(['modelling', 'modelling']) 336 self.entries.append(['molecule', 'molecule']) 337 self.entries.append(['molmol', 'software!MOLMOL']) 338 self.entries.append(['Molmol', 'software!MOLMOL']) 339 340 self.entries.append(['opendx', 'software!OpenDX']) 341 self.entries.append(['OpenDX', 'software!OpenDX']) 342 self.entries.append(['optimise', 'optimise']) 343 self.entries.append(['order parameter', 'order parameter']) 344 345 self.entries.append(['newton', 'minimisation techniques!Newton']) 346 self.entries.append(['newton-CG', 'minimisation techniques!Newton conjugate gradient']) 347 self.entries.append(['NMR', 'NMR']) 348 349 self.entries.append(['PDB', 'PDB']) 350 self.entries.append(['Polak-Ribi.*re', 'minimisation techniques!Polak-Ribiere@Polak-Ribi\`ere']) 351 self.entries.append(['Polak-Ribi.*re +', 'minimisation techniques!Polak-Ribiere@Polak-Ribi\`ere +']) 352 self.entries.append(['plot', 'plot']) 353 self.entries.append(['python', 'Python']) 354 355 self.entries.append(['read', 'read']) 356 self.entries.append(['regular expression', 'regular expression']) 357 self.entries.append(['relaxation', 'relaxation']) 358 self.entries.append(['rotation', 'rotation']) 359 360 self.entries.append(['sequence', 'sequence']) 361 self.entries.append(['script', 'scripting!script file']) 362 self.entries.append(['scripting', 'scripting']) 363 self.entries.append(['simplex', 'minimisation techniques!simplex']) 364 self.entries.append(['sphere', 'diffusion!sphere (isotropic)']) 365 self.entries.append(['spheroid', 'diffusion!spheroid (axially symmetric)']) 366 self.entries.append(['sparky', 'software!Sparky']) 367 self.entries.append(['Sparky', 'software!Sparky']) 368 self.entries.append(['steepest descent', 'minimisation techniques!steepest descent']) 369 370 self.entries.append(['tar', 'tar']) 371 372 self.entries.append(['uncompressed', 'compression!uncompressed']) 373 374 self.entries.append(['write', 'write']) 375 376 self.entries.append(['xeasy', 'software!XEasy']) 377 self.entries.append(['Xeasy', 'software!XEasy']) 378 self.entries.append(['XEasy', 'software!XEasy']) 379 380 # Modifications. 381 for i in xrange(len(self.entries)): 382 # Count the number of words. 383 self.entries[i].append(len(split(self.entries[i][0], ' '))) 384 385 # Accept capitalisation. 386 if search(self.entries[i][0][0], lowercase): 387 self.entries[i][0] = '[' + upper(self.entries[i][0][0]) + self.entries[i][0][0] + ']' + self.entries[i][0][1:] 388 389 # Add a carrot to the start of the match string. 390 self.entries[i][0] = '^' + self.entries[i][0] 391 392 # Reverse the subarray in prepartion for sorting. 393 self.entries[i].reverse() 394 395 # Reverse sort by word count. 396 self.entries.sort(reverse=1) 397 for i in xrange(len(self.entries)): 398 self.entries[i].reverse()
399 400
401 - def latex_formatting(self, string):
402 """Function for handling LaTeX maths environments.""" 403 404 # Angstrom. 405 string = self.safe_replacement(string, 'Angstroms', '\AA') 406 string = self.safe_replacement(string, 'Angstrom', '\AA') 407 408 # Pi. 409 string = self.safe_replacement(string, 'pi', '$\pi$') 410 411 # Less than. 412 string = replace(string, ' < ', ' $<$ ') 413 414 # Less than or equal. 415 string = replace(string, ' <= ', ' $\le$ ') 416 417 # Much less than. 418 string = replace(string, ' << ', ' $<<$ ') 419 420 # Greater than. 421 string = replace(string, ' > ', ' $>$ ') 422 423 # Greater than or equal. 424 string = replace(string, ' >= ', ' $\ge$ ') 425 426 # Much greater than. 427 string = replace(string, ' >> ', ' $>>$ ') 428 429 # 1st, 2nd, etc. 430 string = replace(string, '1st', '1$^\mathrm{st}$') 431 string = replace(string, '2nd', '2$^\mathrm{nd}$') 432 string = replace(string, '3rd', '3$^\mathrm{rd}$') 433 string = replace(string, '4th', '4$^\mathrm{th}$') 434 string = replace(string, '5th', '5$^\mathrm{th}$') 435 string = replace(string, '6th', '6$^\mathrm{th}$') 436 string = replace(string, '7th', '7$^\mathrm{th}$') 437 string = replace(string, '8th', '8$^\mathrm{th}$') 438 string = replace(string, '9th', '9$^\mathrm{th}$') 439 string = replace(string, '0th', '0$^\mathrm{th}$') 440 string = replace(string, '1th', '1$^\mathrm{th}$') 441 string = replace(string, '2th', '2$^\mathrm{th}$') 442 string = replace(string, '3th', '3$^\mathrm{th}$') 443 444 445 # Relaxation data. 446 ################## 447 448 # R1 and R2. 449 string = self.safe_replacement(string, 'R1', 'R$_1$') 450 string = self.safe_replacement(string, 'R2', 'R$_2$') 451 452 453 # Model-free parameters. 454 ######################## 455 456 # S2f, S2s, S2, te, ts, tf, tm, Rex, r. 457 string = self.safe_replacement(string, 'S2f', '$S^2_f$') 458 string = self.safe_replacement(string, 'S2s', '$S^2_s$') 459 string = self.safe_replacement(string, 'S2', '$S^2$') 460 string = self.safe_replacement(string, 'te', '$\\tau_e$') 461 string = self.safe_replacement(string, 'ts', '$\\tau_s$') 462 string = self.safe_replacement(string, 'tf', '$\\tau_f$') 463 string = self.safe_replacement(string, 'tm', '$\\tau_m$') 464 string = self.safe_replacement(string, 'Rex', '$R_{ex}$') 465 string = self.safe_replacement(string, 'r', '$r$') 466 string = self.safe_replacement(string, '<r>', '$<$$r$$>$') 467 468 469 # Spectral densities. 470 ##################### 471 472 # J(w), J(0), J(wX), J(wH). 473 string = replace(string, 'J(w)', '$J(\omega)$') 474 string = replace(string, 'J(0)', '$J(0)$') 475 string = replace(string, 'J(wX)', '$J(\omega_X)$') 476 string = replace(string, 'J(wH)', '$J(\omega_H)$') 477 478 479 # Diffusion tensor parameters. 480 ############################## 481 482 # Diso, Da, Dr, Dx, Dy, Dz, Dpar, Dper, Dratio. 483 string = self.safe_replacement(string, 'Diso', '$\Diff_{iso}$') 484 string = self.safe_replacement(string, 'Da', '$\Diff_a$') 485 string = self.safe_replacement(string, 'Dr', '$\Diff_r$') 486 string = self.safe_replacement(string, 'R', '$\mathfrak{R}$') 487 string = self.safe_replacement(string, 'Dx', '$\Diff_x$') 488 string = self.safe_replacement(string, 'Dy', '$\Diff_y$') 489 string = self.safe_replacement(string, 'Dz', '$\Diff_z$') 490 string = self.safe_replacement(string, 'Dpar', '$\Diff_\Par$') 491 string = self.safe_replacement(string, 'Dper', '$\Diff_\Per$') 492 string = self.safe_replacement(string, 'Dratio', '$\Diff_{ratio}$') 493 494 495 # Angles. 496 ######### 497 498 # alpha, beta, gamma, theta, phi. 499 string = self.safe_replacement(string, 'alpha', '$\\alpha$') 500 string = self.safe_replacement(string, 'beta', '$\\beta$') 501 string = self.safe_replacement(string, 'gamma', '$\\gamma$') 502 string = self.safe_replacement(string, 'theta', '$\\theta$') 503 string = self.safe_replacement(string, 'phi', '$\\phi$') 504 505 506 # Direction cosines. 507 #################### 508 509 # delta_x, delta_y, delta_z. 510 string = self.safe_replacement(string, 'dx', '$\\delta_x$') 511 string = self.safe_replacement(string, 'dy', '$\\delta_y$') 512 string = self.safe_replacement(string, 'dz', '$\\delta_z$') 513 514 515 # Indices. 516 ########## 517 518 # i, j, k, l, m, n, x, y, z, A, b, u. 519 string = self.safe_replacement(string, 'i', '$i$') 520 string = self.safe_replacement(string, 'j', '$j$') 521 string = self.safe_replacement(string, 'k', '$k$') 522 string = self.safe_replacement(string, 'l', '$l$') 523 string = self.safe_replacement(string, 'm', '$m$') 524 string = self.safe_replacement(string, 'n', '$n$') 525 string = self.safe_replacement(string, 'x', '$x$') 526 string = self.safe_replacement(string, 'y', '$y$') 527 string = self.safe_replacement(string, 'z', '$z$') 528 string = self.safe_replacement(string, 'b', '$b$') 529 string = self.safe_replacement(string, 'u', '$u$') 530 531 532 # Misc. 533 ####### 534 535 # tau. 536 string = self.safe_replacement(string, 'tau', '$\\tau$') 537 538 # Polak-Ribi\`ere. 539 string = self.safe_replacement(string, 'Polak-Ribiere', 'Polak-Ribi\`ere') 540 541 542 # Return the new text. 543 return string
544 545
546 - def latex_quotes(self, string):
547 """Function for changing the quotes for LaTeX processing.""" 548 549 # Initialise. 550 new_string = '' 551 in_quote = 0 552 553 # Loop over the characters. 554 for i in xrange(len(string)): 555 # Find the quote marks. 556 if search('\'', string[i]): 557 # Swap the opening ' with `. 558 if not in_quote and (i == 0 or not search('[a-z]', string[i-1])): 559 new_string = new_string + '`' 560 in_quote = 1 561 continue 562 563 # Just exited the quote 564 else: 565 in_quote = 0 566 567 # Append the character. 568 new_string = new_string + string[i] 569 570 return new_string
571 572
573 - def latex_special_chars(self, string):
574 """Function for handling LaTeX special characters.""" 575 576 # Damned backslashes. 577 string = replace(string, '\\', 'This is a backslash to be replaced at the end of this functioN') 578 579 # List of special characters (prefix a backslash). 580 for char in "#$%&_{}": 581 string = replace(string, char, '\\'+char) 582 583 # Doubly special characters (prefix a backslash and postfix '{}'). 584 for char in "^~": 585 string = replace(string, char, '\\'+char+'{}') 586 587 # Damned backslashes! 588 string = replace(string, 'This is a backslash to be replaced at the end of this functioN', '$\\backslash$') 589 590 # Add a backslash to where it really should be. 591 string = replace(string, 'linebreak[0]', '\linebreak[0]') 592 593 # Return the new text. 594 return string
595 596
597 - def quotes(self, index):
598 """Function for placing quotes within the quote environment.""" 599 600 # Split the word by '. 601 elements = split(self.words[index], "'") 602 603 # Single word quote. 604 if len(elements) == 3: 605 self.words[index] = elements[0] + '\quotecmd{' + elements[1] + '}' + elements[2] 606 607 # Weird quote. 608 elif len(elements) > 3: 609 sys.stderr.write('Unknown quote: ' + repr(self.words[index])) 610 sys.exit() 611 612 # Multiword quote. 613 if len(elements) == 2: 614 # Start of the quote. 615 if not self.in_quote and not search('[a-z]$', elements[0]): 616 self.words[index] = elements[0] + '\quotecmd{' + elements[1] 617 self.in_quote = 1 618 619 # End of the quote. 620 elif self.in_quote: 621 self.words[index] = elements[0] + '}' + elements[1] 622 self.in_quote = 0
623 624
625 - def safe_replacement(self, string, text, latex):
626 """Only replace in safe places within the text.""" 627 628 # Combos (if only RE could be used!) 629 630 # A number out the front. 631 string = replace(string, '0'+text, '0'+latex) 632 string = replace(string, '1'+text, '1'+latex) 633 string = replace(string, '2'+text, '2'+latex) 634 string = replace(string, '3'+text, '3'+latex) 635 string = replace(string, '4'+text, '4'+latex) 636 string = replace(string, '5'+text, '5'+latex) 637 string = replace(string, '6'+text, '6'+latex) 638 string = replace(string, '7'+text, '7'+latex) 639 string = replace(string, '8'+text, '8'+latex) 640 string = replace(string, '9'+text, '9'+latex) 641 642 # In a sentence. 643 string = replace(string, ' '+text+',', ' '+latex+',') 644 string = replace(string, ' '+text+'.', ' '+latex+'.') 645 string = replace(string, ' '+text+' ', ' '+latex+' ') 646 string = replace(string, ' '+text+';', ' '+latex+';') 647 string = replace(string, ' '+text+':', ' '+latex+':') 648 649 # In lists []. 650 string = replace(string, '['+text+']', '['+latex+']') 651 string = replace(string, '['+text+' ', '['+latex+' ') 652 string = replace(string, '['+text+',', '['+latex+',') 653 string = replace(string, '['+text+';', '['+latex+';') 654 string = replace(string, ' '+text+']', ' '+latex+']') 655 656 # In lists (). 657 string = replace(string, '('+text+')', '('+latex+')') 658 string = replace(string, '('+text+' ', '('+latex+' ') 659 string = replace(string, '('+text+',', '('+latex+',') 660 string = replace(string, '('+text+';', '('+latex+';') 661 string = replace(string, ' '+text+')', ' '+latex+')') 662 663 # In lists {}. 664 string = replace(string, '{'+text+' ', '{'+latex+' ') 665 string = replace(string, '{'+text+',', '{'+latex+',') 666 string = replace(string, '{'+text+';', '{'+latex+';') 667 string = replace(string, ' '+text+'\\', ' '+latex+'\\') 668 669 # Quoted. 670 string = replace(string, '`'+text+'\'', '`'+latex+'\'') 671 string = replace(string, '`'+text+' ', '`'+latex+' ') 672 string = replace(string, '`'+text+',', '`'+latex+',') 673 string = replace(string, '`'+text+'.', '`'+latex+'.') 674 string = replace(string, '`'+text+';', '`'+latex+';') 675 string = replace(string, ' '+text+'\'', ' '+latex+'\'') 676 677 # End of the line. 678 substring = replace(string[-len(text)-1:], ' '+text, ' '+latex) 679 string = string[0:-len(text)-1] + substring 680 681 substring = replace(string[-len(text)-1:], '.'+text, '.'+latex) 682 string = string[0:-len(text)-1] + substring 683 684 string = replace(string, ' '+text+'\n', ' '+latex+'\n') 685 string = replace(string, '.'+text+'\n', '.'+latex+'\n') 686 687 # Maths 688 string = replace(string, ' '+text+'\^', ' '+latex+'\^') 689 string = replace(string, '('+text+'\^', '('+latex+'\^') 690 string = replace(string, '\n'+text+'\^', '\n'+latex+'\^') 691 692 # At the start of the line. 693 if search('^'+text+'['+punctuation+']', string) or search('^'+text+'['+whitespace+']', string) or search('\n'+text+'['+punctuation+']', string) or search('\n'+text+'['+whitespace+']', string): 694 string = replace(string, text+' ', latex+' ') 695 string = replace(string, text+',', latex+',') 696 string = replace(string, text+'.', latex+'.') 697 string = replace(string, text+';', latex+';') 698 string = replace(string, text+']', latex+']') 699 string = replace(string, text+')', latex+')') 700 string = replace(string, text+'^', latex+'^') 701 string = replace(string, text+'\\', latex+'\\') 702 string = replace(string, text+'\'', latex+'\'') 703 string = replace(string, text+'\n', latex+'\n') 704 705 706 # Return the string. 707 return string
708 709
710 - def tabular_wrapping(self, table, max_char=100):
711 """Determine if column wrapping should occur. 712 713 @param table: The table. 714 @type table: list of lists of str 715 @keyword max_char: The maximum number of characters a column is allowed before wrapping is applied. 716 @type max_char: int 717 @return: The list of flags for wrapping columns. 718 @rtype: list of bool 719 """ 720 721 # The column widths. 722 num_cols = len(table[0]) 723 widths = [0] * num_cols 724 for i in range(len(table)): 725 for j in range(num_cols): 726 # The element is larger than the previous. 727 if len(table[i][j]) > widths[j]: 728 widths[j] = len(table[i][j]) 729 730 # The wrapping. 731 wrap = [] 732 for i in range(len(widths)): 733 if widths[i] > max_char: 734 wrap.append(True) 735 else: 736 wrap.append(False) 737 738 # Return the result. 739 return wrap
740 741
742 - def word_formatting(self, text, bold=False):
743 """Format the text, word by word. 744 745 @param text: The text to format. 746 @type text: str 747 @keyword bold: A flag for the indexing which if True will cause index entries to be in bold font. 748 @type bold: bool 749 @return: The formatted text. 750 @rtype: str 751 """ 752 753 # Initialise. 754 new_text = '' 755 756 # Split the string. 757 self.words = split(text, ' ') 758 759 # Loop over the words one by one. 760 for i in xrange(len(self.words)): 761 # Indexing. 762 self.indexing(i, bold=bold) 763 764 # Quotes. 765 self.quotes(i) 766 767 # Recreate the string. 768 if i == 0: 769 new_text = self.words[i] 770 else: 771 new_text += ' ' + self.words[i] 772 773 # Return the text. 774 return new_text
775 776
777 - def write_item_list(self, item_list):
778 """Format and write out an itemised list. 779 780 @param item_list: The list of items and description lists. 781 @type item_list: list of list of str 782 """ 783 784 # Loop over the elements. 785 latex_lines = [] 786 items = False 787 for i in range(len(item_list)): 788 # LaTeX formatting of the item. 789 item = item_list[i][0] 790 if item == None: 791 item = '' 792 if item != '': 793 items = True 794 item = self.latex_special_chars(item) 795 item = self.latex_formatting(item) 796 item = self.word_formatting(item) 797 798 # LaTeX formatting of the description. 799 desc = self.latex_special_chars(item_list[i][1]) 800 desc = self.latex_formatting(desc) 801 desc = self.word_formatting(desc) 802 803 # Write to file. 804 if item != '': 805 latex_lines.append("\\item[%s --] %s\n" % (item, desc)) 806 else: 807 latex_lines.append("\\item[]%s\n" % desc) 808 809 # Start the environment. 810 if not items: 811 self.file.write("\\begin{itemize}\n") 812 else: 813 self.file.write("\\begin{description}\n") 814 815 # Add the lines. 816 for line in latex_lines: 817 self.file.write(line) 818 819 # End the environment. 820 if not items: 821 self.file.write("\\end{itemize}\n\n") 822 else: 823 self.file.write("\\end{description}\n\n")
824 825
826 - def write_list(self, list):
827 """Format and write out a list. 828 829 @param list: The list. 830 @type list: list of str 831 """ 832 833 # Start the environment. 834 self.file.write("\\begin{itemize}\n") 835 836 # Loop over the elements. 837 for item in list: 838 # LaTeX formatting. 839 item = self.latex_special_chars(item) 840 item = self.latex_formatting(item) 841 item = self.word_formatting(item) 842 843 # Write to file. 844 self.file.write("\\item[]%s\n" % item) 845 846 # End the environment. 847 self.file.write("\\end{itemize}\n\n")
848 849
850 - def write_paragraph(self, text):
851 """Format and write out the paragraph. 852 853 @param text: The single line of text to convert into a LaTeX paragraph. 854 @type text: str 855 """ 856 857 # LaTeX formatting. 858 text = self.latex_special_chars(text) 859 text = self.latex_formatting(text) 860 text = self.word_formatting(text) 861 862 # Write to file. 863 self.file.write(text + "\n\n")
864 865
866 - def write_prompt_example(self, list):
867 """Format and write out the prompt UI examples. 868 869 @param list: The list of prompt UI examples. 870 @type list: list of str 871 """ 872 873 # Loop over the examples. 874 for text in list: 875 # LaTeX formatting. 876 text = self.break_functions(text) 877 text = self.latex_quotes(text) 878 text = self.latex_special_chars(text) 879 880 # Write to file. 881 self.file.write("\\smallexample{%s}\n\n" % text) 882 883 # An extra newline. 884 self.file.write("\n")
885 886
887 - def write_table(self, label):
888 """Format and write out a table. 889 890 @param label: The unique table label. 891 @type label: list of lists of str 892 """ 893 894 # Get the table. 895 table = uf_tables.get_table(label) 896 897 # Add a reference. 898 self.file.write("Please see Table~\\ref{%s} on page~\\pageref{%s}.\n\n" % (label, label)) 899 900 # The table already exists, so skip creating it a second time. 901 if label in self.uf_table_labels: 902 return 903 else: 904 self.uf_table_labels.append(label) 905 906 # Determine the table wrapping. 907 col_wrap = self.tabular_wrapping(table.cells) 908 wrap = sum(col_wrap) 909 910 # The number of rows and columns. 911 num_rows = len(table.cells) 912 num_cols = len(table.headings) 913 914 # Start the centred table. 915 if table.longtable: 916 # A longtable. 917 self.file.write("\\onecolumn\n") 918 self.file.write("\\begin{scriptsize}\n") 919 self.file.write("\\begin{center}\n") 920 self.file.write("\\begin{longtable}{%s}\n" % ("l"*num_cols)) 921 else: 922 # Normal tables. 923 self.file.write("\\begin{table*}\n") 924 self.file.write("\\begin{scriptsize}\n") 925 self.file.write("\\begin{center}\n") 926 927 # A caption. 928 self.file.write("\\caption[%s]{%s}\n" % (table.caption_short, table.caption)) 929 930 # The formatting. 931 if table.longtable: 932 # Start the longtable environment and add the toprule. 933 self.file.write("\\\\\n") 934 self.file.write("\\toprule\n") 935 else: 936 # Start the tabular environment and add the toprule. 937 if wrap: 938 self.file.write("\\begin{tabularx}{\\textwidth}{") 939 else: 940 self.file.write("\\begin{tabular}{") 941 for i in range(num_cols): 942 if col_wrap[i]: 943 text = "X" 944 else: 945 text = "l" 946 self.file.write(text) 947 self.file.write("}\n") 948 self.file.write("\\\\[-5pt]\n") 949 self.file.write("\\toprule\n") 950 951 # Generate the LaTeX headings. 952 for j in range(num_cols): 953 # Column separator. 954 if j > 0: 955 self.file.write(' & ') 956 957 # The cell contents. 958 cell = table.headings[j] 959 cell = self.latex_special_chars(cell) 960 cell = self.latex_formatting(cell) 961 962 # Write the cell contents. 963 self.file.write(cell) 964 965 # End of the header line. 966 self.file.write(" \\\\\n") 967 968 # The central formatting. 969 if table.longtable: 970 self.file.write("\\midrule\n") 971 self.file.write("\\endhead\n\n") 972 self.file.write("\\bottomrule\n") 973 self.file.write("\\endfoot\n") 974 else: 975 # Add the midrule. 976 self.file.write("\\midrule\n") 977 978 # The label for longtables. 979 if table.longtable: 980 self.file.write("\\label{%s}\n" % label) 981 982 # Loop over the main table lines. 983 for i in range(num_rows): 984 # Loop over the columns. 985 for j in range(num_cols): 986 # Column separator. 987 if j > 0: 988 self.file.write(' & ') 989 990 # The cell contents. 991 cell = table.cells[i][j] 992 cell = self.latex_special_chars(cell) 993 cell = self.latex_formatting(cell) 994 995 # Write the cell contents. 996 self.file.write(cell) 997 998 # End of the line. 999 self.file.write(" \\\\\n") 1000 1001 # Terminate. 1002 if table.longtable: 1003 self.file.write("\\end{longtable}\n") 1004 self.file.write("\\end{center}\n") 1005 self.file.write("\\end{scriptsize}\n") 1006 self.file.write("\\twocolumn\n") 1007 else: 1008 self.file.write("\\bottomrule\n") 1009 self.file.write("\\\\[-5pt]\n") 1010 self.file.write("\\label{%s}\n" % label) 1011 if wrap: 1012 self.file.write("\\end{tabularx}\n") 1013 else: 1014 self.file.write("\\end{tabular}\n") 1015 self.file.write("\\end{center}\n") 1016 self.file.write("\\end{scriptsize}\n") 1017 self.file.write("\\end{table*}\n") 1018 1019 # Increment the table counts. 1020 self.table_count += 1 1021 self.uf_table_count += 1 1022 1023 # A some newlines. 1024 self.file.write("\n\n")
1025 1026
1027 - def write_verbatim(self, text):
1028 """Format and write out the verbatim text. 1029 1030 @param text: The text to write out in a LaTeX verbatim environment. 1031 @type text: str 1032 """ 1033 1034 # Write to file. 1035 self.file.write("{\\footnotesize \\begin{verbatim}\n") 1036 self.file.write(text) 1037 self.file.write("\n\\end{verbatim}}\n\n")
1038