* A list of ASCII aliases for special characters has been added.
* New add-text-replacements! command for \paper blocks.
* New markup command \replace.
\relative c' { c\dyn pfsss }
@end lilypond
+@item
+A list of ASCII aliases for special characters can be included.
+@lilypond[quote,verbatim]
+\paper {
+ #(include-special-characters)
+}
+\markup "• † ©right; &OE; &ss; ¶"
+@end lilypond
+
@item
There is a new @code{define-scheme-function} command in analogy to
@code{define-music-function} that can be used to define functions
--- /dev/null
+\version "2.15.13"
+
+#(set-default-paper-size "a4")
+\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)))))
+
+\markuplines \justified-lines \show-special-characters
@menu
* Including LilyPond files::
* Different editions from one source::
-* Text encoding::
+* Special characters::
@end menu
Notation Reference:
@ref{Including LilyPond files}.
+@node Special characters
+@subsection Special characters
+
+@cindex special characters
+@cindex non-ASCII characters
+
+@menu
+* Text encoding::
+* Unicode::
+* ASCII aliases::
+@end menu
+
+
@node Text encoding
-@subsection Text encoding
+@unnumberedsubsubsec Text encoding
-@cindex Unicode
@cindex UTF-8
-@cindex non-ASCII characters
LilyPond uses the character repertoire defined by the Unicode
consortium and ISO/IEC 10646. This defines a unique name and
\addlyrics { \portuguese }
@end lilypond
+
+@node Unicode
+@unnumberedsubsubsec Unicode
+
+@cindex Unicode
+
To enter a single character for which the Unicode code point is
known but which is not available in the editor being used, use
either @code{\char ##xhhhh} or @code{\char #dddd} within a
@end example
+@node ASCII aliases
+@unnumberedsubsubsec ASCII aliases
+
+A list of ASCII aliases for special characters can be included:
+
+@lilypond[quote,verbatim]
+\paper {
+ #(include-special-characters)
+}
+
+\markup "&flqq; – &OE;uvre incomplète… &frqq;"
+
+\score {
+ \new Staff { \repeat unfold 9 a'4 }
+ \addlyrics {
+ This is al -- so wor -- kin'~in ly -- rics: –_&OE;…
+ }
+}
+
+\markup \column {
+ "The replacement can be disabled:"
+ "– &OE; …"
+ \override #'(replacement-alist . ()) "– &OE; …"
+}
+@end lilypond
+
+You can also make your own aliases, either globally:
+
+@lilypond[quote,verbatim]
+\paper {
+ #(add-text-replacements!
+ '(("100" . "hundred")
+ ("dpi" . "dots per inch")))
+}
+\markup "A 100 dpi."
+@end lilypond
+
+or locally:
+
+@lilypond[quote,verbatim]
+\markup \replace #'(("100" . "hundred")
+ ("dpi" . "dots per inch")) "A 100 dpi."
+@end lilypond
+
+@seealso
+Notation Reference:
+@ref{List of special characters}.
+
+Installed Files:
+@file{ly/text-replacements.ly}.
+
+
@node Controlling output
@section Controlling output
* Note head styles::
* Text markup commands::
* Text markup list commands::
+* List of special characters::
* List of articulations::
* Percussion notes::
* Technical glossary::
@include markup-list-commands.tely
+@node List of special characters
+@appendixsec List of special characters
+
+The following special characters references can be used;
+for more details, see @ref{ASCII aliases}.
+
+The HTML syntax is used and most of these references are the same as HTML.
+The rest of them are inspired by @LaTeX{}.
+
+The characters are boxed so that you can see their size.
+A small padding has been added between the character and the box
+for more readability.
+
+@lilypond[quote]
+\include "special-characters.ly"
+@end lilypond
+
+
@node List of articulations
@appendixsec List of articulations
@seealso
Notation Reference:
@ref{Fonts},
-@ref{Text encoding}.
+@ref{Special characters}.
@node grob
non-English languages, or special characters (such as the heart
symbol or slanted quotes), may simply be inserted directly
into the input file, providing it is saved with UTF-8 encoding.
-For more information, see @ref{Text encoding}.
+For more information, see @ref{Special characters}.
@lilypond[quote,verbatim]
\relative c'' { d8 c16 a bes8 f e' d c4 }
@ref{Formatting text},
@ref{Input modes},
@ref{Manual syllable durations},
-@ref{Text encoding}.
+@ref{Special characters}.
Internals Reference:
@rinternals{LyricText}.
--- /dev/null
+\version "2.15.13"
+\header {
+ texidoc = "
+ A list of special character ASCII aliases can be easily included.
+ This works for markups and lyrics.
+"
+}
+
+\paper {
+ #(include-special-characters)
+ indent = 0
+}
+
+\markup \column {
+ \bold "Markup example:"
+ "Input:"
+ \override #'(replacement-alist . ()) \typewriter \justify {
+ №2 – &OE;dipe…
+ }
+ "Output:"
+ \italic \justify {
+ №2 – &OE;dipe…
+ }
+ \vspace #0.5
+ \bold "Lyric example:"
+}
+\new Lyrics \lyricmode {
+ Ce&s;16 -- &s;ez In -- fi -- dè -- les, un c&oe;ur in -- no -- cent
+ ne craint rien&nnbsp;;
+}
ANY_CHAR (.|\n)
PUNCT [?!:'`]
ACCENT \\[`'"^]
+SPECIAL_CHAR [&@]
NATIONAL [\001-\006\021-\027\031\036]
-TEX {AA}|-|{PUNCT}|{ACCENT}|{NATIONAL}
+TEX {AA}|-|{PUNCT}|{ACCENT}|{NATIONAL}|{SPECIAL_CHAR}
DASHED_WORD {A}({AN}|-)*
DASHED_KEY_WORD \\{DASHED_WORD}
#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_EOL);
- while (i < n)
+ int max_length = 0;
+ for (SCM s = replacement_alist; scm_is_pair (s); s = scm_cdr (s))
{
- char cur = (*str)[i];
-
- // avoid the locale-dependent isspace
- if (cur == '\n' || cur == '\t' || cur == '\v')
- (*str)[i] = ' ';
-
- vsize char_len = utf8_char_len (cur);
+ max_length = max (max_length, scm_to_int
+ (scm_string_length (scm_caar (s))));
+ }
- i += char_len;
+ while (i <= str->size ())
+ {
+ for (vsize j = max_length + 1; 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
{
string name = ly_symbol2string (scm_procedure_name (func));
// TODO: Also print the arguments of the markup!
- non_fatal_error (_f("Cyclic markup detected: %s", name));
- return Stencil().smobbed_copy ();
+ non_fatal_error (_f ("Cyclic markup detected: %s", name));
+ return Stencil ().smobbed_copy ();
}
}
/* Check for non-terminating markups, e.g. recursive calls with
* changing arguments */
SCM opt_depth = ly_get_option (ly_symbol2scm ("max-markup-depth"));
- size_t max_depth = robust_scm2int(opt_depth, 1024);
+ size_t max_depth = robust_scm2int (opt_depth, 1024);
if (depth > max_depth)
{
string name = ly_symbol2string (scm_procedure_name (func));
// TODO: Also print the arguments of the markup!
- non_fatal_error (_f("Markup depth exceeds maximal value of %d; "
- "Markup: %s", max_depth, name.c_str ()));
- return Stencil().smobbed_copy ();
+ non_fatal_error (_f ("Markup depth exceeds maximal value of %d; "
+ "Markup: %s", max_depth, name.c_str ()));
+ return Stencil ().smobbed_copy ();
}
encountered_markups.push_back (markup);
/* 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.13"
+
+#(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
+ ("…" . "…")
+ ("–" . "–")
+ ("—" . "—")
+ ("¡" . "¡")
+ ("¿" . "¿")
+ ("&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
+ (" " . " ")
+ (" " . " ")
+ (" " . " ")
+ (" " . " ")
+ ("&nnbsp;" . " ") ; narrow non-breaking space
+ ("‍" . "")
+ ("‌" . "")
+ ("·" . "·") ; interpunct
+
+ ;; General typography
+ ("•" . "•")
+ ("©right;" . "©")
+ ("®istered;" . "®")
+ ("&trademark;" . "™")
+ ("†" . "†")
+ ("‡" . "‡")
+ ("№" . "№")
+ ("ª" . "ª")
+ ("º" . "º")
+ ("¶" . "¶")
+ ("§" . "§")
+ ("°" . "°")
+ ("№" . "№")
+ ("‰" . "‰")
+ ("¦" . "¦")
+
+ ;; Diacritics
+ ("´" . "´")
+ ("´dbl;" . "˝")
+ ("`" . "`")
+ ("˘" . "˘")
+ ("ˇ" . "ˇ")
+ ("¸la;" . "¸")
+ ("&circumflex;" . "^")
+ ("&diaeresis;" . "¨")
+ ("¯on;" . "¯")
+
+ ;; 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
+ ("+" . "+")
+ ("−" . "−")
+ ("×" . "×")
+ ("÷" . "÷")
+ ("¹" . "¹")
+ ("²" . "²")
+ ("³" . "³")
+ ("&sqrt;" . "√")
+ ("&increment;" . "∆")
+ ("&infty;" . "∞")
+ ("∑" . "∑")
+ ("±" . "±")
+ ("&bulletop;" . "∙")
+ ("&partial;" . "∂")
+ ("&neg;" . "¬")
+
+ ;; Currency symbols
+ ("¤cy;" . "¤")
+ ("$" . "$")
+ ("€" . "€")
+ ("£s;" . "£")
+ ("¥" . "¥")
+ ("¢" . "¢"))))
interesting items.")
(remove-first ,boolean? "Remove the first staff of an orchestral
score?")
+ (replacement-alist ,list? "Alist of strings.
+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-grob-interfaces.scm"
"define-stencil-commands.scm"
"titling.scm"
+ "text.scm"
"paper.scm"
"backend-library.scm"
--- /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/>.
+
+
+(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)))