Source code for scamp.text

"""
Module containing utilities for representing text in SCAMP, currently containing the :class:`StaffText` class.
"""

#  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  #
#  This file is part of SCAMP (Suite for Computer-Assisted Music in Python)                      #
#  Copyright © 2020 Marc Evanstein <marc@marcevanstein.com>.                                     #
#                                                                                                #
#  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/>.                                                   #
#  ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  #

from .utilities import SavesToJSON, NoteProperty
import pymusicxml


[docs]class StaffText(SavesToJSON, NoteProperty): """ Represents text that will be attached to the staff at a given note. Place this object in the fourth `properties` argument of :func:`~scamp.instruments.ScampInstrument.play_note`, either alone, or under the "text" key. :param text: the text to display :param italic: whether or not to make text italic :param bold: whether or not to make text bold :param placement: placement relative to the staff; either "above" of "below" :ivar text: the text to display :ivar italic: whether or not to make text italic :ivar bold: whether or not to make text bold :ivar placement: placement relative to the staff; either "above" of "below" """ def __init__(self, text: str, italic: bool = False, bold: bool = False, placement: str = "above"): if placement not in ("above", "below"): raise ValueError("StaffText placement must be either \"above\" or \"below\".") self.text = text self.italic = italic self.bold = bold self.placement = placement
[docs] @classmethod def from_string(cls, string: str): """ Interprets a string as a staff text. For now, it just looks for 1, 2, or 3 leading and trailing asterisks or underscores to make the whole text italic, bold or bold-italic respectively. (This only works on the whole text.) :param string: the text, possible with leading and trailing asterisks/underscores """ if string.startswith("***") and string.endswith("***") or string.startswith("___") and string.endswith("___"): return cls(string[3:-3], bold=True, italic=True) if string.startswith("**") and string.endswith("**") or string.startswith("__") and string.endswith("__"): return cls(string[2:-2], bold=True) if string.startswith("*") and string.endswith("*") or string.startswith("_") and string.endswith("_"): return cls(string[1:-1], italic=True) return cls(string)
[docs] def to_pymusicxml(self) -> pymusicxml.TextAnnotation: """Converts this to a pymusicxml TextAnnotation object.""" return pymusicxml.TextAnnotation(self.text, placement=self.placement, italic=self.italic, bold=self.bold)
[docs] def to_abjad(self) -> 'abjad.Markup': """Converts this to an abjad Markup object.""" from ._dependencies import abjad markup_string = r"\markup " + \ (r"\bold " if self.bold else "") + \ (r"\italic " if self.italic else "") + \ r"{ " + self.text + " }" return abjad().Markup(markup_string)
def _to_dict(self) -> dict: json_dict = {"text": self.text} if self.italic: json_dict["italic"] = True if self.bold: json_dict["bold"] = True if self.placement != "above": json_dict["placement"] = self.placement return json_dict @classmethod def _from_dict(cls, json_dict): return cls(**json_dict) def __eq__(self, other): if not isinstance(other, StaffText): return False return hash(self) == hash(other) def __hash__(self): return hash((self.text, self.bold, self.italic, self.placement)) def __repr__(self): return "StaffText({}{}{}{})".format( "\"{}\"".format(self.text), ", italic={}".format(self.italic) if self.italic else "", ", bold={}".format(self.bold) if self.bold else "", ", placement=\"{}\"".format(self.placement) if self.placement != "above" else "" )