#!/usr/bin/env python3 # # Usage: generate-table-of-functions.py # Prints tables of all functions in md format. import sys import re import util import const LENGTH_OF_CODE_SNIPPET = 15 aliasesContent = util.getFileContents(const.AL_FILENAME) projectsRcContent = util.getFileContents(const.PROJECTS_RC_FILENAME) interestingContent = util.getFileContents(const.LIST_OF_IMPORTANT_FUNCTIONS) # Gets dictionary of options from standard_rc, so they can be # substituted. # Returns: # * dictionary of: "${_<COMMAND-NAME>_OPTIONS[@]}" -> options. def getOptions(): commandsWithOptions = {} for line in projectsRcContent: if ";" in line: tokens = line.split(";") command = "\"${_"+tokens[0].strip().upper()+"_OPTIONS[@]}\"" options = tokens[1].strip() commandsWithOptions[command] = options return commandsWithOptions # Extracts title from the line, and adds a table header after # it. # Arguments: # * line - a line. # * heading - size of the heading. # Returns: # * A heading and a table header in md format. def getTitle(line, heading): ta = "\n" ta += heading+" "+line.strip('#').title()+"\n" ta += "\n" ta += " _Name_ | _Runs_ | _Description_ \n" ta += ":------------- |:--------:| ----------------\n" return ta # Finds line number of the start of the function. # Arguments: # * functionName # Returns: # * line number def getFunctionLineNumber(functionName): functionDefinition = functionName+"() {" lineStart = 0 i = 1 for line in aliasesContent: line = line.strip() if lineStart == 0 and functionDefinition in line: lineStart = i elif lineStart != 0 and line == "}": return (lineStart, i) i += 1 return (lineStart,1) # Returns functions body. # Arguments: # * lineNum - line number of the start of the function # * commandsWithOptions - map of command options # Returns: # * functions body def getFunctionBody(lineNum, commandsWithOptions): i = 1 for line in aliasesContent: if i == lineNum+1: for command, options in commandsWithOptions.items(): if command in line: line = line.replace(command, options) break return line.strip()[:LENGTH_OF_CODE_SNIPPET] i += 1 return "" # Generates hyperlink to the function body. # Arguments: # * lineStart - line number of the start of the function # * lineEnd - line number of the end of the function # * pathToFunctions - relative path to standard_functions file # Returns: # * hyperlink def getLink(lineStart, lineEnd, pathToFunctions): link = pathToFunctions+"standard_functions#L"+str(lineStart)+"-L"+str(lineEnd) return link # Generates tables row. # Arguments: # * shortcut - short name of a function # * explanation - short description # * commandsWithOptions - map of command options # * pathToFunctions - relative path to standard_functions file # Returns: # * example: # **ll** | `__listOrDisp`[**`...`**](standard_aliases#L174-L175) # | List or display directory contents in pager using medium # listing format. def getRow(shortcut, explanation, commandsWithOptions, pathToFunctions): # Do not print aliases that just run the command as sudo. if explanation.startswith("Run ") and \ explanation.endswith(" as super user."): return functionName = util.descriptionToCamelCase(explanation) lineStart, lineEnd = getFunctionLineNumber(functionName) functionBody = getFunctionBody(lineStart, commandsWithOptions).replace('`','') link = getLink(lineStart, lineEnd, pathToFunctions) if len(functionBody) >= LENGTH_OF_CODE_SNIPPET \ or lineEnd - lineStart > 2: functionBody = functionBody.replace('|', '|') runs = "<code>"+functionBody+"</code>[**`...`**]("+link+")" else: runs = "<code>"+functionBody+"</code>" return "**"+shortcut+"** | "+runs+" | "+explanation+"\n" # Returns: # * Tables of functions in md format. def generateTables(): ta = "" # map of: "${_COMMAND_OPTIONS[@]}" -> options commandsWithOptions = getOptions() ta += "Commands\n" ta += "========\n" for line in projectsRcContent: line = line.strip() if line.startswith('# ') and line.endswith(' #'): ta += getTitle(line, "###") continue if ";" in line: continue tokens = line.split(':') if len(tokens) == 2: shortcuts = tokens[0].strip() if not shortcuts: continue explanation = tokens[1].strip() row = getRow(shortcuts, explanation, commandsWithOptions, "../") if row is not None: ta += str(row) return ta # Prints tables of all functions in md format. def main(): ta = generateTables() print(ta) if __name__ == '__main__': main()