On Sun, Jan 25, 2026 at 4:33 AM Ihor Radchenko <[email protected]> wrote:

> Squashing will make sense. They are quite repetitive.
>

Squashed commit (for all but ox-odt) attached. I also attached a commit to
add a better error message when an invalid action or value is passed to
`org-priority', as Jacob pointed out.


> As Jacob pointed, ox-odt fix does not look complete.
> I am not sure if introducing several dozens of styles for each priority
> value will be useful though (imagine editing that style file).
> Maybe we need to generate the style names dynamically in
> `org-odt-template'.


Agreed, I started looking at that last night. I see where I can generate
the styles, I just need to figure out the best way to do it.

Cheers,

Derek

 --
+---------------------------------------------------------------+
| Derek Chen-Becker                                             |
| GPG Key available at https://keybase.io/dchenbecker and       |
| https://pgp.mit.edu/pks/lookup?search=derek%40chen-becker.org |
| Fngrprnt: EB8A 6480 F0A3 C8EB C1E7  7F42 AFC5 AFEE 96E4 6ACC  |
+---------------------------------------------------------------+
From 7fe6b8b93bfb42233b137c74b75a990d2e5c1dd9 Mon Sep 17 00:00:00 2001
From: Derek Chen-Becker <[email protected]>
Date: Sat, 24 Jan 2026 18:57:31 -0700
Subject: [PATCH 2/2] org.el: Add a meaningful message for `org-priority'
 invalid argument

* lisp/org.el (org-priority): Change the error message when an invalid
actions is passed to `org-priority' so that it indicates valid actions and
values based on the current high and low bounds.
---
 lisp/org.el | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/lisp/org.el b/lisp/org.el
index 445f0d9ea..172b5c559 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -11461,7 +11461,12 @@ interactive prompt, it will automatically be converted to uppercase."
 			(if org-priority-start-cycle-with-default
 			    org-priority-default
 			  (1+ org-priority-default))))))
-	 (t (user-error "Invalid action")))
+	 (t (user-error (concat "Invalid action: `%s'.  Action must be one of "
+                                "`up', `down', `set', `remove' or a value "
+                                "between `%s' and `%s'")
+                        action
+                        (org-priority-to-string org-priority-highest)
+                        (org-priority-to-string org-priority-lowest))))
         ;; Check against the current high/low range if we need to wrap
 	(when (not (org-priority-valid-value-p new-value))
 	  (if (and (memq action '(up down))
-- 
2.43.0

From 339b325ab6f4f1b4d472957be4992abb0a58a073 Mon Sep 17 00:00:00 2001
From: Derek Chen-Becker <[email protected]>
Date: Tue, 20 Jan 2026 05:52:56 -0700
Subject: [PATCH 1/2] Fix formatting of numeric priority values in export
 formats

* lisp/ox-ascii.el (org-ascii--build-title): Fix formatting of priority
values to use `org-priority-to-string' instead of assuming a character.

* lisp/ox-md.el (org-md-headline): Fix formatting of priority values to use
`org-priority-to-string' instead of assuming a character.

* lisp/ox-latex.el (org-latex-format-inlinetask-default-function): Use
`org-priority-to-string' to format priority values instead of assuming a
character.

* lisp/ox-texinfo.el (org-texinfo-format-headline-default-function): Use
`org-priority-to-string' to format priority values instead of assuming a
character.

* list/ox-html.el (org-html--priority): Update formatting of the priority
value to use `org-priority-to-string' instead of assuming a character.

* testing/lisp/test-ox-ascii.el: Add a new unit test for the
`org-ascii--build-title' function to exercise both alphabetic and numeric
priority values.

* testing/lisp/test-ox-md.el: Add unit test to exercise numeric priorities
in headlines.

* testing/lisp/test-ox-latex.el: Add unit tests to exercise numeric
priorities in headings.

* testing/lisp/test-ox-texinfo.el: Add unit test to exercise numeric
heading and inline task priorities.

* testing/lisp/test-ox-html.el: Add a unit test to exercise formatting of
priority values.
---
 lisp/ox-ascii.el                |  4 +--
 lisp/ox-html.el                 |  3 ++-
 lisp/ox-latex.el                |  2 +-
 lisp/ox-md.el                   |  4 +--
 lisp/ox-texinfo.el              |  4 +--
 testing/lisp/test-ox-ascii.el   | 26 +++++++++++++++++++
 testing/lisp/test-ox-html.el    | 18 +++++++++++++
 testing/lisp/test-ox-latex.el   | 16 ++++++++++++
 testing/lisp/test-ox-md.el      | 16 ++++++++++++
 testing/lisp/test-ox-texinfo.el | 46 +++++++++++++++++++++++++++++++++
 10 files changed, 131 insertions(+), 8 deletions(-)

diff --git a/lisp/ox-ascii.el b/lisp/ox-ascii.el
index ca9e5eb7c..cdc3f1c64 100644
--- a/lisp/ox-ascii.el
+++ b/lisp/ox-ascii.el
@@ -685,8 +685,8 @@ possible.  It doesn't apply to `inlinetask' elements."
 			   (org-make-tag-string tag-list)))))
 	 (priority
 	  (and (plist-get info :with-priority)
-	       (let ((char (org-element-property :priority element)))
-		 (and char (format "(#%c) " char)))))
+	       (let ((priority-value (org-element-property :priority element)))
+		 (and priority-value (format "(#%s) " (org-priority-to-string priority-value))))))
 	 (first-part (concat numbers todo priority text)))
     (concat
      first-part
diff --git a/lisp/ox-html.el b/lisp/ox-html.el
index ae700b6e6..f21422c94 100644
--- a/lisp/ox-html.el
+++ b/lisp/ox-html.el
@@ -2363,7 +2363,8 @@ INFO is the info plist."
   "Format a priority into HTML.
 PRIORITY is the character code of the priority or nil.  INFO is
 a plist containing export options."
-  (and priority (format "<span class=\"priority\">[%c]</span>" priority)))
+  (and priority (format "<span class=\"priority\">[%s]</span>"
+                        (org-priority-to-string priority))))
 
 ;;;; Tags
 
