<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.lilypond.community/index.php?action=history&amp;feed=atom&amp;title=Alternate_%5CtextSpanner_engraver</id>
	<title>Alternate \textSpanner engraver - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.lilypond.community/index.php?action=history&amp;feed=atom&amp;title=Alternate_%5CtextSpanner_engraver"/>
	<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Alternate_%5CtextSpanner_engraver&amp;action=history"/>
	<updated>2026-04-30T17:29:44Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Alternate_%5CtextSpanner_engraver&amp;diff=6448&amp;oldid=prev</id>
		<title>Lemzwerg at 06:46, 12 March 2026</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Alternate_%5CtextSpanner_engraver&amp;diff=6448&amp;oldid=prev"/>
		<updated>2026-03-12T06:46:28Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 06:46, 12 March 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l234&quot;&gt;Line 234:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 234:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   \context {&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   \context {&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     \Voice&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     \Voice&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     \remove &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;#&quot;&lt;/del&gt;Text_spanner_engraver&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&quot;&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     \remove Text_spanner_engraver&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     \consists \alternateTextSpannerEngraver&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     \consists \alternateTextSpannerEngraver&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   }&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   }&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Lemzwerg</name></author>
	</entry>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Alternate_%5CtextSpanner_engraver&amp;diff=6447&amp;oldid=prev</id>
		<title>Lemzwerg at 06:41, 12 March 2026</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Alternate_%5CtextSpanner_engraver&amp;diff=6447&amp;oldid=prev"/>
		<updated>2026-03-12T06:41:49Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 06:41, 12 March 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l171&quot;&gt;Line 171:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 171:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;		      spanners)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;		      spanners)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             (set! spanners (cons (cons new-idx new) spanners))&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             (set! spanners (cons (cons new-idx new) spanners))&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             (set! spanners&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;             (set! spanners (sort spanners &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;car&lt;/ins&gt;&amp;lt;))))&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;                  &lt;/del&gt;(sort spanners &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;(lambda (x y)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;				   (&lt;/del&gt;&amp;lt; &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;(car x) (car y)))&lt;/del&gt;))))&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         start-events)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         start-events)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Lemzwerg</name></author>
	</entry>
	<entry>
		<id>https://wiki.lilypond.community/index.php?title=Alternate_%5CtextSpanner_engraver&amp;diff=6446&amp;oldid=prev</id>
		<title>Lemzwerg: Created page with &quot;LilyPond&#039;s default text spanner engraver can only handle a single text spanner per voice at a time.  The engraver in this snippet provides an alternate implementation to circumvent this limitation; it uses spanner IDs to specify start and end of overlapping text spanners.  To use it, replace &lt;code&gt;Text_spanner_engraver&lt;/code&gt; with &lt;code&gt;\alternateTextSpannerEngraver&lt;/code&gt;.  The example below demonstrates two possible ways to specify a spanner ID: either define a new com...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.lilypond.community/index.php?title=Alternate_%5CtextSpanner_engraver&amp;diff=6446&amp;oldid=prev"/>
		<updated>2026-03-11T08:15:18Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;LilyPond&amp;#039;s default text spanner engraver can only handle a single text spanner per voice at a time.  The engraver in this snippet provides an alternate implementation to circumvent this limitation; it uses spanner IDs to specify start and end of overlapping text spanners.  To use it, replace &amp;lt;code&amp;gt;Text_spanner_engraver&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;\alternateTextSpannerEngraver&amp;lt;/code&amp;gt;.  The example below demonstrates two possible ways to specify a spanner ID: either define a new com...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;LilyPond&amp;#039;s default text spanner engraver can only handle a single text spanner per voice at a time.  The engraver in this snippet provides an alternate implementation to circumvent this limitation; it uses spanner IDs to specify start and end of overlapping text spanners.&lt;br /&gt;
