]> git.donarmstrong.com Git - lilypond.git/commitdiff
Add layout changing command \layout-from for getting context defs from music
authorDavid Kastrup <dak@gnu.org>
Mon, 20 Feb 2012 17:39:23 +0000 (18:39 +0100)
committerDavid Kastrup <dak@gnu.org>
Wed, 7 Mar 2012 21:03:07 +0000 (22:03 +0100)
input/regression/layout-from.ly [new file with mode: 0644]
ly/context-mods-init.ly

diff --git a/input/regression/layout-from.ly b/input/regression/layout-from.ly
new file mode 100644 (file)
index 0000000..2c0669a
--- /dev/null
@@ -0,0 +1,19 @@
+\version "2.15.31"
+
+\header {
+  texidoc = "
+@code{\\layout-from} can interpret property-setting music for changing
+context definitions inside of layout definitions like @code{\\layout}
+or @code{\\midi}.
+"
+}
+
+\score {
+  \relative c' { cis cis cis cis }
+  \layout {
+    \layout-from { \accidentalStyle "dodecaphonic" }
+  }
+  \midi {
+    \layout-from { \tempo 4 = 240 }
+  }
+}
index 087d4bb155e1a37464111fd584c8a949031fab38..b8361a58ecfb07f0c44629c6ae13db00570379d3 100644 (file)
@@ -16,7 +16,7 @@
 %%%% You should have received a copy of the GNU General Public License
 %%%% along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 
-\version "2.15.6"
+\version "2.15.31"
 
 RemoveEmptyStaves = \with {
   \remove "Axis_group_engraver"
@@ -31,3 +31,78 @@ RemoveEmptyStaves = \with {
   \description "Remove staves which are considered to be empty according
 to the list of interfaces set by @code{keepAliveInterfaces}."
 }
+
+"layout-from" =
+#(define-void-function (parser location bottom music)
+   ((symbol? 'Voice) ly:music?)
+   (_i "To be used in output definitions.  Take the layout instruction
+events from @var{music} and do the equivalent of context modifications
+duplicating their effect.
+
+This is handy for making layout definitions by using property
+definitions like @code{\\accidentalStyle} or definitions like
+@code{\\tabFullNotation} that may work in multiple or unknown
+contexts.
+
+Layout instructions specified without explicit context get mapped to
+the context symbol @var{bottom}, with a default of @code{'Voice}.
+
+For example, you can tell @code{\\layout-from} to apply a contained
+@example
+\\override #'font-size = #2
+@end example
+to @samp{TabVoice} or @samp{Lyrics} context instead of the default
+@samp{Voice} context, if the context where you would normally use
+@var{music} is not one that would have @samp{Voice} as its
+@samp{Bottom}.")
+   (let loop ((m music) (mods #f))
+     ;; The parser turns all sets, overrides etc into something
+     ;; wrapped in ContextSpeccedMusic.  If we ever get a set,
+     ;; override etc that is not wrapped in ContextSpeccedMusic, the
+     ;; user has created it in Scheme himself without providing the
+     ;; required wrapping.  In that case, using #f in the place of a
+     ;; context modification results in a reasonably recognizable
+     ;; error.
+     (if (music-is-of-type? m 'layout-instruction-event)
+        (ly:add-context-mod
+         mods
+         (case (ly:music-property m 'name)
+           ((PropertySet)
+            (list 'assign
+                  (ly:music-property m 'symbol)
+                  (ly:music-property m 'value)))
+           ((PropertyUnset)
+            (list 'unset
+                  (ly:music-property m 'symbol)))
+           ((OverrideProperty)
+            (list 'push
+                  (ly:music-property m 'symbol)
+                  (ly:music-property m 'grob-property-path)
+                  (ly:music-property m 'grob-value)))
+           ((RevertProperty)
+            (list 'pop
+                  (ly:music-property m 'symbol)
+                  (ly:music-property m 'grob-property-path)))))
+        (case (ly:music-property m 'name)
+          ((SequentialMusic SimultaneousMusic)
+           (fold loop mods (ly:music-property m 'elements)))
+          ((ContextSpeccedMusic)
+           ;; It is actually rather embarrassing that we have no
+           ;; reliable way to check for the type of a context-def.
+           ;; Nor have a Scheme way to add to a context-def.
+           (let ((sym (ly:music-property m 'context-type)))
+             (if (eq? sym 'Bottom)
+                 (set! sym bottom))
+             (if (module-bound? (current-module) sym)
+                 (module-set!
+                  (current-module)
+                  sym
+                  #{ \context {
+                                $(module-ref (current-module) sym)
+                                $(loop (ly:music-property m 'element)
+                                       (ly:make-context-mod))
+                     }
+                  #})
+                 (ly:warning music (_f "Cannot find context-def \\~a"
+                                       sym)))))))
+     mods))