From 6d7ba58f880be618ade07f8ea080fe8c4bf8a896 Mon Sep 17 00:00:00 2001 From: cyfraeviolae Date: Wed, 3 Apr 2024 03:10:44 -0400 Subject: venv --- .../site-packages/pygments/lexers/lilypond.py | 226 +++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 venv/lib/python3.11/site-packages/pygments/lexers/lilypond.py (limited to 'venv/lib/python3.11/site-packages/pygments/lexers/lilypond.py') diff --git a/venv/lib/python3.11/site-packages/pygments/lexers/lilypond.py b/venv/lib/python3.11/site-packages/pygments/lexers/lilypond.py new file mode 100644 index 0000000..6b4ed20 --- /dev/null +++ b/venv/lib/python3.11/site-packages/pygments/lexers/lilypond.py @@ -0,0 +1,226 @@ +""" + pygments.lexers.lilypond + ~~~~~~~~~~~~~~~~~~~~~~~~ + + Lexer for LilyPond. + + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import re + +from pygments.lexer import bygroups, default, inherit, words +from pygments.lexers.lisp import SchemeLexer +from pygments.lexers._lilypond_builtins import ( + keywords, pitch_language_names, clefs, scales, repeat_types, units, + chord_modifiers, pitches, music_functions, dynamics, articulations, + music_commands, markup_commands, grobs, translators, contexts, + context_properties, grob_properties, scheme_functions, paper_variables, + header_variables +) +from pygments.token import Token + +__all__ = ["LilyPondLexer"] + +# In LilyPond, (unquoted) name tokens only contain letters, hyphens, +# and underscores, where hyphens and underscores must not start or end +# a name token. +# +# Note that many of the entities listed as LilyPond built-in keywords +# (in file `_lilypond_builtins.py`) are only valid if surrounded by +# double quotes, for example, 'hufnagel-fa1'. This means that +# `NAME_END_RE` doesn't apply to such entities in valid LilyPond code. +NAME_END_RE = r"(?=\d|[^\w\-]|[\-_][\W\d])" + +def builtin_words(names, backslash, suffix=NAME_END_RE): + prefix = r"[\-_^]?" + if backslash == "mandatory": + prefix += r"\\" + elif backslash == "optional": + prefix += r"\\?" + else: + assert backslash == "disallowed" + return words(names, prefix, suffix) + + +class LilyPondLexer(SchemeLexer): + """ + Lexer for input to LilyPond, a text-based music typesetter. + + .. important:: + + This lexer is meant to be used in conjunction with the ``lilypond`` style. + + .. versionadded:: 2.11 + """ + name = 'LilyPond' + url = 'https://lilypond.org' + aliases = ['lilypond'] + filenames = ['*.ly'] + mimetypes = [] + + flags = re.DOTALL | re.MULTILINE + + # Because parsing LilyPond input is very tricky (and in fact + # impossible without executing LilyPond when there is Scheme + # code in the file), this lexer does not try to recognize + # lexical modes. Instead, it catches the most frequent pieces + # of syntax, and, above all, knows about many kinds of builtins. + + # In order to parse embedded Scheme, this lexer subclasses the SchemeLexer. + # It redefines the 'root' state entirely, and adds a rule for #{ #} + # to the 'value' state. The latter is used to parse a Scheme expression + # after #. + + def get_tokens_unprocessed(self, text): + """Highlight Scheme variables as LilyPond builtins when applicable.""" + for index, token, value in super().get_tokens_unprocessed(text): + if token is Token.Name.Function or token is Token.Name.Variable: + if value in scheme_functions: + token = Token.Name.Builtin.SchemeFunction + elif token is Token.Name.Builtin: + token = Token.Name.Builtin.SchemeBuiltin + yield index, token, value + + tokens = { + "root": [ + # Whitespace. + (r"\s+", Token.Text.Whitespace), + + # Multi-line comments. These are non-nestable. + (r"%\{.*?%\}", Token.Comment.Multiline), + + # Simple comments. + (r"%.*?$", Token.Comment.Single), + + # End of embedded LilyPond in Scheme. + (r"#\}", Token.Punctuation, "#pop"), + + # Embedded Scheme, starting with # ("delayed"), + # or $ (immediate). #@ and and $@ are the lesser known + # "list splicing operators". + (r"[#$]@?", Token.Punctuation, "value"), + + # Any kind of punctuation: + # - sequential music: { }, + # - parallel music: << >>, + # - voice separator: << \\ >>, + # - chord: < >, + # - bar check: |, + # - dot in nested properties: \revert NoteHead.color, + # - equals sign in assignments and lists for various commands: + # \override Stem.color = red, + # - comma as alternative syntax for lists: \time 3,3,2 4/4, + # - colon in tremolos: c:32, + # - double hyphen and underscore in lyrics: li -- ly -- pond __ + # (which must be preceded by ASCII whitespace) + (r"""(?x) + \\\\ + | (?<= \s ) (?: -- | __ ) + | [{}<>=.,:|] + """, Token.Punctuation), + + # Pitches, with optional octavation marks, octave check, + # and forced or cautionary accidental. + (words(pitches, suffix=r"=?[',]*!?\??" + NAME_END_RE), Token.Pitch), + + # Strings, optionally with direction specifier. + (r'[\-_^]?"', Token.String, "string"), + + # Numbers. + (r"-?\d+\.\d+", Token.Number.Float), # 5. and .5 are not allowed + (r"-?\d+/\d+", Token.Number.Fraction), + # Integers, or durations with optional augmentation dots. + # We have no way to distinguish these, so we highlight + # them all as numbers. + # + # Normally, there is a space before the integer (being an + # argument to a music function), which we check here. The + # case without a space is handled below (as a fingering + # number). + (r"""(?x) + (?<= \s ) -\d+ + | (?: (?: \d+ | \\breve | \\longa | \\maxima ) + \.* ) + """, Token.Number), + # Separates duration and duration multiplier highlighted as fraction. + (r"\*", Token.Number), + + # Ties, slurs, manual beams. + (r"[~()[\]]", Token.Name.Builtin.Articulation), + + # Predefined articulation shortcuts. A direction specifier is + # required here. + (r"[\-_^][>^_!.\-+]", Token.Name.Builtin.Articulation), + + # Fingering numbers, string numbers. + (r"[\-_^]?\\?\d+", Token.Name.Builtin.Articulation), + + # Builtins. + (builtin_words(keywords, "mandatory"), Token.Keyword), + (builtin_words(pitch_language_names, "disallowed"), Token.Name.PitchLanguage), + (builtin_words(clefs, "disallowed"), Token.Name.Builtin.Clef), + (builtin_words(scales, "mandatory"), Token.Name.Builtin.Scale), + (builtin_words(repeat_types, "disallowed"), Token.Name.Builtin.RepeatType), + (builtin_words(units, "mandatory"), Token.Number), + (builtin_words(chord_modifiers, "disallowed"), Token.ChordModifier), + (builtin_words(music_functions, "mandatory"), Token.Name.Builtin.MusicFunction), + (builtin_words(dynamics, "mandatory"), Token.Name.Builtin.Dynamic), + # Those like slurs that don't take a backslash are covered above. + (builtin_words(articulations, "mandatory"), Token.Name.Builtin.Articulation), + (builtin_words(music_commands, "mandatory"), Token.Name.Builtin.MusicCommand), + (builtin_words(markup_commands, "mandatory"), Token.Name.Builtin.MarkupCommand), + (builtin_words(grobs, "disallowed"), Token.Name.Builtin.Grob), + (builtin_words(translators, "disallowed"), Token.Name.Builtin.Translator), + # Optional backslash because of \layout { \context { \Score ... } }. + (builtin_words(contexts, "optional"), Token.Name.Builtin.Context), + (builtin_words(context_properties, "disallowed"), Token.Name.Builtin.ContextProperty), + (builtin_words(grob_properties, "disallowed"), + Token.Name.Builtin.GrobProperty, + "maybe-subproperties"), + # Optional backslashes here because output definitions are wrappers + # around modules. Concretely, you can do, e.g., + # \paper { oddHeaderMarkup = \evenHeaderMarkup } + (builtin_words(paper_variables, "optional"), Token.Name.Builtin.PaperVariable), + (builtin_words(header_variables, "optional"), Token.Name.Builtin.HeaderVariable), + + # Other backslashed-escaped names (like dereferencing a + # music variable), possibly with a direction specifier. + (r"[\-_^]?\\.+?" + NAME_END_RE, Token.Name.BackslashReference), + + # Definition of a variable. Support assignments to alist keys + # (myAlist.my-key.my-nested-key = \markup \spam \eggs). + (r"""(?x) + (?: [^\W\d] | - )+ + (?= (?: [^\W\d] | [\-.] )* \s* = ) + """, Token.Name.Lvalue), + + # Virtually everything can appear in markup mode, so we highlight + # as text. Try to get a complete word, or we might wrongly lex + # a suffix that happens to be a builtin as a builtin (e.g., "myStaff"). + (r"([^\W\d]|-)+?" + NAME_END_RE, Token.Text), + (r".", Token.Text), + ], + "string": [ + (r'"', Token.String, "#pop"), + (r'\\.', Token.String.Escape), + (r'[^\\"]+', Token.String), + ], + "value": [ + # Scan a LilyPond value, then pop back since we had a + # complete expression. + (r"#\{", Token.Punctuation, ("#pop", "root")), + inherit, + ], + # Grob subproperties are undeclared and it would be tedious + # to maintain them by hand. Instead, this state allows recognizing + # everything that looks like a-known-property.foo.bar-baz as + # one single property name. + "maybe-subproperties": [ + (r"\s+", Token.Text.Whitespace), + (r"(\.)((?:[^\W\d]|-)+?)" + NAME_END_RE, + bygroups(Token.Punctuation, Token.Name.Builtin.GrobProperty)), + default("#pop"), + ] + } -- cgit v1.2.3