@c -*- coding: us-ascii; mode: texinfo; -*- @node Programming work @chapter Programming work @menu * Introduction to programming:: * Programming without compiling:: * Finding functions:: * Code style:: * Debugging LilyPond:: * other stuff:: @end menu @node Introduction to programming @section Introduction to programming FIXME -- decide what goes in here and put it here. I'm not sure what should be here -- CDS @node Programming without compiling @section Programming without compiling Much of the development work in LilyPond takes place by changing *.ly or *.scm files. These changes can be made without compiling LilyPond. Such changes are described in this section. @subsection Modifying distribution files 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 scm/ directory. Both Scheme files and .ly files can be modified and saved with any text editor. It's probably wise to make a backup copy of your files before you modify them, although you can reinstall if the files become corrupted. Once you've modified the files, you can test the changes just by running LilyPond on some input file. It's a good idea to create a file that demonstrates the feature you're trying to add. This file will eventually become a regression test and will be part of the LilyPond distribution. @subsection Desired file formatting 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 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 indentation should be done with spaces. Most editors have settings to 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 crash course}. @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 ineffective. This section describes a process for finding interesting code. @subsection Using the ROADMAP The file ROADMAP is located in the main directory of the lilypond source. ROADMAP lists all of the directories in the LilPond source tree, along with a brief description of the kind of files found in each directory. This can be a very helpful tool for deciding which directories to search when looking for a function. @subsection Using grep to search Having identified a likely subdirectory to search, the grep utility can be used to search for a function name. The format of the grep command is @example 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. 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 scheme files, ly/ for lilypond input (*.ly) files, and lily/ for C++ files. @subsection Using git grep to search If you have used git to obtain the source, you have access to a powerful tool to search for functions. The command: @example git grep functionName @end example will search through all of the files that are present in the git repository looking for functionName. It also presents the results of the search using @code{less}, so the results are displayed one page at a time. @subsection Searching on the git repository at Savannah You can also use the equivalent of git grep on the Savannah server. @itemize @item Go to http://git.sv.gnu.org/gitweb/?p=lilypond.git @item In the pulldown box that says commit, select grep. @item Type functionName in the search box, and hit enter/return @end itemize 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. @menu @end menu @subsection Handling errors As a general rule, you should always try to continue computations, even if there is some kind of error. When the program stops, it is often very hard for a user to pinpoint what part of the input causes an error. Finding the culprit is much easier if there is some viewable output. So functions and methods do not return errorcodes, they never crash, but report a programming_error and try to carry on. @subsection Languages C++ and Python are preferred. Python code should use PEP 8. @subsection Filenames Definitions of classes that are only accessed via pointers (*) or references (&) shall not be included as include files. @verbatim filenames ".hh" Include files ".cc" Implementation files ".icc" Inline definition files ".tcc" non inline Template defs in emacs: (setq auto-mode-alist (append '(("\\.make$" . makefile-mode) ("\\.cc$" . c++-mode) ("\\.icc$" . c++-mode) ("\\.tcc$" . c++-mode) ("\\.hh$" . c++-mode) ("\\.pod$" . text-mode) ) auto-mode-alist)) @end verbatim The class Class_name is coded in @q{class-name.*} @subsection Indentation Standard GNU coding style is used. In emacs: @verbatim (add-hook 'c++-mode-hook '(lambda() (c-set-style "gnu") )) @end verbatim If you like using font-lock, you can also add this to your @q{.emacs}: @verbatim (setq font-lock-maximum-decoration t) (setq c++-font-lock-keywords-3 (append c++-font-lock-keywords-3 '(("\\b\\(a-zA-Z_?+_\\)\\b" 1 font-lock-variable-name-face) ("\\b\\(A-Z?+a-z_?+\\)\\b" 1 font-lock-type-face)) )) @end verbatim @subsection Classes and Types @verbatim This_is_a_class @end verbatim @subsection Members Member variable names end with an underscore: @verbatim Type Class::member_ @end verbatim @subsection Macros Macro names should be written in uppercase completely. @subsection Broken code Do not write broken code. This includes hardwired dependencies, hardwired constants, slow algorithms and obvious limitations. If you can not avoid it, mark the place clearly, and add a comment explaining shortcomings of the code. We reject broken-in-advance on principle. @subsection Naming @subsection Messages Messages need to follow Localization. @subsection Localization This document provides some guidelines for programmers write user messages. To help translations, user messages must follow uniform conventions. Follow these rules when coding for LilyPond. Hopefully, this can be replaced by general GNU guidelines in the future. Even better would be to have an English (en_BR, en_AM) guide helping programmers writing consistent messages for all GNU programs. Non-preferred messages are marked with `+'. By convention, ungrammatical examples are marked with `*'. However, such ungrammatical examples may still be preferred. @itemize @item Every message to the user should be localized (and thus be marked for localization). This includes warning and error messages. @item Don't localize/gettextify: @itemize @item `programming_error ()'s @item `programming_warning ()'s @item debug strings @item output strings (PostScript, TeX, etc.) @end itemize @item Messages to be localised must be encapsulated in `_ (STRING)' or `_f (FORMAT, ...)'. E.g.: @verbatim warning (_ ("need music in a score")); error (_f ("cannot open file: `%s'", file_name)); @end verbatim 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 use. In that case, you'll probably also need to mark these string 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 See also `flower/getopt-long.cc' and `lily/main.cc'. @item Do not use leading or trailing whitespace in messages. If you need whitespace to be printed, prepend or append it to the translated message @verbatim message ("Calculating line breaks..." + " "); @end verbatim @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 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 @item Avoid abbreviations or short forms, use `cannot' and `do not' rather than `can't' or `don't' To avoid having a number of different messages for the same 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 @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 have @verbatim _f ("stem at %s does not fit in beam", moment.str ()) @end verbatim @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 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 @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 @item Do not modularise too much; words frequently cannot be translated without context. It's probably safe to treat most occurences of words like stem, beam, crescendo as separately translatable words. @item When translating, it is preferable to put interesting information at the end of the message, rather than embedded in the middle. This especially applies to frequently used messages, even if this 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 The first nl message, although grammatically and stylistically correct, is not friendly for parsing by humans (even if they speak dutch). I guess we'd prefer something like (2) or (3). @item Do not run make po/po-update with GNU gettext < 0.10.35 @end itemize @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 .gdbinit files. The 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 @node other stuff @section other stuff Copied from an email from Carl. Maybe already included. - how to use a debugger with lilypond. - how to get lilypond running and pause at a guile prompt - brief overview of how lilypond processes a file.