+(defun LilyPond-quick-note-insert()
+ "Insert notes with fewer key strokes by using a simple keyboard piano."
+ (interactive)
+ (setq dutch-notes
+ '(("k" "a") ("l" "b") ("a" "c") ("s" "d")
+ ("d" "e") ("f" "f") ("j" "g") ("r" "r")))
+ (setq dutch-note-ends '("eses" "es" "" "is" "isis"))
+ (setq dutch-note-replacements '("" ""))
+ (setq finnish-note-replacements
+ '(("eeses" "eses") ("ees" "es") ("aeses" "asas") ("aes" "as") ("b" "h")
+ ("beses" "heses") ("bes" "b") ("bis" "his") ("bisis" "hisis")))
+ ; add more translations of the note names
+ (setq spanish-note-replacements
+ '(("c" "do") ("d" "re") ("e" "mi") ("f" "fa") ("g" "sol") ("a" "la") ("b
+" "si")
+ ("cis" "dos") ("cisis" "doss") ("ces" "dob") ("ceses" "dobb")
+ ("dis" "res") ("disis" "ress") ("des" "reb") ("deses" "rebb")
+ ("eis" "mis") ("eisis" "miss") ("ees" "mib") ("eeses" "mibb")
+ ("fis" "fas") ("fisis" "fass") ("fes" "fab") ("feses" "fabb")
+ ("gis" "sols") ("gisis" "solss") ("ges" "solb") ("geses" "solbb")
+ ("ais" "las") ("aisis" "lass") ("aes" "lab") ("aeses" "labb")
+ ("bis" "sis") ("bisis" "siss") ("bes" "sib") ("beses" "sibb")))
+ (setq other-keys "()<>~}")
+ (setq accid 0) (setq octav 0) (setq durat "") (setq dots 0)
+
+ (message "Press h for help.") (sit-for 0 750)
+
+ (setq note-replacements dutch-note-replacements)
+ (setq xkey 0) (setq xinitpoint (point))
+ (< xinitpoint (point))
+ (while (not (= xkey 27)) ; esc to quit
+ (message (format " a[]s[]d f[]j[]k[]l r with %4s%-4s%3s%-4s ie ,' 12345678 . 0 (<~>)/}b\\b\\n Esc"
+ (nth (+ accid 2) dutch-note-ends)
+ (make-string (abs octav) (if (> octav 0) ?' ?,))
+ durat
+ (if (string= durat "") "" (make-string dots ?.))))
+ (setq xkey (read-char-exclusive))
+ (setq x (char-to-string xkey))
+ (setq note (cdr (assoc x dutch-notes)))
+ (cond
+ ((string= x "q") (progn (setq xkey 27))) ; quit
+ ((= xkey 13) (progn (insert "\n") (LilyPond-indent-line))) ; return
+ ((or (= xkey 127) ; backspace is recognized as a char only in Emacs
+ (string= x "b")) ; so, we need to define an another char for XEmacs
+ (progn (narrow-to-region xinitpoint (point))
+ (backward-kill-word 1)
+ (widen)))
+ ((and (string< x "9") (string< "0" x))
+ (progn (setq durat (int-to-string (expt 2 (- (string-to-int x) 1))))
+ (setq dots 0)))
+ ((string= x " ") (insert " "))
+ ((string= x "/") (progn (insert "\\times ")
+ (message "Insert a number for the denominator (\"x/\")")
+ (while (not (and (string< x "9") (string< "0" x)))
+ (setq x (char-to-string (read-char-exclusive))))
+ (insert (format "%s/" x)) (setq x "/")
+ (message "Insert a number for the numerator (\"/y\")")
+ (while (not (and (string< x "9") (string< "0" x)))
+ (setq x (char-to-string (read-char-exclusive))))
+ (insert (format "%s { " x))))
+ ((string= x "0") (progn (setq accid 0) (setq octav 0)
+ (setq durat "") (setq dots 0)))
+ ((string= x "i") (setq accid (if (= accid 2) 0 (max (+ accid 1) 1))))
+ ((string= x "e") (setq accid (if (= accid -2) 0 (min (+ accid -1) -1))))
+ ((string= x "'") (setq octav (if (= octav 4) 0 (max (+ octav 1) 1))))
+ ((string= x ",") (setq octav (if (= octav -4) 0 (min (+ octav -1) -1))))
+ ((string= x ".") (setq dots (if (= dots 4) 0 (+ dots 1))))
+ ((not (null (member x (split-string other-keys ""))))
+ (insert (format "%s " x)))
+ ((not (null note))
+ (progn
+ (setq note
+ (format "%s%s" (car note) (if (string= "r" (car note)) ""
+ (nth (+ accid 2) dutch-note-ends))))
+ (setq notetwo (car (cdr (assoc note note-replacements))))
+ (if (not (null notetwo)) (setq note notetwo))
+ (insert
+ (format "%s%s%s%s "
+ note
+ (if (string= "r" note) ""
+ (make-string (abs octav) (if (> octav 0) ?' ?,)))
+ durat
+ (if (string= durat "") "" (make-string dots ?.))))
+ (setq accid 0) (setq octav 0) (setq durat "") (setq dots 0)))
+ ((string= x "t") (progn (setq note-replacements dutch-note-replacements)
+ (message "Selected Dutch notes")
+ (sit-for 0 750)))
+ ((string= x "n") (progn (setq note-replacements finnish-note-replacements)
+ (message "Selected Finnish/Deutsch notes")
+ (sit-for 0 750)))
+ ; add more translations of the note names
+ ((string= x "p") (progn (setq note-replacements spanish-note-replacements)
+ (message "Selected Spanish notes")
+ (sit-for 0 750)))
+ ((string= x "h")
+ (progn (message "Insert notes with fewer key strokes. For example \"i,5.f\" produces \"fis,32. \".") (sit-for 5 0)
+ (message "Add also \"a ~ a\"-ties, \"a ( ) b\"-slurs and \"< a b >\"-chords.") (sit-for 5 0)
+ (message "There are Du(t)ch, Fin(n)ish/Deutsch (hit 'n') and S(p)anish note names.") (sit-for 5 0)
+ (message "(B)ackspace deletes last note, Ret starts a new indented line and Esc (q)uits.") (sit-for 5 0)
+ (message "Insert note triplets \"\\times 2/3 { a b } \" by typing \"/23ab}\".") (sit-for 5 0)
+ (message "This mode is experimental. Use normal mode to add further details.") (sit-for 5 0)))))
+ (message "Normal editing mode."))
+
+(defun LilyPond-pre-word-search ()
+ "Fetch the alphabetic characters and \\ in front of the cursor."
+ (let ((pre "")
+ (prelen 0)
+ (ch (char-before (- (point) 0))))
+ (while (and ch (or (and (>= ch 65) (<= ch 90)) ; not bolp, A-Z
+ (and (>= ch 97) (<= ch 122)) ; a-z
+ (= ch 92))) ; \\
+ (setq pre (concat (char-to-string ch) pre))
+ (setq prelen (+ prelen 1))
+ (setq ch (char-before (- (point) prelen))))
+ pre))
+
+(defun LilyPond-post-word-search ()
+ "Fetch the alphabetic characters behind the cursor."
+ (let ((post "")
+ (postlen 0)
+ (ch (char-after (+ (point) 0))))
+ (while (and ch (or (and (>= ch 65) (<= ch 90)) ; not eolp, A-Z
+ (and (>= ch 97) (<= ch 122)))) ; a-z
+ (setq post (concat post (char-to-string ch)))
+ (setq postlen (+ postlen 1))
+ (setq ch (char-after (+ (point) postlen))))
+ post))
+
+(defun LilyPond-autocompletion ()
+ "Show completions in mini-buffer for the given word."
+ (interactive)
+ (let ((pre (LilyPond-pre-word-search))
+ (post (LilyPond-post-word-search))
+ (compsstr ""))
+ ;; insert try-completion and show all-completions
+ (if (> (length pre) 0)
+ (progn
+ (setq trycomp (try-completion pre (LilyPond-add-dictionary-word ())))
+ (if (char-or-string-p trycomp)
+ (if (string-equal (concat pre post) trycomp)
+ (goto-char (+ (point) (length post)))
+ (progn
+ (delete-region (point) (+ (point) (length post)))
+ (insert (substring trycomp (length pre) nil))))
+ (progn
+ (delete-region (point) (+ (point) (length post)))
+ (font-lock-fontify-buffer))) ; only inserting fontifies
+
+ (setq complist (all-completions pre (LilyPond-add-dictionary-word ())))
+ (while (> (length complist) 0)
+ (setq compsstr (concat compsstr "\"" (car complist) "\" "))
+ (setq complist (cdr complist)))
+ (message compsstr)
+ (sit-for 0 100)))))
+
+(defun LilyPond-info ()
+ "Launch Info for lilypond."
+ (interactive)
+ (info "lilypond"))
+
+(defun LilyPond-music-glossary-info ()
+ "Launch Info for music-glossary."
+ (interactive)
+ (info "music-glossary"))
+
+(defun LilyPond-internals-info ()
+ "Launch Info for lilypond-internals."
+ (interactive)
+ (info "lilypond-internals"))
+
+(defun LilyPond-info-index-search ()
+ "In `*info*'-buffer, launch `info lilypond --index-search word-under-cursor'"
+ (interactive)
+ (let ((str (concat (LilyPond-pre-word-search) (LilyPond-post-word-search))))
+ (if (and (> (length str) 0)
+ (string-equal (substring str 0 1) "\\"))
+ (setq str (substring str 1 nil)))
+ (LilyPond-info)
+ (Info-index str)))
+
+(defun LilyPond-insert-string (pre)
+ "Insert text to the buffer."
+ (insert pre)
+ (length pre))
+
+(defun LilyPond-insert-between (text pre post)
+ "Insert text to the buffer if non-empty string is given."
+ (let ((str (read-string text)))
+ (if (string-equal str "")
+ 0
+ (progn (setq pre_str_post (concat pre str post))
+ (insert pre_str_post)
+ (length pre_str_post)))))
+
+(defun LilyPond-insert-tag-notes ()
+ "LilyPond notes tag."
+ (interactive)
+ (setq begin (if (LilyPond-mark-active)
+ (mark-marker) (point-marker)))
+ (setq end (point-marker))
+ (goto-char begin)
+ (setq l1 (LilyPond-insert-string "\\notes "))
+ (setq l2 (LilyPond-insert-between "Relative (e.g. c'): " "\\relative " " "))
+ (if (eq l2 0)
+ (setq l2 (LilyPond-insert-between "Transpose (e.g. c c'): " "\\transpose " " ")))
+ (setq l3 (LilyPond-insert-string "{ "))
+ (goto-char (+ end l1 l2 l3))
+ (LilyPond-insert-string " }")
+ (goto-char (+ end l1 l2 l3)))
+
+(defun LilyPond-insert-tag-score ()
+ "LilyPond score tag."
+ (interactive)
+ (setq begin (if (LilyPond-mark-active)
+ (mark-marker) (point-marker)))
+ (setq end (point-marker))
+ (goto-char begin)
+ (setq l1 (LilyPond-insert-string "\\score {\n ")) ; keep track of lengths
+ (goto-char (+ end l1))
+ (LilyPond-insert-string "\n \\paper { }\n")
+ (setq l2 (if (y-or-n-p "Insert \"\\header\" field? ")
+ (+ (LilyPond-insert-string " \\header {")
+ (LilyPond-insert-between "Title: " "\n title = \"" "\"")
+ (LilyPond-insert-between "Subtitle: " "\n subtitle = \"" "\"")
+ (LilyPond-insert-between "Piece: " "\n piece = \"" "\"")
+ (LilyPond-insert-between "Opus: " "\n opus = \"" "\"")
+ (LilyPond-insert-string "\n }\n"))
+ 0))
+ (setq l3 (if (y-or-n-p "Insert \"\\midi\" field? ")
+ (+ (LilyPond-insert-string " \\midi {")
+ (LilyPond-insert-between "Tempo: " " \\tempo (e.g. 4 = 60)" "")
+ (LilyPond-insert-string " }\n"))
+ 0))
+ (setq l4 (LilyPond-insert-string "}\n"))
+ (goto-char (+ end l1)))
+