LSR/871

< LSR
Zur Navigation springen Zur Suche springen
PD Der Inhalt dieser Seite wurde aus dem LilyPond Snippet Repository übernommen und steht unter folgender Lizenz: CC0.
See Public Domain Help Pages for more info.
PD
tag manipulating functions and additional filter by tag functions

LSR Snippet Nr. 871

Beschreibung

If you're using tags frequently, you may find the available functions quite limited. Here is a collection of additional functions to modify the tags, and to filter by the tags.

tag manipulating:

\removeAllTags music
    returns a copy of the music, where all tags are erased. Thus they will not harm when tags are created in a higher level and the music is then filtered by \keepWithTag.
    \copyTag from-tag-symbol to-tag-symbol music
    returns a copy of the music, where all elements tagged with 'from-tag-symbol' also got a tag 'to-tag-symbol'.
    \renameTag from-tag-symbol to-tag-symbol music
    returns a copy of the music, where the tag names 'from-tag-symbol' are altered into 'to-tag-symbol'.
    \removeTag tag-symbol music
    returns a copy of the music, where only the tags 'tag-symbol' are erased, the music is kept.
    \removeTags tag-symbol-list music
    similar to '\removeTag', but takes a list to rub out multiple tags from the music.

filtering by tags:

\keepWithTags tag-symbol-list music
    filters the music and keeps all tagged objects, who's tags are listed in the 'tag-symbol-list'. This 'keep with tag x or y or ...' is such a fundamental idea, it seems to be developed multiple times, and I heard it will be superseeded by the standard LILYPOND command \keepWithTag in near future.
    \keepOrRemoveWithTag tag-symbol list-of-the-relevant-tag-symbols music
    keeps all elements tagged by 'tag-symbol', but it only removes tagged elements out of the 'list-of-the-relevant-tag-symbols'. Thus, this list is an limitation which tags to check. This list my include the 'tag-symbol' which to keep.
    \taggedRep start-tag-symbol end-tag-symbol rep-count-integer music
    is allmost an "\repeat unfold" command. In the first repetition the elements tagged with 'start-tag-symbol' will be kept while the ones with 'end-tag-symbol' will be removed. In the last repetition it's inverted and only the 'end-tag-symbol' tagged elements will be kept while those with 'start-tag-symbol' will be removed. In all repetitions between both tagged elements will be removed.

combined funtions:

\cleansedKeepOrRemoveWithTag tag-symbol list-of-the-relevant-tag-symbols music
    Additional to \keepOrRemoveWithTag all the tags listed in 'list-of-the-relevant-tag-symbols' will be removed from the result to reduce the chance of side effects when the music is filtered again.
    \cleansedTaggedRep start-tag-symbol end-tag-symbol rep-count-integer music
    Additional to \taggedRep the two tags 'start-tag-symbol' and 'end-tag-symbol' will be removed from the result to reduce the chance of side effects when the music is filtered again.
    \keepPart music, \keepScore music and \keepMidi music
    These are predefined \cleansedKeepOrRemoveWithTag commands. The list of the relevant tag symbols is stored in the Parameter PSM = #'(Part Score Midi); their name shows which tag they keep.
auto

Lilypond-Code

%% http://lsr.di.unimi.it/LSR/Item?id=871
%% see also http://lsr.di.unimi.it/LSR/Item?id=219
%% see also http://www.lilypond.org/doc/v2.18/Documentation/notation/different-editions-from-one-source#using-tags

%by: ArnoldTheresius

