In LilyPond v2.25.20 [1], `LilyPond-mode` was renamed to `lilypond-mode`
in commit c7c6f14ede on 25 August 2024.  Org still expects the old name,
which makes LilyPond support moot.  The attached patch fixes it.

[1] https://savannah.gnu.org/projects/lilypond
>From c2786aa6bbc1bf6b5256ad5fab916d20d082c7b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rudolf=20Adamkovi=C4=8D?= <[email protected]>
Date: Tue, 27 Oct 2026 01:20:14 +0100
Subject: [PATCH] lisp/ob-lilypond.el: Support renamed LilyPond major mode

* lisp/ob-lilypond.el (org-babel-tangle-lang-exts): Map lowercase
lilypond blocks to .ly files.
(org-src-lang-modes): Prefer lilypond-mode, with LilyPond-mode as a
fallback.
* lisp/org-src.el (org-src-lang-modes): Document and customize a list
of major modes.
(org-src-get-lang-mode): Select the first available mode.
* testing/lisp/test-ob-lilypond.el
(ob-lilypond/org-babel-tangle-lang-exts)
(ob-lilypond/org-src-lang-mode): Test both language spellings and
major mode names.
---
 lisp/ob-lilypond.el              |  3 ++-
 lisp/org-src.el                  | 31 +++++++++++++++++++------------
 testing/lisp/test-ob-lilypond.el | 21 ++++++++++++++-------
 3 files changed, 35 insertions(+), 20 deletions(-)

diff --git a/lisp/ob-lilypond.el b/lisp/ob-lilypond.el
index b2517fc82..5ab158c63 100644
--- a/lisp/ob-lilypond.el
+++ b/lisp/ob-lilypond.el
@@ -41,7 +41,8 @@ (require 'ob)
 (declare-function org-fold-show-all "org-fold" (&optional types))
 
 (add-to-list 'org-babel-tangle-lang-exts '("LilyPond" . "ly"))
-(add-to-list 'org-src-lang-modes '("lilypond" . LilyPond))
+(add-to-list 'org-babel-tangle-lang-exts '("lilypond" . "ly"))
+(add-to-list 'org-src-lang-modes '("lilypond" . (lilypond LilyPond)))
 
 (defvar org-babel-default-header-args:lilypond '()
   "Default header arguments for lilypond code blocks.
diff --git a/lisp/org-src.el b/lisp/org-src.el
index 7fa8b8034..4eb14f161 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -235,7 +235,8 @@ (defcustom org-src-lang-modes
   "Alist mapping languages to their major mode.
 
 The key is the language name.  The value is the mode name, as
-a string or a symbol, without the \"-mode\" suffix.
+a string or a symbol, without the \"-mode\" suffix.  It may also
+be a list of mode names, tried in order until one is available.
 
 For many languages this is simple, but for language where this is
 not the case, this variable provides a way to simplify things on
@@ -246,7 +247,8 @@ (defcustom org-src-lang-modes
   :type '(repeat
 	  (cons
 	   (string :tag "Language name")
-	   (symbol :tag "Major mode")))
+	   (choice (symbol :tag "Major mode")
+	           (repeat :tag "Major modes" symbol))))
   :safe #'listp)
 
 (defcustom org-src-block-faces nil
@@ -993,16 +995,21 @@ (defun org-src-do-key-sequence-at-code-block (&optional key)
 (defun org-src-get-lang-mode (lang)
   "Return major mode that should be used for LANG.
 LANG is a string, and the returned value is a symbol."
-  (let ((mode (intern
-               (concat
-                (let ((l (or (cdr (assoc lang org-src-lang-modes)) lang)))
-                  (if (symbolp l) (symbol-name l) l))
-                "-mode"))))
-    (cond
-     ((fboundp 'major-mode-remap) (major-mode-remap mode))
-     ((boundp 'major-mode-remap-alist)
-      (or (cdr (assq mode major-mode-remap-alist)) mode))
-     (t mode))))
+  (let* ((names (or (cdr (assoc lang org-src-lang-modes)) lang))
+         (modes (mapcar
+                 (lambda (name)
+                   (let ((mode (intern (concat (if (symbolp name)
+                                                   (symbol-name name)
+                                                 name)
+                                               "-mode"))))
+                     (cond
+                      ((fboundp 'major-mode-remap)
+                       (major-mode-remap mode))
+                      ((boundp 'major-mode-remap-alist)
+                       (or (cdr (assq mode major-mode-remap-alist)) mode))
+                      (t mode))))
+                 (if (listp names) names (list names)))))
+    (or (cl-find-if #'functionp modes) (car modes))))
 
 (defun org-src-get-lang-mode-if-bound (lang &optional fallback fallback-message-p)
   "Return major mode for LANG, if bound, and FALLBACK otherwise.
diff --git a/testing/lisp/test-ob-lilypond.el b/testing/lisp/test-ob-lilypond.el
index 3cfe1f5a9..de9e59430 100644
--- a/testing/lisp/test-ob-lilypond.el
+++ b/testing/lisp/test-ob-lilypond.el
@@ -39,13 +39,20 @@ (ert-deftest ob-lilypond/feature-provision ()
   (should (featurep 'ob-lilypond)))
 
 (ert-deftest ob-lilypond/org-babel-tangle-lang-exts ()
-  (let ((found nil)
-        (list org-babel-tangle-lang-exts))
-    (while list
-      (when (equal (car list) '("LilyPond" . "ly"))
-        (setq found t))
-      (setq list (cdr list)))
-    (should found)))
+  (should (equal (org-babel-effective-tangled-filename
+                  "/score.org" "lilypond" "yes")
+                 "/score.ly"))
+  (should (equal (org-babel-effective-tangled-filename
+                  "/score.org" "LilyPond" "yes")
+                 "/score.ly")))
+
+(ert-deftest ob-lilypond/org-src-lang-mode ()
+  (cl-letf (((symbol-function 'lilypond-mode) #'ignore)
+            ((symbol-function 'LilyPond-mode) #'ignore))
+    (should (eq (org-src-get-lang-mode "lilypond") 'lilypond-mode)))
+  (cl-letf (((symbol-function 'lilypond-mode) nil)
+            ((symbol-function 'LilyPond-mode) #'ignore))
+    (should (eq (org-src-get-lang-mode "lilypond") 'LilyPond-mode))))
 
 (ert-deftest ob-lilypond/org-babel-prep-session:lilypond ()
   (should-error (org-babel-prep-session:lilypond nil nil))
-- 
2.54.0 (Apple Git-157)

-- 
There are only two hard things in computer science: cache invalidation,
naming things, and off-by-one errors.

--- Phil Karlton, Leon Bambrick

Rudolf Adamkovič <[email protected]> [he/him]
http://adamkovic.org

Reply via email to