From c815be6017bbe884ce88bb41f7ec0369ca77914d Mon Sep 17 00:00:00 2001 From: Zach Smith Date: Wed, 25 Apr 2018 20:49:46 -0400 Subject: Factor out languages to their own module --- pycco/languages.py | 60 ++++++++++++++++++++++++++++ pycco/main.py | 113 +++++++++++++++++----------------------------------- tests/test_pycco.py | 12 +++--- 3 files changed, 104 insertions(+), 81 deletions(-) create mode 100644 pycco/languages.py diff --git a/pycco/languages.py b/pycco/languages.py new file mode 100644 index 0000000..48288f0 --- /dev/null +++ b/pycco/languages.py @@ -0,0 +1,60 @@ +""" +A list of the languages that Pycco supports, mapping the file extension to +the name of the Pygments lexer and the symbol that indicates a comment. To +add another language to Pycco's repertoire, add it here. +""" + +__all__ = ("supported_languages",) + +HASH = "#" +SLASH_STAR = "/*" +STAR_SLASH = "*/" +SLASH_SLASH = "//" +DASH_DASH = "--" + +def lang(name, comment_symbol, multistart=None, multiend=None): + result = { + "name": name, + "comment_symbol": comment_symbol + } + if multistart is not None and multiend is not None: + result["multistart"] = multistart + result["multiend"] = multiend + return result + + +c_lang = lang("c", SLASH_SLASH, SLASH_STAR, STAR_SLASH) + +supported_languages = { + ".coffee": lang("coffee-script", HASH, "###", "###"), + + ".pl": lang("perl", HASH), + + ".sql": lang("sql", DASH_DASH, SLASH_STAR, STAR_SLASH), + + ".sh": lang("bash", HASH), + + ".c": c_lang, + + ".h": c_lang, + + ".cl": c_lang, + + ".cpp": lang("cpp", SLASH_SLASH), + + ".js": lang("javascript", SLASH_SLASH, SLASH_STAR, STAR_SLASH), + + ".rb": lang("ruby", HASH, "=begin", "=end"), + + ".py": lang("python", HASH, '"""', '""'), + + ".scm": lang("scheme", ";;", "#|", "|#"), + + ".lua": lang("lua", DASH_DASH, "--[[", "--]]"), + + ".erl": lang("erlang", "%%"), + + ".tcl": lang("tcl", HASH), + + ".hs": lang("haskell", DASH_DASH, "{-", "-}"), +} diff --git a/pycco/main.py b/pycco/main.py index affd38d..9e4a3c9 100644 --- a/pycco/main.py +++ b/pycco/main.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from __future__ import print_function +from __future__ import print_function, absolute_import # Import our external dependencies. import optparse @@ -9,7 +9,8 @@ import sys import time from os import path -import pycco.generate_index as generate_index +from pycco.generate_index import generate_index +from pycco.languages import supported_languages import pygments from markdown import markdown from pycco_resources import css as pycco_css @@ -69,7 +70,7 @@ def _generate_documentation(file_path, code, outdir, preserve_paths, language): """ Helper function to allow documentation generation without file handling. """ - language = get_language(file_path, code, language=language) + language = get_language(file_path, code, language_name=language) sections = parse(code, language) highlight(sections, language, preserve_paths=preserve_paths, outdir=outdir) return generate_html(file_path, sections, preserve_paths=preserve_paths, outdir=outdir) @@ -313,55 +314,10 @@ def generate_html(source, sections, preserve_paths=True, outdir=None): # === Helpers & Setup === -# A list of the languages that Pycco supports, mapping the file extension to -# the name of the Pygments lexer and the symbol that indicates a comment. To -# add another language to Pycco's repertoire, add it here. -languages = { - ".coffee": {"name": "coffee-script", "comment_symbol": "#", - "multistart": '###', "multiend": '###'}, - - ".pl": {"name": "perl", "comment_symbol": "#"}, - - ".sql": {"name": "sql", "comment_symbol": "--"}, - - ".sh": {"name": "bash", "comment_symbol": "#"}, - - ".c": {"name": "c", "comment_symbol": "//", - "multistart": "/*", "multiend": "*/"}, - - ".h": {"name": "c", "comment_symbol": "//", - "multistart": "/*", "multiend": "*/"}, - - ".cpp": {"name": "cpp", "comment_symbol": "//"}, - - ".cl": {"name": "c", "comment_symbol": "//", - "multistart": "/*", "multiend": "*/"}, - - ".js": {"name": "javascript", "comment_symbol": "//", - "multistart": "/*", "multiend": "*/"}, - - ".rb": {"name": "ruby", "comment_symbol": "#", - "multistart": "=begin", "multiend": "=end"}, - - ".py": {"name": "python", "comment_symbol": "#", - "multistart": '"""', "multiend": '"""'}, - - ".scm": {"name": "scheme", "comment_symbol": ";;", - "multistart": "#|", "multiend": "|#"}, - - ".lua": {"name": "lua", "comment_symbol": "--", - "multistart": "--[[", "multiend": "--]]"}, - - ".erl": {"name": "erlang", "comment_symbol": "%%"}, - - ".tcl": {"name": "tcl", "comment_symbol": "#"}, - - ".hs": {"name": "haskell", "comment_symbol": "--", - "multistart": "{-", "multiend": "-}"}, -} - -# Build out the appropriate matchers and delimiters for each language. -for ext, l in languages.items(): +def compile_language(l): + """ + Build out the appropriate matchers and delimiters for each language. + """ language_name = l["name"] comment_symbol = l["comment_symbol"] @@ -382,32 +338,37 @@ for ext, l in languages.items(): l["lexer"] = lexers.get_lexer_by_name(language_name) -def get_language(source, code, language=None): - """Get the current language we're documenting, based on the extension.""" +for entry in supported_languages.values(): + compile_language(entry) - if language is not None: - for l in languages.values(): - if l["name"] == language: - return l +def get_language(source, code, language_name=None): + """ + Get the current language we're documenting, based on the extension. + """ + if language_name is not None: + for entry in supported_languages.values(): + if entry["name"] == language_name: + return entry else: - raise ValueError("Unknown forced language: " + language) + raise ValueError("Unknown forced language: {}".format(language_name)) - m = re.match(r'.*(\..+)', os.path.basename(source)) if source else None - if m and m.group(1) in languages: - return languages[m.group(1)] - else: - try: - lang = lexers.guess_lexer(code).name.lower() - for l in languages.values(): - if l["name"] == lang: - return l - else: - raise ValueError() - except ValueError: - # If pygments can't find any lexers, it will raise its own - # subclass of ValueError. We will catch it and raise ours - # for consistency. - raise ValueError("Can't figure out the language!") + if source: + m = re.match(r'.*(\..+)', os.path.basename(source)) + if m and m.group(1) in supported_languages: + return supported_languages[m.group(1)] + + try: + language_name = lexers.guess_lexer(code).name.lower() + for entry in supported_languages.values(): + if entry["name"] == language_name: + return entry + else: + raise ValueError() + except ValueError: + # If pygments can't find any lexers, it will raise its own + # subclass of ValueError. We will catch it and raise ours + # for consistency. + raise ValueError("Can't figure out the language!") def destination(filepath, preserve_paths=True, outdir=None): @@ -541,7 +502,7 @@ def process(sources, preserve_paths=True, outdir=None, language=None, if index: with open(path.join(outdir, "index.html"), "wb") as f: - f.write(generate_index.generate_index(generated_files, outdir)) + f.write(generate_index(generated_files, outdir)) __all__ = ("process", "generate_documentation") diff --git a/tests/test_pycco.py b/tests/test_pycco.py index 6a98eda..f5ab936 100644 --- a/tests/test_pycco.py +++ b/tests/test_pycco.py @@ -1,3 +1,4 @@ +from __future__ import absolute_import import copy import os import tempfile @@ -8,16 +9,17 @@ from hypothesis import given, example from hypothesis.strategies import lists, text, booleans, choices, none import pycco.generate_index as generate_index +from pycco.languages import supported_languages import pycco.main as p -PYTHON = p.languages['.py'] +PYTHON = supported_languages['.py'] PYCCO_SOURCE = 'pycco/main.py' FOO_FUNCTION = """def foo():\n return True""" def get_language(choice): - return choice(list(p.languages.values())) + return choice(list(supported_languages.values())) @given(lists(text()), text()) @@ -75,10 +77,10 @@ def test_comment_with_only_cross_ref(): @given(text(), text()) def test_get_language_specify_language(source, code): assert p.get_language( - source, code, language="python") == p.languages['.py'] + source, code, language_name="python") == supported_languages['.py'] with pytest.raises(ValueError): - p.get_language(source, code, language="non-existent") + p.get_language(source, code, language_name="non-existent") @given(text() | none()) @@ -155,7 +157,7 @@ def test_generate_documentation(): @given(booleans(), booleans(), choices()) def test_process(preserve_paths, index, choice): - lang_name = choice([l["name"] for l in p.languages.values()]) + lang_name = choice([l["name"] for l in supported_languages.values()]) p.process([PYCCO_SOURCE], preserve_paths=preserve_paths, index=index, outdir=tempfile.gettempdir(), -- cgit v1.2.1