diff --git a/lisp/ox-latex.el b/lisp/ox-latex.el
index a63013adf..844591a43 100644
--- a/lisp/ox-latex.el
+++ b/lisp/ox-latex.el
@@ -2636,7 +2636,7 @@ holding contextual information."
 See `org-latex-format-inlinetask-function' for details."
   (let ((full-title
 	 (concat (when todo (format "\\textbf{\\textsf{\\textsc{%s}}} " todo))
-		 (when priority (format "\\framebox{\\#%c} " priority))
+		 (when priority (format "\\framebox{\\#%s} " (org-priority-to-string priority)))
 		 title
 		 (when tags
 		   (format "\\hfill{}\\textsc{%s}"
diff --git a/lisp/ox-md.el b/lisp/ox-md.el
index c3ca86f88..244523c56 100644
--- a/lisp/ox-md.el
+++ b/lisp/ox-md.el
@@ -409,8 +409,8 @@ a communication channel."
 			     (concat "     " (org-make-tag-string tag-list))))))
 	   (priority
 	    (and (plist-get info :with-priority)
-		 (let ((char (org-element-property :priority headline)))
-		   (and char (format "[#%c] " char)))))
+		 (let ((priority-value (org-element-property :priority headline)))
+		   (and priority-value (format "[#%s] " (org-priority-to-string priority-value))))))
 	   ;; Headline text without tags.
 	   (heading (concat todo priority title))
 	   (style (plist-get info :md-headline-style)))
diff --git a/lisp/ox-texinfo.el b/lisp/ox-texinfo.el
index 2d0735ef0..8fd753296 100644
--- a/lisp/ox-texinfo.el
+++ b/lisp/ox-texinfo.el
@@ -1171,7 +1171,7 @@ holding contextual information."
   "Default format function for a headline.
 See `org-texinfo-format-headline-function' for details."
   (concat (and todo (format "@strong{%s} " todo))
-	  (and priority (format "@emph{#%s} " priority))
+	  (and priority (format "@emph{#%s} " (org-priority-to-string priority)))
 	  text
 	  (and tags (concat " " (org-make-tag-string tags)))))
 
