1   
   2   
   3   
   4   
   5   
   6   
   7   
   8   
   9   
  10   
  11   
  12   
  13   
  14   
  15   
  16   
  17   
  18   
  19   
  20   
  21   
  22   
  23   
  24   
  25   
  26  from inspect import formatargspec, getargspec, getdoc 
  27  from re import match, search 
  28  from string import letters, lowercase, lstrip, punctuation, replace, rstrip, split, upper, whitespace 
  29  import sys 
  30   
  31   
  32  sys.path.append(sys.path[0]) 
  33  sys.path[0] = '../..' 
  34   
  35   
  36  from prompt.interpreter import Interpreter 
  37   
  38   
  40 -    def __init__(self, file='docstring.tex'): 
   41          """Fetch all the docstrings of the user functions and format them LaTeX style.""" 
  42   
  43           
  44          self.script_file = None 
  45          self.intro_string = '' 
  46          self.dummy_mode = 1 
  47   
  48           
  49          self.table_count = 1 
  50   
  51           
  52          interpreter = Interpreter(self) 
  53   
  54           
  55          self.get_blacklist() 
  56   
  57           
  58          self.file = open(file, 'w') 
  59   
  60           
  61          names = sorted(interpreter._locals.keys()) 
  62   
  63           
  64          for name in names: 
  65               
  66              if name in self.blacklist: 
  67                  continue 
  68   
  69               
  70              object = interpreter._locals[name] 
  71   
  72               
  73              if hasattr(object, '__relax_help__'): 
  74                   
  75                  self.doc_user_class(name, object) 
  76                  continue 
  77   
  78               
  79              if not hasattr(object, '__doc__') or not object.__doc__: 
  80                  continue 
  81   
  82               
  83              self.parse_docstring(name, object) 
  84   
  85           
  86          self.file.close() 
   87   
  88   
  90          """Allow the function text to be broken nicely across lines. 
  91   
  92          The '\' character will be added later by the latex_special_chars() method. 
  93          """ 
  94   
  95           
  96          text = replace(text, "(", "(\linebreak[0]") 
  97   
  98           
  99          for char in letters: 
 100              text = replace(text, ".%s" % char, ".\linebreak[0]%s" % char) 
 101   
 102           
 103          text = replace(text, "=", "=\linebreak[0]") 
 104   
 105           
 106          text = replace(text, "\linebreak", "linebreak") 
 107   
 108           
 109          return text 
  110   
 111   
 113          """Document the user class.""" 
 114   
 115           
 116          names = sorted(dir(parent_object)) 
 117   
 118           
 119          for name in names: 
 120               
 121              if search('^_', name): 
 122                  continue 
 123   
 124               
 125              object = getattr(parent_object, name) 
 126   
 127               
 128              if not hasattr(object, '__doc__') or not object.__doc__: 
 129                  continue 
 130   
 131               
 132              self.parse_docstring(parent_name + '.' + name, object) 
  133   
 134   
 136          """Maintained list of objects in the interpreter namespace which should not be documented.""" 
 137   
 138           
 139          self.blacklist = [] 
 140   
 141           
 142          self.blacklist.append('pi') 
 143          self.blacklist.append('script') 
  144   
 145   
 147          """Function of inserting index marks into the text.""" 
 148   
 149           
 150          if bold: 
 151              end_string = '|textbf}' 
 152          else: 
 153              end_string = '}' 
 154   
 155           
 156          for i in xrange(len(self.entries)): 
 157               
 158              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]): 
 159                  self.words[index] = self.words[index] + '\\index{' + self.entries[i][1] + end_string 
 160   
 161               
 162              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]): 
 163                  self.words[index] = self.words[index] + '\\index{' + self.entries[i][1] + end_string 
 164   
 165               
 166              elif self.entries[i][2] == 1 and search(self.entries[i][0], self.words[index]): 
 167                  self.words[index] = self.words[index] + '\\index{' + self.entries[i][1] + end_string 
  168   
 169   
 171          """Function for returning a data structure containing all words which should be indexed.""" 
 172   
 173           
 174          self.entries = [] 
 175   
 176           
 177           
 178   
 179          self.entries.append(['AIC', 'model selection!AIC']) 
 180          self.entries.append(['AICc', 'model selection!AICc']) 
 181          self.entries.append(['angle', 'angles']) 
 182          self.entries.append(['anisotropic', 'diffusion!anisotropic']) 
 183          self.entries.append(['ANOVA', 'model selection!ANOVA']) 
 184          self.entries.append(['asymmetric', 'diffusion!ellipsoid (asymmetric)']) 
 185          self.entries.append(['axially symmetric', 'diffusion!spheroid (axially symmetric)']) 
 186   
 187          self.entries.append(['BIC', 'model selection!BIC']) 
 188          self.entries.append(['BFGS', 'minimisation techniques!BFGS']) 
 189          self.entries.append(['bond length', 'bond length']) 
 190          self.entries.append(['bootstrap', 'model selection!bootstrap']) 
 191          self.entries.append(['bound', 'parameter!bounds']) 
 192          self.entries.append(['Brownian', 'diffusion!Brownian']) 
 193          self.entries.append(['bzip2', 'compression!bzip2']) 
 194   
 195          self.entries.append(['cauchy', 'minimisation techniques!Cauchy point']) 
 196          self.entries.append(['CG-Steihaug', 'minimisation techniques!CG-Steihaug']) 
 197          self.entries.append(['chemical exchange', 'chemical exchange']) 
 198          self.entries.append(['chi-squared', 'chi-squared']) 
 199          self.entries.append(['compression', 'compression']) 
 200          self.entries.append(['conjugate gradient', 'minimisation techniques!conjugate gradient']) 
 201          self.entries.append(['constraint', 'constraint']) 
 202          self.entries.append(['copy', 'copy']) 
 203          self.entries.append(['correlation time', 'correlation time']) 
 204          self.entries.append(['cross-validation', 'model selection!cross-validation']) 
 205   
 206          self.entries.append(['dasha', 'software!Dasha']) 
 207          self.entries.append(['Dasha', 'software!Dasha']) 
 208          self.entries.append(['delete', 'delete']) 
 209          self.entries.append(['diffusion tensor', 'diffusion!tensor']) 
 210          self.entries.append(['display', 'display']) 
 211          self.entries.append(['dogleg', 'minimisation techniques!dogleg']) 
 212   
 213          self.entries.append(['eigenvalue', 'eigenvalues']) 
 214          self.entries.append(['elimination', 'model elimination']) 
 215          self.entries.append(['ellipsoid', 'diffusion!ellipsoid (asymmetric)']) 
 216          self.entries.append(['Euler angle', 'Euler angles']) 
 217          self.entries.append(['exact trust region', 'minimisation techniques!exact trust region']) 
 218   
 219          self.entries.append(['Fletcher-Reeves', 'minimisation techniques!Fletcher-Reeves']) 
 220          self.entries.append(['floating point', 'floating point number']) 
 221   
 222          self.entries.append(['grace', 'software!Grace']) 
 223          self.entries.append(['Grace', 'software!Grace']) 
 224          self.entries.append(['gzip', 'compression!gzip']) 
 225   
 226          self.entries.append(['Hestenes-Stiefel', 'minimisation techniques!Hestenes-Stiefel']) 
 227          self.entries.append(['hypothesis testing', 'model selection!hypothesis testing']) 
 228   
 229          self.entries.append(['isotropic', 'diffusion!sphere (isotropic)']) 
 230   
 231          self.entries.append(['Levenberg-Marquardt', 'minimisation techniques!Levenberg-Marquardt']) 
 232          self.entries.append(['limit', 'parameter!limit']) 
 233   
 234          self.entries.append(['map', 'map']) 
 235          self.entries.append(['method of [Mm]ultipliers', 'minimisation techniques!Method of Multipliers']) 
 236          self.entries.append(['minimise', 'minimisation']) 
 237          self.entries.append(['minimisation', 'minimisation']) 
 238          self.entries.append(['model elimination', 'model elimination']) 
 239          self.entries.append(['modelfree4', 'software!Modelfree']) 
 240          self.entries.append(['Modelfree4', 'software!Modelfree']) 
 241          self.entries.append(['modelling', 'modelling']) 
 242          self.entries.append(['molecule', 'molecule']) 
 243          self.entries.append(['molmol', 'software!MOLMOL']) 
 244          self.entries.append(['Molmol', 'software!MOLMOL']) 
 245   
 246          self.entries.append(['opendx', 'software!OpenDX']) 
 247          self.entries.append(['OpenDX', 'software!OpenDX']) 
 248          self.entries.append(['optimise', 'optimise']) 
 249          self.entries.append(['order parameter', 'order parameter']) 
 250   
 251          self.entries.append(['newton', 'minimisation techniques!Newton']) 
 252          self.entries.append(['newton-CG', 'minimisation techniques!Newton conjugate gradient']) 
 253          self.entries.append(['NMR', 'NMR']) 
 254   
 255          self.entries.append(['PDB', 'PDB']) 
 256          self.entries.append(['Polak-Ribi.*re', 'minimisation techniques!Polak-Ribiere@Polak-Ribi\`ere']) 
 257          self.entries.append(['Polak-Ribi.*re +', 'minimisation techniques!Polak-Ribiere@Polak-Ribi\`ere +']) 
 258          self.entries.append(['plot', 'plot']) 
 259          self.entries.append(['python', 'Python']) 
 260   
 261          self.entries.append(['read', 'read']) 
 262          self.entries.append(['regular expression', 'regular expression']) 
 263          self.entries.append(['relaxation', 'relaxation']) 
 264          self.entries.append(['rotation', 'rotation']) 
 265   
 266          self.entries.append(['sequence', 'sequence']) 
 267          self.entries.append(['script', 'scripting!script file']) 
 268          self.entries.append(['scripting', 'scripting']) 
 269          self.entries.append(['simplex', 'minimisation techniques!simplex']) 
 270          self.entries.append(['sphere', 'diffusion!sphere (isotropic)']) 
 271          self.entries.append(['spheroid', 'diffusion!spheroid (axially symmetric)']) 
 272          self.entries.append(['sparky', 'software!Sparky']) 
 273          self.entries.append(['Sparky', 'software!Sparky']) 
 274          self.entries.append(['steepest descent', 'minimisation techniques!steepest descent']) 
 275   
 276          self.entries.append(['tar', 'tar']) 
 277   
 278          self.entries.append(['uncompressed', 'compression!uncompressed']) 
 279   
 280          self.entries.append(['write', 'write']) 
 281   
 282          self.entries.append(['xeasy', 'software!XEasy']) 
 283          self.entries.append(['Xeasy', 'software!XEasy']) 
 284          self.entries.append(['XEasy', 'software!XEasy']) 
 285   
 286           
 287          for i in xrange(len(self.entries)): 
 288               
 289              self.entries[i].append(len(split(self.entries[i][0], ' '))) 
 290   
 291               
 292              if search(self.entries[i][0][0], lowercase): 
 293                  self.entries[i][0] = '[' + upper(self.entries[i][0][0]) + self.entries[i][0][0] + ']' + self.entries[i][0][1:] 
 294   
 295               
 296              self.entries[i][0] = '^' + self.entries[i][0] 
 297   
 298               
 299              self.entries[i].reverse() 
 300   
 301           
 302          self.entries.sort(reverse=1) 
 303          for i in xrange(len(self.entries)): 
 304              self.entries[i].reverse() 
  305   
 306   
 308          """Change the keyword label to bold sans serif font.""" 
 309   
 310           
 311          string = '' 
 312   
 313           
 314          while True: 
 315               
 316              if self.i+1 > len(self.docstring_lines) or (self.docstring_lines[self.i] == '' and self.docstring_lines[self.i+1] == ''): 
 317                  self.i = self.i + 1 
 318                  break 
 319   
 320               
 321              if self.docstring_lines[self.i] == '': 
 322                  string = string + ' \n ' 
 323   
 324               
 325              else: 
 326                  string = string + self.docstring_lines[self.i] + ' ' 
 327   
 328               
 329              self.i = self.i + 1 
 330   
 331           
 332          self.section.append(string) 
 333          self.section_type.append('keywords') 
  334   
 335   
 479   
 480   
 482          """Function for changing the quotes for LaTeX processing.""" 
 483   
 484           
 485          new_string = '' 
 486          in_quote = 0 
 487   
 488           
 489          for i in xrange(len(string)): 
 490               
 491              if search('\'', string[i]): 
 492                   
 493                  if not in_quote and (i == 0 or not search('[a-z]', string[i-1])): 
 494                      new_string = new_string + '`' 
 495                      in_quote = 1 
 496                      continue 
 497   
 498                   
 499                  else: 
 500                      in_quote = 0 
 501   
 502               
 503              new_string = new_string + string[i] 
 504   
 505          return new_string 
  506   
 507   
 509          """Function for handling LaTeX special characters.""" 
 510   
 511           
 512          string = replace(string, '\\', 'This is a backslash to be replaced at the end of this functioN') 
 513   
 514           
 515          for char in "#$%&_{}": 
 516              string = replace(string, char, '\\'+char) 
 517   
 518           
 519          for char in "^~": 
 520              string = replace(string, char, '\\'+char+'{}') 
 521   
 522           
 523          string = replace(string, 'This is a backslash to be replaced at the end of this functioN', '$\\backslash$') 
 524   
 525           
 526          string = replace(string, 'linebreak[0]', '\linebreak[0]') 
 527   
 528           
 529          return string 
  530   
 531   
 533          """Function for creating LaTeX lists.""" 
 534   
 535           
 536          string = lstrip(self.docstring_lines[self.i]) 
 537   
 538           
 539          j = self.i 
 540          while True: 
 541               
 542              j = j + 1 
 543   
 544               
 545              if len(self.docstring_lines) <= j: 
 546                  list_spacing = 0 
 547                  break 
 548   
 549               
 550              if len(self.docstring_lines[j]) == 0: 
 551                   
 552                  if len(self.docstring_lines) <= j+1: 
 553                      list_spacing = 0 
 554   
 555                   
 556                  elif search('^ ', self.docstring_lines[j+1]): 
 557                      list_spacing = 1 
 558   
 559                   
 560                  else: 
 561                      list_spacing = 0 
 562   
 563                   
 564                  break 
 565   
 566           
 567          if not list_spacing: 
 568               
 569              string = string + ' \n ' 
 570   
 571               
 572              while True: 
 573                   
 574                  self.i = self.i + 1 
 575   
 576                   
 577                  if self.i >= len(self.docstring_lines) or len(self.docstring_lines[self.i]) == 0: 
 578                      break 
 579   
 580                   
 581                  string = string + lstrip(self.docstring_lines[self.i]) + ' \n ' 
 582   
 583           
 584          else: 
 585               
 586              while True: 
 587                   
 588                  self.i = self.i + 1 
 589   
 590                   
 591                  if self.i >= len(self.docstring_lines): 
 592                      break 
 593   
 594                   
 595                  if len(self.docstring_lines[self.i]) == 0: 
 596                       
 597                      string = string + ' \n ' 
 598   
 599                       
 600                      continue 
 601   
 602                   
 603                  if self.i >= len(self.docstring_lines) or not search('^ ', (self.docstring_lines[self.i])): 
 604                      break 
 605   
 606                   
 607                  string = string + ' ' + lstrip(self.docstring_lines[self.i]) 
 608   
 609           
 610          self.i = self.i - 1 
 611   
 612           
 613          self.section.append(string) 
 614          self.section_type.append('list') 
  615   
 616   
 617 -    def num_to_text(self, num): 
  618          """Convert the number to text. 
 619          @param num: The number to convert. 
 620          @type num:  int 
 621          @return:    The number in the format of 'First', 'Second', 'Third', etc. 
 622          @rtype:     str 
 623          """ 
 624   
 625           
 626          list = ['First', 
 627                  'Second', 
 628                  'Third', 
 629                  'Fourth', 
 630                  'Fifth', 
 631                  'Sixth', 
 632                  'Seventh', 
 633                  'Eighth', 
 634                  'Ninth', 
 635                  'Tenth', 
 636                  'Eleventh', 
 637                  'Twelfth' 
 638          ] 
 639   
 640           
 641          return list[num-1] 
  642   
 643   
 645          """Function for extracting the paragraphs from the docstring.""" 
 646   
 647           
 648          string = self.docstring_lines[self.i] 
 649   
 650           
 651          while True: 
 652               
 653              self.i = self.i + 1 
 654   
 655               
 656              if self.i >= len(self.docstring_lines): 
 657                  break 
 658   
 659               
 660              if len(self.docstring_lines[self.i]) == 0: 
 661                  break 
 662   
 663               
 664              if search('^___', self.docstring_lines[self.i]): 
 665                  break 
 666   
 667               
 668              if search('^ ', self.docstring_lines[self.i]): 
 669                  break 
 670   
 671               
 672              string = string + ' ' + self.docstring_lines[self.i] 
 673   
 674           
 675          self.i = self.i - 1 
 676   
 677           
 678          self.section.append(string) 
 679          self.section_type.append('paragraph') 
  680   
 681   
 683          """Function for creating the LaTeX file.""" 
 684   
 685           
 686           
 687   
 688           
 689          sys.stdout.write("User function: %s().\n" % function) 
 690   
 691           
 692          docstring = getdoc(object) 
 693   
 694           
 695          self.docstring_lines = split(docstring, "\n") 
 696   
 697           
 698          self.section = [] 
 699          self.section_type = [] 
 700   
 701   
 702           
 703           
 704   
 705          self.section.append(function) 
 706          self.section_type.append('subsection') 
 707   
 708   
 709           
 710           
 711   
 712           
 713          self.section.append('Synopsis') 
 714          self.section_type.append('subsubsection') 
 715   
 716           
 717          self.section.append(self.docstring_lines[0]) 
 718          self.section_type.append('paragraph') 
 719   
 720   
 721           
 722           
 723   
 724           
 725          self.section.append('Defaults') 
 726          self.section_type.append('subsubsection') 
 727   
 728           
 729          args, varargs, varkw, defaults = getargspec(object) 
 730   
 731           
 732          arguments = formatargspec(args, varargs, varkw, defaults) 
 733   
 734           
 735          self.section.append(arguments) 
 736          self.section_type.append('arguments') 
 737   
 738   
 739           
 740           
 741   
 742           
 743          self.i = 1      
 744          while True: 
 745               
 746              self.i = self.i + 1 
 747   
 748               
 749              if self.i >= len(self.docstring_lines): 
 750                  break 
 751   
 752               
 753              self.docstring_lines[self.i] = rstrip(self.docstring_lines[self.i]) 
 754   
 755               
 756              if self.docstring_lines[self.i] == '': 
 757                  continue 
 758   
 759               
 760              if self.i+1 < len(self.docstring_lines) and search('^~~~', self.docstring_lines[self.i+1]): 
 761                   
 762                  self.section_title = self.docstring_lines[self.i] 
 763                  self.section.append(self.docstring_lines[self.i]) 
 764                  self.section_type.append('subsubsection') 
 765   
 766                   
 767                  self.i = self.i + 2 
 768                  continue 
 769   
 770               
 771              if search('^Keyword ', self.section_title): 
 772                  self.keywords() 
 773   
 774               
 775              elif search('---', self.docstring_lines[self.i]): 
 776                  self.verbatim() 
 777   
 778               
 779              elif search('^relax>', self.docstring_lines[self.i]) or search('^\$ ', self.docstring_lines[self.i]): 
 780                  self.relax_examples() 
 781   
 782               
 783              elif search('^___', self.docstring_lines[self.i]): 
 784                  self.tables() 
 785   
 786               
 787              elif search('^ ', self.docstring_lines[self.i]): 
 788                  self.lists() 
 789   
 790               
 791              else: 
 792                  self.paragraph() 
 793   
 794   
 795   
 796           
 797           
 798   
 799           
 800          self.index_entries() 
 801   
 802           
 803          for i in xrange(len(self.section)): 
 804               
 805              st = self.section_type[i] 
 806   
 807               
 808              if st == 'arguments' or st == 'example': 
 809                  self.section[i] = self.break_functions(self.section[i]) 
 810                  self.section[i] = self.latex_quotes(self.section[i]) 
 811   
 812               
 813              if not st == 'verbatim': 
 814                  self.section[i] = self.latex_special_chars(self.section[i]) 
 815   
 816               
 817              if not st == 'arguments' and not st == 'verbatim' and not st == 'example' and not st == 'subsection': 
 818                  self.section[i] = self.latex_formatting(self.section[i]) 
 819   
 820               
 821              if not st == 'arguments' and not st == 'verbatim' and not st == 'example': 
 822                   
 823                  self.words = split(self.section[i], ' ') 
 824   
 825                   
 826                  self.in_quote = 0 
 827   
 828                   
 829                  for j in xrange(len(self.words)): 
 830                       
 831                      if st == 'subsection' or st == 'subsubsection': 
 832                          self.indexing(j, bold=1) 
 833                      else: 
 834                          self.indexing(j, bold=0) 
 835   
 836                       
 837                      self.quotes(j) 
 838   
 839                       
 840                      if j == 0: 
 841                          self.section[i] = self.words[j] 
 842                      else: 
 843                          self.section[i] = self.section[i] + ' ' + self.words[j] 
 844   
 845   
 846           
 847           
 848   
 849           
 850          longtable = {"molmol.macro_write": [3], 
 851                       "pymol.macro_write": [2] 
 852          } 
 853   
 854           
 855          self.file.write(" \n\n\n") 
 856   
 857           
 858          self.file.write(" \\vspace{20pt}\n") 
 859          self.file.write(" \\rule{\columnwidth}{2pt}\n") 
 860          self.file.write(" \\vspace{-30pt}\n") 
 861   
 862           
 863          table_sub_count = 1 
 864          for i in xrange(len(self.section)): 
 865               
 866              st = self.section_type[i] 
 867   
 868               
 869              if st == 'subsection': 
 870                   
 871                  user_fn = self.section[i] + '()' 
 872   
 873                   
 874                  user_fn = replace(user_fn, '.', '\-.') 
 875                  user_fn = replace(user_fn, '\_', '\-\_') 
 876   
 877                   
 878                  self.file.write(" \n\n \\subsection{" + user_fn + "}") 
 879   
 880                   
 881                  table_sub_count = 1 
 882   
 883               
 884              elif st == 'subsubsection': 
 885                  self.file.write(" \n \\subsubsection{" + self.section[i] + "}") 
 886   
 887               
 888              elif st == 'arguments': 
 889                  self.file.write("\\begin{flushleft}\n") 
 890                  self.file.write("\\textsf{\\textbf{" + self.latex_special_chars(self.break_functions(function)) + "}" + self.section[i] + "}\n") 
 891                  self.file.write("\\end{flushleft}\n") 
 892   
 893               
 894              elif st == 'keywords': 
 895                   
 896                  lines = split(self.section[i], '\n') 
 897   
 898                   
 899                  for line in lines: 
 900                       
 901                      line_elements = split(line, ':') 
 902   
 903                       
 904                      if len(line_elements) > 2: 
 905                          sys.stderr.write("Keyword failure in: " + repr(line) + " \n ") 
 906                          sys.exit() 
 907   
 908                       
 909                      self.file.write("\\keyword{" + line_elements[0] + ":}" + line_elements[1] + " \n\n ") 
 910   
 911   
 912               
 913              elif st == 'verbatim': 
 914                  self.file.write("{\\footnotesize \\begin{verbatim} \n " + self.section[i] + "\\end{verbatim}}") 
 915   
 916               
 917              elif st == 'example': 
 918                  self.file.write("\\example{" + self.section[i] + "}") 
 919   
 920               
 921              elif st == 'table': 
 922                   
 923                  self.file.write("(see table~\\ref{table%s}) \n " % self.table_count) 
 924   
 925                   
 926                  lines = split(self.section[i], '\n') 
 927   
 928                   
 929                  if function in longtable.keys() and table_sub_count in longtable[function]: 
 930                       
 931                      self.file.write("\\onecolumn\n ") 
 932                      self.file.write("\\begin{center}\n ") 
 933                      self.file.write("\\begin{longtable}{" + (int(lines[0]))*"l" + "}\n\n ") 
 934                      self.file.write("\\caption{%s table for the %s user function.}\n\n " % (self.num_to_text(table_sub_count), user_fn)) 
 935                      self.file.write("\\\\\n \\toprule \n ") 
 936   
 937                       
 938                      elements = split(lines[1], 'SEPARATOR') 
 939                      self.file.write(elements[0]) 
 940                      for j in range(1, len(elements)): 
 941                          self.file.write('&' + elements[j]) 
 942                      self.file.write(" \\\\\n ") 
 943   
 944                       
 945                      self.file.write("\\midrule\n ") 
 946                      self.file.write("\\endhead\n\n ") 
 947                      self.file.write("\\bottomrule\n ") 
 948                      self.file.write("\\endfoot\n\n ") 
 949   
 950                       
 951                      self.file.write("\\label{table%s}\n\n " % self.table_count) 
 952   
 953                       
 954                      for line in lines[2:-1]: 
 955                           
 956                          elements = split(line, 'SEPARATOR') 
 957   
 958                           
 959                          self.file.write(elements[0]) 
 960                          for j in range(1, len(elements)): 
 961                              self.file.write('&' + elements[j]) 
 962                          self.file.write(" \\\\\n ") 
 963   
 964                       
 965                      self.file.write("\\end{longtable}\n ") 
 966                      self.file.write("\\end{center}\n ") 
 967                      self.file.write("\\twocolumn\n ") 
 968   
 969                   
 970                  else: 
 971                       
 972                      self.file.write("\\begin{table*}\n ") 
 973                      self.file.write("\\begin{scriptsize}\n ") 
 974                      self.file.write("\\begin{center}\n ") 
 975   
 976                       
 977                      self.file.write("\\caption{%s table for the %s user function.}\n " % (self.num_to_text(table_sub_count), user_fn)) 
 978   
 979                       
 980                      self.file.write("\\begin{tabular}{" + (int(lines[0]))*"l" + "}\n ") 
 981                      self.file.write("\\toprule\n ") 
 982   
 983                       
 984                      elements = split(lines[1], 'SEPARATOR') 
 985                      self.file.write(elements[0]) 
 986                      for j in range(1, len(elements)): 
 987                          self.file.write('&' + elements[j]) 
 988                      self.file.write(" \\\\\n ") 
 989   
 990                       
 991                      self.file.write("\\midrule\n ") 
 992   
 993                       
 994                      for line in lines[2:-1]: 
 995                           
 996                          elements = split(line, 'SEPARATOR') 
 997   
 998                           
 999                          self.file.write(elements[0]) 
