Source code for Musica.Tex.Buffer

####################################################################################################
#
# Musica - A Music Theory Package for Python
# Copyright (C) 2017 Fabrice Salvaire
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
####################################################################################################

####################################################################################################

import copy

from .Package import Packages

####################################################################################################

[docs]class Buffer: LINE_BREAK = r'\\' ############################################## def __init__(self): self._content = [] self.clear() ##############################################
[docs] def __iter__(self): return iter(self._content)
##############################################
[docs] def to_string(self, context): source = '' for item in self._content: if isinstance(item, str): source += item else: source += item.to_string(context) return source
##############################################
[docs] def clear(self): self._content.clear()
##############################################
[docs] def append(self, data, deepcopy=False, newline=True): if isinstance(data, list): for item in data: self._append(item, deepcopy) else: self._append(data, deepcopy) if newline: self._append('\n') return self
##############################################
[docs] def _append(self, data, deepcopy=False): if deepcopy: data = copy.deepcopy(data) # if isinstance(data, str) or isinstance(data, Buffer): self._content.append(data)
####################################################################################################
[docs]class BasicCommandMixin: ##############################################
[docs] @staticmethod def to_tex(x): x = str(x) x = x.replace('♭', r'$\flat$') x = x.replace('♯', r'$\sharp$') return x
##############################################
[docs] @staticmethod def format(pattern, *args, **kwargs): pattern = pattern.replace('{', '{{') pattern = pattern.replace('}', '}}') pattern = pattern.replace('«', '{') pattern = pattern.replace('»', '}') return pattern.format(*args, **kwargs)
##############################################
[docs] def define(self, name, value, unit=''): value = str(value) + unit self.append(self.format(r'\def\«»{«»}', name, value))
##############################################
[docs] def new_command(self, name, number_of_parameters, code): self.append(self.format(r'\newcommand{\«»}[«»]{«»}', name, number_of_parameters, code))
##############################################
[docs] def set_main_font(self, name): self.append(self.format(r'\setmainfont[Ligatures=TeX]{«»}', name))
##############################################
[docs] def font_size(self, font_size, base_line_skip=None): if base_line_skip is None: base_line_skip = 1.2 * font_size self.append(self.format(r'\fontsize{«»}{«:.2f»}', font_size, base_line_skip))
##############################################
[docs] def centerline(self, content): self.append(self.format(r'\centerline{«»}', content))
####################################################################################################
[docs]class ContentCommandMixin: ##############################################
[docs] def page_style(self, style): self.append(r'\pagestyle{%s}' % style)
##############################################
[docs] def empty_page_style(self): self.page_style('empty')
##############################################
[docs] def new_page(self): self.append(r'\newpage')
####################################################################################################
[docs]class PreambuleBuffer(Buffer, BasicCommandMixin): pass
####################################################################################################
[docs]class TexContent(BasicCommandMixin, ContentCommandMixin): ####################################### def __init__(self): self._packages = Packages() self._preambule = PreambuleBuffer() self._content = Buffer() ############################################## @property def packages(self): return self._packages @property def preambule(self): return self._preambule @property def content(self): return self._content ##############################################
[docs] def collect_packages(self): packages = self._packages.clone() for item in self._content: if isinstance(item, TexContent): packages.merge(item.collect_packages()) return packages
##############################################
[docs] def collect_preambule(self): source = self.to_string('preambule') for item in self._content: if isinstance(item, TexContent): source += item.to_string('preambule') return source
##############################################
[docs] def to_string(self, context): if context not in ('preambule', 'content'): raise ValueError("Invalid context {}".format(context)) if context == 'preambule': obj = self._preambule else: obj = self._content return obj.to_string(context)
##############################################
[docs] def append_preambule(self, data, deepcopy=False, newline=True): self._preambule.append(data, deepcopy, newline)
##############################################
[docs] def append(self, data, deepcopy=False, newline=True): self._content.append(data, deepcopy, newline)