parser_standard_options.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Fri Jun 26 19:10:58 2015
  4. @author: pietro
  5. """
  6. from __future__ import print_function
  7. import argparse
  8. import sys
  9. from urllib import urlopen
  10. from build_html import *
  11. def parse_options(lines, startswith='Opt'):
  12. def split_in_groups(lines):
  13. def count_par_diff(line):
  14. open_par = line.count('(')
  15. close_par = line.count(')')
  16. return open_par - close_par
  17. res = None
  18. diff = 0
  19. for line in lines:
  20. if line.startswith('case'):
  21. optname = line.split()[1][:-1]
  22. res = []
  23. # if optname == 'G_OPT_R_BASENAME_INPUT':
  24. # import ipdb; ipdb.set_trace()
  25. elif line == 'break;':
  26. diff = 0
  27. yield optname, res
  28. elif line.startswith('G_'):
  29. diff = count_par_diff(line)
  30. elif diff > 0:
  31. diff -= count_par_diff(line)
  32. else:
  33. res.append(line) if res is not None else None
  34. def split_opt_line(line):
  35. index = line.index('=')
  36. key = line[:index].strip()
  37. default = line[index + 1:].strip()
  38. if default.startswith('_('):
  39. default = default[2:]
  40. return key, default
  41. def parse_glines(glines):
  42. res = {}
  43. key = None
  44. for line in glines:
  45. if line.startswith('/*'):
  46. continue
  47. if line.startswith(startswith) and line.endswith(';'):
  48. key, default = [w.strip() for w in split_opt_line(line[5:])]
  49. res[key] = default
  50. elif line.startswith(startswith):
  51. key, default = split_opt_line(line[5:])
  52. res[key] = [default, ]
  53. else:
  54. if key is not None:
  55. if key not in res:
  56. res[key] = []
  57. start, end = 0, -1
  58. if line.startswith('_('):
  59. start = 2
  60. if line.endswith(');'):
  61. end = -3
  62. elif line.endswith(';'):
  63. end = -2
  64. res[key].append(line[start:end])
  65. # pprint(glines)
  66. # pprint(res)
  67. return res
  68. def clean_value(val):
  69. if isinstance(val, list):
  70. val = ' '.join(val)
  71. return (val.replace('"', '').replace("\'", "'").strip().strip(';')
  72. ).strip().strip('_(').strip().strip(')').strip()
  73. # with open(optionfile, mode='r') as optfile:
  74. lines = [line.strip() for line in lines]
  75. result = []
  76. for optname, glines in split_in_groups(lines):
  77. if glines:
  78. res = parse_glines(glines)
  79. if res:
  80. for key, val in res.items():
  81. res[key] = clean_value(val)
  82. result.append((optname, res))
  83. return result
  84. class OptTable(object):
  85. """"""
  86. def __init__(self, list_of_dict):
  87. self.options = list_of_dict
  88. self.columns = sorted(set([key for _, d in self.options
  89. for key in d.keys()]))
  90. def csv(self, delimiter=';', endline='\n'):
  91. """Return a CSV string with the options"""
  92. csv = []
  93. csv.append(delimiter.join(self.columns))
  94. for optname, options in self.options:
  95. opts = [options.get(col, '') for col in self.columns]
  96. csv.append(delimiter.join([optname, ] + opts))
  97. return endline.join(csv)
  98. def html(self, endline='\n', indent=' ', toptions='border=1'):
  99. """Return a HTML table with the options"""
  100. html = ['<table{0}>'.format(' ' + toptions if toptions else '')]
  101. # write headers
  102. html.append(indent + "<thead>")
  103. html.append(indent + "<tr>")
  104. html.append(indent * 2 + "<th>{0}</th>".format('option'))
  105. for col in self.columns:
  106. html.append(indent * 2 + "<th>{0}</th>".format(col))
  107. html.append(indent + "</tr>")
  108. html.append(indent + "</thead>")
  109. html.append(indent + "<tbody>")
  110. for optname, options in self.options:
  111. html.append(indent + "<tr>")
  112. html.append(indent * 2 + "<td>{0}</td>".format(optname))
  113. for col in self.columns:
  114. html.append(indent * 2 +
  115. "<td>{0}</td>".format(options.get(col, '')))
  116. html.append(indent + "</tr>")
  117. html.append(indent + "</tbody>")
  118. html.append("</table>")
  119. return endline.join(html)
  120. def _repr_html_(self):
  121. """Method used by IPython notebook"""
  122. return self.html()
  123. if __name__ == "__main__":
  124. URL = ('https://trac.osgeo.org/grass/browser/grass/'
  125. 'trunk/lib/gis/parser_standard_options.c?format=txt')
  126. parser = argparse.ArgumentParser(description='Extract GRASS default '
  127. 'options from link.')
  128. parser.add_argument('-f', '--format', default='html', dest='format',
  129. choices=['html', 'csv', 'grass'],
  130. help='Define the output format')
  131. parser.add_argument('-l', '--link', default=URL, dest='url', type=str,
  132. help='Provide the url with the file to parse')
  133. parser.add_argument('-t', '--text', dest='text',
  134. type=argparse.FileType('r'),
  135. help='Provide the file to parse')
  136. parser.add_argument('-o', '--output', default=sys.stdout, dest='output',
  137. type=argparse.FileType('w'),
  138. help='Provide the url with the file to parse')
  139. parser.add_argument('-s', '--starts-with', default='Opt',
  140. dest='startswith', type=str,
  141. help='Extract only the options that starts with this')
  142. parser.add_argument('-p', '--html_params', default='border=1', type=str,
  143. dest='htmlparmas', help="Options for the HTML table")
  144. args = parser.parse_args()
  145. cfile = args.text if args.text else urlopen(args.url, proxies=None)
  146. options = OptTable(parse_options(cfile.readlines(),
  147. startswith=args.startswith))
  148. outform = args.format
  149. if outform in ['csv', 'html']:
  150. print(getattr(options, outform)(), file=args.output)
  151. args.output.close()
  152. else:
  153. year = os.getenv("VERSION_DATE")
  154. name = args.output.name
  155. args.output.close()
  156. topicsfile = open(name, 'w')
  157. topicsfile.write(header1_tmpl.substitute(title="GRASS GIS " \
  158. "%s Reference Manual: Parser standard options index" % grass_version))
  159. topicsfile.write(headerpso_tmpl)
  160. topicsfile.write(options.html(toptions=args.htmlparmas))
  161. write_html_footer(topicsfile, "index.html", year)
  162. topicsfile.close()