1000                          for j in range(1, len(elements)): 
1001                              self.file.write('&' + elements[j]) 
1002                          self.file.write(" \\\\\n ") 
1003   
1004                       
1005                      self.file.write("\\bottomrule\n ") 
1006                      self.file.write("\\label{table%s}\n " % self.table_count) 
1007                      self.file.write("\\end{tabular}\n ") 
1008                      self.file.write("\\end{center}\n ") 
1009                      self.file.write("\\end{scriptsize}\n ") 
1010                      self.file.write("\\end{table*}\n ") 
1011   
1012                   
1013                  self.table_count = self.table_count + 1 
1014                  table_sub_count = table_sub_count + 1 
1015   
1016               
1017              elif st == 'list': 
1018                   
1019                  lines = split(self.section[i], '\n') 
1020   
1021                   
1022                  if len(lines[-1]) == 0: 
1023                      lines = lines[:-1] 
1024   
1025                   
1026                  elements = split(lines[0], ':') 
1027   
1028                   
1029                  if len(elements) > 2: 
1030                      sys.stderr.write("Error: Badly formatted list element.\n") 
1031                      sys.stderr.write("The element is: " + repr(lines[i]) + "\n") 
1032                      sys.exit() 
1033   
1034                   
1035                  if len(elements) == 1: 
1036                      list_type = 0 
1037   
1038                   
1039                  else: 
1040                      list_type = 1 
1041   
1042                   
1043                  if list_type == 1: 
1044                      self.file.write("\\begin{description} \n ") 
1045                  else: 
1046                      self.file.write("\\begin{itemize} \n ") 
1047   
1048                   
1049                  for j in xrange(len(lines)): 
1050                       
1051                      if list_type == 0: 
1052                          self.file.write("\\item[] " + lstrip(lines[j]) + ' \n ') 
1053   
1054                       
1055                      else: 
1056                           
1057                          elements = split(lines[j], ':') 
1058   
1059                           
1060                          if len(elements) != 2: 
1061                              continue 
1062   
1063                           
1064                          self.file.write("\\item[" + lstrip(elements[0]) + " --]" + elements[1] + ' \n ') 
1065   
1066                   
1067                  if list_type == 1: 
1068                      self.file.write("\\end{description} \n ") 
1069                  else: 
1070                      self.file.write("\\end{itemize} \n ") 
1071   
1072               
1073              else: 
1074                  self.file.write(self.section[i] + ' \n ') 
1075   
1076               
1077              self.file.write(" \n\n ") 
 1078   
