import re, json, copy
class MarkdownConverter:
#constructor
def __init__(self, type_colour, function_name_colour, separate_defaults = True, display_defaults = False):
self.type_colour = type_colour
self.function_name_colour = function_name_colour
self.separate_defaults = separate_defaults
self.display_defaults = display_defaults
###
# wraps text in a div element with a given color
#
# @param text the text to wrap
# @param color the desired text color
#
# @return a string representing the now wrapped text
###
def wrap_text(self, text, color):
return "
" + text + "
"
###
# removes previously generated markdown from the file.
#
# @param file_lines a list of lines representing a file.
# @param regexp the regular expression that dictates a match.
###
def clean(self, file_lines, regexp):
start = 0
end = 0
for line_number, line in enumerate(file_lines, 1):
result = re.findall(regexp,line)
if len(result) is not 0:
meta_data = json.loads(result[0])
keys = meta_data.keys()
#classname indicates the beginning of a meta_data section
if 'className' in keys:
start = line_number
#end indicated the end of a meta_data section
if 'end' in keys:
end = line_number - 1
return file_lines[:start] + file_lines[end:]
###
# given a member function, this function derives the alternative versions
#
# @param member_func the member function that is required to be derrived
#
# @return a list of function dictionaries that contain the alternatives, based on the original
###
def derive_functions(self, member_func):
member_functions_derived = []
if len(member_func['params']) is not 0:
param_index = 0
for param in member_func['params']:
if len(param['default']['name']) is 0:
param_index = param_index + 1
else:
break
bare_function = {
'short_name' : member_func['short_name'],
'name' : member_func['name'],
'params' : [],
'description' : member_func['description'],
'returns' : member_func['returns'],
'notes' : member_func['notes'],
'examples' : member_func['examples'],
'return_type' : member_func['return_type'],
}
for i in range(0, param_index):
bare_function['params'] = bare_function['params'] + [member_func['params'][i]]
member_functions_derived = member_functions_derived + [bare_function]
current = copy.copy(bare_function)
#lists retain references, so we have to copy objects to maintain separation
for remainder in range(param_index, len(member_func['params'])):
current['params'] = current['params'] + [member_func['params'][remainder]]
member_functions_derived = member_functions_derived + [current]
current = copy.copy(current)
else:
member_functions_derived = member_functions_derived + [member_func]
return member_functions_derived
###
# given a parameter, this function generates text
#
# @param param the parameter that needs a textual translation
#
# @return a string representing the parameter
###
def gen_param_text(self, param):
text = "\n> "
if param['type'] is not None:
text = text + " " + self.wrap_text(param['type'], self.type_colour)
text = text + " " + param['name']
if self.display_defaults:
if len(param['default']['name']) is not 0:
text = text + " `= " + param['default']['name']
if len(param['default']['value']) is not 0:
text = text + param['default']['value']
text = text + "`"
if 'description' in param.keys():
text = text +" - " + param['description']
text = text.encode('ascii','ignore')
return text
###
# given a list of member functions, this function returns a list of new lines for the
# file currently being processed.
#
# @param class_name the name of the current class (found in the meta data)
# @param member_functions the list of member_functions extracted from XML
#
# @return a list containing the new lines to be inserted into the current file.
###
def gen_member_func_doc(self, class_name, member_functions):
# this is what a member function dictionary contains.
# function = {
# 'short_name':"",
# 'name':"",
# 'return_type':"",
# 'params':[],
# 'description':[],
# 'returns':"",
# 'notes':"",
# 'examples':"",
# 'default':None
# }
lines = []
for index, member_func in enumerate(member_functions,0):
member_functions_derived = []
if index is 0 or member_func['short_name'] != member_functions[index - 1]['short_name']:
if class_name == member_func["short_name"]:
lines.append("##Constructor\n")
else:
lines.append("##" + member_func["short_name"]+"\n")
#we want to clearly separate our different level of functions in the DAL
#so we present methods with defaults as overloads.
if self.separate_defaults is True:
member_functions_derived = member_functions_derived + self.derive_functions(member_func)
for derived_func in member_functions_derived:
#---- short name for urls ----
lines.append("
\n")
short_name = ""
if len(derived_func["return_type"]) is not 0:
short_name = "####" + self.wrap_text(derived_func["return_type"],self.type_colour) + " " +self.wrap_text(derived_func["short_name"], self.function_name_colour) + "("
else:
short_name = "####" + derived_func["short_name"] + "("
last_param = None
if len(derived_func['params']) is not 0:
last_param = derived_func['params'][-1]
#generate parameters for the name of this function
for param in derived_func['params']:
text = ""
if param['type'] is not None:
text = text + " " + self.wrap_text(param['type'], self.type_colour)
text = text + " " + param['name']
if param is not last_param:
short_name = short_name + text +", "
else:
short_name = short_name + text
lines.append(short_name + ")\n")
#-----------------------------
#---- description ----
if len(derived_func['description']) is not 0:
lines.append("#####Description\n")
lines.append(' '.join(derived_func['description']) + "\n")
#-----------------------------
#---- parameters ----
if len(derived_func['params']) is not 0:
lines.append("#####Parameters\n")
for param in derived_func['params']:
lines.append(self.gen_param_text(param) + "\n")
#-----------------------------
#---- returns ----
if len(derived_func['returns']) is not 0:
lines.append("#####Returns\n")
lines.append(derived_func['returns'] + "\n")
#-----------------------------
#---- examples ----
if len(derived_func['examples']) is not 0:
lines.append("#####Example\n")
lines.append("```cpp\n")
lines.append(derived_func['examples'])
lines.append("```\n")
#-----------------------------
#---- notes ----
if len(derived_func['notes']) is not 0:
lines.append("\n!!! note\n")
lines.append(" " + derived_func['notes'].replace('\n','\n '))
lines.append('\n\n')
#-----------------------------
lines.append("____\n")
return lines