parser_standard_options.py 7.1 KB

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