@@ -1209,7 +1209,7 @@ holding contextual information."
 See `org-texinfo-format-inlinetask-function' for details."
   (let ((full-title
 	 (concat (when todo (format "@strong{%s} " todo))
-		 (when priority (format "#%c " priority))
+		 (when priority (format "#%s " (org-priority-to-string priority)))
 		 title
 		 (when tags (org-make-tag-string tags)))))
     (format "@center %s\n\n%s\n" full-title contents)))
diff --git a/testing/lisp/test-ox-ascii.el b/testing/lisp/test-ox-ascii.el
index 0532b89ee..07f9b0580 100644
--- a/testing/lisp/test-ox-ascii.el
+++ b/testing/lisp/test-ox-ascii.el
@@ -82,5 +82,31 @@ left or right
     (should
      (equal org-ascii-text-width (org-current-text-column)))))
 
+(ert-deftest test-ox-ascii/build-title ()
+  "Test title creation."
+  ;; Alphabetical priority cookie
+   (org-test-with-exported-text
+    'ascii
+    "#+OPTIONS: pri:t\n* [#A] Test"
+    (goto-char (point-min))
+    (should
+     (search-forward "1. (#A) Test")))
+  ;; Single digit numeric priority cookie
+   (org-test-with-exported-text
+    'ascii
+    "#+PRIORITIES: 1 10 5\n#+OPTIONS: pri:t\n* [#7] Test"
+    (goto-char (point-min))
+    (should
+     (search-forward "1. (#7) Test")))
+  ;; Double digit numeric priority cookie
+   (org-test-with-exported-text
+    'ascii
+    "#+PRIORITIES: 1 20 5\n#+OPTIONS: pri:t\n* [#14] Test"
+    (goto-char (point-min))
+    (should
+     (search-forward "1. (#14) Test")))
+
+   )
+
 (provide 'test-ox-ascii)
 ;;; test-ox-ascii.el ends here
diff --git a/testing/lisp/test-ox-html.el b/testing/lisp/test-ox-html.el
index 5a8e7df3c..04d7850ad 100644
--- a/testing/lisp/test-ox-html.el
+++ b/testing/lisp/test-ox-html.el
@@ -1106,5 +1106,23 @@ entirely."
         (expected "\n<ul>\n<li>\n<ul>\n<li>1\n<ul>\n<li>1.1</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>2</li>\n</ul>\n"))
     (should (string= (org-html--toc-text toc-entries nil) expected))))
 
+;;; Rendering priorities
+
+(ert-deftest ox-html/test-priority ()
+  "Test the generation of priority values."
+  ;; Alphabetical
+  (should
+   (equal "<span class=\"priority\">[A]</span>"
+          (org-html--priority ?A nil)))
+  ;; Numeric single digit
+  (should
+   (equal "<span class=\"priority\">[8]</span>"
+          (org-html--priority 8 nil)))
+  ;; Numeric double digit
+  (should
+   (equal "<span class=\"priority\">[18]</span>"
+          (org-html--priority 18 nil)))
+  )
+
 (provide 'test-ox-html)
 ;;; test-ox-html.el ends here
diff --git a/testing/lisp/test-ox-latex.el b/testing/lisp/test-ox-latex.el
index 64ab7d467..419cbf079 100644
--- a/testing/lisp/test-ox-latex.el
+++ b/testing/lisp/test-ox-latex.el
@@ -297,6 +297,14 @@ is suppressed
    'latex
    "#+OPTIONS: pri:t
 * [#42] Test
+"
+   (goto-char (point-min))
+   (should (search-forward "\\framebox{\\#42}")))
+  ;; Test inline task (level >= org-inlinetask-min-level, default 15)
+  (org-test-with-exported-text
+   'latex
+   "#+OPTIONS: pri:t inline:t
+***************** [#42] Test
 "
    (goto-char (point-min))
    (should (search-forward "\\framebox{\\#42}"))))
@@ -307,6 +315,14 @@ is suppressed
    'latex
    "#+OPTIONS: pri:t
 * [#C] Test
+"
+   (goto-char (point-min))
+   (should (search-forward "\\framebox{\\#C}")))
+  ;; Test inline task (level >= org-inlinetask-min-level, default 15)
+  (org-test-with-exported-text
+   'latex
+   "#+OPTIONS: pri:t inline:t
+***************** [#C] Test
 "
    (goto-char (point-min))
    (should (search-forward "\\framebox{\\#C}"))))
diff --git a/testing/lisp/test-ox-md.el b/testing/lisp/test-ox-md.el
index 8f5b473d1..99548bb3f 100644
--- a/testing/lisp/test-ox-md.el
+++ b/testing/lisp/test-ox-md.el
@@ -130,5 +130,21 @@
         (should (search-forward "[babel org file](examples/babel.org)"))
         (should (search-forward "[babel script](examples/babel.el)"))))))
 
+(ert-deftest ox-md/headline-priority ()
+  "Test formatting of headlines with priority."
+  (let ((export-buffer "*Test MD Export*")
+        (org-export-show-temporary-export-buffer nil))
+    (org-test-with-temp-text "#+options: toc:nil pri:t
+* [#A] Test
+* [#7] Test 2
+* [#23] Test 3
+"
+        (org-export-to-buffer 'md export-buffer)
+        (with-current-buffer export-buffer
+          (goto-char (point-min))
+          (should (search-forward "# [#A] Test"))
+          (should (search-forward "# [#7] Test 2"))
+          (should (search-forward "# [#23] Test 3"))))))
+
 (provide 'test-ox-md)
 ;;; test-ox-md.el ends here
diff --git a/testing/lisp/test-ox-texinfo.el b/testing/lisp/test-ox-texinfo.el
index e34a2137f..57175b4be 100644
--- a/testing/lisp/test-ox-texinfo.el
+++ b/testing/lisp/test-ox-texinfo.el
@@ -629,5 +629,51 @@ Headings exported as list items have no such problem."
           (re-search-forward "^@anchor{Heading 2-2-2}$")
           (re-search-forward "^@subheading Heading 2-2-2$")))))))
 
+(ert-deftest test-ox-texinfo/heading-priorities ()
+  "Test formatting of priority in headings."
+  (should
+   (org-test-with-temp-text
+       (string-join
+        (list "#+OPTIONS: pri:t"
+              "* [#A] Heading 1"
+              "* [#8] Heading 2"
+              "* [#27] Heading 3")
+        "\n")
+     (let ((export-buffer "*Test Texinfo Export*")
+           (org-export-show-temporary-export-buffer nil))
+       (org-export-to-buffer 'texinfo export-buffer
+         nil nil nil nil nil
+         #'texinfo-mode)
+       (with-current-buffer export-buffer
+         (goto-char (point-min))
+         (and
+          (re-search-forward "^* Heading 1::$")
+          (re-search-forward "^* Heading 2::$")
+          (re-search-forward "^* Heading 3::$")
+          (re-search-forward "@emph{#A}")
+          (re-search-forward "@emph{#8}")
+          (re-search-forward "@emph{#27}")))))))
+
+(ert-deftest test-ox-texinfo/inlinetask-priorities ()
+  "Test formatting of priority in headings."
+  (should
+   (org-test-with-temp-text
+       (string-join
+        (list "#+OPTIONS: inline:t pri:t"
+              "*************** [#C] Inlinetask 1"
+              "*************** [#11] Inlinetask 2")
+        "\n")
+     (let ((export-buffer "*Test Texinfo Export*")
+           (org-export-show-temporary-export-buffer nil))
+       (org-export-to-buffer 'texinfo export-buffer
+         nil nil nil nil nil
+         #'texinfo-mode)
+       (with-current-buffer export-buffer
+         (goto-char (point-min))
+         (and
+          (re-search-forward "^@center #C Inlinetask 1$")
+          (re-search-forward "^@center #11 Inlinetask 2$")
+          ))))))
+
 (provide 'test-ox-texinfo)
 ;;; test-ox-texinfo.el end here
-- 
2.43.0

Reply via email to