1079   
1081          """Function for placing quotes within the quote environment.""" 
1082   
1083           
1084          elements = split(self.words[index], "'") 
1085   
1086           
1087          if len(elements) == 3: 
1088              self.words[index] = elements[0] + '\quotecmd{' + elements[1] + '}' + elements[2] 
1089   
1090           
1091          elif len(elements) > 3: 
1092              sys.stderr.write('Unknown quote: ' + repr(self.words[index])) 
1093              sys.exit() 
1094   
1095           
1096          if len(elements) == 2: 
1097               
1098              if not self.in_quote and not search('[a-z]$', elements[0]): 
1099                  self.words[index] = elements[0] + '\quotecmd{' + elements[1] 
1100                  self.in_quote = 1 
1101   
1102               
1103              elif self.in_quote: 
1104                  self.words[index] = elements[0] + '}' + elements[1] 
1105                  self.in_quote = 0 
 1106   
1107   
1109          """Use typewriter font for relax examples.""" 
1110   
1111           
1112          string = self.docstring_lines[self.i] 
1113   
1114           
1115          while True: 
1116               
1117              self.i = self.i + 1 
1118   
1119               
1120              if self.i >= len(self.docstring_lines) or self.docstring_lines[self.i] == '' or search('^relax>', self.docstring_lines[self.i]) or search('^\$ ', self.docstring_lines[self.i]): 
1121                  self.i = self.i - 1 
1122                  break 
1123   
1124               
1125              string = string + ' ' + lstrip(self.docstring_lines[self.i]) 
1126   
1127           
1128          string = self.break_functions(string) 
1129   
1130           
1131          self.section.append(string) 
1132          self.section_type.append('example') 
 1133   
