add-text-replacements! command for \paper blocks.
\replace to add replacements directly inside markups.
--- /dev/null
+\version "2.15.0"
+\header {
+ texidoc = "
+ A list of special characters ASCII aliases can be easily included.
+ This works for markups and lyrics.
+ "
+}
+
+\paper {
+ #(include-special-characters)
+}
+
+#(define-markup-list-command (show-special-characters layout props) ()
+ (let ((defs (ly:output-def-lookup layout 'text-font-defaults)))
+ (interpret-markup-list layout props
+ (map (lambda (pair)
+ (markup #:override '(line-width . 18) #:fill-line (
+ #:override '(replacement-alist . ()) (car pair)
+ #:override '(thickness . 0.1) #:box (cdr pair))))
+ (list-tail (assoc-get 'replacement-alist defs) 3)))))
+
+\markup "List of the special characters:"
+\markuplines \justified-lines \show-special-characters
+
+\markup { \vspace #2 "Markup example:" }
+\markup { \vspace #1 "§numero;2 §ndash; §OE;dipe§hellip; Qui de ton complexe e§s;t épargné§nnbsp;? (B. Bordage §copyright; 2011)" }
+\markup { \vspace #1 "Lyric example:" }
+\new Lyrics \lyricmode {
+ Ce§s;16 -- §s;ez In -- fi -- dè -- les, un c§oe;ur in -- no -- cent ne §s;çau -- roit vous plai -- re~en -- cor§nnbsp;;
+}
#include "warn.hh"
static void
-replace_whitespace (string *str)
+replace_special_characters (string *str, SCM props)
{
vsize i = 0;
- vsize n = str->size ();
+ SCM replacement_alist = ly_chain_assoc_get (ly_symbol2scm ("replacement-alist"),
+ props,
+ SCM_BOOL_F);
- while (i < n)
- {
- char cur = (*str)[i];
-
- // avoid the locale-dependent isspace
- if (cur == '\n' || cur == '\t' || cur == '\v')
- (*str)[i] = ' ';
+ if (!to_boolean (scm_list_p (replacement_alist))
+ || to_boolean (scm_null_p (replacement_alist)))
+ return;
- vsize char_len = utf8_char_len (cur);
+ int max_length = 0;
+ for (SCM s = replacement_alist; scm_is_pair (s); s = scm_cdr (s))
+ {
+ max_length = max (max_length, scm_to_int
+ (scm_string_length (scm_caar (s))));
+ }
- i += char_len;
+ while (i <= str->size ())
+ {
+ for (int j = max_length; j > 0; j--)
+ {
+ string dummy = str->substr (i, j);
+ string ligature = robust_scm2string
+ (ly_assoc_get (ly_string2scm (dummy),
+ replacement_alist, SCM_BOOL_F), "");
+ if (ligature != "")
+ str->replace (i, j, ligature);
+ }
+ i += utf8_char_len ((*str)[i]);
}
}
Output_def *layout = unsmob_output_def (layout_smob);
Font_metric *fm = select_encoded_font (layout, props);
- replace_whitespace (&str);
+ replace_special_characters (&str, props);
/*
We want to filter strings with a music font that pass through
/* properties */
"baseline-skip "
+ "replacement-alist "
"text "
"word-space "
"text-direction "
#(define text-font-defaults
`((font-encoding . latin1)
(baseline-skip . 3)
+ (replacement-alist . ,default-string-replacement-alist)
(word-space . 0.6)))
+ \include "text-replacements.ly"
+
}
--- /dev/null
+%%%% This file is part of LilyPond, the GNU music typesetter.
+%%%%
+%%%% Copyright (C) 2011 Bertrand Bordage <bordage.bertrand@gmail.com>
+%%%%
+%%%% LilyPond is free software: you can redistribute it and/or modify
+%%%% it under the terms of the GNU General Public License as published by
+%%%% the Free Software Foundation, either version 3 of the License, or
+%%%% (at your option) any later version.
+%%%%
+%%%% LilyPond is distributed in the hope that it will be useful,
+%%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
+%%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+%%%% GNU General Public License for more details.
+%%%%
+%%%% 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.7"
+
+#(define (add-text-replacements! alist)
+ (assoc-set! text-font-defaults 'replacement-alist
+ (cdaar
+ (internal-add-text-replacements (list text-font-defaults) alist))))
+
+#(define (include-special-characters)
+ (add-text-replacements!
+ '(; Punctuation
+ ("§hellip;" . "…")
+ ("§ndash;" . "–")
+ ("§mdash;" . "—")
+ ("§iexcl;" . "¡")
+ ("§iquest;" . "¿")
+ ("§solidus;" . "∕") ; this is not a slash,
+ ; contrary to what is said in Unicode.
+
+ ; French, German and English quotes open/close
+ ("§flq;" . "‹")
+ ("§frq;" . "›")
+ ("§flqq;" . "«")
+ ("§frqq;" . "»")
+ ("§glq;" . "‚")
+ ("§grq;" . "‘")
+ ("§glqq;" . "„")
+ ("§grqq;" . "“")
+ ("§elq;" . "‘")
+ ("§erq;" . "’")
+ ("§elqq;" . "“")
+ ("§erqq;" . "”")
+
+ ; Word dividers
+ ("§ensp;" . " ")
+ ("§emsp;" . " ")
+ ("§thinsp;" . " ")
+ ("§nbsp;" . " ")
+ ("§nnbsp;" . " ") ; narrow non-breaking space
+ ("§zwj;" . "")
+ ("§zwnj;" . "")
+ ("§middot;" . "·") ; interpunct
+
+ ; General typography
+ ("§bull;" . "•")
+ ("§copyright;" . "©")
+ ("§registered;" . "®")
+ ("§trademark;" . "™")
+ ("§dagger;" . "†")
+ ("§Dagger;" . "‡")
+ ("§numero;" . "№")
+ ("§ordf;" . "ª")
+ ("§ordm;" . "º")
+ ("§para;" . "¶")
+ ("§sect;" . "§")
+ ("§deg;" . "°")
+ ("§numero;" . "№")
+ ("§permil;" . "‰")
+ ("§brvbar;" . "¦")
+
+ ; Diacritics
+ ("§acute;" . "´")
+ ("§acutedbl;" . "˝")
+ ("§grave;" . "`")
+ ("§breve;" . "˘")
+ ("§caron;" . "ˇ")
+ ("§cedilla;" . "¸")
+ ("§circumflex;" . "^")
+ ("§diaeresis;" . "¨")
+ ("§macron;" . "¯")
+
+ ; Non-ASCII Letters (Excluding Accented Letters)
+ ("§aa;" . "å")
+ ("§AA;" . "Å")
+ ("§ae;" . "æ")
+ ("§AE;" . "Æ")
+ ("§dh;" . "ð")
+ ("§DH;" . "Ð")
+ ("§dj;" . "đ")
+ ("§DJ;" . "Đ")
+ ("§l;" . "ł")
+ ("§L;" . "Ł")
+ ("§ng;" . "ŋ")
+ ("§NG;" . "Ŋ")
+ ("§o;" . "ø")
+ ("§O;" . "Ø")
+ ("§oe;" . "œ")
+ ("§OE;" . "Œ")
+ ("§s;" . "ſ")
+ ("§ss;" . "ß")
+ ("§th;" . "þ")
+ ("§TH;" . "Þ")
+
+ ; Mathematical symbols
+ ("§plus;" . "+")
+ ("§minus;" . "−")
+ ("§times;" . "×")
+ ("§div;" . "÷")
+ ("§sup1;" . "¹")
+ ("§sup2;" . "²")
+ ("§sup3;" . "³")
+ ("§sqrt;" . "√")
+ ("§increment;" . "∆")
+ ("§infty;" . "∞")
+ ("§sum;" . "∑")
+ ("§pm;" . "±")
+ ("§bulletop;" . "∙")
+ ("§partial;" . "∂")
+ ("§neg;" . "¬")
+
+ ; Currency symbols
+ ("§currency;" . "¤")
+ ("§dollar;" . "$")
+ ("§euro;" . "€")
+ ("§pounds;" . "£")
+ ("§yen;" . "¥")
+ ("§cent;" . "¢"))))
interesting items.")
(remove-first ,boolean? "Remove the first staff of an orchestral
score?")
+ (replacement-alist ,list? "Alist of strings or characters.
+The key is a string of the pattern to be replaced. The value is a
+string of what should be displayed. Useful for ligatures.")
(restore-first ,boolean? "Print a natural before the
accidental.")
(rhythmic-location ,rhythmic-location? "Where (bar number,
}
@end lilypond"
(let* ((ref-size (ly:output-def-lookup layout 'text-font-size 12))
- (text-props (list (ly:output-def-lookup layout 'text-font-defaults)))
- (ref-word-space (chain-assoc-get 'word-space text-props 0.6))
- (ref-baseline (chain-assoc-get 'baseline-skip text-props 3))
- (magnification (/ size ref-size)))
- (interpret-markup layout
- (cons `((baseline-skip . ,(* magnification ref-baseline))
- (word-space . ,(* magnification ref-word-space))
- (font-size . ,(magnification->font-size magnification)))
- props)
- arg)))
+ (text-props (list (ly:output-def-lookup layout 'text-font-defaults)))
+ (ref-word-space (chain-assoc-get 'word-space text-props 0.6))
+ (ref-baseline (chain-assoc-get 'baseline-skip text-props 3))
+ (magnification (/ size ref-size)))
+ (interpret-markup
+ layout
+ (cons
+ `((baseline-skip . ,(* magnification ref-baseline))
+ (word-space . ,(* magnification ref-word-space))
+ (font-size . ,(magnification->font-size magnification)))
+ props)
+ arg)))
(define-markup-command (fontsize layout props increment arg)
(number? markup?)
smaller
}
@end lilypond"
- (let ((entries (list
- (cons 'baseline-skip (* baseline-skip (magstep increment)))
- (cons 'word-space (* word-space (magstep increment)))
- (cons 'font-size (+ font-size increment)))))
- (interpret-markup layout (cons entries props) arg)))
+ (interpret-markup
+ layout
+ (cons
+ `((baseline-skip . ,(* baseline-skip (magstep increment)))
+ (word-space . ,(* word-space (magstep increment)))
+ (font-size . ,(+ font-size increment)))
+ props)
+ arg))
(define-markup-command (magnify layout props sz arg)
(number? markup?)
#:pattern (1+ count) X space pattern
right))))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Replacements
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define-markup-command (replace layout props replacements arg)
+ (list? markup?)
+ #:category font
+ "
+Used to automatically replace a string by another in the markup @var{arg}.
+Each pair of the alist @var{replacements} specifies what should be replaced.
+The @code{key} is the string to be replaced by the @code{value} string.
+
+@lilypond[verbatim, quote]
+\\markup \\replace #'((\"thx\" . \"Thanks!\")) thx
+@end lilypond"
+ (interpret-markup
+ layout
+ (internal-add-text-replacements
+ props
+ replacements)
+ (markup arg)))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Markup list commands
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-public (laissez-vibrer::print grob)
(ly:tie::print grob))
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; text replacements
+
+(define-public default-string-replacement-alist
+ '(; Whitespaces
+ ("\t" . " ")
+ ("\n" . " ")
+ ("\v" . " ")))
+
+(define-public (internal-add-text-replacements props alist)
+ (let* ((dummy-replacements (chain-assoc-get 'replacement-alist props '()))
+ (new-replacements
+ (append dummy-replacements alist)))
+ (prepend-alist-chain 'replacement-alist new-replacements props)))