]> git.donarmstrong.com Git - lilypond.git/blob - ly/context-mods-init.ly
Add layout changing command \layout-from for getting context defs from music
[lilypond.git] / ly / context-mods-init.ly
1 %%%% This file is part of LilyPond, the GNU music typesetter.
2 %%%%
3 %%%% Copyright (C) 2011--2012 Han-Wen Nienhuys <hanwen@xs4all.nl>
4 %%%%                    Jan Nieuwenhuizen <janneke@gnu.org>
5 %%%%
6 %%%% LilyPond is free software: you can redistribute it and/or modify
7 %%%% it under the terms of the GNU General Public License as published by
8 %%%% the Free Software Foundation, either version 3 of the License, or
9 %%%% (at your option) any later version.
10 %%%%
11 %%%% LilyPond is distributed in the hope that it will be useful,
12 %%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
13 %%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 %%%% GNU General Public License for more details.
15 %%%%
16 %%%% You should have received a copy of the GNU General Public License
17 %%%% along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18
19 \version "2.15.31"
20
21 RemoveEmptyStaves = \with {
22   \remove "Axis_group_engraver"
23   % If RemoveEmptyStaves is called twice, two
24   % Hara_kiri_engravers would be added, which leads to a
25   % warning.
26   % This code makes sure that no previous Hara_kiri_engraver
27   % is left before adding a new one.
28   \remove "Hara_kiri_engraver"
29   \consists "Hara_kiri_engraver"
30   \override VerticalAxisGroup #'remove-empty = ##t
31   \description "Remove staves which are considered to be empty according
32 to the list of interfaces set by @code{keepAliveInterfaces}."
33 }
34
35 "layout-from" =
36 #(define-void-function (parser location bottom music)
37    ((symbol? 'Voice) ly:music?)
38    (_i "To be used in output definitions.  Take the layout instruction
39 events from @var{music} and do the equivalent of context modifications
40 duplicating their effect.
41
42 This is handy for making layout definitions by using property
43 definitions like @code{\\accidentalStyle} or definitions like
44 @code{\\tabFullNotation} that may work in multiple or unknown
45 contexts.
46
47 Layout instructions specified without explicit context get mapped to
48 the context symbol @var{bottom}, with a default of @code{'Voice}.
49
50 For example, you can tell @code{\\layout-from} to apply a contained
51 @example
52 \\override #'font-size = #2
53 @end example
54 to @samp{TabVoice} or @samp{Lyrics} context instead of the default
55 @samp{Voice} context, if the context where you would normally use
56 @var{music} is not one that would have @samp{Voice} as its
57 @samp{Bottom}.")
58    (let loop ((m music) (mods #f))
59      ;; The parser turns all sets, overrides etc into something
60      ;; wrapped in ContextSpeccedMusic.  If we ever get a set,
61      ;; override etc that is not wrapped in ContextSpeccedMusic, the
62      ;; user has created it in Scheme himself without providing the
63      ;; required wrapping.  In that case, using #f in the place of a
64      ;; context modification results in a reasonably recognizable
65      ;; error.
66      (if (music-is-of-type? m 'layout-instruction-event)
67          (ly:add-context-mod
68           mods
69           (case (ly:music-property m 'name)
70             ((PropertySet)
71              (list 'assign
72                    (ly:music-property m 'symbol)
73                    (ly:music-property m 'value)))
74             ((PropertyUnset)
75              (list 'unset
76                    (ly:music-property m 'symbol)))
77             ((OverrideProperty)
78              (list 'push
79                    (ly:music-property m 'symbol)
80                    (ly:music-property m 'grob-property-path)
81                    (ly:music-property m 'grob-value)))
82             ((RevertProperty)
83              (list 'pop
84                    (ly:music-property m 'symbol)
85                    (ly:music-property m 'grob-property-path)))))
86          (case (ly:music-property m 'name)
87            ((SequentialMusic SimultaneousMusic)
88             (fold loop mods (ly:music-property m 'elements)))
89            ((ContextSpeccedMusic)
90             ;; It is actually rather embarrassing that we have no
91             ;; reliable way to check for the type of a context-def.
92             ;; Nor have a Scheme way to add to a context-def.
93             (let ((sym (ly:music-property m 'context-type)))
94               (if (eq? sym 'Bottom)
95                   (set! sym bottom))
96               (if (module-bound? (current-module) sym)
97                   (module-set!
98                    (current-module)
99                    sym
100                    #{ \context {
101                                  $(module-ref (current-module) sym)
102                                  $(loop (ly:music-property m 'element)
103                                         (ly:make-context-mod))
104                       }
105                    #})
106                   (ly:warning music (_f "Cannot find context-def \\~a"
107                                         sym)))))))
108      mods))