From 02fe038744e634b42f1a3377c4f0dc3d25e80344 Mon Sep 17 00:00:00 2001
From: Valentin Villenave <valentin@villenave.net>
Date: Sun, 24 Oct 2010 01:26:17 +0200
Subject: [PATCH] Fix #903: a simpler syntax for note names language

This commit adds a new
  \language "foo"
command, where "foo" is the (case-insensitive) name of
any supported language, e.g. "italiano", "suomi" etc.

This function may be used at top-level or anywhere else,
even in -dsafe mode.
Non-supported languages arguments are, well, not supported:
if no recognizable string is provided, ly:gulp-file will just
barf its standard error message.

To preserve full compatibility with existing code, this patch
leaves .ly language files unchanged (therefore, the old syntax
is still perfectly valid).  Since all it does is extract the
pitchnames alist from whatever file it processes, more complex
files such as "arabic.ly" are not supported and will output
an error message explaining that \include should be used instead.

In spite of this limitation, this method is a convenient way
of presenting foreign users with a simplified syntax, without
having to bloat the parser with yet another keyword.  Of
course, it may be superseeded in the future with a more
specialized implementation, possibly doing away with .ly files
(if we reach a point where preserving compatibility is no
longer an issue).
---
 Documentation/changes.tely           |  8 +++++++
 Documentation/notation/pitches.itely | 30 +++++++++++++++++++-----
 ly/music-functions-init.ly           | 35 ++++++++++++++++++++++++++--
 3 files changed, 65 insertions(+), 8 deletions(-)

diff --git a/Documentation/changes.tely b/Documentation/changes.tely
index 6ea50df006..9002f977b4 100644
--- a/Documentation/changes.tely
+++ b/Documentation/changes.tely
@@ -66,6 +66,14 @@ which scares away people.
 
 @end ignore
 
+
+@item
+A new @code{\language} command makes it easier to select
+note names languages: instead of the usual
+@code{\include "italiano.ly"} syntax (which is still
+supported and recommended), it is possible to just type
+@code{\language "italiano"}.
+
 @item
 auotbeaming is now disabled by @code{\cadenzaOn} and enabled by
 @code{\cadenzaOff}.  Beaming in cadenzas should be indicated manually.
diff --git a/Documentation/notation/pitches.itely b/Documentation/notation/pitches.itely
index 0451385176..7be5119049 100644
--- a/Documentation/notation/pitches.itely
+++ b/Documentation/notation/pitches.itely
@@ -439,14 +439,32 @@ any standard.
 @cindex language, pitch names in other
 
 There are predefined sets of note and accidental names for various
-other languages.  To use them, include the language-specific init
-file listed below.  For example, to use English note names, add
-@code{@w{\include "english.ly"}} to the input file.
+other languages.  These may be selected using the following
+shortcut syntax:
+
+@example
+\language "italiano"
+@end example
+
+@noindent
+for Italian note names, or any other supported language listed below.
+Alternatively, the relevant language-specific file may be directly
+included in the input file; the previous example could equally be
+written as follows:
+
+@example
+\include "italiano.ly"
+@end example
+
+@noindent
+The latter syntax is actually more reliable, in that it allows for more
+complex files to be included: for instance the @file{arabic.ly} file is
+not supported by the @code{@bs{}language} shortcut, and can only be
+processed through the @code{@bs{}include} command.
 
 @warning{Because some other include files (such as @code{@w{predefined-fretboards.ly}})
-use default (Nederlands) note names, the @code{@bs{}include}
-command for the language file should be placed after all other
-LilyPond distribution files.}
+use default (Nederlands) note names, it is recommended to select the note name language
+@emph{after} having included all other LilyPond distribution files.}
 
 The available language files and the note names they define are:
 
diff --git a/ly/music-functions-init.ly b/ly/music-functions-init.ly
index 8ac1deda01..6419b642e6 100644
--- a/ly/music-functions-init.ly
+++ b/ly/music-functions-init.ly
@@ -25,9 +25,12 @@
 %% this file is alphabetically sorted.
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
-%% need SRFI-1 for filter; optargs for lambda*
+%% need SRFI-1 for filter;
+%% optargs for lambda*;
+%% regex for string-match
 #(use-modules (srfi srfi-1)
-	      (ice-9 optargs))
+	      (ice-9 optargs)
+	      (ice-9 regex))
 
 %% TODO: using define-music-function in a .scm causes crash.
 
@@ -360,6 +363,34 @@ label =
 					   'page-label label))))
 
 
+language =
+#(define-music-function (parser location str) (string?)
+   (_i "Select note-names language.")
+   ;; This function is a hack around the old language
+   ;; selection system, using separate .ly files for each
+   ;; supported languages.
+   ;; TODO: re-implement language selection in a cleaner way.
+   (let* ((file-name (string-append (string-downcase! str) ".ly"))
+
+	  ; Ugh.  ly:gulp-file's "file not found" error message
+	  ; won't be much informative in this specific case.
+	  (raw-string (ly:gulp-file file-name))
+
+	  ; extract the pitchnames alist.
+	  (delim-alist (string-match "`\\(.*\\)\\)\\s[ |\n]?\\)" raw-string ))
+	  (extract-alist (if delim-alist
+			     (match:substring delim-alist)
+			     #f)))
+
+     (if extract-alist
+	 (begin
+	   (if (ly:get-option 'verbose)
+	       (ly:message (_ "Using ~a note names...") str))
+	   (ly:parser-set-note-names parser (eval-string extract-alist)))
+	 (ly:error (_ "Cannot process ~a as a language file.
+Use \\include \"~a\" instead.") file-name file-name))
+     make-void-music))
+
 
 makeClusters =
 #(define-music-function (parser location arg) (ly:music?)
-- 
2.39.5