parser_standard_options.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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] = [
  63. default,
  64. ]
  65. else:
  66. if key is not None:
  67. if key not in res:
  68. res[key] = []
  69. start, end = 0, -1
  70. if line.startswith("_("):
  71. start = 2
  72. if line.endswith(");"):
  73. end = -3
  74. elif line.endswith(";"):
  75. end = -2
  76. res[key].append(line[start:end])
  77. # pprint(glines)
  78. # pprint(res)
  79. return res
  80. def clean_value(val):
  81. if isinstance(val, list):
  82. val = " ".join(val)
  83. return (
  84. (val.replace('"', "").replace("'", "'").strip().strip(";"))
  85. .strip()
  86. .strip("_(")
  87. .strip()
  88. .strip(")")
  89. .strip()
  90. )
  91. # with open(optionfile, mode='r') as optfile:
  92. lines = [line.strip() for line in lines]
  93. result = []
  94. for optname, glines in split_in_groups(lines):
  95. if glines:
  96. res = parse_glines(glines)
  97. if res:
  98. for key, val in res.items():
  99. res[key] = clean_value(val)
  100. result.append((optname, res))
  101. return result
  102. class OptTable(object):
  103. """"""
  104. def __init__(self, list_of_dict):
  105. self.options = list_of_dict
  106. self.columns = sorted(set([key for _, d in self.options for key in d.keys()]))
  107. def csv(self, delimiter=";", endline="\n"):
  108. """Return a CSV string with the options"""
  109. csv = []
  110. csv.append(delimiter.join(self.columns))
  111. for optname, options in self.options:
  112. opts = [options.get(col, "") for col in self.columns]
  113. csv.append(
  114. delimiter.join(
  115. [
  116. optname,
  117. ]
  118. + opts
  119. )
  120. )
  121. return endline.join(csv)
  122. def html(self, endline="\n", indent=" ", toptions="border=1"):
  123. """Return a HTML table with the options"""
  124. html = ["<table{0}>".format(" " + toptions if toptions else "")]
  125. # write headers
  126. html.append(indent + "<thead>")
  127. html.append(indent + "<tr>")
  128. html.append(indent * 2 + "<th>{0}</th>".format("option"))
  129. for col in self.columns:
  130. html.append(indent * 2 + "<th>{0}</th>".format(col))
  131. html.append(indent + "</tr>")
  132. html.append(indent + "</thead>")
  133. html.append(indent + "<tbody>")
  134. for optname, options in self.options:
  135. html.append(indent + "<tr>")
  136. html.append(indent * 2 + "<td>{0}</td>".format(optname))
  137. for col in self.columns:
  138. html.append(indent * 2 + "<td>{0}</td>".format(options.get(col, "")))
  139. html.append(indent + "</tr>")
  140. html.append(indent + "</tbody>")
  141. html.append("</table>")
  142. return endline.join(html)
  143. def _repr_html_(self):
  144. """Method used by IPython notebook"""
  145. return self.html()
  146. if __name__ == "__main__":
  147. URL = (
  148. "https://trac.osgeo.org/grass/browser/grass/"
  149. "trunk/lib/gis/parser_standard_options.c?format=txt"
  150. )
  151. parser = argparse.ArgumentParser(
  152. description="Extract GRASS default " "options from link."
  153. )
  154. parser.add_argument(
  155. "-f",
  156. "--format",
  157. default="html",
  158. dest="format",
  159. choices=["html", "csv", "grass"],
  160. help="Define the output format",
  161. )
  162. parser.add_argument(
  163. "-l",
  164. "--link",
  165. default=URL,
  166. dest="url",
  167. type=str,
  168. help="Provide the url with the file to parse",
  169. )
  170. parser.add_argument(
  171. "-t",
  172. "--text",
  173. dest="text",
  174. type=argparse.FileType("r"),
  175. help="Provide the file to parse",
  176. )
  177. parser.add_argument(
  178. "-o",
  179. "--output",
  180. default=sys.stdout,
  181. dest="output",
  182. type=argparse.FileType("w"),
  183. help="Provide the url with the file to parse",
  184. )
  185. parser.add_argument(
  186. "-s",
  187. "--starts-with",
  188. default="Opt",
  189. dest="startswith",
  190. type=str,
  191. help="Extract only the options that starts with this",
  192. )
  193. parser.add_argument(
  194. "-p",
  195. "--html_params",
  196. default="border=1",
  197. type=str,
  198. dest="htmlparmas",
  199. help="Options for the HTML table",
  200. )
  201. args = parser.parse_args()
  202. cfile = args.text if args.text else urlopen(args.url, proxies=None)
  203. options = OptTable(parse_options(cfile.readlines(), startswith=args.startswith))
  204. outform = args.format
  205. if outform in ["csv", "html"]:
  206. print(getattr(options, outform)(), file=args.output)
  207. args.output.close()
  208. else:
  209. year = os.getenv("VERSION_DATE")
  210. name = args.output.name
  211. args.output.close()
  212. topicsfile = open(name, "w")
  213. topicsfile.write(
  214. header1_tmpl.substitute(
  215. title="GRASS GIS "
  216. "%s Reference Manual: Parser standard options index" % grass_version
  217. )
  218. )
  219. topicsfile.write(headerpso_tmpl)
  220. topicsfile.write(options.html(toptions=args.htmlparmas))
  221. write_html_footer(topicsfile, "index.html", year)
  222. topicsfile.close()