]> git.donarmstrong.com Git - lilypond.git/blobdiff - Documentation/contributor/programming-work.itexi
Merge branch 'lilypond/translation'
[lilypond.git] / Documentation / contributor / programming-work.itexi
index 916741a96f5d96c4cc94694655ba7f5216714315..0e0d3c723e0c0cc31242df27356a56936ea96537 100644 (file)
@@ -8,6 +8,7 @@
 * Programming without compiling::
 * Finding functions::
 * Code style::
+* Warnings Errors Progress and Debug Output::
 * Debugging LilyPond::
 * Tracing object relationships::
 * Adding or modifying features::
@@ -15,6 +16,7 @@
 * Engraver tutorial::
 * Callback tutorial::
 * LilyPond scoping::
+* Scheme->C interface::
 * LilyPond miscellany::
 @end menu
 
@@ -218,7 +220,7 @@ grep -i functionName subdirectory/*
 
 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
+functionName.  The @option{-i} option makes @command{grep} ignore
 case -- this can be very useful if you are not yet familiar with
 our capitalization conventions.
 
@@ -318,76 +320,61 @@ The class Class_name is coded in @q{class-name.*}
 @node Indentation
 @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
-
-Some source files may not currently have proper indenting.  If this
-is the case, it is desirable to fix the improper indenting when the
-file is modified, with the hope of continually improving the code.
+Standard GNU coding style is used.
 
+@subsubheading Indenting files with @code{fixcc.py} (recommended)
 
-@subheading Indenting files with fixcc.py
-
-LilyPond provides a python script that will correct the indentation
-on a c++ file:
+LilyPond provides a python script that will adjust the indentation
+and spacing on a @code{.cc} or @code{.hh} file to very near the
+GNU standard:
 
 @example
-scripts/auxiliar/fixcc.py lily/my-test-file.cc
+scripts/auxiliar/fixcc.py FILENAME
 @end example
 
-Be sure you replace @file{my-test-file.cc} with the name of the file
-that you edited.
-
-If you are editing a file that contains an ADD_TRANSLATOR or ADD_INTERFACE
-macro, the fixcc.py script will move the final parenthesis up one line
-from where it should be.  Please check the end of the file before
-you run fixcc.py, and then put the final parenthesis and semicolon
-back on a line by themselves.
+This can be run on all files at once, but this is not recommended
+for normal contributors or developers.
 
+@smallexample
+scripts/auxiliar/fixcc.py \
+  $(find flower lily -name '*cc' -o -name '*hh' | grep -v /out)
+@end smallexample
 
-@subheading Indenting files with emacs in script mode
 
-@c email to wl@gnu.org when I get here.
+@subsubheading Indenting with emacs
 
-@warning{this is pending some confirmation on -devel.  July 2009 -gp}
+The following hooks will produce indentation which is similar to
+our official indentation as produced with @code{fixcc.py}.
 
-Command-line script to format stuff with emacs:
+@example
+(add-hook 'c++-mode-hook
+     '(lambda ()
+        (c-set-style "gnu")
+        (setq indent-tabs-mode nil))
+@end example
 
-@smallexample
-#!/bin/sh
-emacs $1 -batch --eval '(indent-region (point-min) (point-max) nil)' -f save-buffer
-@end smallexample
+If you like using font-lock, you can also add this to your
+@file{.emacs}:
 
-(that's all on one line)
+@example
+(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 example 
 
-Save it as a shell script, then run on the file(s) you modified.
 
 @subheading Indenting with vim
 
-Although emacs indentation is the LilyPond standard, acceptable
+Although emacs indentation is the GNU standard, acceptable
 indentation can usually be accomplished with vim.  Some hints for
 vim are as follows:
 
 A workable .vimrc:
 
-@verbatim
+@example
 set cindent
 set smartindent
 set autoindent
@@ -399,22 +386,22 @@ set incsearch
 set ignorecase smartcase
 set hlsearch
 set confirm
-set statusline=%F%m%r%h%w\ %{&ff}\ %Y\ [ASCII=\%03.3b]\ [HEX=\%02.2B]\ %04l,%04v\ %p%%\ [LEN=%L]
+set statusline=%F%m%r%h%w\ %@{&ff@}\ %Y\ [ASCII=\%03.3b]\ [HEX=\%02.2B]\ %04l,%04v\ %p%%\ [LEN=%L]
 set laststatus=2
 set number
 " Remove trailing whitespace on write
 autocmd BufWritePre * :%s/\s\+$//e
-@end verbatim
+@end example
 
-With this .vimrc, files can be reindented automatically by highlighting
-the lines to be indented in visual mode (use V to enter visual mode)
-and pressing =.
+With this @file{.vimrc}, files can be reindented automatically by
+highlighting the lines to be indented in visual mode (use V to
+enter visual mode) and pressing @code{=}.
 
-A scheme.vim file will help improve the indentation.  This one
-was suggested by Patrick McCarty.  It should be saved in
-~/.vim/after/syntax/scheme.vim.
+A @file{scheme.vim} file will help improve the indentation.  This
+one was suggested by Patrick McCarty.  It should be saved in
+@file{~/.vim/after/syntax/scheme.vim}.
 
-@verbatim
+@example
 " Additional Guile-specific 'forms'
 syn keyword schemeSyntax define-public define*-public
 syn keyword schemeSyntax define* lambda* let-keywords*
@@ -445,7 +432,7 @@ set lw-=set!
 
 " Try to highlight all ly: procedures
 syn match schemeFunc "ly:[^) ]\+"
-@end verbatim
+@end example
 
 
 @node Naming conventions
@@ -727,6 +714,167 @@ Do not run make po/po-update with GNU gettext < 0.10.35
 @end itemize
 
 
+@node Warnings Errors Progress and Debug Output
+@section Warnings, Errors, Progress and Debug Output
+
+@unnumberedsubsec Available log levels
+
+LilyPond has several loglevels, which specify how verbose the output on
+the console should be:
+@itemize
+@item NONE: No output at all, even on failure
+@item ERROR: Only error messages
+@item WARN: Only error messages and warnings
+@item BASIC_PROGRESS: Warnings, errors and basic progress (success, etc.)
+@item PROGRESS: Warnings, errors and full progress messages
+@item INFO: Warnings, errors, progress and more detailed information (default)
+@item DEBUG: All messages, including vull debug messages (very verbose!)
+@end itemize
+
+The loglevel can either be set with the environment variable
+@code{LILYPOND_LOGLEVEL} or on the command line with the @option{--loglevel=...}
+option.
+
+@unnumberedsubsec Functions for debug and log output
+
+LilyPond has two different types of error and log functions:
+@itemize 
+
+@item
+If a warning or error is caused by an identified position in the input file,
+e.g. by a grob or by a music expression, the functions of the @code{Input}
+class provide logging functionality that prints the position of the message
+in addition to the message.
+
+@item
+If a message can not be associated with a particular position in an input file,
+e.g. the output file cannot be written, then the functions in the 
+@code{flower/include/warn.hh} file will provide logging functionality that 
+only prints out the message, but no location.
+
+@end itemize
+
+There are also Scheme functions to access all of these logging functions from
+scheme.  In addition, the Grob class contains some convenience wrappers for
+even easier access to these functions.
+
+The message and debug functions in @code{warn.hh} also have an optional 
+argument @code{newline}, which specifies whether the message should always
+start on a new line or continue a previous message.
+By default, @code{progress_indication} does NOT start on a new line, but rather
+continue the previous output.  They also do not have a particular input
+position associated, so there are no progress functions in the Input class.
+All other functions by default start their output on a new line.
+
+The error functions come in three different flavors: fatal error messages,
+programming error messages and normal error messages.  Errors written
+by the @code{error ()} function will cause LilyPond to exit immediately,
+errors by @code{Input::error ()} will continue the compilation, but
+return a non-zero return value of the lilypond call (i.e. indicate an 
+unsuccessful program execution).  All other errors will be printed on the 
+console, but not exit LilyPond or indicate an unsuccessful return code.
+Their only differences to a warnings are the displayed text and that
+they will be shown with loglevel @code{ERROR}.
+
+If the Scheme option @code{warning-as-error} is set, any warning will be
+treated as if @code{Input::error} was called.
+
+
+@unnumberedsubsec All logging functions at a glance
+
+@multitable @columnfractions 0.16 0.42 0.42
+@headitem
+@tab C++, no location
+@tab C++ from input location
+
+@item ERROR
+@tab @code{error ()}, @code{programming_error (msg)}, @code{non_fatal_error (msg)}
+@tab @code{Input::error (msg)}, @code{Input::programming_error (msg)}
+
+@item WARN
+@tab @code{warning (msg)}
+@tab @code{Input::warning (msg)}
+
+@item BASIC
+@tab @code{basic_progress (msg)}
+@tab -
+
+@item PROGRESS
+@tab @code{progress_indication (msg)}
+@tab -
+
+@item INFO
+@tab @code{message (msg)}
+@tab @code{Input::message (msg)}
+
+@item DEBUG
+@tab @code{debug_output (msg)}
+@tab @code{Input::debug_output (msg)}
+
+@item @tab @tab
+
+@headitem
+@tab C++ from a Grob
+@tab Scheme, music expression
+
+@item ERROR
+@tab @code{Grob::programming_error (msg)}
+@tab -
+
+@item WARN
+@tab @code{Grob::warning (msg)}
+@tab @code{(ly:music-warning music msg)}
+
+@item BASIC
+@tab -
+@tab -
+
+@item PROGRESS
+@tab -
+@tab -
+
+@item INFO
+@tab -
+@tab @code{(ly:music-message music msg)}
+
+@item DEBUG
+@tab -
+@tab -
+
+@item @tab @tab
+
+@headitem
+@tab Scheme, no location
+@tab Scheme, input location
+
+@item ERROR
+@tab -
+@tab @code{(ly:error msg args)}, @code{(ly:programming-error msg args)}
+
+@item WARN
+@tab @code{(ly:warning msg args)}
+@tab @code{(ly:input-warning input msg args)}
+
+@item BASIC
+@tab @code{(ly:basic-progress msg args)}
+@tab -
+
+@item PROGRESS
+@tab @code{(ly:progress msg args)}
+@tab -
+
+@item INFO
+@tab @code{(ly:message msg args)}
+@tab @code{(ly:input-message input msg args)}
+
+@item DEBUG
+@tab @code{(ly:debug msg args)}
+@tab -
+
+@end multitable
+
+
+
 
 @node Debugging LilyPond
 @section Debugging LilyPond
@@ -1056,7 +1204,7 @@ number of different platforms:
 In order for the Graphviz tool to work, config.make must be modified.
 It is probably a good idea to first save a copy of config.make under
 a different name.  Then, edit config.make by removing every occurrence
-of @code{-DNDEBUG}.
+of @option{-DNDEBUG}.
 
 @item Rebuilding LilyPond
 
@@ -1104,7 +1252,7 @@ dot -Tpdf graphviz.log > graphviz.pdf
 
 The pdf file can then be viewed with any pdf viewer.
 
-When compiled without @code{-DNDEBUG}, lilypond may run slower
+When compiled without @option{-DNDEBUG}, lilypond may run slower
 than normal.  The original configuration can be restored by either
 renaming the saved copy of @code{config.make} or rerunning
 @code{configure}.  Then rebuild lilypond with
@@ -1396,7 +1544,7 @@ Otherwise, a developer with push privileges will push the patch.
 Once the patch has been pushed, all the relevant issues should be
 closed.
 
-On Rietveld, the author should log in an close the issue either by
+On Rietveld, the author should log in and close the issue either by
 using the @q{Edit Issue} link, or by clicking the circled x icon
 to the left of the issue name.
 
@@ -1571,6 +1719,16 @@ Engraver_name::acknowledge_interface_name (Grob_info info)
 @}
 @end example
 
+Acknowledge functions are called in the order engravers are
+@code{\consist}-ed (the only exception is if you set
+@code{must-be-last} to @code{#t}).
+
+If useful things are to be done to the acknowledged grobs, this
+should be deferred until all the acknowledging has finished, i.e.,
+store the acknowledged grobs and process the information in a
+@code{process-acknowledged ()} or @code{stop-translation-timestep ()} 
+function.
+
 
 @node Engraver declaration/documentation
 @subsection Engraver declaration/documentation
@@ -1654,6 +1812,137 @@ a manner that allows it to be garbage-collected when the module is
 dispersed, either by being stored module-locally, or in weak hash
 tables.
 
+
+@node Scheme->C interface
+@section Scheme->C interface
+
+Most of the C functions interfacing with Guile/Scheme used in LilyPond
+are described in the API Reference of the
+@uref{http://www.gnu.org/software/guile/manual/html_node/index.html,
+GUILE Reference Manual}.
+
+The remaining functions are defined in @file{lily/lily-guile.cc},
+@file{lily/include/lily-guile.hh} and
+@file{lily/include/lily-guile-macros.hh}.
+Although their names are meaningful there's a few things you should know
+about them.
+
+@menu
+* Comparison::
+* Conversion::
+@end menu
+
+@node Comparison
+@subsection Comparison
+
+This is the trickiest part of the interface.
+
+Mixing Scheme values with C comparison operators won't produce any crash
+or warning when compiling but must be avoided:
+
+@example
+scm_string_p (scm_value) == SCM_BOOL_T
+@end example
+
+As we can read in the reference, @code{scm_string_p} returns a Scheme
+value: either @code{#t} or @code{#f} which are written @code{SCM_BOOL_T}
+and @code{SCM_BOOL_F} in C.  This will work, but it is not following
+to the API guidelines.  For further information, read this discussion:
+
+@smallexample
+@uref{http://lists.gnu.org/archive/html/lilypond-devel/2011-08/msg00646.html}
+@end smallexample
+
+There are functions in the Guile reference that returns C values
+instead of Scheme values.  In our example, a function called
+@code{scm_is_string} (described after @code{string?} and @code{scm_string_p})
+returns the C value 0 or 1.
+
+So the best solution was simply:
+
+@example
+scm_is_string (scm_value)
+@end example
+
+There a simple solution for almost every common comparison.  Another example:
+we want to know if a Scheme value is a non-empty list.  Instead of:
+
+@example
+(scm_is_true (scm_list_p (scm_value)) && scm_value != SCM_EOL)
+@end example
+
+one can usually use:
+
+@example
+scm_is_pair (scm_value)
+@end example
+
+since a list of at least one member is a pair.  This test is
+cheap; @code{scm_list_p} is actually quite more complex since it makes
+sure that its argument is neither a `dotted list' where the last pair
+has a non-null @code{cdr}, nor a circular list.  There are few
+situations where the complexity of those tests make sense.
+
+Unfortunately, there is not a @code{scm_is_[something]} function for
+everything.  That's one of the reasons why LilyPond has its own Scheme
+interface.  As a rule of thumb, tests that are cheap enough to be
+worth inlining tend to have such a C interface.  So there is
+@code{scm_is_pair} but not @code{scm_is_list}, and @code{scm_is_eq}
+but not @code{scm_is_equal}.
+
+@subheading General definitions
+
+@subsubheading bool to_boolean (SCM b)
+
+Return @code{true} if @var{b} is @code{SCM_BOOL_T}, else return @code{false}.
+
+This should be used instead of @code{scm_is_true} and
+@code{scm_is_false} for properties since in Lilypond, unset properties
+are read as an empty list, and by convention unset Boolean properties
+default to false.  Since both @code{scm_is_true} and
+@code{scm_is_false} only compare with @code{##f} in line with what
+Scheme's conditionals do, they are not really useful for checking the
+state of a Boolean property.
+
+@subsubheading bool ly_is_[something] (args)
+
+Behave the same as scm_is_[something] would do if it existed.
+
+@subsubheading bool is_[type] (SCM s)
+
+Test whether the type of @var{s} is [type].
+[type] is a LilyPond-only set of values (direction, axis...).  More
+often than not, the code checks Lilypond specific C++-implemented
+types using
+
+@subsubheading [type *] unsmob_[type] (SCM s)
+
+This tries converting a Scheme object to a pointer of the desired
+kind.  If the Scheme object is of the wrong type, a pointer value
+of@w{ }@code{0} is returned, making this suitable for a Boolean test.
+
+@node Conversion
+@subsection Conversion
+
+@subheading General definitions
+
+@subsubheading bool to_boolean (SCM b)
+
+Return @code{true} if @var{b} is @code{SCM_BOOL_T}, else return @code{false}.
+
+This should be used instead of @code{scm_is_true} and @code{scm_is_false}
+for properties since empty lists are sometimes used to unset them.
+
+@subsubheading [C type] ly_scm2[C type] (SCM s)
+
+Behave the same as scm_to_[C type] would do if it existed.
+
+@subsubheading [C type] robust_scm2[C type] (SCM s, [C type] d)
+
+Behave the same as scm_to_[C type] would do if it existed.
+Return @var{d} if type verification fails.
+
+
 @node LilyPond miscellany
 @section LilyPond miscellany
 
@@ -1694,6 +1983,16 @@ We create lots of extra grobs (eg. a BarNumber at every bar line) but
 most of them are not drawn.  See the break-visibility property in
 item-interface.
 
+Here is another e-mail exchange.  Janek WarchoĊ‚ asked for a starting point
+to fixing 1301 (change clef colliding with notes).  Neil Puttock replied:
+
+The clef is on a loose column (it floats before the head), so the
+first place I'd look would be lily/spacing-loose-columns.cc (and
+possibly lily/spacing-determine-loose-columns.cc).
+I'd guess the problem is the way loose columns are spaced between
+other columns: in this snippet, the columns for the quaver and tuplet
+minim are so close together that the clef's column gets dumped on top
+of the quaver (since it's loose, it doesn't influence the spacing).
 
 @node Info from Han-Wen email
 @subsection Info from Han-Wen email