def get_tag(self, site=None): """ Gets tag. """ tag = Tag(self._tag) tag = tag.append(site) return tag
def add_final_bar_line(self, abbreviation="|.", to_each_voice=False): r""" Add final bar line to end of score. >>> staff = abjad.Staff("c'4 d'4 e'4 f'4") >>> score = abjad.Score([staff]) >>> abjad.show(score) # doctest: +SKIP .. docs:: >>> abjad.f(score) \new Score << \new Staff { c'4 d'4 e'4 f'4 } >> >>> bar_line = score.add_final_bar_line() >>> abjad.show(score) # doctest: +SKIP .. docs:: >>> abjad.f(score) \new Score << \new Staff { c'4 d'4 e'4 f'4 \bar "|." %! SCORE_1 } >> Set ``to_each_voice`` to true to make part extraction easier. Returns bar line. """ import abjad bar_line = abjad.BarLine(abbreviation) if not to_each_voice: last_leaf = abjad.inspect(self).leaf(-1) abjad.attach(bar_line, last_leaf, tag=Tag("SCORE_1")) else: for voice in abjad.iterate(self).components(abjad.Voice): last_leaf = abjad.inspect(voice).leaf(-1) abjad.attach(bar_line, last_leaf, tag=Tag("SCORE_1")) return bar_line
def get_tags(self): r""" Gets tags. .. container:: example >>> string = r' %@% \with-color %! MEASURE_NUMBER:SM31' >>> abjad.Line(string).get_tags() [Tag('MEASURE_NUMBER'), Tag('SM31')] .. container:: example REGRESSION. Works with multiple ``%!`` prefixes: >>> string = r' %@% \with-color %! SM31 %! SM32' >>> line = abjad.Line(string) >>> line.get_tags() [Tag('SM31'), Tag('SM32')] Returns list of zero or more strings. """ tags = [] if " %! " in self.string: for chunk in self.string.split(" %! ")[1:]: parts = chunk.split() parts = parts[0].split(":") tags_ = [Tag(_) for _ in parts] tags.extend(tags_) return tags
def __call__(self): """ Calls score template. Returns score. """ import abjad staves = [] site = "abjad.GroupedStavesScoreTemplate.__call__()" tag = Tag(site) for index in range(self.staff_count): number = index + 1 voice = abjad.Voice([], name="Voice_{}".format(number), tag=tag) staff = abjad.Staff([voice], name="Staff_{}".format(number), tag=tag) staves.append(staff) self.voice_abbreviations["v{}".format(number)] = voice.name staff_group = abjad.StaffGroup(staves, name="Grouped_Staves_Staff_Group", tag=tag) score = abjad.Score([staff_group], name="Grouped_Staves_Score", tag=tag) return score
def handle_shifted_clefs(path) -> "Job": """ Handles shifted clefs. """ def activate(tags): return abjad_tags.SHIFTED_CLEF in tags deactivate: typing.Optional[typing.Callable] # then deactivate shifted clefs at BOL: if path.is__segments(): metadata_source = path.parent else: metadata_source = path string = "bol_measure_numbers" bol_measure_numbers = metadata_source.get_metadatum(string) if bol_measure_numbers: bol_measure_numbers = [ Tag(f"MEASURE_{_}") for _ in bol_measure_numbers ] def deactivate(tags): if abjad_tags.SHIFTED_CLEF not in tags: return False if any(_ in tags for _ in bol_measure_numbers): return True return False else: deactivate = None return Job( activate=(activate, "shifted clef"), deactivate=(deactivate, "BOL clef"), path=path, title="handling shifted clefs ...", )
def _get_format_pieces(self, tag=None): result = [] if self.date_time_token is not None: string = f"% {self.date_time_token}" result.append(string) result.extend(self._get_formatted_comments()) includes = [] if self.lilypond_version_token is not None: string = f"{self.lilypond_version_token}" includes.append(string) if self.lilypond_language_token is not None: string = f"{self.lilypond_language_token}" includes.append(string) tag = Tag("abjad.LilyPondFile._get_format_pieces()") includes = LilyPondFormatManager.tag(includes, tag=self.get_tag(tag)) includes = "\n".join(includes) if includes: result.append(includes) postincludes = [] if self.use_relative_includes: string = "#(ly:set-option 'relative-includes #t)" postincludes.append(string) postincludes.extend(self._get_formatted_includes()) postincludes.extend(self._get_formatted_scheme_settings()) result.extend(postincludes) result.extend(self._get_formatted_blocks()) return result
def __init__( self, context: str = None, edition: typing.Union[str, Tag] = None, manifest: str = None, prototype: str = None, value: typing.Any = None, ) -> None: if context is not None: assert isinstance(context, str), repr(context) self._context = context edition_ = None if edition is not None: edition_ = Tag(edition) self._edition = edition_ if manifest is not None: assert isinstance(manifest, str), repr(manifest) assert prototype is None self._manifest = manifest if prototype is not None: assert isinstance(prototype, str), repr(prototype) assert manifest is None self._prototype = prototype if value is not None: if not isinstance(value, (int, str, dict)): assert type(value).__name__ == "PersistentOverride", repr( value) self._value = value
def __getattr__(self, name: str) -> Tag: """ Gets tag with ``name``. Raises attribute error when ``name`` is unknown. """ if name not in self._known_tags: raise AttributeError(f"unknown tag {name!r}.") return Tag(name)
def _attach_lilypond_one_voice(self): from .Voice import Voice anchor_leaf = self._get_on_beat_anchor_leaf() anchor_voice = abjad_inspect(anchor_leaf).parentage().get(Voice) final_anchor_leaf = abjad_inspect(anchor_voice).leaf(-1) next_leaf = abjad_inspect(final_anchor_leaf).leaf(1) literal = LilyPondLiteral(r"\oneVoice", format_slot="absolute_before") if abjad_inspect(next_leaf).has_indicator(literal): return if isinstance(next_leaf._parent, OnBeatGraceContainer): return if next_leaf._parent._is_on_beat_anchor_voice(): return site = "abjad.OnBeatGraceContainer._attach_lilypond_one_voice()" tag = Tag(site) tag = tag.append(abjad_tags.ONE_VOICE_COMMAND) attach(literal, next_leaf, tag=tag)
def _format_leaf_nucleus(self): strings = self._get_body() if self.tag: tag = Tag(self.tag) strings = LilyPondFormatManager.tag( strings, tag=tag, ) return ['nucleus', strings]
def __call__(self): """ Calls score template. Returns score. """ import abjad staves = [] site = "abjad.GroupedRhythmicStavesScoreTemplate.__call__()" tag = Tag(site) if isinstance(self.staff_count, int): for index in range(self.staff_count): number = index + 1 name = "Voice_{}".format(number) voice = abjad.Voice([], name=name, tag=tag) name = "Staff_{}".format(number) staff = abjad.Staff([voice], name=name, tag=tag) staff.lilypond_type = "RhythmicStaff" abjad.annotate(staff, "default_clef", abjad.Clef("percussion")) staves.append(staff) key = "v{}".format(number) self.voice_abbreviations[key] = voice.name elif isinstance(self.staff_count, list): for staff_index, voice_count in enumerate(self.staff_count): staff_number = staff_index + 1 name = "Staff_{}".format(staff_number) staff = abjad.Staff(name=name, tag=tag) staff.lilypond_type = "RhythmicStaff" assert 1 <= voice_count for voice_index in range(voice_count): voice_number = voice_index + 1 if voice_count == 1: voice_identifier = str(staff_number) else: voice_identifier = "{}_{}".format(staff_number, voice_number) staff.simultaneous = True name = "Voice_{}".format(voice_identifier) voice = abjad.Voice([], name=name, tag=tag) staff.append(voice) key = "v{}".format(voice_identifier) self.voice_abbreviations[key] = voice.name staves.append(staff) grouped_rhythmic_staves_staff_group = abjad.StaffGroup( staves, name="Grouped_Rhythmic_Staves_Staff_Group", tag=tag ) grouped_rhythmic_staves_score = abjad.Score( [grouped_rhythmic_staves_staff_group], name="Grouped_Rhythmic_Staves_Score", tag=tag, ) return grouped_rhythmic_staves_score
def _attach_lilypond_one_voice(self): from .Voice import Voice anchor_leaf = self._get_on_beat_anchor_leaf() anchor_voice = abjad_inspect(anchor_leaf).parentage().get(Voice) final_anchor_leaf = abjad_inspect(anchor_voice).leaf(-1) next_leaf = abjad_inspect(final_anchor_leaf).leaf(1) literal = LilyPondLiteral(r"\oneVoice") if abjad_inspect(next_leaf).has_indicator(literal): return site = "abjad.OnBeatGraceContainer._attach_lilypond_one_voice()" tag = Tag(site) attach(literal, next_leaf, tag=tag)
def _attach( self, argument, deactivate=None, tag=None, ): assert not self, repr(self) assert isinstance(argument, Selection), repr(argument) assert argument.are_leaves(), repr(argument) self._extend(argument) self._deactivate = deactivate if tag is not None: tag = Tag(tag) self._tag = tag
def _get_formatted_blocks(self): result = [] tag = Tag("abjad.LilyPondFile._get_formatted_blocks()") tag = self.get_tag(tag) for item in self.items: if "_get_lilypond_format" in dir(item) and not isinstance(item, str): try: string = item._get_lilypond_format(tag=tag) except TypeError: string = item._get_lilypond_format() if string: result.append(string) else: result.append(str(item)) return result
def _get_formatted_scheme_settings(self): result = [] tag = Tag("abjad.LilyPondFile._get_formatted_scheme_settings()") tag = self.get_tag(tag) default_paper_size = self.default_paper_size if default_paper_size is not None: dimension, orientation = default_paper_size string = f'#(set-default-paper-size "{dimension}" \'{orientation})' result.append(string) global_staff_size = self.global_staff_size if global_staff_size is not None: string = f"#(set-global-staff-size {global_staff_size})" result.append(string) if result: result = LilyPondFormatManager.tag(result, tag=tag) result = ["\n".join(result)] return result
def _get_formatted_includes(self): result = [] tag = Tag("abjad.LilyPondFile._get_formatted_includes()") tag = self.get_tag(tag) for include in self.includes: if isinstance(include, str): string = rf'\include "{include}"' result.append(string) elif isinstance(include, pathlib.Path): string = rf'\include "{include!s}"' result.append(string) elif isinstance(include, LilyPondLiteral): string = str(include.argument) result.append(string) else: result.append(format(include)) if result: result = LilyPondFormatManager.tag(result, tag=tag) result = ["\n".join(result)] return result
def handle_mol_tags(path) -> "Job": """ Handles MOL (middle-of-line) tags. """ if path.is__segments(): path = path.parent # activate all middle-of-line tags def activate(tags): tags_ = set([abjad_tags.NOT_MOL, abjad_tags.ONLY_MOL]) return bool(set(tags) & tags_) deactivate: typing.Optional[callable_type] # then deactivate conflicting middle-of-line tags bol_measure_numbers = path.get_metadatum("bol_measure_numbers") if bol_measure_numbers: nonmol_measure_numbers = bol_measure_numbers[:] final_measure_number = path.get_metadatum("final_measure_number") if final_measure_number is not None: nonmol_measure_numbers.append(final_measure_number + 1) nonmol_measure_numbers = [ Tag(f"MEASURE_{_}") for _ in nonmol_measure_numbers ] def deactivate(tags): if abjad_tags.NOT_MOL in tags: if not bool(set(tags) & set(nonmol_measure_numbers)): return True if abjad_tags.ONLY_MOL in tags: if bool(set(tags) & set(nonmol_measure_numbers)): return True return False else: deactivate = None return Job( activate=(activate, "MOL"), deactivate=(deactivate, "conflicting MOL"), path=path, title="handling MOL tags ...", )
def _make_global_context(self): site = "abjad.ScoreTemplate._make_global_context()" tag = Tag(site) global_rests = Context( lilypond_type="GlobalRests", name="Global_Rests", tag=tag, ) global_skips = Context( lilypond_type="GlobalSkips", name="Global_Skips", tag=tag, ) global_context = Context( [global_rests, global_skips], lilypond_type="GlobalContext", simultaneous=True, name="Global_Context", tag=tag, ) return global_context
def __illustrate__(self, default_paper_size=None, global_staff_size=None, includes=None): """ Illustrates score template. """ score: Score = self() site = "abjad.ScoreTemplate.__illustrate__()" tag = Tag(site) for voice in iterate(score).components(Voice): skip = Skip(1, tag=tag) voice.append(skip) self.attach_defaults(score) lilypond_file: LilyPondFile = score.__illustrate__() lilypond_file = new( lilypond_file, default_paper_size=default_paper_size, global_staff_size=global_staff_size, includes=includes, ) return lilypond_file
def handle_fermata_bar_lines(path) -> "Job": """ Handles fermata bar lines. """ if path.is__segments(): path = path.parent def activate(tags): return bool(set(tags) & set([abjad_tags.FERMATA_MEASURE])) deactivate: typing.Optional[callable_type] # then deactivate non-EOL tags: bol_measure_numbers = path.get_metadatum("bol_measure_numbers") if bol_measure_numbers: eol_measure_numbers = [_ - 1 for _ in bol_measure_numbers[1:]] final_measure_number = path.get_metadatum("final_measure_number") if final_measure_number is not None: eol_measure_numbers.append(final_measure_number) eol_measure_numbers = [ Tag(f"MEASURE_{_}") for _ in eol_measure_numbers ] def deactivate(tags): if abjad_tags.FERMATA_MEASURE in tags: if not bool(set(tags) & set(eol_measure_numbers)): return True return False else: deactivate = None return Job( activate=(activate, "bar line adjustment"), deactivate=(deactivate, "EOL fermata bar line"), path=path, title="handling fermata bar lines ...", )
def handle_edition_tags(path) -> "Job": """ Handles edition tags. The logic here is important: * deactivations run first: -TAG (where TAG is either my directory or my buildtype) +TAG (where TAG is neither my directory nor my buildtype) * activations run afterwards: TAG_SET such that there exists at least one build-forbid -TAG (equal to neither my directory nor my buildtype) in TAG_SET and such that there exists no -TAG (equal to either my directory or my buildtype) in TAG_SET +TAG (where TAG is either my directory or my buildtype) Notionally: first we deactivate anything that is tagged EITHER specifically against me OR specifically for another build; then we activate anything that is deactivated for editions other than me; then we activate anything is tagged specifically for me. .. todo: Tests. """ if path.parent.is_segment(): my_name = "SEGMENT" elif path.is_score_build() or path.parent.is_score_build(): my_name = "SCORE" elif path.is_parts() or path.is_part(): my_name = "PARTS" else: raise Exception(path) this_edition = Tag(f"+{String(my_name).to_shout_case()}") not_this_edition = Tag(f"-{String(my_name).to_shout_case()}") if path.is_dir(): directory_name = path.name else: directory_name = path.parent.name this_directory = Tag(f"+{String(directory_name).to_shout_case()}") not_this_directory = Tag(f"-{String(directory_name).to_shout_case()}") def deactivate(tags) -> bool: if not_this_edition in tags: return True if not_this_directory in tags: return True for tag in tags: if str(tag).startswith("+"): return True return False def activate(tags) -> bool: for tag in tags: if tag in [not_this_edition, not_this_directory]: return False for tag in tags: if str(tag).startswith("-"): return True return bool(set(tags) & set([this_edition, this_directory])) return Job( activate=(activate, "this-edition"), deactivate=(deactivate, "other-edition"), deactivate_first=True, path=path, title="handling edition tags ...", )
def attach_defaults(self, argument) -> typing.List: """ Attaches defaults to all staff and staff group contexts in ``argument`` when ``argument`` is a score. Attaches defaults to ``argument`` (without iterating ``argument``) when ``argument`` is a staff or staff group. Returns list of one wrapper for every indicator attached. """ assert isinstance(argument, (Score, Staff, StaffGroup)), repr(argument) wrappers: typing.List[Wrapper] = [] tag = const.REMOVE_ALL_EMPTY_STAVES empty_prototype = (MultimeasureRest, Skip) prototype = (Staff, StaffGroup) if isinstance(argument, Score): staff__groups = select(argument).components(prototype) staves = select(argument).components(Staff) elif isinstance(argument, Staff): staff__groups = [argument] staves = [argument] else: assert isinstance(argument, StaffGroup), repr(argument) staff__groups = [argument] staves = [] for staff__group in staff__groups: leaf = None voices = select(staff__group).components(Voice) # find leaf 0 in first nonempty voice for voice in voices: leaves = [] for leaf_ in select(voice).leaves(): if inspect(leaf_).has_indicator(const.HIDDEN): leaves.append(leaf_) if not all(isinstance(_, empty_prototype) for _ in leaves): leaf = inspect(voice).leaf(0) break # otherwise, find first leaf in voice in non-removable staff if leaf is None: for voice in voices: voice_might_vanish = False for component in inspect(voice).parentage(): if inspect(component).annotation(tag) is True: voice_might_vanish = True if not voice_might_vanish: leaf = inspect(voice).leaf(0) if leaf is not None: break # otherwise, as last resort find first leaf in first voice if leaf is None: leaf = inspect(voices[0]).leaf(0) if leaf is None: continue instrument = inspect(leaf).indicator(instruments.Instrument) if instrument is None: string = "default_instrument" instrument = inspect(staff__group).annotation(string) if instrument is not None: wrapper = attach( instrument, leaf, context=staff__group.lilypond_type, tag=Tag("abjad.ScoreTemplate.attach_defaults(1)"), wrapper=True, ) wrappers.append(wrapper) margin_markup = inspect(leaf).indicator(MarginMarkup) if margin_markup is None: string = "default_margin_markup" margin_markup = inspect(staff__group).annotation(string) if margin_markup is not None: wrapper = attach( margin_markup, leaf, tag=abjad_tags.NOT_PARTS.append( Tag("abjad.ScoreTemplate.attach_defaults(2)")), wrapper=True, ) wrappers.append(wrapper) for staff in staves: leaf = inspect(staff).leaf(0) clef = inspect(leaf).indicator(Clef) if clef is not None: continue clef = inspect(staff).annotation("default_clef") if clef is not None: wrapper = attach( clef, leaf, tag=Tag("abjad.ScoreTemplate.attach_defaults(3)"), wrapper=True, ) wrappers.append(wrapper) return wrappers
def NOT_PARTS(self): """ Not parts. """ return Tag("-PARTS")
def ONLY_SEGMENT(self): """ Only segment. """ return Tag("+SEGMENT")
def ONLY_SCORE(self): """ Only score. """ return Tag("+SCORE")
def ONLY_PARTS(self): """ Only parts. """ return Tag("+PARTS")
def NOT_SEGMENT(self): """ Not segment. """ return Tag("-SEGMENT")
def add_final_markup(self, markup, extra_offset=None): r""" Adds ``markup`` to end of score. .. container:: example Adds markup to last leaf: >>> staff = abjad.Staff("c'4 d'4 e'4 f'4") >>> score = abjad.Score([staff]) >>> place = abjad.Markup('Bremen - Boston - LA.', direction=abjad.Down) >>> date = abjad.Markup('July 2010 - May 2011.') >>> markup = abjad.Markup.right_column([place, date], direction=abjad.Down) >>> markup = markup.italic() >>> markup = score.add_final_markup( ... markup, ... extra_offset=(0.5, -2), ... ) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(score) \new Score << \new Staff { c'4 d'4 e'4 \once \override TextScript.extra-offset = #'(0.5 . -2) f'4 _ \markup { %! SCORE_2 \italic %! SCORE_2 \right-column %! SCORE_2 { %! SCORE_2 "Bremen - Boston - LA." %! SCORE_2 "July 2010 - May 2011." %! SCORE_2 } %! SCORE_2 } %! SCORE_2 } >> .. container:: example Adds markup to last multimeasure rest: >>> staff = abjad.Staff("c'4 d'4 e'4 f'4") >>> staff.append(abjad.MultimeasureRest((4, 4))) >>> score = abjad.Score([staff]) >>> place = abjad.Markup( ... 'Bremen - Boston - LA.', ... direction=abjad.Down, ... ) >>> date = abjad.Markup('July 2010 - May 2011.') >>> markup = abjad.Markup.right_column( ... [place, date], ... direction=abjad.Down, ... ) >>> markup = markup.italic() >>> markup = score.add_final_markup( ... markup, ... extra_offset=(14.5, -2), ... ) >>> abjad.show(staff) # doctest: +SKIP .. docs:: >>> abjad.f(score) \new Score << \new Staff { c'4 d'4 e'4 f'4 \once \override MultiMeasureRestText.extra-offset = #'(14.5 . -2) R1 _ \markup { %! SCORE_2 \italic %! SCORE_2 \right-column %! SCORE_2 { %! SCORE_2 "Bremen - Boston - LA." %! SCORE_2 "July 2010 - May 2011." %! SCORE_2 } %! SCORE_2 } %! SCORE_2 } >> Returns none. """ import abjad selection = abjad.select(self) last_leaf = selection._get_component(abjad.Leaf, -1) markup = copy.copy(markup) abjad.attach(markup, last_leaf, tag=Tag("SCORE_2")) if extra_offset is not None: if isinstance(last_leaf, abjad.MultimeasureRest): grob_proxy = abjad.override(last_leaf).multi_measure_rest_text else: grob_proxy = abjad.override(last_leaf).text_script grob_proxy.extra_offset = extra_offset return markup
def NOT_SCORE(self): """ Not score. """ return Tag("-SCORE")
def __call__(self): """ Calls string quartet score template. Returns score. """ import abjad site = "abjad.StringQuartetScoreTemplate.__call__()" tag = Tag(site) # make first violin voice and staff first_violin_voice = abjad.Voice( [], name="First_Violin_Voice", tag=tag ) first_violin_staff = abjad.Staff( [first_violin_voice], name="First_Violin_Staff", tag=tag ) clef = abjad.Clef("treble") abjad.annotate(first_violin_staff, "default_clef", clef) violin = abjad.Violin() abjad.annotate(first_violin_staff, "default_instrument", violin) literal = abjad.LilyPondLiteral(r"\tag #'first-violin", "before") abjad.attach(literal, first_violin_staff) # make second violin voice and staff second_violin_voice = abjad.Voice( [], name="Second_Violin_Voice", tag=tag ) second_violin_staff = abjad.Staff( [second_violin_voice], name="Second_Violin_Staff", tag=tag ) clef = abjad.Clef("treble") abjad.annotate(second_violin_staff, "default_clef", clef) violin = abjad.Violin() abjad.annotate(second_violin_staff, "default_instrument", violin) literal = abjad.LilyPondLiteral(r"\tag #'second-violin", "before") abjad.attach(literal, second_violin_staff) # make viola voice and staff viola_voice = abjad.Voice([], name="Viola_Voice", tag=tag) viola_staff = abjad.Staff( [viola_voice], name="Viola_Staff", tag=tag ) clef = abjad.Clef("alto") abjad.annotate(viola_staff, "default_clef", clef) viola = abjad.Viola() abjad.annotate(viola_staff, "default_instrument", viola) literal = abjad.LilyPondLiteral(r"\tag #'viola", "before") abjad.attach(literal, viola_staff) # make cello voice and staff cello_voice = abjad.Voice([], name="Cello_Voice", tag=tag) cello_staff = abjad.Staff( [cello_voice], name="Cello_Staff", tag=tag ) clef = abjad.Clef("bass") abjad.annotate(cello_staff, "default_clef", clef) cello = abjad.Cello() abjad.annotate(cello_staff, "default_instrument", cello) literal = abjad.LilyPondLiteral(r"\tag #'cello", "before") abjad.attach(literal, cello_staff) # make string quartet staff group string_quartet_staff_group = abjad.StaffGroup( [ first_violin_staff, second_violin_staff, viola_staff, cello_staff, ], name="String_Quartet_Staff_Group", tag=tag, ) # make string quartet score string_quartet_score = abjad.Score( [string_quartet_staff_group], name="String_Quartet_Score", tag=tag, ) # return string quartet score return string_quartet_score