1134   
1136          """Only replace in safe places within the text.""" 
1137   
1138           
1139   
1140           
1141          string = replace(string,    '0'+text,           '0'+latex) 
1142          string = replace(string,    '1'+text,           '1'+latex) 
1143          string = replace(string,    '2'+text,           '2'+latex) 
1144          string = replace(string,    '3'+text,           '3'+latex) 
1145          string = replace(string,    '4'+text,           '4'+latex) 
1146          string = replace(string,    '5'+text,           '5'+latex) 
1147          string = replace(string,    '6'+text,           '6'+latex) 
1148          string = replace(string,    '7'+text,           '7'+latex) 
1149          string = replace(string,    '8'+text,           '8'+latex) 
1150          string = replace(string,    '9'+text,           '9'+latex) 
1151   
1152           
1153          string = replace(string,    ' '+text+',',       ' '+latex+',') 
1154          string = replace(string,    ' '+text+'.',       ' '+latex+'.') 
1155          string = replace(string,    ' '+text+' ',       ' '+latex+' ') 
1156          string = replace(string,    ' '+text+';',       ' '+latex+';') 
1157          string = replace(string,    ' '+text+':',       ' '+latex+':') 
1158   
1159           
1160          string = replace(string,    '['+text+']',       '['+latex+']') 
1161          string = replace(string,    '['+text+' ',       '['+latex+' ') 
1162          string = replace(string,    '['+text+',',       '['+latex+',') 
1163          string = replace(string,    '['+text+';',       '['+latex+';') 
1164          string = replace(string,    ' '+text+']',       ' '+latex+']') 
1165   
1166           
1167          string = replace(string,    '('+text+')',       '('+latex+')') 
1168          string = replace(string,    '('+text+' ',       '('+latex+' ') 
1169          string = replace(string,    '('+text+',',       '('+latex+',') 
1170          string = replace(string,    '('+text+';',       '('+latex+';') 
1171          string = replace(string,    ' '+text+')',       ' '+latex+')') 
1172   
1173           
1174          string = replace(string,    '{'+text+' ',       '{'+latex+' ') 
1175          string = replace(string,    '{'+text+',',       '{'+latex+',') 
1176          string = replace(string,    '{'+text+';',       '{'+latex+';') 
1177          string = replace(string,    ' '+text+'\\',      ' '+latex+'\\') 
1178   
1179           
1180          string = replace(string,    '`'+text+'\'',      '`'+latex+'\'') 
1181          string = replace(string,    '`'+text+' ',       '`'+latex+' ') 
1182          string = replace(string,    '`'+text+',',       '`'+latex+',') 
1183          string = replace(string,    '`'+text+'.',       '`'+latex+'.') 
1184          string = replace(string,    '`'+text+';',       '`'+latex+';') 
1185          string = replace(string,    ' '+text+'\'',      ' '+latex+'\'') 
1186   
1187           
1188          substring = replace(string[-len(text)-1:],    ' '+text,      ' '+latex) 
1189          string = string[0:-len(text)-1] + substring 
1190   
1191          substring = replace(string[-len(text)-1:],    '.'+text,      '.'+latex) 
1192          string = string[0:-len(text)-1] + substring 
1193   
1194          string = replace(string,    ' '+text+'\n',      ' '+latex+'\n') 
1195          string = replace(string,    '.'+text+'\n',      '.'+latex+'\n') 
1196   
1197           
1198          string = replace(string,    ' '+text+'\^',      ' '+latex+'\^') 
1199          string = replace(string,    '('+text+'\^',      '('+latex+'\^') 
1200          string = replace(string,    '\n'+text+'\^',     '\n'+latex+'\^') 
1201   
1202           
1203          if search('^'+text+'['+punctuation+']', string) or search('^'+text+'['+whitespace+']', string) or search('\n'+text+'['+punctuation+']', string) or search('\n'+text+'['+whitespace+']', string): 
1204              string = replace(string,    text+' ',           latex+' ') 
1205              string = replace(string,    text+',',           latex+',') 
1206              string = replace(string,    text+'.',           latex+'.') 
1207              string = replace(string,    text+';',           latex+';') 
1208              string = replace(string,    text+']',           latex+']') 
1209              string = replace(string,    text+')',           latex+')') 
1210              string = replace(string,    text+'^',           latex+'^') 
1211              string = replace(string,    text+'\\',          latex+'\\') 
1212              string = replace(string,    text+'\'',          latex+'\'') 
1213              string = replace(string,    text+'\n',          latex+'\n') 
1214   
1215   
1216           
1217          return string 
 1218   