%tested: \version "2.17.97"

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% START of my personal include file 'tagging.ly'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#(define (remove-all-tags music)
  (if (ly:music? music)
   (let*
    ((es (ly:music-property music 'elements))
     (e (ly:music-property music 'element))
     (as (ly:music-property music 'articulations))
     (tags (ly:music-property music 'tags)))
    (if (not (eq? tags '()))
     (ly:music-set-property! music 'tags '()))
    (for-each remove-all-tags es)
    (remove-all-tags e)
    (for-each remove-all-tags as))
   music))

removeAllTags =
#(define-music-function
  (parser location music) (ly:music?)
  (_i "Delete all the tags in all elements of @var{music}")
  (let
   ((new-music (ly:music-deep-copy music)))
   (remove-all-tags new-music)
   new-music))


#(define (copy-tags-in-music tag-from tag-to music)
  (if (ly:music? music)
   (let*
    ((es (ly:music-property music 'elements))
     (e (ly:music-property music 'element))
     (as (ly:music-property music 'articulations))
     (tags (ly:music-property music 'tags)))
    (if (memq tag-from tags)
     (if (not (memq tag-to tags))
      (ly:music-set-property! music 'tags (cons tag-to tags))))
    (for-each (lambda (x) (copy-tags-in-music tag-from tag-to x)) es)
    (copy-tags-in-music tag-from tag-to e)
    (for-each (lambda (x) (copy-tags-in-music tag-from tag-to x)) as))
   music))

copyTag =
#(define-music-function
  (parser location tag-from tag-to music) (symbol? symbol? ly:music?)
  (_i "To all elements of @var{music} which are tagged with @var{tag-from} add a tag @var{tag-to}.")
  (let
   ((new-music (ly:music-deep-copy music)))
   (copy-tags-in-music tag-from tag-to new-music)
   new-music))


#(define (rename-tag-in-music tag-from tag-to music)
  (if (ly:music? music)
   (let*
    ((es (ly:music-property music 'elements))
     (e (ly:music-property music 'element))
     (as (ly:music-property music 'articulations))
     (tags (ly:music-property music 'tags)))
    (if (memq tag-from tags)
     (let
      ((nt (delq tag-from tags)))
      (if (memq tag-to tags)
       (ly:music-set-property! music 'tags nt)
       (ly:music-set-property! music 'tags (cons tag-to nt)))))
    (for-each (lambda (x) (rename-tag-in-music tag-from tag-to x)) es)
    (rename-tag-in-music tag-from tag-to e)
    (for-each (lambda (x) (rename-tag-in-music tag-from tag-to x)) as))
   music))

renameTag =
#(define-music-function
  (parser location tag-from tag-to music) (symbol? symbol? ly:music?)
  (_i "Replace an existing tag @var{tag-from} with tag @var{tag-to} in all elements of @var{music}")
  (let
   ((new-music (ly:music-deep-copy music)))
   (rename-tag-in-music tag-from tag-to new-music)
   new-music))


#(define (remove-tag-in-music tag music)
  (if (ly:music? music)
   (let*
    ((es (ly:music-property music 'elements))
     (e (ly:music-property music 'element))
     (as (ly:music-property music 'articulations))
     (tags (ly:music-property music 'tags)))
    (if (memq tag tags)
     (ly:music-set-property! music 'tags
      (filter (lambda (x) (not (eq? x tag))) tags)))
    (for-each (lambda (x) (remove-tag-in-music tag x)) es)
    (remove-tag-in-music tag e)
    (for-each (lambda (x) (remove-tag-in-music tag x)) as))
   music))

removeTag =
#(define-music-function
  (parser location tag music) (symbol? ly:music?)
  (_i "Remove the specified tag @var{tag} in all elements of @var{music}")
  (let
   ((new-music (ly:music-deep-copy music)))
   (remove-tag-in-music tag new-music)
   new-music))


#(define (remove-tags-in-music tag-list music)
  (if (ly:music? music)
   (let*
    ((es (ly:music-property music 'elements))
     (e (ly:music-property music 'element))
     (as (ly:music-property music 'articulations))
     (tags (ly:music-property music 'tags)))
    (ly:music-set-property! music 'tags
     (filter (lambda (x) (not (memq x tag-list))) tags))
    (for-each (lambda (x) (remove-tags-in-music tag-list x)) es)
    (remove-tags-in-music tag-list e)
    (for-each (lambda (x) (remove-tags-in-music tag-list x)) as))
   music))

removeTags =
#(define-music-function
  (parser location tag-list music) (list? ly:music?)
  (_i "Remove all the tags specified in the list @var{tag-list} in all elements of @var{music}")
  (let
   ((new-music (ly:music-deep-copy music)))
   (remove-tags-in-music tag-list new-music)
   new-music))


keepWithTags =
#(define-music-function
  (parser location taglist music) (list? ly:music?)
  (_i "Include only elements of @var{music} that are tagged with at least one tag out of the list @var{taglist}.")
  (music-filter
   (lambda (m)
    (let*
     ((tags (ly:music-property m 'tags))
      (res #f))
     (for-each
      (lambda (tag) (if (memq tag tags) (set! res #t)))
      taglist)
     (or
      (eq? tags '())
      res)))
   music))


#(define (remove-with-tags taglist music)
  (music-filter
   (lambda (m)
    (let*
     ((tags (ly:music-property m 'tags))
      (result #t))
     (for-each
      (lambda (tag) (if (memq tag tags) (set! result #f)))
      taglist)
     (or
      (eq? tags '())
      result)))
   music))


#(define (keep-or-remove-with-tag keep-tag remove-taglist music)
  (music-filter
   (lambda (m)
    (let*
     ((tags (ly:music-property m 'tags))
      (res #t))
     (if (not (memq keep-tag tags))
      (for-each
       (lambda (tag) (if (memq tag tags) (set! res #f)))
       remove-taglist))
     (or
      (eq? tags '())
      res)))
   music))

keepOrRemoveWithTag =
#(define-music-function
  (parser location keep-tag remove-taglist music) (symbol? list? ly:music?)
  (_i "Keep the elements of @var{music} which are tagged with @var{keep-tag}, otherwise remove them only if they are tagged with at least one symbol out the list @var{remove-taglist}.")
  (music-filter
   (lambda (m)
    (let*
     ((tags (ly:music-property m 'tags))
      (res #t))
     (if (not (memq keep-tag tags))
      (for-each
       (lambda (tag) (if (memq tag tags) (set! res #f)))
       remove-taglist))
     (or
      (eq? tags '())
      res)))
   music))


cleansedKeepOrRemoveWithTag =
#(define-music-function
  (parser location keep-tag remove-taglist music) (symbol? list? ly:music?)
  (_i "Keep the elements of @var{music} which are tagged with @var{keep-tag}, otherwise remove them only if they are tagged with at least one symbol out the list @var{remove-taglist}. Finally wipe out all tags listed in the @var{remove-taglist} so they will not harm any future keepWithTag.")
  (let
   ((new-music (ly:music-deep-copy 
      (music-filter
       (lambda (m)
        (let*
         ((tags (ly:music-property m 'tags))
          (res #t))
         (if (not (memq keep-tag tags))
          (for-each
           (lambda (tag) (if (memq tag tags) (set! res #f)))
           remove-taglist))
         (or
          (eq? tags '())
          res)))
       music))))
   (remove-tags-in-music remove-taglist new-music)
   new-music))


taggedRep =
#(define-music-function
  (parser location start-tag end-tag rep-count music) (symbol? symbol? integer? ly:music?)
  (_i "Repeat the @var{music} unfolded @var{rep-count} times. In the first repeat output keep @var{start-tag} and remove @var{end-tag} tagged elements, in the middle remove both, and at the end keep @var{end-tag} and remove @var{start-tag} tagged elements.")
  (if (<= rep-count 1)
   music
   (make-music 'SequentialMusic 'elements
    (if (<= rep-count 2)
     (list
      (keep-or-remove-with-tag start-tag (list start-tag end-tag) (ly:music-deep-copy music))
      (keep-or-remove-with-tag end-tag (list start-tag end-tag) (ly:music-deep-copy music)))
     (list
      (keep-or-remove-with-tag start-tag (list start-tag end-tag) (ly:music-deep-copy music))
      (make-music 'UnfoldedRepeatedMusic
       'elements '() 'repeat-count (- rep-count 2) 'element
       (remove-with-tags (list start-tag end-tag) (ly:music-deep-copy music)))
      (keep-or-remove-with-tag end-tag (list start-tag end-tag) (ly:music-deep-copy music)))))))

cleansedTaggedRep =
#(define-music-function
  (parser location start-tag end-tag rep-count music) (symbol? symbol? integer? ly:music?)
  (_i "Repeat the @var{music} unfolded @var{rep-count} times. In the first repeat output keep @var{start-tag} and remove @var{end-tag} tagged elements, in the middle remove both, and at the end keep @var{end-tag} and remove @var{start-tag} tagged elements. Finally 'rub out' the remaining tags @var{start-tag} and @var{end-tag} from the music so they will not harm any \\keepWithTag in the future.")
  (let
   ((new-music
     (if (<= rep-count 1)
      music
      (make-music 'SequentialMusic 'elements
       (if (<= rep-count 2)
        (list
         (keep-or-remove-with-tag start-tag (list start-tag end-tag) (ly:music-deep-copy music))
         (keep-or-remove-with-tag end-tag (list start-tag end-tag) (ly:music-deep-copy music)))
        (list
         (keep-or-remove-with-tag start-tag (list start-tag end-tag) (ly:music-deep-copy music))
         (make-music 'UnfoldedRepeatedMusic
          'elements '() 'repeat-count (- rep-count 2) 'element
          (remove-with-tags (list start-tag end-tag) (ly:music-deep-copy music)))
         (keep-or-remove-with-tag end-tag (list start-tag end-tag) (ly:music-deep-copy music))))))))
   (remove-tags-in-music (list start-tag end-tag) new-music)
   new-music))

PSM = #'(Part Score Midi)

keepPart =
#(define-music-function (parser location music) (ly:music?)
  #{ \cleansedKeepOrRemoveWithTag #'Part \PSM $music #} )

keepScore =
#(define-music-function (parser location music) (ly:music?)
  #{ \cleansedKeepOrRemoveWithTag #'Score \PSM $music #} )

keepMidi =
#(define-music-function (parser location music) (ly:music?)
  #{ \cleansedKeepOrRemoveWithTag #'Midi \PSM $music #} )

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% END of my personal include file 'tagging.ly'
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\markup { \null \translate #'( 1 . -3 ) \null } % 2.14.2 LSR problem workaroud

% Settings to keep all on one page:

\header  { tagline = ##f }

myLayout = \with {
  fontSize = #-4.5
  \override StaffSymbol.staff-space = #(magstep -4.5)
  \override StaffSymbol.thickness = #(magstep -4.5)
}

\paper { 
  score-markup-spacing =
    #'((basic-distance . 0)
       (minimum-distance . 0)
       (padding . 3.5)
       (stretchability . 0))
}

Music = {
  \tag #'A { a'4_"A"-\tag #'Strings ^"arco [for Strings]" -\tag #'Winds ^"non legato [for Winds]"}
  \tag #'B { b'4_"B" }
  \tag #'C { c''4_"C" }

  \tag #'Midi { d''32(_"Midi" \repeat unfold 7 { e''32 d'' } e'') }
  \tag #'Part \tag #'Score { e''2\trill -\tag #'Part _"Part" -\tag #'Score _"Score" }

  \tag #'InExposition { f''4_"Exp." }
  \tag #'InCoda { c''4_"Coda" }
}

\markup \fontsize #-3 \typewriter \override #'(baseline-skip . 1.7) \column {
  "Music = {"
  "  \\tag #'A { a'4_\"A\"-\\tag #'Strings ^\"arco [for Strings]\" -\\tag #'Winds ^\"non legato [for Winds]\"}"
  "  \\tag #'B { b'4_\"B\" }"
  "  \\tag #'C { c''4_\"C\" }"
  "  "
  "  \\tag #'Midi { d''32(_\"Midi\" \\repeat unfold 7 { e''32 d'' } e'') }"
  "  \\tag #'Part \\tag #'Score { e''2\\trill -\\tag #'Part _\"Part\" -\\tag #'Score _\"Score\" }"
  "  "
  "  \\tag #'InExposition { f''4_\"Exp.\" }"
  "  \\tag #'InCoda { c''4_\"Coda\" }"
  "}"
  " "
}

\score {
  \new Staff \myLayout {
    \keepWithTag #'FOO \removeAllTags \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \with-color #grey "\\keepWithTag #'FOO" \bold "\\removeAllTags" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepWithTags #'(Strings A Part InCoda) \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \bold "\\keepWithTags #'(Strings A Part InCoda)" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepWithTag #'Part \copyTag #'A #'Part \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \with-color #grey "\\keepWithTag #'Part" \bold "\\copyTag #'A #'Part" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepWithTag #'FOO \removeTag #'B \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \with-color #grey "\\keepWithTag #'FOO" \bold "\\removeTag #'B" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepWithTag #'FOO \removeTags #'(A B C) \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \with-color #grey "\\keepWithTag #'FOO" \bold "\\removeTags #'(A B C)" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepWithTag #'Part \renameTag #'B #'Part \renameTag #'InCoda #'Part \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \with-color #grey "\\keepWithTag #'Part"
                      \bold "\\renameTag #'B #'Part \\renameTag #'InCoda #'Part" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepOrRemoveWithTag #'Part #'(Part Score Midi) \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \bold "\keepOrRemoveWithTag #'Part #'(Part Score Midi)" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepWithTag #'FOO \cleansedKeepOrRemoveWithTag #'Part #'(Part Score Midi) \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \with-color #grey "\\keepWithTag #'FOO" \bold "\\cleansedKeepOrRemoveWithTag #'Part #'(Part Score Midi)" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \keepWithTag #'FOO \keepPart \Music
  }
  \header {
    piece = \markup \fontsize #-3 { \with-color #grey "\\keepWithTag #'FOO" \bold "\\keepPart" \italic "\\Music" }
  }
}

\score {
  \new Staff \myLayout {
    \taggedRep #'FirstOnly #'LastOnly #5 {
      c'16 -\tag #'FirstOnly \f \< d' e' f' g' a' b' c''
      d''\> c'' b' a' g' f' e' d' -\tag #'LastOnly \p
    }
  }
  \header {
    piece = \markup \fontsize #-3 {
      \bold "\\taggedRep #'FirstOnly #'LastOnly #5 "
      \scale #'(0.95 . 1.0) "{ c'16 -\\tag #'FirstOnly \\f \\< d' ... d''\\> ... d' -\\tag #'LastOnly \\p }"
    }
  }
}

Unterseiten