mirror of https://github.com/patacrep/patacrep.git
Louis
11 years ago
4 changed files with 141 additions and 65 deletions
@ -0,0 +1,79 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
import glob |
||||
|
import importlib |
||||
|
import logging |
||||
|
import os |
||||
|
|
||||
|
from songbook_core.errors import SongbookError |
||||
|
|
||||
|
LOGGER = logging.getLogger(__name__) |
||||
|
|
||||
|
class Content: |
||||
|
"""Content item of type 'example'.""" |
||||
|
|
||||
|
def render(self): |
||||
|
"""Render this content item. |
||||
|
|
||||
|
Returns a string, to be placed verbatim in the generated .tex file. |
||||
|
""" |
||||
|
return "" |
||||
|
|
||||
|
# Block management |
||||
|
|
||||
|
def begin_new_block(self, previous): |
||||
|
"""Return a boolean stating if a new block is to be created. |
||||
|
|
||||
|
# Arguments |
||||
|
|
||||
|
- previous: the songbook.content.Content object of the previous item. |
||||
|
|
||||
|
# Return |
||||
|
|
||||
|
True if the renderer has to close previous block, and begin a new one, |
||||
|
False otherwise. |
||||
|
|
||||
|
# Default |
||||
|
|
||||
|
The default behavior of this method (if not defined in this child |
||||
|
class) is: begin a new block if the previous item is not an instance of |
||||
|
the same class. |
||||
|
""" |
||||
|
return False |
||||
|
|
||||
|
def begin_block(self): |
||||
|
"""Return the string to begin a block.""" |
||||
|
return "" |
||||
|
|
||||
|
def end_block(self): |
||||
|
"""Return the string to end a block.""" |
||||
|
return "" |
||||
|
|
||||
|
class ContentError(SongbookError): |
||||
|
def __init__(self, keyword, message): |
||||
|
self.keyword = keyword |
||||
|
self.message = message |
||||
|
|
||||
|
def __str__(self): |
||||
|
return "Content: {}: {}".format(self.keyword, self.message) |
||||
|
|
||||
|
def load_plugins(): |
||||
|
"""Load all content plugins, and return a dictionary of those plugins. |
||||
|
|
||||
|
Return value: a dictionary where: |
||||
|
- keys are the keywords ; |
||||
|
- values are functions triggered when this keyword is met. |
||||
|
""" |
||||
|
plugins = {} |
||||
|
for name in glob.glob(os.path.join(os.path.dirname(__file__), "*.py")): |
||||
|
if name.endswith(".py") and os.path.basename(name) != "__init__.py": |
||||
|
plugin = importlib.import_module( |
||||
|
'songbook_core.content.{}'.format(os.path.basename(name[:-len('.py')])) |
||||
|
) |
||||
|
for (key, value) in plugin.CONTENT_PLUGINS.items(): |
||||
|
if key in plugins: |
||||
|
LOGGER.warning("File %s: Keyword '%s' is already used. Ignored.", os.path.relpath(name), key) |
||||
|
continue |
||||
|
plugins[key] = value |
||||
|
return plugins |
@ -1,65 +0,0 @@ |
|||||
#!/usr/bin/env python |
|
||||
# -*- coding: utf-8 -*- |
|
||||
|
|
||||
"""Example of a plugin managing a content type. |
|
||||
|
|
||||
TODO: Explain""" |
|
||||
|
|
||||
import songbook.content |
|
||||
|
|
||||
class Example(songbook.content.Content): |
|
||||
"""Content item of type 'example'.""" |
|
||||
|
|
||||
def render(self, TODO): |
|
||||
"""Render this content item. |
|
||||
|
|
||||
Returns a string, to be placed verbatim (? TODO) in the generated .tex |
|
||||
file. |
|
||||
""" |
|
||||
return "" |
|
||||
|
|
||||
# Block management |
|
||||
|
|
||||
def begin_new_block(self, previous): |
|
||||
"""Return a boolean stating if a new block is to be created. |
|
||||
|
|
||||
# Arguments |
|
||||
|
|
||||
- previous: the songbook.content.Content object of the previous item. |
|
||||
|
|
||||
# Return |
|
||||
|
|
||||
True if the renderer has to close previous block, and begin a new one, |
|
||||
False otherwise. |
|
||||
|
|
||||
# Default |
|
||||
|
|
||||
The default behavior of this method (if not defined in this child |
|
||||
class) is: begin a new block if the previous item is not an instance of |
|
||||
the same class. |
|
||||
""" |
|
||||
return False |
|
||||
|
|
||||
def begin_block(self, TODO): |
|
||||
"""Return the string to begin a block.""" |
|
||||
return "" |
|
||||
|
|
||||
def end_block(self, TODO): |
|
||||
"""Return the string to end a block.""" |
|
||||
return "" |
|
||||
|
|
||||
|
|
||||
def parse(keyword, arguments): |
|
||||
"""Parse songbook .sb content item. |
|
||||
|
|
||||
Takes as argument the keyword triggerring this content, and the list of |
|
||||
arguments, e.g. for a content item '["picture", "*.png", "*.jpg"]', the |
|
||||
call of this function is: |
|
||||
|
|
||||
> parse('picture', ["*.png", "*.jpg"]) |
|
||||
|
|
||||
Return a list of (subclasses of) songbook.content.Content objects. |
|
||||
""" |
|
||||
return Example(keyword, arguments) |
|
||||
|
|
||||
songbook.content.register('example', parse) |
|
@ -0,0 +1,37 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from songbook_core.content import Content |
||||
|
|
||||
|
KEYWORDS = [ |
||||
|
"part", |
||||
|
"chapter", |
||||
|
"section", |
||||
|
"subsection", |
||||
|
"subsubsection", |
||||
|
"paragraph", |
||||
|
"subparagraph", |
||||
|
] |
||||
|
FULL_KEYWORDS = KEYWORDS + [ "{}*".format(keyword) for keyword in KEYWORDS] |
||||
|
|
||||
|
class Section(Content): |
||||
|
def __init__(self, keyword, name, short = None): |
||||
|
self.keyword = keyword |
||||
|
self.name = name |
||||
|
self.short = short |
||||
|
|
||||
|
def render(self): |
||||
|
if (short is None): |
||||
|
return r'\{}{{{}}}'.format(self.keyword, self.name) |
||||
|
else: |
||||
|
return r'\{}[{}]{{{}}}'.format(self.keyword, self.short, self.name) |
||||
|
|
||||
|
def parse(keyword, arguments): |
||||
|
if (keyword not in KEYWORDS) and (len(arguments) != 1): |
||||
|
raise ContentError(keyword, "Starred section names must have exactly one argument.") |
||||
|
if (len(arguments) not in [1, 2]): |
||||
|
raise ContentError(keyword, "Section can have one or two arguments.") |
||||
|
return [Section(keyword, *arguments)] |
||||
|
|
||||
|
|
||||
|
CONTENT_PLUGINS = dict([(keyword, parse) for keyword in FULL_KEYWORDS]) |
@ -0,0 +1,25 @@ |
|||||
|
#!/usr/bin/env python |
||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from songbook_core.content import Content |
||||
|
|
||||
|
KEYWORDS = [ |
||||
|
"songchapter", |
||||
|
"songsection", |
||||
|
] |
||||
|
|
||||
|
class SongSection(Content): |
||||
|
def __init__(self, keyword): |
||||
|
self.keyword = keyword |
||||
|
self.name = name |
||||
|
|
||||
|
def render(self): |
||||
|
return r'\{}{{{}}}'.format(self.keyword, self.name) |
||||
|
|
||||
|
def parse(keyword, arguments): |
||||
|
if (keyword not in KEYWORDS) and (len(arguments) != 1): |
||||
|
raise ContentError(keyword, "Starred section names must have exactly one argument.") |
||||
|
return [SongSection(keyword, *arguments)] |
||||
|
|
||||
|
|
||||
|
CONTENT_PLUGINS = dict([(keyword, parse) for keyword in KEYWORDS]) |
Loading…
Reference in new issue