&lt;br /&gt;
To use it, replace &amp;lt;code&amp;gt;Text_spanner_engraver&amp;lt;/code&amp;gt; with &amp;lt;code&amp;gt;\alternateTextSpannerEngraver&amp;lt;/code&amp;gt;.  The example below demonstrates two possible ways to specify a spanner ID: either define a new command or use the &amp;lt;code&amp;gt;\=&amp;lt;/code&amp;gt; command to directly set the ID.&lt;br /&gt;
&lt;br /&gt;
To control the vertical order of text spanners, use the standard way of tweaking the &amp;lt;code&amp;gt;outside-staff-priority&amp;lt;/code&amp;gt; property.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;lilypond version=&amp;quot;2.24&amp;quot;&amp;gt;&lt;br /&gt;
% LSR written by Dave Nalesnik&lt;br /&gt;
% LSR https://lists.gnu.org/archive/html/lilypond-user/2026-01/msg00006.html&lt;br /&gt;
&lt;br /&gt;
% Incorporating some code from the rewrite in Scheme of&lt;br /&gt;
% Text_spanner_engraver in input/regression/scheme-text-spanner.ly&lt;br /&gt;
&lt;br /&gt;
#(define (add-bound-item spanner item)&lt;br /&gt;
   (if (null? (ly:spanner-bound spanner LEFT))&lt;br /&gt;
       (ly:spanner-set-bound! spanner LEFT item)&lt;br /&gt;
       (ly:spanner-set-bound! spanner RIGHT item)))&lt;br /&gt;