1219   
1221          """Function for creating LaTeX tables.""" 
1222   
1223           
1224          self.i = self.i + 1 
1225   
1226           
1227          num_col = len(split(self.docstring_lines[self.i], '|')) 
1228          string = repr(num_col-2) + ' \n ' 
1229   
1230           
1231          if num_col == 1: 
1232              sys.stderr.write('Not a table!') 
1233              sys.exit() 
1234   
1235           
1236          self.i = self.i + 1 
1237   
1238           
1239          headings = split(self.docstring_lines[self.i], '|') 
1240          headings = headings[1:-1] 
1241          for j in xrange(len(headings)): 
1242              headings[j] = lstrip(rstrip(headings[j])) 
1243   
1244           
1245          string = string + headings[0] 
1246          for j in range(1, len(headings)): 
1247              string = string + " SEPARATOR " + headings[j] 
1248          string = string + ' \n ' 
1249   
1250           
1251          self.i = self.i + 3 
1252   
1253           
1254          while True: 
1255               
1256              if self.i >= len(self.docstring_lines) or search('^\\|_', self.docstring_lines[self.i]): 
1257                  self.i = self.i + 1 
1258                  break 
1259   
1260               
1261              columns = split(self.docstring_lines[self.i], '|') 
1262   
1263               
1264              if len(columns) > 1: 
1265                  string = string + lstrip(rstrip(columns[1])) 
1266                  for j in range(2, len(columns)-1): 
1267                      string = string + " SEPARATOR " + lstrip(rstrip(columns[j])) 
1268                  string = string + ' \n ' 
1269              else: 
1270                  string = string + columns[0] + ' \n ' 
1271   
1272               
1273              self.i = self.i + 1 
1274   
1275           
1276          self.section.append(string) 
1277          self.section_type.append('table') 
 1278   
1279   
1281          """Function for extracting the verbatim docstring section.""" 
1282   
1283           
1284          string = '' 
1285   
1286           
1287          while True: 
1288               
1289              self.i = self.i + 1 
1290   
1291               
1292              if self.i >= len(self.docstring_lines) or search('---', self.docstring_lines[self.i]): 
1293                  self.i = self.i + 1 
1294                  break 
1295   
1296               
1297              string = string + self.docstring_lines[self.i] + ' \n ' 
1298   
1299           
1300          self.section.append(string) 
1301          self.section_type.append('verbatim')