Features of quickly
Supported document types
quickly supports LilyPond, Html, LaTeX and Scheme documents. DocBook and TexInfo are in the works.
Html, LaTeX, DocBook and TexInfo are used to edit documents for
lilypond-book
, a script provided by the LilyPond project that can extract
fragments of LilyPond music and run other document processors to produce output
of the texts with the musical fragments properly inserted. quickly is able to
recognize LilyPond music inside these document formats and allows the user to
manipulate the music.
Importing quickly
adds those language definitions to the parce registry.
Most language definitions included in quickly.lang
inherit from the
language defitions with the same name from parce.
So, after importing quickly
, parce.find()
will find the language
definitions of quickly:
>>> import parce
>>> parce.find('lilypond').language
parce.lang.lilypond.LilyPond
>>> import quickly
>>> parce.find('lilypond').language
quickly.lang.lilypond.LilyPond
Music manipulations
Most of quickly’s features manipulate music on the DOM document level, writing back the modifications to the originating text, without interfering with other parts of the source text.
There are four “levels” at which documents can be manipulated: a DOM node tree,
a Range
of a DOM tree, a parce Document
, or a
selection of a parce document, specified by a parce Cursor
.
All manipulation functions can handle all four levels of operation, because
they inherit Edit
. Typically only the
edit_range()
method needs to be implemented for
the others to work equally well. Most modules have convenience functions that
can be called with all four types.
Transpose
Transposing music is done using the transpose
module. A
Transposer is created that can actually transpose pitches according to the
user’s wish, and optionally a PitchProcessor that reads and writes LilyPond
pitch names in all languages.
An example; create a document:
>>> import parce, quickly
>>> doc = parce.Document(parce.find("lilypond"), r"music = { c d e f g }", transformer=True)
Create a transposer:
>>> from quickly.pitch import Pitch
>>> from quickly.transpose import transpose, Transposer
>>> p1 = Pitch(-1, 0, 0) # -> c
>>> p2 = Pitch(-1, 3, 0) # -> f
>>> t = Transposer(p1, p2)
Now transpose the music from c
to f
and view the result:
>>> transpose(doc, t)
>>> doc.text()
"music = { f g a bes c' }"
Using the cursor, we can also operate on a fragment of the document:
>>> cur = parce.Cursor(doc, 12, 15) # only the second and third note
>>> transpose(cur, t)
>>> doc.text()
"music = { f c' d' bes c' }"
Only the second and third note are transposed. The function transpose()
is a convenience function that creates a Transpose
object and calls
its edit()
method.
Convert pitches to and from relative notation
The relative
module contains functions to convert music to and
from relative notation. These functions also use the PitchProcessor to read and
write pitch names in all languages, and automatically adapt to the pitch
language used in a document.
To convert all music from relative to absolute notation:
>>> import parce
>>> from quickly import find
>>> doc = parce.Document(find("lilypond"), r"music = \relative c' { c d e f g }", transformer=True)
>>> from quickly.relative import rel2abs
>>> rel2abs(doc)
>>> doc.text()
"music = { c' d' e' f' g' }"
And convert back to relative:
>>> from quickly.relative import abs2rel
>>> abs2rel(doc)
>>> doc.text()
"music = \\relative c' { c d e f g }"
The function abs2rel()
and rel2abs()
are convenience functions that
create respectively a Abs2rel
or Rel2abs
object and call
their edit()
method.
Time and rhythm
The rhythm
module provides easy-to-use functions and classes to modify
the durations of music. Nodes that have a duration (such as notes, rests,
spacers, skips, drum notes but also lyric words) always inherit
Durable
, and can have a Duration
child
node that writes the duration. Durable nodes also have convenient attributes
duration
and scaling
to
manipulate their Duration and DurationScaling child nodes.
That makes it not too complicated to build nice functions editing these nodes, that are used to refactor or modify existing music:
remove all durations from music |
|
remove scaling e.g. ( |
|
remove only scaling that contains a fraction from the durations |
|
write the duration after all notes, rests etc |
|
only write the duration if different from the previous |
|
modify duration log, number of dots and/or scaling |
|
extract durations to a list of (duration, scaling) tuples |
|
overwrite durations in music from a list of (duration, scaling) tuples |
There is also the time
module, which provides functions to compute the
length of musical fragments, or to compute the musical position a text cursor
is at. Low level duration logic is in the duration
module.