@chapter Programming work
@menu
-* Introduction to programming::
-* Programming without compiling::
-* Finding functions::
+* Overview of LilyPond architecture::
+* LilyPond programming languages::
+* Programming without compiling::
+* Finding functions::
* Code style::
+* Debugging LilyPond::
@end menu
+@node Overview of LilyPond architecture::
+@section Overview of LilyPond architecture::
-@node Introduction to programming
-@section Introduction to programming
+TODO -- put in brief description along with link to Erik Sandberg's
+thesis.
-blah blah
+Key concepts:
+
+Parsing converts input file to scheme music expressions.
+
+Iterating converts scheme music expressions into a context tree.
+
+Translation converts the context tree into graphical and/or midi output.
+
+Music expressions provide relative timing for music events.
+
+Contexts provide an evaluation environment within which an engraver converts
+the music event to output.
+
+Question: What is an engraver? I think an engraver handles both iteration
+and translation, but I need to check on that.
+
+Sandberg says that "translator" and "engraver" are synonymous for his thesis;
+the distinction between them is not relevant for that document. What is the
+difference?
+
+@node LilyPond programming languages
+@section LilyPond programming languages
+
+Programming in LilyPond is done in a variety of programming languages. Each
+language is used for a specific purpose or purposes. This section describes
+the languages used and provides links to reference manuals and tutorials for
+the relevant language.
+
+@subsection C++
+
+The core functionality of LilyPond is implemented in C++.
+
+C++ is so ubiquitous that it is difficult to identify either a reference
+manual or a tutorial. Programmers unfamiliar with C++ will need to spend some
+time to learn the language before attempting to modify the C++ code.
+
+The C++ code calls Scheme/GUILE through the GUILE interface, which is
+documented in the
+@uref{http://www.gnu.org/software/guile/manual/html_node/index.html, GUILE
+ Reference Manual}.
+
+@subsection GNU Bison
+
+The LilyPond parser is implemented in Bison, a GNU parser generator. The
+Bison homepage is found at @uref{http://www.gnu.org/software/bison/,
+gnu.org}. The manual (which includes both a reference and tutorial) is
+@uref{http://www.gnu.org/software/bison/manual/index.html, available} in a
+variety of formats.
+
+@subsection GNU Make
+
+GNU Make is used to control the compiling process and to build the
+documentation and the website. GNU Make documentation is available at
+@uref{http://www.gnu.org/software/make/manual/, the GNU website}.
+
+@subsection GUILE or Scheme
+
+GUILE is the dialect of Scheme that is used as LilyPond's extension language. Many extensions to LilyPond are written entirely in GUILE. The
+@uref{http://www.gnu.org/software/guile/manual/html_node/index.html,
+GUILE Reference Manual} is available online.
+
+@uref{http://mitpress.mit.edu/sicp/full-text/book/book.html, Structure and
+Interpretation of Computer Programs}, a popular textbook used to teach
+programming in Scheme is available in its entirety online.
+
+@subsection MetaFont
+
+MetaFont is used to create the music fonts used by LilyPond. A MetaFont
+tutorial is available at @uref{http://metafont.tutorial.free.fr/, the
+METAFONT tutorial page}.
+
+@subsection PostScript
+
+PostScript is used to generate graphical output. A brief PostScript tutorial
+is @uref{http://local.wasp.uwa.edu.au/~pbourke/dataformats/postscript/,
+available online}. The
+@uref{http://www.adobe.com/devnet/postscript/pdfs/PLRM.pdf, PostScript Lanugage
+Reference} is available online in PDF format.
+
+@subsection Python
+
+Python is used for XML2ly and is used for buillding the documentation and the
+website.
+
+Python documentation is available at @uref{http://www.python.org/doc/,
+python.org}.
@node Programming without compiling
@section Programming without compiling
@subsection Modifying distribution files
-Mving uch of LilyPond is written in Scheme or LilyPond input files. These
+Much of LilyPond is written in Scheme or LilyPond input files. These
files are interpreted when the program is run, rather than being compiled
when the program is built, and are present in all LilyPond distributions.
You will find .ly files in the ly/ directory and the Scheme files in the
Files that are part of the LilyPond distribution have Unix-style line
endings (LF), rather than DOS (CR+LF) or MacOS 9 and earlier (CR). Make
-sure you use the necessary tools ensure that Unix-style line endings are
+sure you use the necessary tools to ensure that Unix-style line endings are
preserved in the patches you create.
Tab characters should not be included in files for distribution. All
allow the setting of tab stops and ensuring that no tab characters are
included in the file.
+Scheme files and LilyPond files should be written according to standard
+style guidelines. Scheme file guidelines can be found at
+@uref{http://community.schemewiki.org/?scheme-style}. Following these
+guidelines will make your code easier to read. Both you and others that
+work on your code will be glad you followed these guidelines.
+
+For LilyPond files, you should follow the guidelines for LilyPond snippets
+in the documentation. You can find these guidelines at
+@ref{Texinfo introduction and usage policy}.
+
@node Finding functions
@section Finding functions
When making changes or fixing bugs in LilyPond, one of the initial
-challenges is finding out where in the code tree the functions to be
-modified live. With nearly 3000 files in the source tree,
-trial-and-error searching is generally inefective. This section describes
-a process for finding interesting code.
+challenges is finding out where in the code tree the functions to
+be modified live. With nearly 3000 files in the source tree,
+trial-and-error searching is generally ineffective. This section
+describes a process for finding interesting code.
@subsection Using the ROADMAP
be used to search for a function name. The format of the grep command is
@example
-grep functionName subdirectory/*
+grep -i functionName subdirectory/*
@end example
This command will search all the contents of the directory subdirectory/
-and display every line in any of the files that contains functionName.
+and display every line in any of the files that contains
+functionName. The @code{-i} option makes @command{grep} ignore
+case -- this can be very useful if you are not yet familiar with
+our capitalization conventions.
-THe most likely directories to grep for function names are scm/ for
+The most likely directories to grep for function names are scm/ for
scheme files, ly/ for lilypond input (*.ly) files, and lily/ for C++
files.
This will initiate a search of the remote git repository.
-
@node Code style
@section Code style
@c email to wl@gnu.org when I get here.
@subsection Classes and Types
@verbatim
- This_is_a_class
+This_is_a_class
@end verbatim
Member variable names end with an underscore:
@verbatim
- Type Class::member_
+Type Class::member_
@end verbatim
@item
Messages to be localised must be encapsulated in `_ (STRING)' or
-`_f (FORMAT, ...)'. Eg:
+`_f (FORMAT, ...)'. E.g.:
-@verbatim
- warning (_ ("need music in a score"));
- error (_f ("cannot open file: `%s'", file_name));
-@end verbatim
+@example
+warning (_ ("need music in a score"));
+error (_f ("cannot open file: `%s'", file_name));
+@end example
In some rare cases you may need to call `gettext ()' by hand. This
happens when you pre-define (a list of) string constants for later
constants for translation, using `_i (STRING)'. The `_i' macro is
a no-op, it only serves as a marker for `xgettext'.
-@verbatim
- char const* messages[] = {
- _i ("enable debugging output"),
- _i ("ignore lilypond version"),
- 0
- };
-
-
- void
- foo (int i)
- {
- puts (gettext (messages i));
- }
-@end verbatim
+@example
+char const* messages[] = @{
+ _i ("enable debugging output"),
+ _i ("ignore lilypond version"),
+ 0
+@};
+
+void
+foo (int i)
+@{
+ puts (gettext (messages i));
+@}
+@end example
See also `flower/getopt-long.cc' and `lily/main.cc'.
whitespace to be printed, prepend or append it to the translated
message
-@verbatim
- message (Calculating line breaks... + " ");
-@end verbatim
-
+@example
+message ("Calculating line breaks..." + " ");
+@end example
+
@item
Error or warning messages displayed with a file name and line
number never start with a capital, eg,
-@verbatim
- foo.ly: 12: not a duration: 3
-@end verbatim
+@example
+foo.ly: 12: not a duration: 3
+@end example
Messages containing a final verb, or a gerund (`-ing'-form) always
start with a capital. Other (simpler) messages start with a
lowercase letter
-@verbatim
- Processing foo.ly...
- `foo': not declared.
- Not declaring: `foo'.
-@end verbatim
+@example
+Processing foo.ly...
+`foo': not declared.
+Not declaring: `foo'.
+@end example
@item
Avoid abbreviations or short forms, use `cannot' and `do not'
situation, we'll use quoting like this `"message: `%s'"' for all
strings. Numbers are not quoted:
-@verbatim
- _f ("cannot open file: `%s'", name_str)
- _f ("cannot find character number: %d", i)
-@end verbatim
+@example
+_f ("cannot open file: `%s'", name_str)
+_f ("cannot find character number: %d", i)
+@end example
@item
Think about translation issues. In a lot of cases, it is better to
translate a whole message. The english grammar mustn't be imposed
on the translator. So, instead of
-@verbatim
- stem at + moment.str () + does not fit in beam
-@end verbatim
+@example
+stem at + moment.str () + does not fit in beam
+@end example
have
-@verbatim
- _f ("stem at %s does not fit in beam", moment.str ())
-@end verbatim
+@example
+_f ("stem at %s does not fit in beam", moment.str ())
+@end example
@item
Split up multi-sentence messages, whenever possible. Instead of
-@verbatim
- warning (_f ("out of tune! Can't find: `%s'",
-"Key_engraver"));
- warning (_f ("cannot find font `%s', loading default",
- font_name));
-@end verbatim
+@example
+warning (_f ("out of tune! Can't find: `%s'", "Key_engraver"));
+warning (_f ("cannot find font `%s', loading default", font_name));
+@end example
rather say:
-@verbatim
- warning (out of tune:;
- warning (_f ("cannot find: `%s', "Key_engraver"));
- warning (_f ("cannot find font: `%s', font_name));
- warning (_f ("Loading default font"));
-@end verbatim
+@example
+warning (_ ("out of tune:"));
+warning (_f ("cannot find: `%s', "Key_engraver"));
+warning (_f ("cannot find font: `%s', font_name));
+warning (_f ("Loading default font"));
+@end example
@item
If you must have multiple-sentence messages, use full punctuation.
Use two spaces after end of sentence punctuation. No punctuation
(esp. period) is used at the end of simple messages.
-@verbatim
- _f ("Non-matching braces in text `%s', adding braces", text)
- Debug output disabled. Compiled with NPRINT.
- _f ("Huh? Not a Request: `%s'. Ignoring.", request)
-@end verbatim
+@example
+_f ("Non-matching braces in text `%s', adding braces", text)
+_ ("Debug output disabled. Compiled with NPRINT.")
+_f ("Huh? Not a Request: `%s'. Ignoring.", request)
+@end example
@item
Do not modularise too much; words frequently cannot be translated
would mean sacrificing a bit of eloquency. This holds for original
messages too, of course.
-@verbatim
- en: cannot open: `foo.ly'
- + nl: kan `foo.ly' niet openen (1)
- kan niet openen: `foo.ly'* (2)
- niet te openen: `foo.ly'* (3)
-@end verbatim
+@example
+en: cannot open: `foo.ly'
++ nl: kan `foo.ly' niet openen (1)
+kan niet openen: `foo.ly'* (2)
+niet te openen: `foo.ly'* (3)
+@end example
The first nl message, although grammatically and stylistically
+@node Debugging LilyPond
+@section Debugging LilyPond
+
+The most commonly used tool for debugging LilyPond is the GNU debugger
+gdb. Use of gdb is described in this section.
+
+@subsection Debugging overview
+
+Using a debugger simplifies troubleshooting in at least two ways.
+
+First, breakpoints can be set to pause execution at any desired point.
+Then, when execution has paused, debugger commands can be issued to
+explore the values of various variables or to execute functions.
+
+Second, the debugger allows the display of a stack trace, which shows
+the sequence in which functions are called and the arguments to the
+various function calls.
+
+
+@subsection Compiling with debugging information
+
+In order to use a debugger with LilyPond, it is necessary to compile
+LilyPond with debugging information. This is accomplished by ...
+
+TODO -- get good description here, or perhaps add debugging compile
+to AU1.1 as it comes to CG and just use a reference here.
+
+TODO -- Test the following to make sure it is true.
+
+If you want to be able to set breakpoints in Scheme functions, it is
+necessary to compile guile with debugging information. This is done
+by ...
+
+TODO -- get compiling description for guile here.
+
+@subsection Typical gdb usage
+
+@subsection Typical .gdbinit files
+
+The behavior of gdb can be readily customized through the use of
+@var{.gdbinit} files. A @var{.gdbinit} file is a file named
+@var{.gdbinit} (notice the @qq{.} at the beginning of the file name)
+ that is placed in a user's home directory.
+
+The @var{.gdbinit} file below is from Han-Wen. It sets breakpoints
+for all errors and defines functions for displaying scheme objects
+(ps), grobs (pgrob), and parsed music expressions (pmusic).
+
+@example
+file lily/out/lilypond
+b scm_error
+b programming_error
+b Grob::programming_error
+
+define ps
+ print ly_display_scm($arg0)
+ end
+ define pgrob
+ print ly_display_scm($arg0->self_scm_)
+ print ly_display_scm($arg0->mutable_property_alist_)
+ print ly_display_scm($arg0->immutable_property_alist_)
+ print ly_display_scm($arg0->object_alist_)
+ end
+ define pmusic
+ print ly_display_scm($arg0->self_scm_)
+ print ly_display_scm($arg0->mutable_property_alist_)
+ print ly_display_scm($arg0->immutable_property_alist_)
+ end
+@end example
+
+@subsection Using Guile interactively with LilyPond
+
+In order to experiment with Scheme programming in the LilyPond
+environment, it is convenient to have a Guile interpreter that
+has all the LilyPond modules loaded. This requires the following
+steps.
+
+First, define a Scheme symbol for the active module
+in the .ly file:
+
+@example
+#(module-define! (resolve-module '(guile-user))
+ 'lilypond-module (current-module))
+@end example
+
+Second, place a Scheme function in the .ly file that gives an interactive Guile
+prompt:
+
+@example
+#(top-repl)
+@end example
+
+When the .ly file is compiled, this causes the compilation to be interrupted
+and an interactive guile prompt to appear. When the guile prompt appears,
+the LilyPond active module must be set as the current guile module:
+
+@example
+guile> (set-current-module lilypond-module)
+@end example
+
+Proper operation of these commands can be demonstrated by typing the name
+of a LilyPond public scheme function to see if it's properly defined:
+
+@example
+guile> fret-diagram-verbose-markup
+#<procedure fret-diagram-verbose-markup (layout props marking-list)>
+@end example
+
+If the LilyPond module has not been correctly loaded, an error
+message will be generated:
+
+@example
+guile> fret-diagram-verbose-markup
+ERROR: Unbound variable: fret-diagram-verbose-markup
+ABORT: (unbound-variable)
+@end example
+
+Once the module is properly loaded, any valid LilyPond Scheme expression
+can be entered at the interactive prompt.
+
+After the investigation is complete, the interactive guile interpreter
+can be exited:
+
+@example
+guile> (quit)
+@end example
+
+The compilation of the .ly file will then continue.
+