&lt;br /&gt;
#(define (set-axis! grob axis)&lt;br /&gt;
   (when (not (number? (ly:grob-property grob &amp;#039;side-axis)))&lt;br /&gt;
     (set! (ly:grob-property grob &amp;#039;side-axis) axis)&lt;br /&gt;
     (ly:grob-chain-callback&lt;br /&gt;
      grob&lt;br /&gt;
      (if (eq? axis X)&lt;br /&gt;
          ly:side-position-interface::x-aligned-side&lt;br /&gt;
          side-position-interface::y-aligned-side)&lt;br /&gt;
      (if (eq? axis X)&lt;br /&gt;
	  &amp;#039;X-offset&lt;br /&gt;
	  &amp;#039;Y-offset))))&lt;br /&gt;
&lt;br /&gt;
#(define (assign-spanner-index orig-ls)&lt;br /&gt;
   &amp;quot;Determine an available position of a new spanner in an ordered&lt;br /&gt;
sequence of spanners (a list of pairs, where the car of the pair&lt;br /&gt;
gives the position).  The goal is for the sequence to begin with&lt;br /&gt;
zero and contain no gaps.  Return the index representing the&lt;br /&gt;
spanner&amp;#039;s position.&lt;br /&gt;
&lt;br /&gt;
Examples (only showing the cars of the pairs):&lt;br /&gt;
&lt;br /&gt;
  (0 1)   =&amp;gt; 2&lt;br /&gt;
  (2 3)   =&amp;gt; 0&lt;br /&gt;
  (0 3)   =&amp;gt; 1&lt;br /&gt;
  (0 1 3) =&amp;gt; 2&lt;br /&gt;
&amp;quot;&lt;br /&gt;
   (if (null? orig-ls)&lt;br /&gt;
       0&lt;br /&gt;
       (let loop ((ls orig-ls)&lt;br /&gt;
		  (insert? #t)&lt;br /&gt;
		  (result 0))&lt;br /&gt;
         (cond&lt;br /&gt;
          ((null? ls)&lt;br /&gt;
	   result)&lt;br /&gt;
          ;; Position at head of list.&lt;br /&gt;
          ((and insert? (&amp;gt; (caar orig-ls) 0))&lt;br /&gt;
           (loop ls #f 0))&lt;br /&gt;
          ;; No gaps, put at end of list.&lt;br /&gt;
          ((and insert? (null? (cdr ls)))&lt;br /&gt;
           (loop (cdr ls) #f (1+ (caar ls))))&lt;br /&gt;
          ;; Fill lowest position of gap.&lt;br /&gt;
          ((and insert?&lt;br /&gt;
                (&amp;gt; (caadr ls) (1+ (caar ls))))&lt;br /&gt;
           (loop (cdr ls) #f (1+ (caar ls))))&lt;br /&gt;
          (else&lt;br /&gt;
	   (loop (cdr ls) insert? result))))))&lt;br /&gt;
&lt;br /&gt;
alternateTextSpannerEngraver =&lt;br /&gt;
#(lambda (context)&lt;br /&gt;
   (let (;; A list of pairs comprising a spanner index (not&lt;br /&gt;
	 ;; `spanner-id` values) and a spanner which has been begun.&lt;br /&gt;
         (spanners &amp;#039;())&lt;br /&gt;
         (finished &amp;#039;()) ; A list of spanners in completion stage.&lt;br /&gt;
         (start-events &amp;#039;()) ; A list of START events.&lt;br /&gt;
         (stop-events &amp;#039;())) ; A list of STOP events.&lt;br /&gt;
     (make-engraver&lt;br /&gt;
      ;; `\startTextSpan`, `\stopTextSpan`, and the like create&lt;br /&gt;
      ;; events which we collect here.&lt;br /&gt;
      (listeners&lt;br /&gt;
       ((text-span-event engraver event)&lt;br /&gt;
        (if (= START (ly:event-property event &amp;#039;span-direction))&lt;br /&gt;
            (set! start-events (cons event start-events))&lt;br /&gt;
            (set! stop-events (cons event stop-events)))))&lt;br /&gt;
&lt;br /&gt;
      ;; Populate `note-columns` property of spanners.  Bounds are&lt;br /&gt;
      ;; set to note columns, and each spanner keeps a record of&lt;br /&gt;
      ;; the note columns it traverses.&lt;br /&gt;
      (acknowledgers&lt;br /&gt;
       ((note-column-interface engraver grob source-engraver)&lt;br /&gt;
        (for-each (lambda (s)&lt;br /&gt;
                    (ly:pointer-group-interface::add-grob&lt;br /&gt;
                     (cdr s) &amp;#039;note-columns grob)&lt;br /&gt;
                    (when (null? (ly:spanner-bound (cdr s) LEFT))&lt;br /&gt;
                      (add-bound-item (cdr s) grob)))&lt;br /&gt;
		  spanners)&lt;br /&gt;
        ;; `finished` only contains spanners, no indices.&lt;br /&gt;
        (for-each (lambda (f)&lt;br /&gt;
                    (ly:pointer-group-interface::add-grob&lt;br /&gt;
                     f &amp;#039;note-columns grob)&lt;br /&gt;
                    (when (null? (ly:spanner-bound f RIGHT))&lt;br /&gt;
                      (add-bound-item f grob)))&lt;br /&gt;
		  finished)))&lt;br /&gt;
&lt;br /&gt;
      ((process-music trans)&lt;br /&gt;
       ;; Move begun spanners from `span` to `finished`.  We do&lt;br /&gt;
       ;; this on the basis of `spanner-id`.  If we find a match&lt;br /&gt;
       ;; -- either the strings are the same, or both are unset --&lt;br /&gt;
       ;; a transfer can be made.  Return a warning if we find no&lt;br /&gt;
       ;; match: spanner hasn&amp;#039;t been properly begun.&lt;br /&gt;
       (for-each&lt;br /&gt;
        (lambda (es)&lt;br /&gt;
          (let ((es-id (ly:event-property es &amp;#039;spanner-id)))&lt;br /&gt;
            (let loop ((sp spanners))&lt;br /&gt;
              (if (null? sp)&lt;br /&gt;
                  (ly:warning &amp;quot;No spanner to end!&amp;quot;)&lt;br /&gt;
                  (let ((sp-id (ly:event-property&lt;br /&gt;
                                (event-cause (cdar sp))&lt;br /&gt;
				&amp;#039;spanner-id)))&lt;br /&gt;
                    (cond&lt;br /&gt;
                     ((equal? sp-id es-id)&lt;br /&gt;
                      (set! finished (cons (cdar sp) finished))&lt;br /&gt;
                      (set! spanners&lt;br /&gt;
			    (remove (lambda (s)&lt;br /&gt;
				      (eq? s (car sp))) spanners)))&lt;br /&gt;
                     (else&lt;br /&gt;
		      (loop (cdr sp)))))))))&lt;br /&gt;
        stop-events)&lt;br /&gt;
&lt;br /&gt;
       ;; The end of our spanners can be acknowledged by other&lt;br /&gt;
       ;; engravers, thus announce them.&lt;br /&gt;
       (for-each&lt;br /&gt;
        (lambda (f)&lt;br /&gt;
          (ly:engraver-announce-end-grob trans f (event-cause f)))&lt;br /&gt;
        finished)&lt;br /&gt;
&lt;br /&gt;
       ;; Make spanners in response to START events.&lt;br /&gt;
       ;;&lt;br /&gt;
       ;; Each new spanner is assigned an index denoting its&lt;br /&gt;
       ;; position relative to other active spanners.  This is&lt;br /&gt;
       ;; enforced (for the moment) by adding a small amount to&lt;br /&gt;
       ;; the spanner&amp;#039;s `outside-staff-priority` proportional to&lt;br /&gt;
       ;; this index.  This is unlikely to result in conflicts,&lt;br /&gt;
       ;; though a better solution may be to organize the spanners&lt;br /&gt;
       ;; by a new alignment grob.&lt;br /&gt;
       ;;&lt;br /&gt;
       ;; Also, add any existing spanners to the&lt;br /&gt;
       ;; `side-support-elements` array of the new spanner.  This&lt;br /&gt;
       ;; ensures correct ordering over line breaks when&lt;br /&gt;
       ;; `outside-staff-priority` is set to `#f` (which means&lt;br /&gt;
       ;; that it is no longer an outside-staff object -- not the&lt;br /&gt;
       ;; default).&lt;br /&gt;
       (for-each&lt;br /&gt;
        (lambda (es)&lt;br /&gt;
          (let* ((new (ly:engraver-make-grob&lt;br /&gt;
		       trans &amp;#039;TextSpanner es))&lt;br /&gt;
                 (new-idx (assign-spanner-index spanners))&lt;br /&gt;
                 (new-osp (ly:grob-property&lt;br /&gt;
			   new &amp;#039;outside-staff-priority))&lt;br /&gt;
                 (new-osp (if (number? new-osp)&lt;br /&gt;
                              (+ new-osp (/ new-idx 1000.0))&lt;br /&gt;
                              new-osp)))&lt;br /&gt;
            (set! (ly:grob-property&lt;br /&gt;
		   new &amp;#039;outside-staff-priority) new-osp)&lt;br /&gt;
            (set-axis! new Y)&lt;br /&gt;
            ;; Add spanners with a lower index than the new&lt;br /&gt;
            ;; spanner to its `side-support-elements` list.  This&lt;br /&gt;
            ;; allows new spanners to fill gaps under the topmost&lt;br /&gt;
            ;; spanner.&lt;br /&gt;
            (for-each (lambda (sp)&lt;br /&gt;
			(when (&amp;lt; (car sp) new-idx)&lt;br /&gt;
			  (ly:pointer-group-interface::add-grob&lt;br /&gt;
			   new &amp;#039;side-support-elements (cdr sp))))&lt;br /&gt;
		      spanners)&lt;br /&gt;
            (set! spanners (cons (cons new-idx new) spanners))&lt;br /&gt;
            (set! spanners&lt;br /&gt;
                  (sort spanners (lambda (x y)&lt;br /&gt;
				   (&amp;lt; (car x) (car y)))))))&lt;br /&gt;
        start-events)&lt;br /&gt;
&lt;br /&gt;
       ;; Events have served their purpose for this timestep.&lt;br /&gt;
       ;; Clear the way for new events in later timesteps.&lt;br /&gt;
       (set! start-events &amp;#039;())&lt;br /&gt;
       (set! stop-events &amp;#039;()))&lt;br /&gt;
&lt;br /&gt;
      ((stop-translation-timestep trans)&lt;br /&gt;
       ;; Set bounds of spanners to `PaperColumns` grobs if they&lt;br /&gt;
       ;; haven&amp;#039;t been set.  This allows spanners to be drawn&lt;br /&gt;
       ;; between spacers.&lt;br /&gt;
       ;;&lt;br /&gt;
       ;; Other uses?  Doesn&amp;#039;t appear to affect whether spanners&lt;br /&gt;
       ;; can de drawn between rests.&lt;br /&gt;
       (for-each (lambda (s)&lt;br /&gt;
		   (when (null? (ly:spanner-bound (cdr s) LEFT))&lt;br /&gt;
		     (ly:spanner-set-bound!&lt;br /&gt;
		      (cdr s) LEFT&lt;br /&gt;
		      (ly:context-property context&lt;br /&gt;
					   &amp;#039;currentMusicalColumn))))&lt;br /&gt;
		 spanners)&lt;br /&gt;
       (for-each (lambda (f)&lt;br /&gt;
		   (when (null? (ly:spanner-bound f RIGHT))&lt;br /&gt;
		     (ly:spanner-set-bound!&lt;br /&gt;
		      f RIGHT&lt;br /&gt;
		      (ly:context-property context&lt;br /&gt;
					   &amp;#039;currentMusicalColumn))))&lt;br /&gt;
		 finished)&lt;br /&gt;
       (set! finished &amp;#039;()))&lt;br /&gt;
&lt;br /&gt;
      ((finalize trans)&lt;br /&gt;
       ;; If spanner ends on spacer at end of context?&lt;br /&gt;
       (for-each (lambda (f)&lt;br /&gt;
                   (when (null? (ly:spanner-bound f RIGHT))&lt;br /&gt;
                     (ly:spanner-set-bound!&lt;br /&gt;
		      f RIGHT&lt;br /&gt;
                      (ly:context-property context&lt;br /&gt;
					   &amp;#039;currentMusicalColumn))))&lt;br /&gt;
		 finished)&lt;br /&gt;
       (set! finished &amp;#039;())&lt;br /&gt;
       ;; User didn&amp;#039;t end spanner.&lt;br /&gt;
       (for-each (lambda (sp)&lt;br /&gt;
		   (ly:warning &amp;quot;incomplete spanner removed!&amp;quot;)&lt;br /&gt;
		   (ly:grob-suicide! (cdr sp)))&lt;br /&gt;
		 spanners)&lt;br /&gt;
       (set! spanners &amp;#039;())))))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% EXAMPLE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&lt;br /&gt;
&lt;br /&gt;
startTextSpanOne =&lt;br /&gt;
#(make-music &amp;#039;TextSpanEvent &amp;#039;span-direction START &amp;#039;spanner-id &amp;quot;1&amp;quot;)&lt;br /&gt;
stopTextSpanOne =&lt;br /&gt;
#(make-music &amp;#039;TextSpanEvent &amp;#039;span-direction STOP &amp;#039;spanner-id &amp;quot;1&amp;quot;)&lt;br /&gt;
startTextSpanTwo =&lt;br /&gt;
#(make-music &amp;#039;TextSpanEvent &amp;#039;span-direction START &amp;#039;spanner-id &amp;quot;2&amp;quot;)&lt;br /&gt;
stopTextSpanTwo =&lt;br /&gt;
#(make-music &amp;#039;TextSpanEvent &amp;#039;span-direction STOP &amp;#039;spanner-id &amp;quot;2&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
\layout {&lt;br /&gt;
  \context {&lt;br /&gt;
    \Voice&lt;br /&gt;
    \remove #&amp;quot;Text_spanner_engraver&amp;quot;&lt;br /&gt;
    \consists \alternateTextSpannerEngraver&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
\relative c&amp;#039; {&lt;br /&gt;
  \override TextSpanner.style = ##f&lt;br /&gt;
  \override TextSpanner.thickness = 10&lt;br /&gt;
  % \override TextSpanner.to-barline = ##t&lt;br /&gt;
&lt;br /&gt;
  a4 \tweak color #red \startTextSpan&lt;br /&gt;
    b \tweak color #green \startTextSpanOne&lt;br /&gt;
    c \tweak color #blue \startTextSpanTwo&lt;br /&gt;
    d \=3\startTextSpan |&lt;br /&gt;
  a4\stopTextSpan&lt;br /&gt;
    b \stopTextSpanOne&lt;br /&gt;
      \tweak color #red \startTextSpan&lt;br /&gt;
    c \stopTextSpanTwo&lt;br /&gt;
      \tweak color #green \startTextSpanOne&lt;br /&gt;
    d \=3\stopTextSpan&lt;br /&gt;
      \tweak color #blue \startTextSpanTwo |&lt;br /&gt;
  a4 \=3\startTextSpan&lt;br /&gt;
    b c d | \break&lt;br /&gt;
&lt;br /&gt;
  a4 b c d |&lt;br /&gt;
  a4\stopTextSpan&lt;br /&gt;
    \stopTextSpanOne&lt;br /&gt;
    \stopTextSpanTwo&lt;br /&gt;
    \=3\stopTextSpan&lt;br /&gt;
    b &lt;br /&gt;
    c \startTextSpan&lt;br /&gt;
    d \tweak outside-staff-priority #0 \=1\startTextSpan |&lt;br /&gt;
  a4 b&lt;br /&gt;
    c \=1\stopTextSpan&lt;br /&gt;
    d \stopTextSpan |&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/lilypond&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Contexts and engravers]]&lt;br /&gt;
[[Category:Editorial annotations]]&lt;br /&gt;
[[Category:Expressive marks]]&lt;br /&gt;
[[Category:Scheme]]&lt;br /&gt;
[[Category:Workaround]]&lt;br /&gt;
[[Category:Snippet]]&lt;/div&gt;</summary>
		<author><name>Lemzwerg</name></author>
	</entry>
</feed>