diff --git a/elixir/api.py b/elixir/api.py index 99aba6a4..f4e3beb8 100755 --- a/elixir/api.py +++ b/elixir/api.py @@ -46,14 +46,15 @@ def on_get(self, req, resp, project, ident): if version == 'latest': version = query.query('latest') - symbol_definitions, symbol_references, symbol_doccomments = query.query('ident', version, ident, family) + symbol_definitions, symbol_references, symbol_doccomments, peaks = query.query('ident', version, ident, family) resp.status = falcon.HTTP_200 resp.content_type = falcon.MEDIA_JSON resp.media = { 'definitions': [sym.__dict__ for sym in symbol_definitions], 'references': [sym.__dict__ for sym in symbol_references], - 'documentations': [sym.__dict__ for sym in symbol_doccomments] + 'documentations': [sym.__dict__ for sym in symbol_doccomments], + 'peeks': peaks } query.close() diff --git a/elixir/query.py b/elixir/query.py index ff14d4b1..0838cb04 100755 --- a/elixir/query.py +++ b/elixir/query.py @@ -259,9 +259,12 @@ def query(self, cmd, *args): # DT bindings compatible strings are handled differently if family == 'B': - return self.get_idents_comps(version, ident) + defs, refs, docs = self.get_idents_comps(version, ident) else: - return self.get_idents_defs(version, ident, family) + defs, refs, docs = self.get_idents_defs(version, ident, family) + + peeks = self.get_peeks_of_syms(version, defs, refs) + return defs, refs, docs, peeks else: return 'Unknown subcommand: ' + cmd + '\n' @@ -402,10 +405,37 @@ def get_idents_defs(self, version, ident, family): symbol_doccomments.append(SymbolInstance(path, docline)) return symbol_definitions, symbol_references, symbol_doccomments + + def get_peeks_of_syms(self, version, symbol_definitions, symbol_references): + + peeks = {} + + def request_peeks(syms): + if len(syms) > 100: + return + for sym in syms: + if sym.path not in peeks: + peeks[sym.path] = {} + + content = self.scriptLines('get-file', version, "/" + sym.path) + + if type(sym.line) is int: + lines = (sym.line,) + else: + lines = map(int, sym.line.split(',')) + + for num in lines: + index = num - 1 + if index >= 0 and index < len(content): + peeks[sym.path][num] = decode(content[index]).strip() + + request_peeks(symbol_definitions) + request_peeks(symbol_references) + return peeks def cmd_ident(q, version, ident, family, **kwargs): - symbol_definitions, symbol_references, symbol_doccomments = q.query("ident", version, ident, family) + symbol_definitions, symbol_references, symbol_doccomments, peeks = q.query("ident", version, ident, family) print("Symbol Definitions:") for symbol_definition in symbol_definitions: print(symbol_definition) @@ -418,6 +448,11 @@ def cmd_ident(q, version, ident, family, **kwargs): for symbol_doccomment in symbol_doccomments: print(symbol_doccomment) + print("\nSymbol peeks:") + for file, content in peeks.items(): + for num, line in content.items(): + print(f"{file}:{num}: {line}") + def cmd_file(q, version, path, **kwargs): code = q.query("file", version, path) print(code) diff --git a/elixir/web.py b/elixir/web.py index 2a0cbbbb..262fc1e8 100755 --- a/elixir/web.py +++ b/elixir/web.py @@ -635,11 +635,12 @@ def generate_source_page(ctx, q, project, version, path): # type: type of the symbol # path: path of the file that contains the symbol # line: list of LineWithURL -SymbolEntry = namedtuple('SymbolEntry', 'type, path, lines') +# peeks: map of code line previews for this path +SymbolEntry = namedtuple('SymbolEntry', 'type, path, lines, peeks') # Converts SymbolInstance into SymbolEntry # path of SymbolInstance will be appended to base_url -def symbol_instance_to_entry(base_url, symbol): +def symbol_instance_to_entry(base_url, symbol, peeks): # TODO this should be a responsibility of Query if type(symbol.line) is str: line_numbers = symbol.line.split(',') @@ -647,11 +648,13 @@ def symbol_instance_to_entry(base_url, symbol): line_numbers = [symbol.line] lines = [ - LineWithURL(l, f'{ base_url }/{ symbol.path }#L{ l }') + LineWithURL(int(l), f'{ base_url }/{ symbol.path }#L{ l }') for l in line_numbers ] - return SymbolEntry(symbol.type, symbol.path, lines) + current_peeks = peeks.get(symbol.path, {}) + + return SymbolEntry(symbol.type, symbol.path, lines, current_peeks) # Generates response (status code and optionally HTML) of the `ident` route # ctx: RequestContext @@ -662,15 +665,16 @@ def generate_ident_page(ctx, q, project, version, family, ident): source_base_url = get_source_base_url(project, version) - symbol_definitions, symbol_references, symbol_doccomments = q.query('ident', version, ident, family) + symbol_definitions, symbol_references, symbol_doccomments, peeks = q.query('ident', version, ident, family) symbol_sections = [] + empty_peeks = {} if len(symbol_definitions) or len(symbol_references): if len(symbol_doccomments): symbol_sections.append({ 'title': 'Documented', - 'symbols': {'_unknown': [symbol_instance_to_entry(source_base_url, sym) for sym in symbol_doccomments]}, + 'symbols': {'_unknown': [symbol_instance_to_entry(source_base_url, sym, empty_peeks) for sym in symbol_doccomments]}, }) if len(symbol_definitions): @@ -679,9 +683,9 @@ def generate_ident_page(ctx, q, project, version, family, ident): # TODO this should be a responsibility of Query for sym in symbol_definitions: if sym.type not in defs_by_type: - defs_by_type[sym.type] = [symbol_instance_to_entry(source_base_url, sym)] + defs_by_type[sym.type] = [symbol_instance_to_entry(source_base_url, sym, peeks)] else: - defs_by_type[sym.type].append(symbol_instance_to_entry(source_base_url, sym)) + defs_by_type[sym.type].append(symbol_instance_to_entry(source_base_url, sym, peeks)) symbol_sections.append({ 'title': 'Defined', @@ -695,7 +699,7 @@ def generate_ident_page(ctx, q, project, version, family, ident): if len(symbol_references): symbol_sections.append({ 'title': 'Referenced', - 'symbols': {'_unknown': [symbol_instance_to_entry(source_base_url, sym) for sym in symbol_references]}, + 'symbols': {'_unknown': [symbol_instance_to_entry(source_base_url, sym, peeks) for sym in symbol_references]}, }) else: symbol_sections.append({ diff --git a/static/dynamic-references.js b/static/dynamic-references.js index c2816bac..4ea94464 100644 --- a/static/dynamic-references.js +++ b/static/dynamic-references.js @@ -28,7 +28,7 @@ function identUrl(project, ident, version, family) { ] */ -function generateSymbolDefinitionsHTML(symbolDefinitions, project, version) { +function generateSymbolDefinitionsHTML(symbolDefinitions, peeks, project, version) { let result = ""; let typesCount = {}; let previous_type = ""; @@ -55,7 +55,7 @@ function generateSymbolDefinitionsHTML(symbolDefinitions, project, version) { previous_type = sd.type; } let ln = sd.line.toString().split(','); - if (ln.length == 1) { + if (ln.length == 1 && !peeks) { let n = ln[0]; result += `
{{ symbol.peeks[line] }}+ {% endif %} +