emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [PATCH] babel output seems to drop anything before % (in session)
  @ 2022-06-18  3:20 11% ` Ihor Radchenko
  0 siblings, 0 replies; 20+ results
From: Ihor Radchenko @ 2022-06-18  3:20 UTC (permalink / raw)
  To: Felix Freeman; +Cc: emacs-orgmode, kaushal.modi, nick

[-- Attachment #1: Type: text/plain, Size: 788 bytes --]

"Felix Freeman" <libsys@hacktivista.org> writes:

> Today I stumbed upon the same bug.
>
> Sadly I have no idea how to fix it, but thought it would be nice to post
> about it here so the bug doesn't get lost in the sands of time.

I finally managed to get some working fix.
At least it kind of works on my system using bash.
The idea is changing shell prompt to something unique when we initialize
the session.

See the attached patch.

Please test this on "sh" "zsh" "fish" "csh" "ash" "dash" "ksh" "mksh"
and "posh".
Especially on fish, csh, and posh (which I believe refers to
PowerShell).

Also, doing PS1="blabla > " in bash may not always work. At least it
does not work with https://github.com/nojhan/liquidprompt

So, more reliable ways to change prompt are welcome.

Best,
Ihor


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-disabled-test-for-in-babel-shell-output.patch --]
[-- Type: text/x-patch, Size: 2022 bytes --]

From 141f810a658d652e1cb3a147c5f71659f62df86f Mon Sep 17 00:00:00 2001
Message-Id: <141f810a658d652e1cb3a147c5f71659f62df86f.1655522152.git.yantar92@gmail.com>
From: Daniele Pizzolli <dan+git@toel.it>
Date: Wed, 5 May 2021 17:00:28 +0200
Subject: [PATCH 1/2] Add disabled test for % in babel shell output

---
 testing/lisp/test-ob-shell.el | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/testing/lisp/test-ob-shell.el b/testing/lisp/test-ob-shell.el
index 2f346f699..e81058ac7 100644
--- a/testing/lisp/test-ob-shell.el
+++ b/testing/lisp/test-ob-shell.el
@@ -106,6 +106,35 @@ (ert-deftest ob-shell/simple-list ()
 	   "#+BEGIN_SRC sh :results output :var l='(1 2)\necho ${l}\n#+END_SRC"
 	   (org-trim (org-babel-execute-src-block))))))
 
+(ert-deftest ob-shell/percent-simple ()
+  "Test percent in output."
+  (should
+   (equal "one 0% two\ntree 0% four"
+	  (org-test-with-temp-text
+	   "#+BEGIN_SRC bash :results output verbatim\necho one 0% two\necho tree 0% four\n#+END_SRC"
+	   (org-trim (org-babel-execute-src-block)))))
+  (should
+   (equal "five 0% two\ntree 0% four"
+	  (org-test-with-temp-text
+	   "#+BEGIN_SRC bash :results output verbatim\necho five 0% two\necho tree 0% four\n#+END_SRC"
+	   (org-trim (org-babel-execute-src-block))))))
+
+(ert-deftest ob-shell/percent-session ()
+  "Test percent in output for session.
+
+At the second iteration the string before % is dropped."
+  :expected-result :failed
+  (should
+   (equal "one 0% two\ntree 0% four"
+	  (org-test-with-temp-text
+	   "#+BEGIN_SRC bash :results output verbatim :session sess\necho one 0% two\necho tree 0% four\n#+END_SRC"
+	   (org-trim (org-babel-execute-src-block)))))
+  (should
+   (equal "five 0% six\nseven 0% eight"
+	  (org-test-with-temp-text
+	   "#+BEGIN_SRC bash :results output verbatim :session sess\necho five 0% six\necho seven 0% eight\n#+END_SRC"
+	   (org-trim (org-babel-execute-src-block))))))
+
 (provide 'test-ob-shell)
 
 ;;; test-ob-shell.el ends here
-- 
2.35.1


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-ob-shell-Fix-output-containing-strings-matching-comi.patch --]
[-- Type: text/x-patch, Size: 6579 bytes --]

From 4f7a1369e72b22836cb74931c7c86e845155a729 Mon Sep 17 00:00:00 2001
Message-Id: <4f7a1369e72b22836cb74931c7c86e845155a729.1655522152.git.yantar92@gmail.com>
In-Reply-To: <141f810a658d652e1cb3a147c5f71659f62df86f.1655522152.git.yantar92@gmail.com>
References: <141f810a658d652e1cb3a147c5f71659f62df86f.1655522152.git.yantar92@gmail.com>
From: Ihor Radchenko <yantar92@gmail.com>
Date: Sat, 18 Jun 2022 11:11:12 +0800
Subject: [PATCH 2/2] ob-shell: Fix output containing strings matching
 `comint-prompt-regexp'

* lisp/ob-comint.el (org-babel-comint-wait-for-output): Do not rely on
`face-at-point' returning non-nil.
* lisp/ob-shell.el (org-babel-shell-set-prompt-commands): New constant
holding shell-specific commands to change prompt.
(org-babel-prompt-command): New variable holding command to be user to
set distinguishable prompt.
(org-babel-shell-initialize): Set `org-babel-prompt-command' according
to shell name.
(org-babel-sh-prompt): New variable holding default shell prompt.
(org-babel-sh-initiate-session): Change the default prompt to
`org-babel-sh-prompt' and alter `comint-prompt-regexp' to match it
tightly.
* testing/lisp/test-ob-shell.el (ob-shell/percent-session): Do not
expect failure in the fixed test.

Fixes https://list.orgmode.org/CKK9TULBP2BG.2UITT31YJV03J@laptop/T/#mc8e3ca2f5f1b9a94040a68b4c6201234b209041c
---
 lisp/ob-comint.el             |  4 +---
 lisp/ob-shell.el              | 42 ++++++++++++++++++++++++++++++-----
 testing/lisp/test-ob-shell.el |  4 ++--
 3 files changed, 39 insertions(+), 11 deletions(-)

diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el
index 427aba341..1d3e24607 100644
--- a/lisp/ob-comint.el
+++ b/lisp/ob-comint.el
@@ -124,9 +124,7 @@ (defun org-babel-comint-wait-for-output (buffer)
     (while (progn
              (goto-char comint-last-input-end)
              (not (and (re-search-forward comint-prompt-regexp nil t)
-                       (goto-char (match-beginning 0))
-                       (string= (face-name (face-at-point))
-                                "comint-highlight-prompt"))))
+                     (goto-char (match-beginning 0)))))
       (accept-process-output (get-buffer-process buffer)))))
 
 (defun org-babel-comint-eval-invisibly-and-wait-for-file
diff --git a/lisp/ob-shell.el b/lisp/ob-shell.el
index c25941a44..f80783653 100644
--- a/lisp/ob-shell.el
+++ b/lisp/ob-shell.el
@@ -42,6 +42,23 @@ (declare-function orgtbl-to-generic "org-table" (table params))
 (defvar org-babel-default-header-args:shell '())
 (defvar org-babel-shell-names)
 
+(defconst org-babel-shell-set-prompt-commands
+  '(("fish" . "function fish_prompt\n\techo \"%s\"\nend")
+    ("csh" . "set prompt=\"%s\"")
+    ("posh" . "function prompt { \"%s\" }")
+    (t . "PS1=\"%s\""))
+  "Alist assigning shells with their prompt setting command.
+
+Each element of the alist associates a shell type from
+`org-babel-shell-names' with a template used to create a command to
+change the default prompt.  The template is an argument to `format'
+that will be called with a single additional argument: prompt string.
+
+The fallback association template is defined in (t . \"template\")
+alist element.")
+
+(defvar org-babel-prompt-command)
+
 (defun org-babel-shell-initialize ()
   "Define execution functions associated to shell names.
 This function has to be called whenever `org-babel-shell-names'
@@ -51,7 +68,10 @@ (defun org-babel-shell-initialize ()
     (eval `(defun ,(intern (concat "org-babel-execute:" name))
 	       (body params)
 	     ,(format "Execute a block of %s commands with Babel." name)
-	     (let ((shell-file-name ,name))
+	     (let ((shell-file-name ,name)
+                   (org-babel-prompt-command
+                    (or (alist-get ,name org-babel-shell-set-prompt-commands)
+                        (alist-get t org-babel-shell-set-prompt-commands))))
 	       (org-babel-execute:shell body params))))
     (eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name))
 	     'org-babel-variable-assignments:shell
@@ -206,6 +226,13 @@ (defun org-babel-sh-var-to-string (var &optional sep hline)
       (mapconcat echo-var var "\n"))
      (t (funcall echo-var var)))))
 
+(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'"
+  "String to indicate that evaluation has completed.")
+(defvar org-babel-sh-eoe-output "org_babel_sh_eoe"
+  "String to indicate that evaluation has completed.")
+(defvar org-babel-sh-prompt "org_babel_sh_prompt> "
+  "String to set prompt in session shell.")
+
 (defun org-babel-sh-initiate-session (&optional session _params)
   "Initiate a session named SESSION according to PARAMS."
   (when (and session (not (string= session "none")))
@@ -213,17 +240,20 @@ (defun org-babel-sh-initiate-session (&optional session _params)
       (or (org-babel-comint-buffer-livep session)
           (progn
 	    (shell session)
+            ;; Set unique prompt for easier analysis of the output.
+            (org-babel-comint-wait-for-output (current-buffer))
+            (org-babel-comint-input-command
+             (current-buffer)
+             (format org-babel-prompt-command org-babel-sh-prompt))
+            (setq-local comint-prompt-regexp
+                        (concat "^" (regexp-quote org-babel-sh-prompt)
+                                " *"))
 	    ;; Needed for Emacs 23 since the marker is initially
 	    ;; undefined and the filter functions try to use it without
 	    ;; checking.
 	    (set-marker comint-last-output-start (point))
 	    (get-buffer (current-buffer)))))))
 
-(defvar org-babel-sh-eoe-indicator "echo 'org_babel_sh_eoe'"
-  "String to indicate that evaluation has completed.")
-(defvar org-babel-sh-eoe-output "org_babel_sh_eoe"
-  "String to indicate that evaluation has completed.")
-
 (defun org-babel-sh-evaluate (session body &optional params stdin cmdline)
   "Pass BODY to the Shell process in BUFFER.
 If RESULT-TYPE equals `output' then return a list of the outputs
diff --git a/testing/lisp/test-ob-shell.el b/testing/lisp/test-ob-shell.el
index e81058ac7..2bfc29228 100644
--- a/testing/lisp/test-ob-shell.el
+++ b/testing/lisp/test-ob-shell.el
@@ -122,8 +122,8 @@ (ert-deftest ob-shell/percent-simple ()
 (ert-deftest ob-shell/percent-session ()
   "Test percent in output for session.
 
-At the second iteration the string before % is dropped."
-  :expected-result :failed
+Percent is matching the default value of `comint-prompt-regexp', which
+can cause issues with analysis."
   (should
    (equal "one 0% two\ntree 0% four"
 	  (org-test-with-temp-text
-- 
2.35.1


^ permalink raw reply related	[relevance 11%]

* Re: Org 9.6-pre and Bash sessions
  @ 2022-10-21  5:29  6%       ` Ihor Radchenko
  0 siblings, 0 replies; 20+ results
From: Ihor Radchenko @ 2022-10-21  5:29 UTC (permalink / raw)
  To: Rudolf Adamkovič; +Cc: Ihor Radchenko, emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 811 bytes --]

Ihor Radchenko <yantar92@posteo.net> writes:

> Rudolf Adamkovič <salutis@me.com> writes:
>
>> :
>> : > > hello
>>
>> on the subsequent runs.
>>
>> Better than the new version but still wrong. :)
>
> And this is what drove me crazy during debugging. I do not understand
> the logic of all that ob-comint code.
>
> I have identified that the hang happens because Org does not change PS2
> prompt. Just PS1. But fixing this would yield to
>
> : org_babel_sh_prompt> org_babel_sh_prompt> hello
>
> Then, I tried to see how the original code works. And it does not
> :facepalm:
>
> I asked emacs-devel
> https://yhetil.org/emacs-devel/87y1tgqhmc.fsf@localhost/T/#u

See the attached tentative patch.
I'd appreciate some testing. Hopefully, I did not break anything.
Comint is tricky.


[-- Attachment #2: 0001-ob-shell-Fix-multi-line-scripts-in-sessions.patch --]
[-- Type: text/x-patch, Size: 4766 bytes --]

From 4c6eead351cbdce1b9210a738c65b3a139d1cc0c Mon Sep 17 00:00:00 2001
Message-Id: <4c6eead351cbdce1b9210a738c65b3a139d1cc0c.1666330028.git.yantar92@posteo.net>
From: Ihor Radchenko <yantar92@posteo.net>
Date: Fri, 21 Oct 2022 13:21:57 +0800
Subject: [PATCH] ob-shell: Fix multi-line scripts in sessions
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* lisp/ob-comint.el (org-babel-comint-with-output): Cleanup empty
output.  Such output is spitted unnecessarily for multi-line scripts.
* lisp/ob-shell.el (org-babel-shell-set-prompt-commands): Disable
PS2 and equivalent prompts.  Make sure that PROMPT_COMMAND does not
interfere with PS1 setting in POSIX shells.
(org-babel-sh-evaluate): Do not send input line-by-line.  Instead, let
`org-babel-coming-with-output' handle waiting for the output as well
as recording it.  Update to the new `org-babel-coming-with-output'
behavior of cleaning empty outputs.
* testing/lisp/test-ob-shell.el (test-ob-shell/session): Add test.

Reported-by: Rudolf Adamkovič <salutis@me.com>
Link: https://list.orgmode.org/orgmode/m2r0zboix1.fsf@me.com/
---
 lisp/ob-comint.el             |  2 +-
 lisp/ob-shell.el              | 29 ++++++++++++++---------------
 testing/lisp/test-ob-shell.el |  6 +++++-
 3 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/lisp/ob-comint.el b/lisp/ob-comint.el
index 36a55d36c..ec7d3f6c9 100644
--- a/lisp/ob-comint.el
+++ b/lisp/ob-comint.el
@@ -109,7 +109,7 @@ (defmacro org-babel-comint-with-output (meta &rest body)
 		      "\n" "[\r\n]+" (regexp-quote (or ,full-body "")))
 		     string-buffer))
 	   (setq string-buffer (substring string-buffer (match-end 0))))
-	 (split-string string-buffer comint-prompt-regexp)))))
+         (delete "" (split-string string-buffer comint-prompt-regexp))))))
 
 (defun org-babel-comint-input-command (buffer cmd)
   "Pass CMD to BUFFER.
diff --git a/lisp/ob-shell.el b/lisp/ob-shell.el
index 4d579ae87..d38d2d335 100644
--- a/lisp/ob-shell.el
+++ b/lisp/ob-shell.el
@@ -47,10 +47,15 @@ (defvar org-babel-default-header-args:shell '())
 (defvar org-babel-shell-names)
 
 (defconst org-babel-shell-set-prompt-commands
-  '(("fish" . "function fish_prompt\n\techo \"%s\"\nend")
-    ("csh" . "set prompt=\"%s\"")
+  '(;; Fish has no PS2 equivalent.
+    ("fish" . "function fish_prompt\n\techo \"%s\"\nend")
+    ;; prompt2 is like PS2 in POSIX shells.
+    ("csh" . "set prompt=\"%s\"\nset prompt2=\"\"")
+    ;; PowerShell, similar to fish, does not have PS2 equivalent.
     ("posh" . "function prompt { \"%s\" }")
-    (t . "PS1=\"%s\""))
+    ;; PROMPT_COMMAND can override PS1 settings.  Disable it.
+    ;; Disable PS2 to avoid garbage in multi-line inputs.
+    (t . "PROMPT_COMMAND=;PS1=\"%s\";PS2="))
   "Alist assigning shells with their prompt setting command.
 
 Each element of the alist associates a shell type from
@@ -299,20 +304,14 @@ (defun org-babel-sh-evaluate (session body &optional params stdin cmdline)
 	     #'org-babel-sh-strip-weird-long-prompt
 	     (mapcar
 	      #'org-trim
-	      (butlast
+	      (butlast ; Remove eoe indicator
 	       (org-babel-comint-with-output
 		   (session org-babel-sh-eoe-output t body)
-		 (dolist (line (append (split-string (org-trim body) "\n")
-				       (list org-babel-sh-eoe-indicator)))
-		   (insert line)
-		   (comint-send-input nil t)
-		   (while (save-excursion
-			    (goto-char comint-last-input-end)
-			    (not (re-search-forward
-				  comint-prompt-regexp nil t)))
-		     (accept-process-output
-		      (get-buffer-process (current-buffer))))))
-	       2))
+                 (insert (org-trim body) "\n"
+                         org-babel-sh-eoe-indicator)
+		 (comint-send-input nil t))
+               ;; Remove `org-babel-sh-eoe-indicator' output line.
+	       1))
 	     "\n"))
 	   ;; External shell script, with or without a predefined
 	   ;; shebang.
diff --git a/testing/lisp/test-ob-shell.el b/testing/lisp/test-ob-shell.el
index a0d5a8d22..05c369174 100644
--- a/testing/lisp/test-ob-shell.el
+++ b/testing/lisp/test-ob-shell.el
@@ -46,7 +46,11 @@ (ert-deftest test-ob-shell/session ()
 ob-comint.el, which was not previously tested."
   (let ((res (org-babel-execute:sh "echo 1; echo 2" '((:session . "yes")))))
     (should res)
-    (should (listp res))))
+    (should (listp res)))
+  ;; Test multi-line input.
+  (let ((res (org-babel-execute:sh "if true; then\necho \"yes\"\nfi" '((:session . "yes")))))
+    (should res)
+    (should (string= "yes" res))))
 
 ; A list of tests using the samples in ob-shell-test.org
 (ert-deftest ob-shell/generic-uses-no-arrays ()
-- 
2.35.1


[-- Attachment #3: Type: text/plain, Size: 225 bytes --]



-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>

^ permalink raw reply related	[relevance 6%]

* Evaluate, execute, oh my!
@ 2022-11-17 22:18  6% Rudolf Adamkovič
  0 siblings, 0 replies; 20+ results
From: Rudolf Adamkovič @ 2022-11-17 22:18 UTC (permalink / raw)
  To: emacs-orgmode

From the "Headings and Headlines" thread:

> P.S. We should also harmonize `evaluate' and `execute'; I can never
> tell which one to look for when completing.

Based on my experience, normally, we "evaluate" expressions for their
results and we "execute" statements for their effects.  That said, in
Emacs Lisp, one "evaluates" a buffer, even if for side effects.

Below, I include the completions I see in my Emacs.

Functions "org" + "eval":

- ob-session-async-org-babel-R-evaluate-session
- org-agenda-skip-eval
- org-babel-R-evaluate
- org-babel-R-evaluate-external-process
- org-babel-R-evaluate-session
- org-babel-check-confirm-evaluate
- org-babel-check-evaluate
- org-babel-comint-async-delete-dangling-and-eval
- org-babel-comint-eval-invisibly-and-wait-for-file
- org-babel-confirm-evaluate
- org-babel-eval
- org-babel-eval-error-notify
- org-babel-eval-headers
- org-babel-eval-read-file
- org-babel-eval-wipe-error-buffer
- org-babel-groovy-evaluate
- org-babel-java--expand-for-evaluation
- org-babel-java-evaluate
- org-babel-julia-evaluate
- org-babel-julia-evaluate-external-process
- org-babel-julia-evaluate-session
- org-babel-lua-evaluate
- org-babel-lua-evaluate-external-process
- org-babel-lua-evaluate-session
- org-babel-octave-evaluate
- org-babel-octave-evaluate-external-process
- org-babel-octave-evaluate-session
- org-babel-perl-evaluate
- org-babel-python-async-evaluate-session
- org-babel-python-evaluate
- org-babel-python-evaluate-external-process
- org-babel-python-evaluate-session
- org-babel-ruby-evaluate
- org-babel-sh-evaluate
- org-eval
- org-eval-in-calendar
- org-eval-in-environment
- org-evaluate-time-range
- org-list--generic-eval
- org-table-eval-formula
- org-table-maybe-eval-formula

Variables "org" + "eval":

- org-babel-lisp-eval-fn
- org-babel-no-eval-on-ctrl-c-ctrl-c
- org-confirm-babel-evaluate
- org-export-babel-evaluate
- org-table-formula-evaluate-inline

Functions "org" + "exec":

- org-agenda-execute
- org-agenda-execute-calendar-command
- org-babel-C-execute
- org-babel-execute-buffer
- org-babel-execute-maybe
- org-babel-execute-safely-maybe
- org-babel-execute-src-block
- org-babel-execute-src-block-maybe
- org-babel-execute-subtree
- org-babel-execute:C
- org-babel-execute:C++
- org-babel-execute:D
- org-babel-execute:R
- org-babel-execute:ash
- org-babel-execute:awk
- org-babel-execute:bash
- org-babel-execute:calc
- org-babel-execute:clojure
- org-babel-execute:clojurescript
- org-babel-execute:cpp
- org-babel-execute:csh
- org-babel-execute:css
- org-babel-execute:dash
- org-babel-execute:ditaa
- org-babel-execute:dot
- org-babel-execute:elisp
- org-babel-execute:emacs-lisp
- org-babel-execute:eshell
- org-babel-execute:fish
- org-babel-execute:forth
- org-babel-execute:fortran
- org-babel-execute:gnuplot
- org-babel-execute:groovy
- org-babel-execute:haskell
- org-babel-execute:java
- org-babel-execute:js
- org-babel-execute:julia
- org-babel-execute:ksh
- org-babel-execute:latex
- org-babel-execute:lilypond
- org-babel-execute:lisp
- org-babel-execute:lua
- org-babel-execute:makefile
- org-babel-execute:matlab
- org-babel-execute:maxima
- org-babel-execute:mksh
- org-babel-execute:ocaml
- org-babel-execute:octave
- org-babel-execute:org
- org-babel-execute:perl
- org-babel-execute:plantuml
- org-babel-execute:posh
- org-babel-execute:processing
- org-babel-execute:python
- org-babel-execute:ruby
- org-babel-execute:sass
- org-babel-execute:scheme
- org-babel-execute:screen
- org-babel-execute:sed
- org-babel-execute:sh
- org-babel-execute:shell
- org-babel-execute:sql
- org-babel-execute:sqlite
- org-babel-execute:zsh
- org-babel-forth-session-execute
- org-babel-haskell-execute
- org-babel-lilypond-execute-tangled-ly
- org-babel-lob-execute-maybe
- org-babel-map-executables
- org-babel-scheme-execute-with-geiser
- org-babel-screen-session-execute-string
- org-execute-file-search-in-bibtex

Variables "org" + "exec":

- org-babel-after-execute-hook
- org-babel-python--exec-tmpfile
- org-execute-file-search-functions
- org-plantuml-exec-mode
- org-plantuml-executable-args
- org-plantuml-executable-path

Rudy
-- 
"Mathematics takes us still further from what is human into the region
of absolute necessity, to which not only the actual world, but every
possible world, must conform."
-- Bertrand Russell, 1902

Rudolf Adamkovič <salutis@me.com> [he/him]
Studenohorská 25
84103 Bratislava
Slovakia


^ permalink raw reply	[relevance 6%]

* Re: [PATCH] lisp/ob-screen.el: Support ~:var~ header args for babel blocks
  @ 2023-02-27  1:59  9%             ` Ken Mankoff
  2023-02-27 19:43  0%               ` Ihor Radchenko
  0 siblings, 1 reply; 20+ results
From: Ken Mankoff @ 2023-02-27  1:59 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Max Nikulin, emacs-orgmode

Hi Ihor,

On 2023-02-26 at 04:18 -08, Ihor Radchenko <yantar92@posteo.net> wrote:
>> +;; Reuse the variable assignment code from ob-shell
>> +(defalias 'org-babel-variable-assignments:screen
>> +  'org-babel-variable-assignments:shell)
>
> This will work, but you are relying on implementation detail of
> ob-shell.el. A more safe approach would be calling
> org-babel-variable-assignments:LANG depending on the :cmd header arg.
> For :cmd bash - org-babel-variable-assignments:bash, for :cmd fish -
> org-babel-variable-assignments:fish.
>
> To archive this, you can define a full
> org-babel-variable-assignments:screen function that does what I
> described.

You're pushing my lisp skills here. Which is fine, but I might need some help.

In ob-shell I see

(defcustom org-babel-shell-names
  '("sh" "bash" "zsh" "fish" "csh" "ash" "dash" "ksh" "mksh" "posh")

Should I create a function that, using case statement or something similar, checks for each of these and calls that flavor? I think I could do that.


But if I also see org-babel-shell-initialize in ob-shell that looks like it creates defaliases for each of these to (org-babel-execute:shell) and #'org-babel-variable-assignments:shell.

I'm not sure how that is very different from what I've done. I'm not sure what to do here, nor how to do what you suggest (yet - I've only read it so far, not spent a lot of time experimenting and searching, so I may be able to implement what I think is a solution to what you wrote, but I doubt it'll be what you expect).

  -k.


^ permalink raw reply	[relevance 9%]

* Re: [PATCH] lisp/ob-screen.el: Support ~:var~ header args for babel blocks
  2023-02-27  1:59  9%             ` Ken Mankoff
@ 2023-02-27 19:43  0%               ` Ihor Radchenko
  0 siblings, 0 replies; 20+ results
From: Ihor Radchenko @ 2023-02-27 19:43 UTC (permalink / raw)
  To: Ken Mankoff; +Cc: Max Nikulin, emacs-orgmode

Ken Mankoff <mankoff@gmail.com> writes:

>> To archive this, you can define a full
>> org-babel-variable-assignments:screen function that does what I
>> described.
>
> You're pushing my lisp skills here. Which is fine, but I might need some help.
>
> In ob-shell I see
>
> (defcustom org-babel-shell-names
>   '("sh" "bash" "zsh" "fish" "csh" "ash" "dash" "ksh" "mksh" "posh")
>
> Should I create a function that, using case statement or something similar, checks for each of these and calls that flavor? I think I could do that.

Not each of these. AFAIU, :cmd header property in ob-screen defines
which shell to use. Knowing shell name, you can deduce the function name
to be used for variable assignments. See how it is done in
`org-babel-expand-src-block'.

> But if I also see org-babel-shell-initialize in ob-shell that looks like it creates defaliases for each of these to (org-babel-execute:shell) and #'org-babel-variable-assignments:shell.

The convention is for every possible #+begin_src lang to have
org-babel-variable-assignments:LANG.
ob-shell just tries to avoid unnecessary code duplication and instead of
writing identical org-babel-variable-assignments:sh
org-babel-variable-assignments:bash, org-babel-variables-assignents:zsh,
..., it generates them using a macro.

> I'm not sure how that is very different from what I've done. I'm not sure what to do here, nor how to do what you suggest (yet - I've only read it so far, not spent a lot of time experimenting and searching, so I may be able to implement what I think is a solution to what you wrote, but I doubt it'll be what you expect).

AFAIU, you don't need to juggle with macros as ob-shell does. Something
similar to `org-babel-expand-src-block' will do.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[relevance 0%]

* Re: [SUGGESTION] ob-shell async result output should not contains shell prompt
  @ 2023-03-23 11:12 11%           ` Christopher M. Miles
  0 siblings, 0 replies; 20+ results
From: Christopher M. Miles @ 2023-03-23 11:12 UTC (permalink / raw)
  To: Matt; +Cc: numbchild, Ihor Radchenko, emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 3574 bytes --]


Matt <matt@excalamus.com> writes:

>  ---- On Wed, 22 Mar 2023 23:25:50 -0400  Christopher M. Miles  wrote --- 
>  > 
>  > The ob-shell async result output contains the shell prompt. I think it
>  > should not be captured.
>  > 
>  > #+begin_src shell :session "test2" :async t
>  > sleep 30
>  > echo "hello, world"
>  > #+end_src
>  > 
>  > #+RESULTS[(2023-03-23 11:19:22) 461ed5de684f6e619890709175ec73e80b67b2d6]:
>  > : bash-5.2$ hello, world
>
> Thanks for reporting this.
>
> Try using for the babel language whatever shell the variable `shell-file-name' gives.  For example, if `shell-file-name' is /bin/bash, do this:
>
> #+begin_src bash :session "test2" :async t
> sleep 1
> echo "hello, world"
> #+end_src
>
> Is there a reason you're using "shell" instead of one of the shells listed in `org-babel-shell-names'?

Using language identities like bellowing:

#+begin_src sh :session "*ob-shell*" :async t
sleep 30
echo "hello, world"
#+end_src

#+RESULTS[(2023-03-23 19:14:12) dd777a237986481833c08eb5eceac717576eddb7]:
: org_babel_sh_prompt> hello, world

#+begin_src bash :session "*ob-shell-bash*" :async t
sleep 30
echo "hello, world"
#+end_src

#+RESULTS[(2023-03-23 19:14:15) 23f9ad130f7a1268e21821c6baaea2b057c70d3e]:
: org_babel_sh_prompt> hello, world

#+begin_src zsh :session "*ob-shell-zsh*" :async t
sleep 30
echo "hello, world"
#+end_src

#+RESULTS[(2023-03-23 19:14:17) 2bb44d96c2e482a90c5a89bdde0b64d0319663a1]:
: %                                                                                                                                                                      
:  
: %                                                                                                                                                                      
:  
: hello, world
: %                                                                                                                                                                      
:  

Still got a prompt. Is this intended? I think the output should be kept clean because the result
output might be used as input for other source blocks as data.

Maybe error in my Org babel settings? Bellowing is my system and variable values:

#+begin_src emacs-lisp
system-type
#+end_src

#+RESULTS[(2023-03-23 19:27:13) 7df8395169a77d83cb6a5a6efc2223d412813efa]:
: darwin

#+begin_src emacs-lisp
shell-file-name
#+end_src

#+RESULTS[(2023-03-23 19:26:33) e6fed18a9a543dd6320385ee715d9ee68b464a04]:
: /opt/homebrew/bin/bash

#+begin_src emacs-lisp
org-babel-sh-prompt
#+end_src

#+RESULTS[(2023-03-23 19:30:12) f6efc29dba5be2171eba0a25abec19908fb1c6be]:
: org_babel_sh_prompt> 

#+begin_src emacs-lisp
org-babel-shell-names
#+end_src

#+RESULTS[(2023-03-23 19:27:27) 360d6d35db3eb48deb664349eed34b7541923ca2]:
| sh | bash | zsh | fish | csh | ash | dash | ksh | mksh | posh |

#+begin_src emacs-lisp :results pp
org-babel-shell-set-prompt-commands
#+end_src

#+RESULTS[(2023-03-23 19:27:44) 910fbbafc6fea4a1846f5a31f8b7dd102eca4928]:
: (("fish" . "function fish_prompt\n	echo \"%s\"\nend")
:  ("csh" . "set prompt=\"%s\"\nset prompt2=\"\"")
:  ("posh" . "function prompt { \"%s\" }")
:  (t . "PROMPT_COMMAND=;PS1=\"%s\";PS2="))

-- 

[ stardiviner ]
I try to make every word tell the meaning that I want to express without misunderstanding.

Blog: https://stardiviner.github.io/
IRC(libera.chat, freenode): stardiviner, Matrix: stardiviner
GPG: F09F650D7D674819892591401B5DF1C95AE89AC3

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]

^ permalink raw reply	[relevance 11%]

* [BUG] No font lock in src blocks for shells in org-babel-shell-names (was Re: Font lock for org-babel shell scripts?)
  @ 2023-03-28 21:53 12% ` Matt
    0 siblings, 1 reply; 20+ results
From: Matt @ 2023-03-28 21:53 UTC (permalink / raw)
  To: Derek Chen-Becker; +Cc: Emacs-orgmode

Of the shells given in `org-babel-shell-names' (that is, "sh" "bash" "zsh" "fish" "csh" "ash" "dash" "ksh" "mksh" "posh"), only "sh" and "bash" have font locking in source blocks.

For example,

#+begin_src sh
  if [ -z $TEST ]; then
      echo Fontified
  fi
#+end_src

#+begin_src bash
  if [ -z $TEST ]; then
      echo Fontified
  fi
#+end_src

#+begin_src zsh
  if [ -z $TEST ]; then
      echo No fontification
  fi
#+end_src

#+begin_src fish
  if [ -z $TEST ]; then
     echo No fontification
  fi
#+end_src

#+begin_src csh
  if [ -z $TEST ]; then
      echo No fontification
  fi
#+end_src

#+begin_src ash
  if [ -z $TEST ]; then
      echo No fontification
  fi
#+end_src

#+begin_src dash
  if [ -z $TEST ]; then
      echo No fontification
  fi
#+end_src

#+begin_src ksh
  if [ -z $TEST ]; then
      echo No fontification
  fi
#+end_src

#+begin_src mksh
  if [ -z $TEST ]; then
      echo No fontification
  fi
#+end_src

#+begin_src posh
  if [ -z $TEST ]; then
      echo No fontification
  fi
#+end_src

 Does anyone know which function is responsible for re-fontifing source blocks?


^ permalink raw reply	[relevance 12%]

* Re: [BUG] No font lock in src blocks for shells in org-babel-shell-names (was Re: Font lock for org-babel shell scripts?)
  @ 2023-03-30  8:56 10%         ` Ihor Radchenko
  2023-03-30 23:10  0%           ` Derek Chen-Becker
  2023-04-01 23:21 10%           ` Matt
  0 siblings, 2 replies; 20+ results
From: Ihor Radchenko @ 2023-03-30  8:56 UTC (permalink / raw)
  To: Matt; +Cc: Derek Chen-Becker, Emacs-orgmode

Matt <matt@excalamus.com> writes:

> I think this approach will work fine.   I tried examples for each shell type and keywords like if/then/else and function names are highlighted.

Even for posh (powershell)?

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[relevance 10%]

* Re: [BUG] No font lock in src blocks for shells in org-babel-shell-names (was Re: Font lock for org-babel shell scripts?)
  2023-03-30  8:56 10%         ` Ihor Radchenko
@ 2023-03-30 23:10  0%           ` Derek Chen-Becker
  2023-04-01 23:21 10%           ` Matt
  1 sibling, 0 replies; 20+ results
From: Derek Chen-Becker @ 2023-03-30 23:10 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Matt, Emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1172 bytes --]

Would it be fair to use the sh-ancestor-alist as a basis for all of the
supported shell variants?

https://github.com/emacs-mirror/emacs/blob/master/lisp/progmodes/sh-script.el#L177

Cheers,

Derek

On Thu, Mar 30, 2023 at 2:54 AM Ihor Radchenko <yantar92@posteo.net> wrote:

> Matt <matt@excalamus.com> writes:
>
> > I think this approach will work fine.   I tried examples for each shell
> type and keywords like if/then/else and function names are highlighted.
>
> Even for posh (powershell)?
>
> --
> Ihor Radchenko // yantar92,
> Org mode contributor,
> Learn more about Org mode at <https://orgmode.org/>.
> Support Org development at <https://liberapay.com/org-mode>,
> or support my work at <https://liberapay.com/yantar92>
>


-- 
+---------------------------------------------------------------+
| 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  |
+---------------------------------------------------------------+

[-- Attachment #2: Type: text/html, Size: 3327 bytes --]

^ permalink raw reply	[relevance 0%]

* Re: [BUG] No font lock in src blocks for shells in org-babel-shell-names (was Re: Font lock for org-babel shell scripts?)
  2023-03-30  8:56 10%         ` Ihor Radchenko
  2023-03-30 23:10  0%           ` Derek Chen-Becker
@ 2023-04-01 23:21 10%           ` Matt
  2023-04-03 17:42  0%             ` Derek Chen-Becker
  1 sibling, 1 reply; 20+ results
From: Matt @ 2023-04-01 23:21 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: Derek Chen-Becker, Emacs-orgmode


 ---- On Thu, 30 Mar 2023 04:55:32 -0400  Ihor Radchenko  wrote --- 
 > Matt matt@excalamus.com> writes:
 > 
 > > I think this approach will work fine.   I tried examples for each shell type and keywords like if/then/else and function names are highlighted.
 > 
 > Even for posh (powershell)?

Yes.  It's not great since sh-mode looks for Korn-based keywords.  It does string highlighting and common keywords like 'if', 'exit', and 'param'.



^ permalink raw reply	[relevance 10%]

* Re: [BUG] No font lock in src blocks for shells in org-babel-shell-names (was Re: Font lock for org-babel shell scripts?)
  2023-04-01 23:21 10%           ` Matt
@ 2023-04-03 17:42  0%             ` Derek Chen-Becker
  0 siblings, 0 replies; 20+ results
From: Derek Chen-Becker @ 2023-04-03 17:42 UTC (permalink / raw)
  To: Matt; +Cc: Ihor Radchenko, Emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1719 bytes --]

I fiddled around a little bit this weekend and confirmed that this (sloppy)
code makes highlighting work for all shell types that sh-script supports:

;;A quick hack to try and support more shells syntax highlight in org babel
(require 'sh-script)
(require 'ob-shell)
(let ((shells (seq-filter (lambda (shell) (not (eq shell 'sh)))
(flatten-tree sh-ancestor-alist))))
  (let ((toAppend (mapcar (lambda (shell) `(,(symbol-name shell) . sh))
shells)))
    (setq org-src-lang-modes (-distinct (append toAppend
org-src-lang-modes)))))

I'm a relative newcomer to elisp, so comments and suggestions are welcome.
This is basically what I meant by "dynamically amend org-src-lang-modes
based on the contents of sh-ancestor-alist".

Thanks,

Derek

On Sat, Apr 1, 2023 at 5:22 PM Matt <matt@excalamus.com> wrote:

>
>  ---- On Thu, 30 Mar 2023 04:55:32 -0400  Ihor Radchenko  wrote ---
>  > Matt matt@excalamus.com> writes:
>  >
>  > > I think this approach will work fine.   I tried examples for each
> shell type and keywords like if/then/else and function names are
> highlighted.
>  >
>  > Even for posh (powershell)?
>
> Yes.  It's not great since sh-mode looks for Korn-based keywords.  It does
> string highlighting and common keywords like 'if', 'exit', and 'param'.
>
>

-- 
+---------------------------------------------------------------+
| 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  |
+---------------------------------------------------------------+

[-- Attachment #2: Type: text/html, Size: 3793 bytes --]

^ permalink raw reply	[relevance 0%]

* Re: bash source code block: problem after ssh commands
  @ 2023-11-22 17:06  9%                                           ` Max Nikulin
  0 siblings, 0 replies; 20+ results
From: Max Nikulin @ 2023-11-22 17:06 UTC (permalink / raw)
  To: emacs-orgmode

On 22/11/2023 02:01, Bruno Barbier wrote:
> Ihor Radchenko writes:
>> __By default__, Org should produce more expected behavior - what users
>> would get from running a script file rather than from redirecting stdin.
>> We can optionally leave the stdin redirection as an option to be used by
>> the users who understand the peculiarities.
> 
> I agree that it would be simpler to switch to the script-like behavior
> by default on org side.  About the interactive-like behavior, that
> would be nice to keep it, if some people rely on it in their existing
> documents (I personally don't).

I do not like recommendations

     curl https://... | sudo bash

but I regularly see them. So some users might expect behavior like 
namely stdin, not like interactive prompt commands.

Perhaps even sessions may be switched to creation of a temporary file 
and executing "source tmpfile.sh". However it may be shell-specific (posh?).

Likely it is possible to implement a header argument to explicitly 
control whether `process-file' should be used or the block should be 
executed as a temporary script file. Currently it is implicitly 
determined from other header arguments.

P.S.

https://mywiki.wooledge.org/BashFAQ/089
"I'm reading a file line by line and running ssh or ffmpeg, only the 
first line gets processed!"

A similar case, but only data is read from stdin, script is a regular 
file, no difference bash vs. dash.



^ permalink raw reply	[relevance 9%]

* ob-shell:  proposal to remove "posh"
@ 2024-01-11 20:30 20% Matt
  2024-01-12 10:04 12% ` Morgan Willcock
                   ` (2 more replies)
  0 siblings, 3 replies; 20+ results
From: Matt @ 2024-01-11 20:30 UTC (permalink / raw)
  To: emacs-orgmode

Hi,

I would like people's thoughts on removing the "posh" language header.

ob-shell.el supports a "posh" shell.  What is "posh?"

* Posh is not PowerShell
"posh" was added to =ob-shell= in fb09863f with no commit message on December 13, 2013 (Friday the 13th!).
https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=fb09863fbb35bf15bcf78262b6e31b8b8b8617e7

A mail message the same day says,

> Eric Schulte writes:
> >> How about the following resolution?  We rename ob-sh.el to ob-shell.el.
> >> New "shell" code blocks could use the value of the
> >> `org-babel-sh-command' environment variable.  Then sh, bash, zsh, csh,
> >> ash, dash (am I missing any other common ones) use the specific shell
> >> specified.
>
> I've also seen ksh, mksh, posh (the latter specifically for POSIX
> compatibility checks).
https://list.orgmode.org/878uvychr1.fsf@pinto.chemeng.ucl.ac.uk/T/#mc20039f988519d409294dc604b5e0dc0f439307b

There was discussion about different shells, Eric asked for others, "posh" was mentioned as "specially for POSIX compatibility checks", and then a "posh" was added to ob-shell.el by Eric (fb09863f).
https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=fb09863fbb35bf15bcf78262b6e31b8b8b8617e7

Around that time are a few stack exchange answers suggesting to use posh, the "Policy-compliant Ordinary SHell", to test for posix compliance.  Debian distributed it by saying, "using posh as your /bin/sh may reveal breakage."  It seems that posh was used to check for POSIX compliance.  It's still available on Debian.
https://unix.stackexchange.com/questions/48786/how-can-i-test-for-posix-compliance-of-shell-scripts
https://web.archive.org/web/20130930231522/https://packages.debian.org/sid/posh
https://packages.debian.org/sid/posh

Wikipedia claims PowerShell is based on POSIX.  However, it's not clear if it's "POSIX compliant" (and, if it were, I would be shocked if someone seriously suggested using it for POSIX compatibility checks).
https://en.wikipedia.org/wiki/PowerShell#Grammar

Checking the Microsoft documentation, I find no mention of "posh."  PowerShell 7 introduced a "pwsh.exe" binary.  However, the same page has a reference for Windows PowerShell 5.1, corresponding to "powershell.exe".  This is also corroborated by Wikipedia which says "PowerShell 7 is the replacement for PowerShell Core 6.x products as well as Windows PowerShell 5.1, which is the last supported Windows PowerShell version."  "posh" was added to =ob-shell= on December 13, 2013.  This would correspond to Powershell 3 or 4 which, AFAIU, both have the binary "powershell.exe."
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_pwsh?view=powershell-7.4
https://en.wikipedia.org/wiki/PowerShell#PowerShell_7

It's possible that Eric meant to add PowerShell and abbreviated it to "posh."  However, it appears much more likely that it refers to the "Policy-compliant Ordinary SHell." (https://salsa.debian.org/clint/posh)

* Now what?
So, if we're agreed that "posh" is not PowerShell, what should we do about this?

I propose dropping "posh" from =org-babel-shell-names= and removing it from =org-babel-shell-set-prompt-commands=.  That is, let's not explicitly support the "Policy-compliant Ordinary SHell" or PowerShell.

We never supported PowerShell intentionally and only came to it by accident.  I don't think anyone has used the "Policy-compliant Ordinary SHell" in at least 2 years.  Die-hard adherents to either can still use them, even if we removed the "posh" language header.

** We didn't begin "supporting" PowerShell intentionally (AFAICT)
Up to 2020 and through most of 2022, Powershell wasn't considered supported.
https://list.orgmode.org/87pn707jdz.fsf@gnu.org/T/#u

August 26, 2022 changed that with commit a35d1636.  When =org-babel-shell-set-prompt-commands= was added to set the shell prompt, PowerShell syntax was included for completeness because people thought "posh" was PowerShell.  AFAIK, no one explicitly asked for PowerShell support as an end-user (then or after).  The inclusion of PowerShell appears based on the misunderstanding of "posh" as PowerShell.  Since then, the handful of list messages mentioning PowerShell assume it's supported.  That "support" is all based on commit a35d1636.
https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=a35d163685908386833a3d549ed110931bf3915a
https://list.orgmode.org/?q=d%3A17%2FJune%2F2022..+AND+powershell
https://list.orgmode.org/?q=d%3A17%2FJune%2F2022..+AND+posh

AFAICT, PowerShell is mainly (only?) used for tests by people on the mailing list to check that ob-shell can run them.  Occasionally, (once every few years) someone specifically asks about it or comments on how it's not (well) supported.  Only after commit a35d1636 did people begin saying that PowerShell is supported.  People do use PowerShell.  However, there are only 36 hits for it on the list in (since Babel was made in 2009) and only a handful of side comments since the change.

** No one uses the "Policy-compliant Ordinary SHell"
The change on August 26, 2022 should have caused a breaking error for someone using the "Policy-compliant Ordinary SHell."  The prompt for "posh" in "org-babel-shell-set-prompt-commands" is valid PowerShell syntax (AFAIKT) and invalid bash/dash syntax:

function prompt { "org_babel_sh_prompt> " }

It's not clear to me what this would do in the "Policy-compliant Ordinary SHell."  In Bash, functions are defined using a form like:

function fname [()] compound-command [ redirections ]

It says, "Note that for historical reasons, in the most common usage the curly braces that surround the body of the function must be separated from the body by blanks or newlines. This is because the braces are reserved words and are only recognized as such when they are separated from the command list by whitespace or another shell metacharacter. Also, when using the braces, the list must be terminated by a semicolon, a ‘&’, or a newline."
https://www.gnu.org/software/bash/manual/bash.html#Shell-Functions

So, for 'bash --posix', the syntax is invalid.  Dash simply errors out with "dash: 1: function: not found".  Whatever it does on a POSIX-y shell, it's a show-stopper.

I don't have "posh" available, but I've run the following using dash and bash.  It causes Emacs to hang until you hit C-g.  Maybe the "Policy-compliant Ordinary SHell" is different and the command works?  Since it fails for 'bash --posix' and dash, I doubt it.  Here's what I ran:

(org-babel-do-load-languages 'org-babel-load-languages '((shell . t)))

(defconst org-babel-shell-set-prompt-commands
  '((t . "function prompt { \"%s\" }")))

#+begin_src dash :session *dash*
  echo "hi"
#+end_src

Canceling and switching to the shell that was created, the prompt is "> " (the PS2 prompt).  This swallows all input that's not an error.  =org-babel-execute:shell= calls =org-babel-sh-initiate-session= which calls =org-babel-comint-wait-for-output= which waits for the =comint-prompt-regexp= which is "org_babel_sh_prompt> ", not "> ", so Emacs hangs.

There have been no complaints from "Policy-compliant Ordinary SHell" users after August 26, 2022 about "posh" being broken.  The talk of "posh" (and PowerShell, specifically) since August 26, 2022 is often as an aside.

I conclude that no one uses (or at least cares much about using) the "Policy-compliant Ordinary SHell."

** Both the "Policy-compliant Ordinary SHell" and PowerShell are usable without "posh"
Since the "Policy-compliant Ordinary SHell" is POSIX, it should be straight-forward to use with the "shell" language by replacing "shell-file-name."  The "shell" language header will hit the default prompt command which is general POSIX syntax (that is, it changes PS1 and PS2).  A shebang should also work.

I had access to a Windows 10 machine recently and verified the following makes PowerShell "work".  I use quotes because the following outputs a banner and often fails to remove the prompt, just like the current "posh" behavior.

(org-babel-do-load-languages 'org-babel-load-languages '((shell . t)))

;;; Setup for non-sessions
(setq shell-file-name "C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe")

#+begin_src shell :results output
echo "hello"
#+end_src

;;; Setup for sessions
;; required by `shell.el' in `shell' command
(setq explicit-shell-file-name
      "C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe")
(setq explicit-powershell.exe-args '("-NoExit"))

;; required by `ob-shell.el' in Org 9.6.6 (distributed with Emacs
;; 29.1 which is the latest build of Emacs for Windows)
(setq org-babel-prompt-command "function prompt { \"org_babel_sh_prompt> \" }")

#+begin_src shell :results output :session *powershell*
echo "world"
#+end_src

* My stance
The unfortunate reality is we "support" PowerShell currently.  We have code explicitly to handle PowerShell.  Changing that could, technically, break someone's workflow.

Here's how I reason it:

First, AFAIK no PowerShell user would refer to it as "posh".  At best they may say "pwsh" and most likely "powershell".

We could keep "posh" for the "Policy-compliant Ordinary SHell" and add languages for "pwsh" or "powershell".  This would need to be communicated PowerShell users.

I don't know what other keyword we could use for the "Policy-compliant Ordinary SHell".  We could keep "posh" for PowerShell, drop all "support" for the "Policy-compliant Ordinary SHell", and commit to PowerShell only.  This would need to be communicated to the "Policy-compliant Ordinary SHell" users.

In any case, we need to communicate our decision, in ORG-NEWS, through our mailing list communications, and definitely by updating the comment.

The cost of keeping PowerShell means maintaining it and whatever weirdo stuff comes with it.

I suggest we make the "t" in =org-babel-shell-set-prompt-commands= a catch-all for anything with PS1/PS2 (anything POSIX-y?) and remove the "posh" language header.  The "t" case should handle bash, dash, and (I suspect) the "Policy-compliant Ordinary SHell".  This has the potential to break someone using "posh" for PowerShell.  However, I see no indication of anyone seriously using it.  We've said for years we don't support it.  The only places I'm aware of saying we support PowerShell is the code comment and a few people on the mailing list.  Moreover, a "breakage" happens anyway, for either "Policy-compliant Ordinary SHell" users (as currently likely exists) or PowerShell users (if we give a new keyword).  If we're going to have to put a work-around or message out there anyway, I figure let's see about removing any semblance of supporting PowerShell until we talk it over.

Fortunately, when I wrote the Worg page, I put "the "Policy-compliant Ordinary SHell" for "posh."  So, the only place someone might think that PowerShell is supported is from the code comment or from the mailing list.

** PowerShell or cmd.exe?
I'm not claiming that people haven't wanted PowerShell support.  It's been discussed a few times on the list.  It always reduces to "it would be nice, however we lack a developer or the equipment, so sadly no."

As current ob-shell maintainer, here's how I see it:

I like the idea of supporting PowerShell.  I like the idea of supporting cmd.exe much, much more.

Both are associated with a non-free system.  Providing support (even partially) for non-free systems is good because it provides an opportunity to teach people about software freedom.

AFAIKT, both PowerShell and cmd are MIT licensed:
- https://github.com/microsoft/terminal
- https://github.com/PowerShell/PowerShell

The thought of compiling either for a GNU system is...ugh.  But maybe someone else has gotten them working?  Otherwise, it looks like Microsoft distributes a developer VM image of Windows.

All together, this means there's no *technical* barrier preventing us from running (and hence developing for) PowerShell or cmd.

It's important to note that Emacs defaults to cmdproxy.exe on Windows.  Using "shell" in Babel on Windows returns from cmd.exe (through cmdproxy.exe).  I believe it's best to support the defaults first.

Because it's the default, I've always used cmd when using Emacs on Windows.  I would personally much prefer support for cmd.exe over PowerShell.  That is, I'd be happy to work on PowerShell stuff after cmd stuff and both after cleaning up ob-shell, ob-comint, and ob-eval.

Thoughts overall?

--
Matt Trzcinski
Emacs Org maintainer (ob-shell)
Learn more about Org mode at https://orgmode.org
Support Org development at https://liberapay.com/org-mode



^ permalink raw reply	[relevance 20%]

* Re: ob-shell:  proposal to remove "posh"
  2024-01-11 20:30 20% ob-shell: proposal to remove "posh" Matt
@ 2024-01-12 10:04 12% ` Morgan Willcock
  2024-01-12 15:49 11%   ` Matt
  2024-01-13 10:43 26% ` Matt
  2024-01-13 18:02 26% ` Ihor Radchenko
  2 siblings, 1 reply; 20+ results
From: Morgan Willcock @ 2024-01-12 10:04 UTC (permalink / raw)
  To: Matt; +Cc: emacs-orgmode

Matt <matt@excalamus.com> writes:

> AFAIKT, both PowerShell and cmd are MIT licensed:
> - https://github.com/microsoft/terminal
> - https://github.com/PowerShell/PowerShell
>
> The thought of compiling either for a GNU system is...ugh.  But maybe someone else has gotten them working?  Otherwise, it looks like Microsoft distributes a developer VM image of Windows.
>
> All together, this means there's no *technical* barrier preventing us from running (and hence developing for) PowerShell or cmd.

As I understand it, the code for the cmd.exe shell is not released
anywhere.

What is in the "terminal" repository mentioned above is the code for the
console host process conhost.exe, which is the server process used to
host the shell process and present it (i.e. this is the terminal and not
the shell).

That said, I imagine Wine does contain its own implementation of
cmd.exe, although I wouldn't expect it to be 100% compatible with the
real thing.

-- 
Morgan Willcock


^ permalink raw reply	[relevance 12%]

* Re: ob-shell:  proposal to remove "posh"
  2024-01-12 10:04 12% ` Morgan Willcock
@ 2024-01-12 15:49 11%   ` Matt
  0 siblings, 0 replies; 20+ results
From: Matt @ 2024-01-12 15:49 UTC (permalink / raw)
  To: Morgan Willcock; +Cc: emacs-orgmode


 ---- On Fri, 12 Jan 2024 11:04:33 +0100  Morgan Willcock  wrote --- 

 > As I understand it, the code for the cmd.exe shell is not released
 > anywhere.

Ah, okay.  I clearly didn't search too hard for it.

 > That said, I imagine Wine does contain its own implementation of
 > cmd.exe, although I wouldn't expect it to be 100% compatible with the
 > real thing.

That's an interesting idea.  Might be a "good enough" work around.  The VM image I mentioned says, "The VM will require a minimum of 8GB of RAM and at least 70GB of disk space". XD

--
Matt Trzcinski
Emacs Org contributor (ob-shell)
Learn more about Org mode at https://orgmode.org
Support Org development at https://liberapay.com/org-mode



^ permalink raw reply	[relevance 11%]

* Re: ob-shell:  proposal to remove "posh"
  2024-01-11 20:30 20% ob-shell: proposal to remove "posh" Matt
  2024-01-12 10:04 12% ` Morgan Willcock
@ 2024-01-13 10:43 26% ` Matt
  2024-01-13 18:02 26% ` Ihor Radchenko
  2 siblings, 0 replies; 20+ results
From: Matt @ 2024-01-13 10:43 UTC (permalink / raw)
  Cc: emacs-orgmode


 ---- On Thu, 11 Jan 2024 21:30:59 +0100  Matt  wrote --- 

 > The change on August 26, 2022 should have caused a breaking error for someone using the "Policy-compliant Ordinary SHell."  The prompt for "posh" in "org-babel-shell-set-prompt-commands" is valid PowerShell syntax (AFAIKT) and invalid bash/dash syntax:
 > 
 > function prompt { "org_babel_sh_prompt> " }
 > 
 > It's not clear to me what this would do in the "Policy-compliant Ordinary SHell." 

It would cause an error.

I was able to build the "Policy-compliant Ordinary SHell" on Guix using:

#+begin_src guile
(use-modules (guix packages)
             (guix download)
             (guix build-system gnu)
             (gnu packages autotools)
             (gnu packages perl)
             ((guix licenses) #:prefix license:))

(define-public posh
  (package
    (name "posh")
    (version "0.14.1")
    (source (origin
              (method url-fetch)
              (uri (string-append
                    "https://salsa.debian.org/clint/posh/-/archive/debian/"
                    version "/posh-debian-" version ".tar.gz"))
              (sha256
               (base32
                "070xnn996cjnc5yzp5819y36sgfikkrplhri4kx5r36h1fmp641d"))))
    (native-inputs (list autoconf automake perl))
    (build-system gnu-build-system)
    (home-page "https://salsa.debian.org/clint/posh")
    (synopsis "Policy-compliant Ordinary SHell")
    (description
     "Policy-compliant Ordinary SHell
posh is a stripped-down version of pdksh that aims for compliance with
Debian's policy, and few extra features.")
    (license (list license:gpl2+))))

posh
#+end_src

The result is:

ahab@pequod /gnu/store/64wiqdp9lqjgsz0jg1v1sq2b3afincrb-posh-0.14.1/bin$ ./posh
$ function prompt { "org_babel_sh_prompt> " }
./posh: function: not found

This is expected because "function" is not a keyword in the "Policy-compliant Ordinary SHell."  According to the man page:

#+begin_quote
name () command

  Defines the function name. See Functions below. Note that redirections
  specified after a function definition are performed whenever the
  function is executed, not when the function definition is executed.

-- https://manpages.debian.org/bookworm/posh/posh.1.en.html
#+end_quote

So, yes, indeed, commit a35d1636 introduced a breaking change for the "Policy-compliant Ordinary SHell."

--
Matt Trzcinski
Emacs Org contributor (ob-shell)
Learn more about Org mode at https://orgmode.org
Support Org development at https://liberapay.com/org-mode



^ permalink raw reply	[relevance 26%]

* Re: ob-shell:  proposal to remove "posh"
  2024-01-11 20:30 20% ob-shell: proposal to remove "posh" Matt
  2024-01-12 10:04 12% ` Morgan Willcock
  2024-01-13 10:43 26% ` Matt
@ 2024-01-13 18:02 26% ` Ihor Radchenko
  2024-01-15 20:11 25%   ` Matt
  2 siblings, 1 reply; 20+ results
From: Ihor Radchenko @ 2024-01-13 18:02 UTC (permalink / raw)
  To: Matt; +Cc: emacs-orgmode

Matt <matt@excalamus.com> writes:

> There was discussion about different shells, Eric asked for others, "posh" was mentioned as "specially for POSIX compatibility checks", and then a "posh" was added to ob-shell.el by Eric (fb09863f).
> https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=fb09863fbb35bf15bcf78262b6e31b8b8b8617e7
>
> Around that time are a few stack exchange answers suggesting to use posh, the "Policy-compliant Ordinary SHell", to test for posix compliance.  Debian distributed it by saying, "using posh as your /bin/sh may reveal breakage."  It seems that posh was used to check for POSIX compliance.  It's still available on Debian.
> https://unix.stackexchange.com/questions/48786/how-can-i-test-for-posix-compliance-of-shell-scripts
> https://web.archive.org/web/20130930231522/https://packages.debian.org/sid/posh
> https://packages.debian.org/sid/posh

It is also still available on Gentoo.

> ** No one uses the "Policy-compliant Ordinary SHell"
> The change on August 26, 2022 should have caused a breaking error for someone using the "Policy-compliant Ordinary SHell."  The prompt for "posh" in "org-babel-shell-set-prompt-commands" is valid PowerShell syntax (AFAIKT) and invalid bash/dash syntax:
>
> function prompt { "org_babel_sh_prompt> " }
>
> It's not clear to me what this would do in the "Policy-compliant Ordinary SHell."  In Bash, functions are defined using a form like:
>
> function fname [()] compound-command [ redirections ]

Simply because I struggled to find what is "posh" at the time I wrote that
code. I only found some obscure page (on the web!) saying the posh might
be PowerShell.
My commit a35d16368 did not intend to introduce anything new.

It turns out that we never supported PowerShell and never announced such
support. So we do not really need to support PowerShell.

> * My stance
> The unfortunate reality is we "support" PowerShell currently.  We have code explicitly to handle PowerShell.  Changing that could, technically, break someone's workflow.

We do not. It was just my mistake trying to figure out what is "posh".
Since posh is POSIX-compliant, generic PS1/PS2 variables should work, and we
do not need a special entry in `org-babel-shell-set-prompt-commands' -
we can remove "posh" record from there.

I'd rather keep the value in `org-babel-shell-names' though. It should
do no harm.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[relevance 26%]

* Re: ob-shell:  proposal to remove "posh"
  2024-01-13 18:02 26% ` Ihor Radchenko
@ 2024-01-15 20:11 25%   ` Matt
  2024-01-15 21:16 12%     ` Ihor Radchenko
  0 siblings, 1 reply; 20+ results
From: Matt @ 2024-01-15 20:11 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-orgmode


 ---- On Sat, 13 Jan 2024 19:00:16 +0100  Ihor Radchenko  wrote --- 
 
 > Since posh is POSIX-compliant, generic PS1/PS2 variables should work, and we
 > do not need a special entry in `org-babel-shell-set-prompt-commands' -
 > we can remove "posh" record from there.
 > 
 > I'd rather keep the value in `org-babel-shell-names' though. It should
 > do no harm.

Done https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/

--
Matt Trzcinski
Emacs Org contributor (ob-shell)
Learn more about Org mode at https://orgmode.org
Support Org development at https://liberapay.com/org-mode



^ permalink raw reply	[relevance 25%]

* Re: ob-shell:  proposal to remove "posh"
  2024-01-15 20:11 25%   ` Matt
@ 2024-01-15 21:16 12%     ` Ihor Radchenko
  0 siblings, 0 replies; 20+ results
From: Ihor Radchenko @ 2024-01-15 21:16 UTC (permalink / raw)
  To: Matt; +Cc: emacs-orgmode

Matt <matt@excalamus.com> writes:

>  ---- On Sat, 13 Jan 2024 19:00:16 +0100  Ihor Radchenko  wrote --- 
>  
>  > Since posh is POSIX-compliant, generic PS1/PS2 variables should work, and we
>  > do not need a special entry in `org-babel-shell-set-prompt-commands' -
>  > we can remove "posh" record from there.
>
> Done https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/

Thanks!

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at <https://orgmode.org/>.
Support Org development at <https://liberapay.com/org-mode>,
or support my work at <https://liberapay.com/yantar92>


^ permalink raw reply	[relevance 12%]

* Re: multipage html output
  @ 2024-08-05 16:52  1%                   ` Orm Finnendahl
  0 siblings, 0 replies; 20+ results
From: Orm Finnendahl @ 2024-08-05 16:52 UTC (permalink / raw)
  To: emacs-orgmode

[-- Attachment #1: Type: text/plain, Size: 1730 bytes --]

Hi,

 attached are the patches for the multipage html export proposal. The
tgz file contains all commits after branching from the main branch to
the org-html-multipage branch (see:
https://github.com/ormf/org-mode/tree/org-html-multipage)

There are also diffs for the only changed files, ox.el, ox-html.el and
org-manual.org between 2a4fdffac163e91f6ed2055ec34cbcadf8b95dec of the
main branch and my last commit to my org-html-multipage branch.

Let me know if there are problems or you need anything. I tried to be
conformant to Org in general and hope I succeeded. Let me know what
you think.

--
Orm



Am Samstag, den 27. Juli 2024 um 19:39:36 Uhr (+0000) schrieb Ihor Radchenko:
> Orm Finnendahl <orm.finnendahl@selma.hfmdk-frankfurt.de> writes:
> 
> >  html multipage output is fully working now in the org-export
> > compliant way sketched by Ihor.
> 
> Great!
> 
> > There is a small issue with org-export-as from ox.el: On my machine
> > applying the :filter-final-output functions to the final output
> > strings delete their :output-file Text Property. Below is a commented
> > somewhat ugly fix just to show what was necessary to make it
> > work. Maybe you have a better idea about how to change it.
> 
> `org-html-final-function' strips the text properties.  You can modify
> it. Or, better, you can add an additional filter to ox-html that will
> apply the necessary text properties (to make sure that user filters that
> do no care about text properties never interfere).
> 
> -- 
> Ihor Radchenko // yantar92,
> Org mode contributor,
> Learn more about Org mode at <https://orgmode.org/>.
> Support Org development at <https://liberapay.com/org-mode>,
> or support my work at <https://liberapay.com/yantar92>
> 

[-- Attachment #2: ox-html-multipage-patches.tgz --]
[-- Type: application/gzip, Size: 51795 bytes --]

[-- Attachment #3: ox.el.patch --]
[-- Type: text/plain, Size: 17371 bytes --]

*** org-mode/lisp/ox.el	2024-08-05 17:15:57.631928954 +0200
--- org-mode-multipage/lisp/ox.el	2024-08-03 12:57:24.346459632 +0200
***************
*** 215,220 ****
--- 215,221 ----
      (:filter-latex-fragment . org-export-filter-latex-fragment-functions)
      (:filter-line-break . org-export-filter-line-break-functions)
      (:filter-link . org-export-filter-link-functions)
+     (:multipage-split . org-export-multipage-split-functions)
      (:filter-node-property . org-export-filter-node-property-functions)
      (:filter-options . org-export-filter-options-functions)
      (:filter-paragraph . org-export-filter-paragraph-functions)
***************
*** 1883,1891 ****
  INFO is a plist containing export directives."
    (let ((type (org-element-type blob)))
      ;; Return contents only for complete parse trees.
!     (if (eq type 'org-data) (lambda (_datum contents _info) contents)
!       (let ((transcoder (cdr (assq type (plist-get info :translate-alist)))))
! 	(and (functionp transcoder) transcoder)))))
  
  (defun org-export--keep-spaces (data info)
    "Non-nil, when post-blank spaces after removing DATA should be preserved.
--- 1884,1894 ----
  INFO is a plist containing export directives."
    (let ((type (org-element-type blob)))
      ;; Return contents only for complete parse trees.
!     (let ((transcoder (cdr (assq type (plist-get info :translate-alist)))))
!       (cond
!        ((functionp transcoder) transcoder)
!        ;; Use default org-data transcoder unless specified.
!        ((eq type 'org-data) #'org-export-transcode-org-data)))))
  
  (defun org-export--keep-spaces (data info)
    "Non-nil, when post-blank spaces after removing DATA should be preserved.
***************
*** 1928,1934 ****
  
  The `:filter-parse-tree' filters are not applied.
  
! Return a string."
    (or (gethash data (plist-get info :exported-data))
        ;; Handle broken links according to
        ;; `org-export-with-broken-links'.
--- 1931,1937 ----
  
  The `:filter-parse-tree' filters are not applied.
  
! Return a string or a list of strings."
    (or (gethash data (plist-get info :exported-data))
        ;; Handle broken links according to
        ;; `org-export-with-broken-links'.
***************
*** 2194,2199 ****
--- 2197,2205 ----
  as a plist.  It must return a string that will be used as the
  final export output.")
  
+ (defvar org-export-multipage-split-functions nil
+   "List of functions applied when multipage output has to be split.")
+ 
  
  ;;;; Elements Filters
  
***************
*** 2537,2542 ****
--- 2543,2549 ----
    (let (plist)
      ;; Install user-defined filters with `org-export-filters-alist'
      ;; and filters already in INFO (through ext-plist mechanism).
+     (setq tmp-info info)
      (dolist (p org-export-filters-alist)
        (let* ((prop (car p))
  	     (info-value (plist-get info prop))
***************
*** 2548,2553 ****
--- 2555,2561 ----
  			 (append (if (listp info-value) info-value
  				   (list info-value))
  				 default-value)))))
+     (setq global-prop org-export-filters-alist)
      ;; Prepend backend specific filters to that list.
      (dolist (p (org-export-get-all-filters (plist-get info :back-end)))
        ;; Single values get consed, lists are appended.
***************
*** 2967,2973 ****
  with external parameters overriding Org default settings, but
  still inferior to file-local settings.
  
! Return code as a string."
    (when (symbolp backend) (setq backend (org-export-get-backend backend)))
    (org-export-barf-if-invalid-backend backend)
    (org-fold-core-ignore-modifications
--- 2975,2983 ----
  with external parameters overriding Org default settings, but
  still inferior to file-local settings.
  
! Return code as a string or a list of strings.
! The returned strings will have their `org-export-info' property set to
! export information channel."
    (when (symbolp backend) (setq backend (org-export-get-backend backend)))
    (org-export-barf-if-invalid-backend backend)
    (org-fold-core-ignore-modifications
***************
*** 3004,3034 ****
                         backend info subtreep visible-only ext-plist))
  	   ;; Eventually transcode TREE.  Wrap the resulting string into
  	   ;; a template.
! 	   (let* ((body (org-element-normalize-string
! 		         (or (org-export-data (plist-get info :parse-tree) info)
!                              "")))
! 		  (inner-template (cdr (assq 'inner-template
! 					     (plist-get info :translate-alist))))
! 		  (full-body (org-export-filter-apply-functions
! 			      (plist-get info :filter-body)
! 			      (if (not (functionp inner-template)) body
! 			        (funcall inner-template body info))
! 			      info))
! 		  (template (cdr (assq 'template
! 				       (plist-get info :translate-alist))))
!                   (output
!                    (if (or (not (functionp template)) body-only) full-body
! 	             (funcall template full-body info))))
               ;; Call citation export finalizer.
               (when (plist-get info :with-cite-processors)
!                (setq output (org-cite-finalize-export output info)))
! 	     ;; Remove all text properties since they cannot be
! 	     ;; retrieved from an external process.  Finally call
! 	     ;; final-output filter and return result.
! 	     (org-no-properties
! 	      (org-export-filter-apply-functions
! 	       (plist-get info :filter-final-output)
! 	       output info)))))))))
  
  (defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist)
    "Annotate the INFO plist according to the BACKEND.
--- 3014,3059 ----
                         backend info subtreep visible-only ext-plist))
  	   ;; Eventually transcode TREE.  Wrap the resulting string into
  	   ;; a template.
! 	   (let ((output
!                   (or (org-export-data (plist-get info :parse-tree) info)
!                       "")))
!              (setq output (ensure-list output))
               ;; Call citation export finalizer.
               (when (plist-get info :with-cite-processors)
!                (setq output
!                      (mapcar
!                       (lambda (o) (org-cite-finalize-export o info))
!                       output)))
!              (let ((filters (plist-get info :filter-final-output)))
!                ;; Call final-output filter and return result.
!                (setq output
!                      (mapcar
!                       (lambda (o) (org-export-filter-apply-functions filters o info))
!                       output)))
!              ;; Apply org-export-info property.
!              (setq output
!                    (mapcar
!                     (lambda (o) (org-add-props o nil
!                              :output-file (get-text-property 0 :output-file o)
!                              'org-export-info info))
!                     output))
!              (if (length= output 1) (car output) output))))))))
! 
! (defun org-export-transcode-org-data (_ body info)
!   "Transcode `org-data' node with BODY.  Return transcoded string.
! INFO is the communication channel plist."
!   (let* ((inner-template (cdr (assq 'inner-template
! 				    (plist-get info :translate-alist))))
! 	 (full-body (org-export-filter-apply-functions
! 		     (plist-get info :filter-body)
! 		     (if (not (functionp inner-template)) body
! 		       (funcall inner-template body info))
! 		     info))
! 	 (template (cdr (assq 'template
! 			      (plist-get info :translate-alist))))
!          (body-only (memq 'body-only (plist-get info :export-options))))
!     (if (or (not (functionp template)) body-only) full-body
!       (funcall template full-body info))))
  
  (defun org-export--annotate-info (backend info &optional subtreep visible-only ext-plist)
    "Annotate the INFO plist according to the BACKEND.
***************
*** 3107,3120 ****
          (_ nil)))
      ;; Install user's and developer's filters.
      (setq info (org-export-install-filters info))
      ;; Call options filters and update export options.  We do not
      ;; use `org-export-filter-apply-functions' here since the
      ;; arity of such filters is different.
      (let ((backend-name (org-export-backend-name backend)))
        (dolist (filter (plist-get info :filter-options))
!         (let ((result (funcall filter info backend-name)))
!           (when result (setq info result)))))
      ;; Parse buffer.
      (setq tree (org-element-parse-buffer nil visible-only 'defer))
      ;; Prune tree from non-exported elements and transform
      ;; uninterpreted elements or objects in both parse tree and
--- 3132,3147 ----
          (_ nil)))
      ;; Install user's and developer's filters.
      (setq info (org-export-install-filters info))
+ 
      ;; Call options filters and update export options.  We do not
      ;; use `org-export-filter-apply-functions' here since the
      ;; arity of such filters is different.
      (let ((backend-name (org-export-backend-name backend)))
        (dolist (filter (plist-get info :filter-options))
!           (let ((result (funcall filter info backend-name)))
!             (when result (setq info result)))))
      ;; Parse buffer.
+ 
      (setq tree (org-element-parse-buffer nil visible-only 'defer))
      ;; Prune tree from non-exported elements and transform
      ;; uninterpreted elements or objects in both parse tree and
***************
*** 3131,3136 ****
--- 3158,3166 ----
      ;; to communication channel.  This is responsible for setting
      ;; :parse-tree to TREE.
      (setq info (org-export--collect-tree-properties tree info))
+     (when (plist-get info :multipage)
+       (setq tree (org-export-filter-apply-functions
+                   (plist-get info :multipage-split) tree info)))
      ;; Process citations and bibliography.  Replace each citation
      ;; and "print_bibliography" keyword in the parse tree with
      ;; the output of the selected citation export processor.
***************
*** 6140,6145 ****
--- 6170,6195 ----
       ("uk" :html "&#1040;&#1074;&#1090;&#1086;&#1088;" :utf-8 "Автор")
       ("zh-CN" :html "&#20316;&#32773;" :utf-8 "作者")
       ("zh-TW" :html "&#20316;&#32773;" :utf-8 "作者"))
+     ("Chapter %s"
+      ("ar" :default "الفصل %s")
+      ("cs" :default "kapitola %s")
+      ("da" :default "kapitel %s")
+      ("de" :default "Kapitel %s")
+      ("es" :ascii "capitulo %s" :html "cap&iacute;tulo %s" :default "capítulo %s")
+      ("et" :html "peat&#252;kk %s" :utf-8 "peatükk %s")
+      ("fa" :default "فصل %s")
+      ("fr" :default "chapitre %s")
+      ("it" :default "capitolo %s")
+      ("ja" :default "章 %s")
+      ("nl" :default "hoofdstuk %s"
+       :html "hoofdstuk&nbsp;%s" :latex "hoofdstuk~%s")
+      ("pt_BR" :ascii "capitulo %s" :html "cap&iacute;tulo %s" :default "capítulo %s")
+      ("ro" :default "capitol %s")
+      ("ru" :html "&#1075;&#1083;&#1072;&#1074;&#1072;&nbsp;%s"
+       :utf-8 "глава %s")
+      ("sl" :default "odsek %s")
+      ("tr" :html "b&#246;l&#252;m" :default "bölüm %s")
+      ("zh-CN" :html "&#31456;&#33410;" :utf-8 "章节 %s"))
      ("Continued from previous page"
       ("ar" :default "تتمة الصفحة السابقة")
       ("cs" :default "Pokračování z předchozí strany")
***************
*** 6269,6274 ****
--- 6319,6326 ----
       ("sv" :default "Illustration")
       ("tr" :default "Şekil")
       ("zh-CN" :html "&#22270;" :utf-8 "图"))
+     ("Fig. %s"
+      ("de" :default "Abb. %s"))
      ("Figure %d:"
       ("ar" :default "شكل %d:")
       ("cs" :default "Obrázek %d:")
***************
*** 6436,6441 ****
--- 6488,6515 ----
       ("sl" :default "Reference")
       ("sv" :default "Referenser")
       ("tr" :default "Referanslar"))
+     ("Section %s"
+      ("ar" :default "انظر قسم %s")
+      ("cs" :default "sekce %s")
+      ("da" :default "afsnit %s")
+      ("de" :default "Abschnitt %s")
+      ("es" :ascii "seccion %s" :html "secci&oacute;n %s" :default "sección %s")
+      ("et" :html "peat&#252;kki %s" :utf-8 "peatükki %s")
+      ;;          ("fa" :default "نمایش بخش %s")
+      ("fr" :default "section %s")
+      ("it" :default "sezione %s")
+      ;;          ("ja" :default "セクション %s を参照")
+      ("nl" :default "sectie %s"
+       :html "sectie&nbsp;%s" :latex "sectie~%s")
+      ("pt_BR" :html "se&ccedil;&atilde;o %s" :default "seção %s"
+       :ascii "secao %s")
+      ("ro" :default "secțiunea %s")
+      ("ru" :html "&&#1088;&#1072;&#1079;&#1076;&#1077;&#1083; %s"
+       :utf-8 "раздел %s")
+      ("sl" :default "poglavje %d")
+      ("tr" :default "bölüm %s")
+      ;;          ("zh-CN" :html "&#21442;&#35265;&#31532;%s&#33410;" :utf-8 "参见第%s节")
+      )
      ("See figure %s"
       ("cs" :default "Viz obrázek %s")
       ("et" :default "Vaata joonist %s")
***************
*** 6813,6818 ****
--- 6887,6918 ----
  	(switch-to-buffer-other-window buffer))
        buffer)))
  
+ (defun org-export--write-output (output encoding)
+   "Write OUTPUT to file with ENCODING.
+ OUTPUT may be a string or a list of strings.
+ The target file is retrieved from :output-file OUTPUT property or
+ :output-file property in plist stored in `org-export-info' property of
+ each string.
+ 
+ Return the file name or a list of file names."
+   (if (listp output) (mapcar #'org-export--write-output output)
+     (setq tmp-debug output)
+     (let ((file (or
+                  (get-text-property 0 :output-file output)
+                  (plist-get
+                   (get-text-property 0 'org-export-info output)
+                   :output-file))))
+       (with-temp-buffer
+         (insert output)
+         ;; Ensure final newline.  This is what was done
+         ;; historically, when we used `write-file'.
+         ;; Note that adding a newline is only safe for
+         ;; non-binary data.
+         (unless (bolp) (insert "\n"))
+         (let ((coding-system-for-write encoding))
+ 	  (write-region nil nil file))
+         file))))
+ 
  ;;;###autoload
  (defun org-export-to-file
      (backend file &optional async subtreep visible-only body-only ext-plist
***************
*** 6861,6893 ****
  	    `(let ((output
  		    (org-export-as
  		     ',backend ,subtreep ,visible-only ,body-only
! 		     ',ext-plist)))
! 	       (with-temp-buffer
! 		 (insert output)
!                  ;; Ensure final newline.  This is what was done
!                  ;; historically, when we used `write-file'.
!                  ;; Note that adding a newline is only safe for
!                  ;; non-binary data.
!                  (unless (bolp) (insert "\n"))
! 		 (let ((coding-system-for-write ',encoding))
! 		   (write-region nil nil ,file)))
! 	       (or (ignore-errors (funcall ',post-process ,file)) ,file)))
          (let ((output (org-export-as
!                        backend subtreep visible-only body-only ext-plist)))
!           (with-temp-buffer
!             (insert output)
!             ;; Ensure final newline.  This is what was done
!             ;; historically, when we used `write-file'.
!             ;; Note that adding a newline is only safe for
!             ;; non-binary data.
!             (unless (bolp) (insert "\n"))
!             (let ((coding-system-for-write encoding))
! 	      (write-region nil nil file)))
            (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output))
              (org-kill-new output))
            ;; Get proper return value.
!           (or (and (functionp post-process) (funcall post-process file))
! 	      file))))))
  
  (defun org-export-output-file-name (extension &optional subtreep pub-dir)
    "Return output file's name according to buffer specifications.
--- 6961,6983 ----
  	    `(let ((output
  		    (org-export-as
  		     ',backend ,subtreep ,visible-only ,body-only
! 		     ',ext-plist))
!                    file)
!                (setq file (org-export--write-output output ',encoding))
!                (let ((post (lambda (f) (or (ignore-errors (funcall ',post-process f)) f))))
!                  (if (listp file) (mapcar post file) (funcall post file)))))
          (let ((output (org-export-as
!                        backend subtreep visible-only body-only ext-plist))
!               file)
!           (setq file (org-export--write-output output encoding))
            (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output))
              (org-kill-new output))
            ;; Get proper return value.
!           (let ((post (lambda (f)
!                         (or (and (functionp post-process)
!                                  (funcall post-process f))
! 	                    f))))
!             (if (listp file) (mapcar post file) (funcall post file))))))))
  
  (defun org-export-output-file-name (extension &optional subtreep pub-dir)
    "Return output file's name according to buffer specifications.

[-- Attachment #4: ox-html.el.patch --]
[-- Type: text/plain, Size: 85342 bytes --]

*** org-mode/lisp/ox-html.el	2024-08-05 17:15:57.628595589 +0200
--- org-mode-multipage/lisp/ox-html.el	2024-08-05 17:11:54.979585435 +0200
***************
*** 4,9 ****
--- 4,11 ----
  
  ;; Author: Carsten Dominik <carsten.dominik@gmail.com>
  ;;      Jambunathan K <kjambunathan at gmail dot com>
+ ;;      multipage export by Orm Finnendahl
+ ;;      <orm dot finnendahl at selma dot hfmdk-frankfurt dot de>
  ;; Maintainer: TEC <orgmode@tec.tecosaur.net>
  ;; Keywords: outlines, hypermedia, calendar, text
  
***************
*** 82,88 ****
--- 84,94 ----
      (latex-fragment . org-html-latex-fragment)
      (line-break . org-html-line-break)
      (link . org-html-link)
+     (multipage-inner-template . org-html-multipage-inner-template)
+     (multipage-template . org-html-multipage-template)
      (node-property . org-html-node-property)
+     (org-data . org-html-transcode-org-data)
+ ;;;    (org-page . org-html-transcode-org-page)
      (paragraph . org-html-paragraph)
      (plain-list . org-html-plain-list)
      (plain-text . org-html-plain-text)
***************
*** 108,118 ****
--- 114,126 ----
      (verse-block . org-html-verse-block))
    :filters-alist '((:filter-options . org-html-infojs-install-script)
  		   (:filter-parse-tree . org-html-image-link-filter)
+                    (:multipage-split . org-html-multipage-split)
  		   (:filter-final-output . org-html-final-function))
    :menu-entry
    '(?h "Export to HTML"
         ((?H "As HTML buffer" org-html-export-as-html)
  	(?h "As HTML file" org-html-export-to-html)
+ 	(?m "As HTML Multipage files" org-html-export-to-multipage)
  	(?o "As HTML file and open"
  	    (lambda (a s v b)
  	      (if a (org-html-export-to-html t s v b)
***************
*** 134,141 ****
      (:html-head "HTML_HEAD" nil org-html-head newline)
      (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline)
      (:subtitle "SUBTITLE" nil nil parse)
!     (:html-head-include-default-style
!      nil "html-style" org-html-head-include-default-style)
      (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts)
      (:html-allow-name-attribute-in-anchors
       nil nil org-html-allow-name-attribute-in-anchors)
--- 142,148 ----
      (:html-head "HTML_HEAD" nil org-html-head newline)
      (:html-head-extra "HTML_HEAD_EXTRA" nil org-html-head-extra newline)
      (:subtitle "SUBTITLE" nil nil parse)
!     (:html-head-include-default-style nil "html-style" org-html-head-include-default-style)
      (:html-head-include-scripts nil "html-scripts" org-html-head-include-scripts)
      (:html-allow-name-attribute-in-anchors
       nil nil org-html-allow-name-attribute-in-anchors)
***************
*** 158,163 ****
--- 165,190 ----
      (:html-mathjax-options nil nil org-html-mathjax-options)
      (:html-mathjax-template nil nil org-html-mathjax-template)
      (:html-metadata-timestamp-format nil nil org-html-metadata-timestamp-format)
+     (:html-multipage-clear-export-directory nil "html-multipage-clear-export-directory"
+                                             org-html-multipage-clear-export-directory)
+     (:html-multipage-export-directory
+      nil "html-multipage-export-directory" org-html-multipage-export-directory)
+     (:html-multipage-head-include-default-style
+      nil "html-multipage-include-default-style" org-html-multipage-head-include-default-style)
+     (:html-multipage-join-empty-bodies
+      nil "html-multipage-join-empty-bodies" org-html-multipage-join-empty-bodies)
+     (:html-multipage-nav-format nil nil org-html-multipage-nav-format)
+     (:html-multipage-numbered-filenames nil "html-multipage-numbered-filenames"
+                                         org-html-multipage-numbered-filenames)
+     (:html-multipage-open nil "html-multipage-open" org-html-multipage-open)
+     (:html-multipage-postamble-position
+      nil "html-multipage-postamble-position" org-html-multipage-postamble-position)
+     (:html-multipage-preamble-position
+      nil "html-multipage-preamble-position" org-html-multipage-preamble-position)
+     (:html-multipage-split-hooks nil nil org-html-multipage-split-hooks)
+     (:html-multipage-split-level nil "html-multipage-split-level" org-html-multipage-split-level)
+     (:html-multipage-toc-to-top nil "html-multipage-toc-to-top" org-html-multipage-toc-to-top)
+     (:html-numbered-link-format nil nil org-html-numbered-link-format)
      (:html-postamble-format nil nil org-html-postamble-format)
      (:html-preamble-format nil nil org-html-preamble-format)
      (:html-prefer-user-labels nil nil org-html-prefer-user-labels)
***************
*** 171,179 ****
       nil nil org-html-table-use-header-tags-for-first-column)
      (:html-tag-class-prefix nil nil org-html-tag-class-prefix)
      (:html-text-markup-alist nil nil org-html-text-markup-alist)
      (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix)
      (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel)
!     (:html-use-infojs nil nil org-html-use-infojs)
      (:html-validation-link nil nil org-html-validation-link)
      (:html-viewport nil nil org-html-viewport)
      (:html-inline-images nil nil org-html-inline-images)
--- 198,207 ----
       nil nil org-html-table-use-header-tags-for-first-column)
      (:html-tag-class-prefix nil nil org-html-tag-class-prefix)
      (:html-text-markup-alist nil nil org-html-text-markup-alist)
+     (:html-toc-title nil "html-toc-title" org-html-toc-title)
      (:html-todo-kwd-class-prefix nil nil org-html-todo-kwd-class-prefix)
      (:html-toplevel-hlevel nil nil org-html-toplevel-hlevel)
!     (:html-use-infojs nil nil org-export-html-use-infojs)
      (:html-validation-link nil nil org-html-validation-link)
      (:html-viewport nil nil org-html-viewport)
      (:html-inline-images nil nil org-html-inline-images)
***************
*** 186,191 ****
--- 214,221 ----
      (:html-klipse-css nil nil org-html-klipse-css)
      (:html-klipse-js nil nil org-html-klipse-js)
      (:html-klipse-selection-script nil nil org-html-klipse-selection-script)
+ ;;;    (:multipage-split nil nil org-html-multipage-split)
+ ;;;    (:multipage nil nil org-html-multipage)
      (:infojs-opt "INFOJS_OPT" nil nil)
      ;; Redefine regular options.
      (:creator "CREATOR" nil org-html-creator-string)
***************
*** 462,467 ****
--- 492,720 ----
    :package-version '(Org . "9.5")
    :type 'string)
  
+ (defcustom org-html-multipage-style-default
+   "<style type=\"text/css\">
+ #content { margin: auto;
+            display: grid;
+            position: absolute;
+            padding-top: 1em;
+            grid-template-rows: 4em 1fr;
+            grid-template-columns: 27em 1fr;
+            grid-template-areas: \"toc title\"
+                                 \"toc content\";
+ }
+ 
+ header {
+     grid-area: title;
+ }
+ 
+ #table-of-contents {
+     grid-area: toc;
+     height: 100%;
+ }
+ 
+ #page-main-body {
+     grid-area: content;
+     height: 100%;
+     overflow: auto;
+     padding: 4em;
+ }
+ 
+ #page-text-body {
+     height: 100%;
+     width: 100%;
+     overflow: auto;
+ }
+ 
+ .title  { text-align: center;
+            margin-bottom: .2em; }
+ .subtitle { text-align: center;
+             font-size: medium;
+             font-weight: bold;
+             margin-top:0; }
+ .todo   { font-family: monospace; color: red; }
+ .done   { font-family: monospace; color: green; }
+ .priority { font-family: monospace; color: orange; }
+ .tag    { background-color: #eee; font-family: monospace;
+           padding: 2px; font-size: 80%; font-weight: normal; }
+ .timestamp { color: #bebebe; }
+ .timestamp-kwd { color: #5f9ea0; }
+ .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
+ .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
+ .org-center { margin-left: auto; margin-right: auto; text-align: center; }
+ .underline { text-decoration: underline; }
+ #postamble p, #preamble p { font-size: 90%; margin: .2em; }
+ p.verse { margin-left: 3%; }
+ pre {
+   border: 1px solid #e6e6e6;
+   border-radius: 3px;
+   background-color: #f2f2f2;
+   padding: 8pt;
+   font-family: monospace;
+   overflow: auto;
+   margin: 1.2em;
+ }
+ pre.src {
+   position: relative;
+   overflow: auto;
+ }
+ pre.src:before {
+   display: none;
+   position: absolute;
+   top: -8px;
+   right: 12px;
+   padding: 3px;
+   color: #555;
+   background-color: #f2f2f299;
+ }
+ pre.src:hover:before { display: inline; margin-top: 14px;}
+ /* Languages per Org manual */
+ pre.src-asymptote:before { content: 'Asymptote'; }
+ pre.src-awk:before { content: 'Awk'; }
+ pre.src-authinfo::before { content: 'Authinfo'; }
+ pre.src-C:before { content: 'C'; }
+ /* pre.src-C++ doesn't work in CSS */
+ pre.src-clojure:before { content: 'Clojure'; }
+ pre.src-css:before { content: 'CSS'; }
+ pre.src-D:before { content: 'D'; }
+ pre.src-ditaa:before { content: 'ditaa'; }
+ pre.src-dot:before { content: 'Graphviz'; }
+ pre.src-calc:before { content: 'Emacs Calc'; }
+ pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
+ pre.src-fortran:before { content: 'Fortran'; }
+ pre.src-gnuplot:before { content: 'gnuplot'; }
+ pre.src-haskell:before { content: 'Haskell'; }
+ pre.src-hledger:before { content: 'hledger'; }
+ pre.src-java:before { content: 'Java'; }
+ pre.src-js:before { content: 'Javascript'; }
+ pre.src-latex:before { content: 'LaTeX'; }
+ pre.src-ledger:before { content: 'Ledger'; }
+ pre.src-lisp:before { content: 'Lisp'; }
+ pre.src-lilypond:before { content: 'Lilypond'; }
+ pre.src-lua:before { content: 'Lua'; }
+ pre.src-matlab:before { content: 'MATLAB'; }
+ pre.src-mscgen:before { content: 'Mscgen'; }
+ pre.src-ocaml:before { content: 'Objective Caml'; }
+ pre.src-octave:before { content: 'Octave'; }
+ pre.src-org:before { content: 'Org mode'; }
+ pre.src-oz:before { content: 'OZ'; }
+ pre.src-plantuml:before { content: 'Plantuml'; }
+ pre.src-processing:before { content: 'Processing.js'; }
+ pre.src-python:before { content: 'Python'; }
+ pre.src-R:before { content: 'R'; }
+ pre.src-ruby:before { content: 'Ruby'; }
+ pre.src-sass:before { content: 'Sass'; }
+ pre.src-scheme:before { content: 'Scheme'; }
+ pre.src-screen:before { content: 'Gnu Screen'; }
+ pre.src-sed:before { content: 'Sed'; }
+ pre.src-sh:before { content: 'shell'; }
+ pre.src-sql:before { content: 'SQL'; }
+ pre.src-sqlite:before { content: 'SQLite'; }
+ /* additional languages in org.el's org-babel-load-languages alist */
+ pre.src-forth:before { content: 'Forth'; }
+ pre.src-io:before { content: 'IO'; }
+ pre.src-J:before { content: 'J'; }
+ pre.src-makefile:before { content: 'Makefile'; }
+ pre.src-maxima:before { content: 'Maxima'; }
+ pre.src-perl:before { content: 'Perl'; }
+ pre.src-picolisp:before { content: 'Pico Lisp'; }
+ pre.src-scala:before { content: 'Scala'; }
+ pre.src-shell:before { content: 'Shell Script'; }
+ pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
+ /* additional language identifiers per \"defun org-babel-execute\"
+      in ob-*.el */
+ pre.src-cpp:before  { content: 'C++'; }
+ pre.src-abc:before  { content: 'ABC'; }
+ pre.src-coq:before  { content: 'Coq'; }
+ pre.src-groovy:before  { content: 'Groovy'; }
+ /* additional language identifiers from org-babel-shell-names in
+    ob-shell.el: ob-shell is the only babel language using a lambda to put
+    the execution function name together. */
+ pre.src-bash:before  { content: 'bash'; }
+ pre.src-csh:before  { content: 'csh'; }
+ pre.src-ash:before  { content: 'ash'; }
+ pre.src-dash:before  { content: 'dash'; }
+ pre.src-ksh:before  { content: 'ksh'; }
+ pre.src-mksh:before  { content: 'mksh'; }
+ pre.src-posh:before  { content: 'posh'; }
+ /* Additional Emacs modes also supported by the LaTeX listings package */
+ pre.src-ada:before { content: 'Ada'; }
+ pre.src-asm:before { content: 'Assembler'; }
+ pre.src-caml:before { content: 'Caml'; }
+ pre.src-delphi:before { content: 'Delphi'; }
+ pre.src-html:before { content: 'HTML'; }
+ pre.src-idl:before { content: 'IDL'; }
+ pre.src-mercury:before { content: 'Mercury'; }
+ pre.src-metapost:before { content: 'MetaPost'; }
+ pre.src-modula-2:before { content: 'Modula-2'; }
+ pre.src-pascal:before { content: 'Pascal'; }
+ pre.src-ps:before { content: 'PostScript'; }
+ pre.src-prolog:before { content: 'Prolog'; }
+ pre.src-simula:before { content: 'Simula'; }
+ pre.src-tcl:before { content: 'tcl'; }
+ pre.src-tex:before { content: 'TeX'; }
+ pre.src-plain-tex:before { content: 'Plain TeX'; }
+ pre.src-verilog:before { content: 'Verilog'; }
+ pre.src-vhdl:before { content: 'VHDL'; }
+ pre.src-xml:before { content: 'XML'; }
+ pre.src-nxml:before { content: 'XML'; }
+ /* add a generic configuration mode; LaTeX export needs an additional
+    (add-to-list 'org-latex-listings-langs '(conf \" \")) in .emacs */
+ pre.src-conf:before { content: 'Configuration File'; }
+ 
+ table { border-collapse:collapse; }
+ caption.t-above { caption-side: top; }
+ caption.t-bottom { caption-side: bottom; }
+ td, th { vertical-align:top;  }
+ th.org-right  { text-align: center;  }
+ th.org-left   { text-align: center;   }
+ th.org-center { text-align: center; }
+ td.org-right  { text-align: right;  }
+ td.org-left   { text-align: left;   }
+ td.org-center { text-align: center; }
+ dt { font-weight: bold; }
+ .footpara { display: inline; }
+ .footdef  { margin-bottom: 1em; }
+ .figure { padding: 1em; }
+ .figure p { text-align: center; }
+ .equation-container {
+   display: table;
+   text-align: center;
+   width: 100%;
+ }
+ .equation {
+   vertical-align: middle;
+ }
+ .equation-label {
+   display: table-cell;
+   text-align: right;
+   vertical-align: middle;
+ }
+ .inlinetask {
+   padding: 10px;
+   border: 2px solid gray;
+   margin: 10px;
+   background: #ffffcc;
+ }
+ #org-div-home-and-up
+  { text-align: right; font-size: 70%; white-space: nowrap; }
+ textarea { overflow-x: auto; }
+ .linenr { font-size: smaller }
+ .code-highlighted { background-color: #ffff00; }
+ .org-info-js_info-navigation { border-style: none; }
+ #org-info-js_console-label
+   { font-size: 10px; font-weight: bold; white-space: nowrap; }
+ .org-info-js_search-highlight
+   { background-color: #ffff00; color: #000000; font-weight: bold; }
+ .org-svg { }
+ </style>"
+   "The default style specification for exported HTML files.
+ You can use `org-html-head' and `org-html-head-extra' to add to
+ this style.  If you don't want to include this default style,
+ customize `org-html-head-include-default-style'."
+   :group 'org-export-html
+   :package-version '(Org . "9.8")
+   :type 'string)
  \f
  ;;; User Configuration Variables
  
***************
*** 486,492 ****
      (home LINK_HOME :html-link-home))
    "JavaScript options, long form for script, default values.")
  
! (defcustom org-html-use-infojs 'when-configured
    "Non-nil when Sebastian Rose's Java Script org-info.js should be active.
  This option can be nil or t to never or always use the script.
  It can also be the symbol `when-configured', meaning that the
--- 739,745 ----
      (home LINK_HOME :html-link-home))
    "JavaScript options, long form for script, default values.")
  
! (defcustom org-export-html-use-infojs 'when-configured
    "Non-nil when Sebastian Rose's Java Script org-info.js should be active.
  This option can be nil or t to never or always use the script.
  It can also be the symbol `when-configured', meaning that the
***************
*** 501,506 ****
--- 754,766 ----
  	  (const :tag "When configured in buffer" when-configured)
  	  (const :tag "Always" t)))
  
+ ;; (defcustom org-html-multipage nil
+ ;;   "Boolean indicating multipage export."
+ ;;   :group 'org-export-html
+ ;;   :version "29.4"
+ ;;   :package-version '(Org . "9.8")
+ ;;   :type 'boolean)
+ 
  (defcustom org-html-infojs-options
    (mapcar (lambda (x) (cons (car x) (nth 2 x))) org-html-infojs-opts-table)
    "Options settings for the INFOJS JavaScript.
***************
*** 849,854 ****
--- 1109,1129 ----
    :group 'org-export-html
    :type 'boolean)
  
+ (defcustom org-html-numbered-link-format
+   '("Chapter %s"
+     "Section %s"
+     "Fig. %s")
+   "Format for the labels of numbered links.
+ 
+  The first string is used for links to Chapters, the second for
+ links to Sections and the third for links to Figures. %s will be
+ replaced by the number of the reference. The strings get
+ translated using org-html--translate."
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'list)
+ 
  ;;;; Links :: Inline images
  
  (defcustom org-html-inline-images t
***************
*** 1384,1389 ****
--- 1659,1673 ----
  	  (list (string :tag "Language")
  		(string :tag "Format string"))))
  
+ (defcustom org-html-toc-title "Table of Contents"
+   "The string tp be used for the title of the table of contents. It
+ will be passed to org-html-translate."
+   :group 'org-export-html
+   :package-version '(Org . "9.8")
+   :version "29.4"
+   :type 'string
+   :safe #'stringp)
+ 
  (defcustom org-html-validation-link
    "<a href=\"https://validator.w3.org/check?uri=referer\">Validate</a>"
    "Link to HTML validation service."
***************
*** 1522,1529 ****
--- 1806,1954 ----
    :version "24.4"
    :package-version '(Org . "8.0")
    :type 'boolean)
+ 
+ (defcustom org-html-multipage-clear-export-directory t
+   "Boolean. If non-nil remove all .html files from the export
+ directory before exporting."
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'boolean)
+ 
+ (defcustom org-html-multipage-export-directory "html"
+   "The default directory for exported HTML files."
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'string)
+ 
+ (defcustom org-html-multipage-head-include-default-style t
+   "Non-nil means include the default style in exported HTML files.
+ The actual style is defined in `org-html-style-default' and
+ should not be modified.  Use `org-html-head' to use your own
+ style information."
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'boolean)
+ 
+ (defcustom org-html-multipage-join-empty-bodies t
+   "Recursively join subheadlines, if a headline doesn't contain any
+ text before its Subheadline.
+ 
+ Example:
+ 
+ * Headline 1
+ ** Subheadline 1.1
+ *** Subsubheadline 1.1.1
+     Text of Subsubheadline 1.1.1
+ 
+ will be put on the same HTML page if this option is set,
+ otherwise Headline 1 And Subheadline 1.1 will be put on a
+ separate HTML page with empty content.
+ "
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'boolean)
+ 
+ (defcustom org-html-multipage-nav-format
+   '("<div id=\"org-div-nav-menu\">%s</div>"
+ "Next: <a accesskey=\"n\" href=\"%s\"> %s </a>,&nbsp;"
+ "Previous: <a accesskey=\"p\" href=\"%s\"> %s </a>,&nbsp;"
+ "Up: <a accesskey=\"u\" href=\"%s\"> %s </a>,&nbsp;"
+ "Home: <a accesskey=\"h\" href=\"%s\"> %s </a>")
+   "Snippets used to insert the NEXT, PREV, HOME and UP links in
+ multipage output. The list contains format strings for the HTML
+ div and the navigation elements. The %s in the HTML div will
+ receive a concatenated string of the navigation elements. The
+ first %s in the navigation elements will receive the link,
+ the second the title"
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'list)
+ 
+ (defcustom org-html-multipage-numbered-filenames t
+   "Boolean indicating whether filenames in multipage export should
+ get their headline-numbering prepended. Note: This option is
+ independent of the num: option and the backend guarantees that
+ filenames are unique in any case."
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'boolean)
+ 
+ (defcustom org-html-multipage-open 'nil
+   "If and where to open the top page of the multipage html after
+ export."
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type '(choice (const browser) (const buffer) (const nil)))
+ 
+ (defcustom org-html-multipage-postamble-position 'bottom
+   "The position of the postamble in the html output.
+ 
+   bottom - at the bottom of the page, directly before </body>
+ 
+   text-content - at the bottom of the text-content.
+   "
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type '(choice (const bottom) (const text-content)))
+ 
+ (defcustom org-html-multipage-preamble-position 'top
+   "If and where to open the top page of the multipage html after
+ export.
+ 
+   top - at the top of the page, directly after <body>
+ 
+   text-content - at the top of the text-content.
+ 
+ "
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type '(choice (const top) (const text-content)))
+ 
+ (defcustom org-html-multipage-split-hooks nil
+   "list of additional custom functions to be called during the
+ export after multipage splitting has taken place and before
+ transcoding with info as input.
+ "
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'list)
+ 
+ (defcustom org-html-multipage-split-level 'toc
+   "How to split the ORG file into multiple HTML pages.
+ 
+    toc - split each entry of the toc into a separate page.
+ 
+    number - a number indicating the maximum headline-level for
+             splitting.
+ "
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type '(choice (const toc) (number :tag "Headline Level" 3)))
+ 
+ (defcustom org-html-multipage-toc-to-top t
+   "If t links in the TOC will always point to the top of the page,
+ otherwise it will link directly to the referenced headline
+ element."
+   :group 'org-export-html
+   :version "29.4"
+   :package-version '(Org . "9.8")
+   :type 'boolean)
+ 
  ;;;###autoload
  (put 'org-html-head-include-default-style 'safe-local-variable 'booleanp)
+ (put 'org-html-multipage-head-include-default-style 'safe-local-variable 'booleanp)
+ (put 'org-html-multipage-join-empty-bodies 'safe-local-variable 'booleanp)
  
  (defcustom org-html-head ""
    "Org-wide head definitions for exported HTML files.
***************
*** 1873,1890 ****
  (defun org-html-footnote-section (info)
    "Format the footnote section.
  INFO is a plist used as a communication channel."
!   (pcase (org-export-collect-footnote-definitions info)
      (`nil nil)
      (definitions
-      (format
-       (plist-get info :html-footnotes-section)
-       (org-html--translate "Footnotes" info)
        (format
!        "\n%s\n"
!        (mapconcat
! 	(lambda (definition)
! 	  (pcase definition
! 	    (`(,n ,label ,def)
               ;; Do not assign number labels as they appear in Org mode
               ;; - the footnotes are re-numbered by
               ;; `org-export-get-footnote-number'.  If the label is not
--- 2298,2315 ----
  (defun org-html-footnote-section (info)
    "Format the footnote section.
  INFO is a plist used as a communication channel."
!   (pcase (org-export-collect-footnote-definitions info (plist-get info :tl-headline))
      (`nil nil)
      (definitions
        (format
!        (plist-get info :html-footnotes-section)
!        (org-html--translate "Footnotes" info)
!        (format
! 	"\n%s\n"
! 	(mapconcat
! 	 (lambda (definition)
! 	   (pcase definition
! 	     (`(,n ,label ,def)
               ;; Do not assign number labels as they appear in Org mode
               ;; - the footnotes are re-numbered by
               ;; `org-export-get-footnote-number'.  If the label is not
***************
*** 1911,1918 ****
  			       (if (not inline?) contents
  				 (format "<p class=\"footpara\">%s</p>"
  					 contents))))))))
! 	definitions
! 	"\n"))))))
  
  \f
  ;;; Template
--- 2336,2343 ----
  			       (if (not inline?) contents
  				 (format "<p class=\"footpara\">%s</p>"
  					 contents))))))))
! 	 definitions
! 	 "\n"))))))
  
  \f
  ;;; Template
***************
*** 2018,2025 ****
  INFO is a plist used as a communication channel."
    (org-element-normalize-string
     (concat
!     (when (plist-get info :html-head-include-default-style)
!       (org-element-normalize-string org-html-style-default))
      (org-html-normalize-string-or-function (plist-get info :html-head) info)
      (org-html-normalize-string-or-function (plist-get info :html-head-extra)
                                             info)
--- 2443,2453 ----
  INFO is a plist used as a communication channel."
    (org-element-normalize-string
     (concat
!     (if (plist-get info :multipage)
!         (when (plist-get info :html-multipage-head-include-default-style)
!           (org-element-normalize-string org-html-multipage-style-default))
!       (when (plist-get info :html-head-include-default-style)
!         (org-element-normalize-string org-html-style-default)))
      (org-html-normalize-string-or-function (plist-get info :html-head) info)
      (org-html-normalize-string-or-function (plist-get info :html-head-extra)
                                             info)
***************
*** 2206,2212 ****
  holding export options."
    (concat
     ;; Table of contents.
!    (let ((depth (plist-get info :with-toc)))
       (when depth (org-html-toc depth info)))
     ;; Document contents.
     contents
--- 2634,2644 ----
  holding export options."
    (concat
     ;; Table of contents.
!    (let* ((with-toc (plist-get info :with-toc))
!           (depth (if with-toc
!                      (if (numberp with-toc)
!                          with-toc
!                        (plist-get info :headline-levels)))))
       (when depth (org-html-toc depth info)))
     ;; Document contents.
     contents
***************
*** 2477,2484 ****
  of contents as a string, or nil if it is empty."
    (let ((toc-entries
  	 (mapcar (lambda (headline)
! 		   (cons (org-html--format-toc-headline headline info)
! 			 (org-export-get-relative-level headline info)))
  		 (org-export-collect-headlines info depth scope))))
      (when toc-entries
        (let* ((toc-id-counter (plist-get info :org-html--toc-counter))
--- 2909,2918 ----
  of contents as a string, or nil if it is empty."
    (let ((toc-entries
  	 (mapcar (lambda (headline)
! 		   (cl-list*
!                     (org-html--format-toc-headline headline info)
!                     nil ;;; no hidden attribute
!                     (org-export-get-relative-level headline info)))
  		 (org-export-collect-headlines info depth scope))))
      (when toc-entries
        (let* ((toc-id-counter (plist-get info :org-html--toc-counter))
***************
*** 2497,2503 ****
  		    (let ((top-level (plist-get info :html-toplevel-hlevel)))
  		      (format "<h%d>%s</h%d>\n"
  			      top-level
! 			      (org-html--translate "Table of Contents" info)
  			      top-level))
  		    toc
  		    (format "</%s>\n" outer-tag))))))))
--- 2931,2940 ----
  		    (let ((top-level (plist-get info :html-toplevel-hlevel)))
  		      (format "<h%d>%s</h%d>\n"
  			      top-level
! 			      (org-html--translate
!                                (or (plist-get info :html-toc-title)
!                                    org-html-toc-title)
!                                info)
  			      top-level))
  		    toc
  		    (format "</%s>\n" outer-tag))))))))
***************
*** 2505,2527 ****
  (defun org-html--toc-text (toc-entries)
    "Return innards of a table of contents, as a string.
  TOC-ENTRIES is an alist where key is an entry title, as a string,
! and value is its relative level, as an integer."
!   (let* ((prev-level (1- (cdar toc-entries)))
  	 (start-level prev-level))
      (concat
       (mapconcat
        (lambda (entry)
  	(let ((headline (car entry))
! 	      (level (cdr entry)))
  	  (concat
! 	   (let* ((cnt (- level prev-level))
! 		  (times (if (> cnt 0) (1- cnt) (- cnt))))
! 	     (setq prev-level level)
! 	     (concat
! 	      (org-html--make-string
! 	       times (cond ((> cnt 0) "\n<ul>\n<li>")
! 			   ((< cnt 0) "</li>\n</ul>\n")))
! 	      (if (> cnt 0) "\n<ul>\n<li>" "</li>\n<li>")))
  	   headline)))
        toc-entries "")
       (org-html--make-string (- prev-level start-level) "</li>\n</ul>\n"))))
--- 2942,2974 ----
  (defun org-html--toc-text (toc-entries)
    "Return innards of a table of contents, as a string.
  TOC-ENTRIES is an alist where key is an entry title, as a string,
! second element a flag whether the entry gets a
! class=\"toc-hidden\" attribute and the third element is its
! relative level, as an integer."
!   (let* ((prev-level (1- (cddar toc-entries)))
  	 (start-level prev-level))
      (concat
       (mapconcat
        (lambda (entry)
  	(let ((headline (car entry))
!               (hidden (cadr entry))
! 	      (level (cddr entry)))
  	  (concat
! 	   (format
!             (let* ((cnt (- level prev-level))
!                    (times (if (> cnt 0) (1- cnt) (- cnt))))
!               (setq prev-level level)
!               (concat
!                (org-html--make-string
!                 times (cond ((> cnt 0) (format "\n<ul class=\"ul-toc-level-%d\">\n<li>" level))
!                             ((< cnt 0) "</li>\n</ul>\n")))
!                (if (> cnt 0)
!                    (concat "\n<ul"
!                            (format " class=\"ul-toc-level-%d\"" level)
!                            ">\n<li%s>")
!                  "</li>\n<li%s>")))
!             (if hidden (format " class=\"toc-hidden toc-level-%d\"" level)
!               (format " class=\"toc-level-%d\"" level)))
  	   headline)))
        toc-entries "")
       (org-html--make-string (- prev-level start-level) "</li>\n</ul>\n"))))
***************
*** 2572,2578 ****
  					 (org-html--translate "Listing %d:" info))))
  		(mapconcat
  		 (lambda (entry)
! 		   (let ((label (org-html--reference entry info t))
  			 (title (org-trim
  				 (org-export-data
  				  (or (org-export-get-caption entry t)
--- 3019,3025 ----
  					 (org-html--translate "Listing %d:" info))))
  		(mapconcat
  		 (lambda (entry)
! 		   (let ((label (org-html--full-reference entry info t))
  			 (title (org-trim
  				 (org-export-data
  				  (or (org-export-get-caption entry t)
***************
*** 2610,2616 ****
  					 (org-html--translate "Table %d:" info))))
  		(mapconcat
  		 (lambda (entry)
! 		   (let ((label (org-html--reference entry info t))
  			 (title (org-trim
  				 (org-export-data
  				  (or (org-export-get-caption entry t)
--- 3057,3063 ----
  					 (org-html--translate "Table %d:" info))))
  		(mapconcat
  		 (lambda (entry)
! 		   (let ((label (org-html--full-reference entry info t))
  			 (title (org-trim
  				 (org-export-data
  				  (or (org-export-get-caption entry t)
***************
*** 2759,2765 ****
     (let ((prev (org-export-get-previous-element footnote-reference info)))
       (when (org-element-type-p prev 'footnote-reference)
         (plist-get info :html-footnote-separator)))
!    (let* ((n (org-export-get-footnote-number footnote-reference info))
            (label (org-element-property :label footnote-reference))
            ;; Do not assign number labels as they appear in Org mode -
            ;; the footnotes are re-numbered by
--- 3206,3215 ----
     (let ((prev (org-export-get-previous-element footnote-reference info)))
       (when (org-element-type-p prev 'footnote-reference)
         (plist-get info :html-footnote-separator)))
!    (let* ((n (org-export-get-footnote-number
!               footnote-reference info
!               (if (plist-get info :multipage)
!                   (org-html-get-multipage-tl-headline footnote-reference info))))
            (label (org-element-property :label footnote-reference))
            ;; Do not assign number labels as they appear in Org mode -
            ;; the footnotes are re-numbered by
***************
*** 2795,2801 ****
  CONTENTS holds the contents of the headline.  INFO is a plist
  holding contextual information."
    (unless (org-element-property :footnote-section-p headline)
!     (let* ((numberedp (org-export-numbered-headline-p headline info))
             (numbers (org-export-get-headline-number headline info))
             (level (+ (org-export-get-relative-level headline info)
                       (1- (plist-get info :html-toplevel-hlevel))))
--- 3245,3253 ----
  CONTENTS holds the contents of the headline.  INFO is a plist
  holding contextual information."
    (unless (org-element-property :footnote-section-p headline)
!     (let* ((numberedp (if (plist-get info :multipage)
!                           (plist-get info :section-numbers)
!                           (org-export-numbered-headline-p headline info)))
             (numbers (org-export-get-headline-number headline info))
             (level (+ (org-export-get-relative-level headline info)
                       (1- (plist-get info :html-toplevel-hlevel))))
***************
*** 3023,3028 ****
--- 3475,3481 ----
       ((string= key "HTML") value)
       ((string= key "TOC")
        (let ((case-fold-search t))
+         (setq global-key keyword)
  	(cond
  	 ((string-match "\\<headlines\\>" value)
  	  (let ((depth (and (string-match "\\<[0-9]+\\>" value)
***************
*** 3033,3039 ****
  		   (org-export-resolve-link
  		    (org-strip-quotes (match-string 1 value)) info))
  		  ((string-match-p "\\<local\\>" value) keyword)))) ;local
! 	    (org-html-toc depth info scope)))
  	 ((string= "listings" value) (org-html-list-of-listings info))
  	 ((string= "tables" value) (org-html-list-of-tables info))))))))
  
--- 3486,3496 ----
  		   (org-export-resolve-link
  		    (org-strip-quotes (match-string 1 value)) info))
  		  ((string-match-p "\\<local\\>" value) keyword)))) ;local
! 	    (if (plist-get info :multipage)
!                 (progn
!                   (setq global-key keyword)
!                   (org-html-multipage-toc depth (cl-list* :full-toc t info) scope))
!               (org-html-toc depth info scope))))
  	 ((string= "listings" value) (org-html-list-of-listings info))
  	 ((string= "tables" value) (org-html-list-of-tables info))))))))
  
***************
*** 3187,3193 ****
  
  (defun org-html-image-link-filter (data _backend info)
  "Process image links that are inside descriptions.
! DATA is the parse tree.  INFO is and info plist.
  See `org-export-insert-image-links' for more details."
    (org-export-insert-image-links data info org-html-inline-image-rules))
  
--- 3644,3650 ----
  
  (defun org-html-image-link-filter (data _backend info)
  "Process image links that are inside descriptions.
! DATA is the parse tree.  INFO is an info plist.
  See `org-export-insert-image-links' for more details."
    (org-export-insert-image-links data info org-html-inline-image-rules))
  
***************
*** 3367,3389 ****
  			(org-element-property :raw-link link) info))))
  	  ;; Link points to a headline.
  	  (`headline
! 	   (let ((href (org-html--reference destination info))
  		 ;; What description to use?
  		 (desc
  		  ;; Case 1: Headline is numbered and LINK has no
  		  ;; description.  Display section number.
  		  (if (and (org-export-numbered-headline-p destination info)
  			   (not desc))
! 		      (mapconcat #'number-to-string
! 				 (org-export-get-headline-number
! 				  destination info) ".")
  		    ;; Case 2: Either the headline is un-numbered or
  		    ;; LINK has a custom description.  Display LINK's
  		    ;; description or headline's title.
  		    (or desc
  			(org-export-data
  			 (org-element-property :title destination) info)))))
! 	     (format "<a href=\"#%s\"%s>%s</a>" href attributes desc)))
  	  ;; Fuzzy link points to a target or an element.
  	  (_
             (if (and destination
--- 3824,3860 ----
  			(org-element-property :raw-link link) info))))
  	  ;; Link points to a headline.
  	  (`headline
! 	   (let ((href
!                   (org-html--full-reference
!                    (if (plist-get info :multipage)
!                        (alist-get destination
!                                   (plist-get info :stripped-hl-to-parse-tree-hl))
!                      destination)
!                    info))
  		 ;; What description to use?
  		 (desc
  		  ;; Case 1: Headline is numbered and LINK has no
  		  ;; description.  Display section number.
  		  (if (and (org-export-numbered-headline-p destination info)
  			   (not desc))
!                       (let ((headline-number (org-export-get-headline-number
!                                               destination info)))
!                         (if (> (length headline-number) 1)
!                             (format
!                              (org-html--translate (nth 1 org-html-numbered-link-format) info)
!                              (mapconcat #'number-to-string
!                                         headline-number "."))
!                             (format
!                              (org-html--translate (nth 0 org-html-numbered-link-format) info)
!                              (mapconcat #'number-to-string
!                                         headline-number "."))))
  		    ;; Case 2: Either the headline is un-numbered or
  		    ;; LINK has a custom description.  Display LINK's
  		    ;; description or headline's title.
  		    (or desc
  			(org-export-data
  			 (org-element-property :title destination) info)))))
! 	     (format "<a href=\"%s\"%s>%s</a>" href attributes desc)))
  	  ;; Fuzzy link points to a target or an element.
  	  (_
             (if (and destination
***************
*** 3394,3422 ****
  	       ;; environment.  Use "ref" or "eqref" macro, depending on user
                 ;; preference to refer to those in the document.
                 (format (plist-get info :html-equation-reference-format)
!                        (org-html--reference destination info))
!              (let* ((ref (org-html--reference destination info))
                      (org-html-standalone-image-predicate
                       #'org-html--has-caption-p)
                      (counter-predicate
                       (if (org-element-type-p destination 'latex-environment)
                           #'org-html--math-environment-p
                         #'org-html--has-caption-p))
!                     (number
  		     (cond
  		      (desc nil)
  		      ((org-html-standalone-image-p destination info)
! 		       (org-export-get-ordinal
! 			(org-element-map destination 'link #'identity info t)
! 			info '(link) 'org-html-standalone-image-p))
  		      (t (org-export-get-ordinal
  			  destination info nil counter-predicate))))
                      (desc
  		     (cond (desc)
! 			   ((not number) "No description for this link")
! 			   ((numberp number) (number-to-string number))
  			   (t (mapconcat #'number-to-string number ".")))))
!                (format "<a href=\"#%s\"%s>%s</a>" ref attributes desc)))))))
       ;; Coderef: replace link with the reference name or the
       ;; equivalent line number.
       ((string= type "coderef")
--- 3865,3895 ----
  	       ;; environment.  Use "ref" or "eqref" macro, depending on user
                 ;; preference to refer to those in the document.
                 (format (plist-get info :html-equation-reference-format)
!                        (org-html--full-reference destination info))
!              (let* ((ref (org-html--full-reference destination info))
                      (org-html-standalone-image-predicate
                       #'org-html--has-caption-p)
                      (counter-predicate
                       (if (org-element-type-p destination 'latex-environment)
                           #'org-html--math-environment-p
                         #'org-html--has-caption-p))
!                     (numbered-ref
  		     (cond
  		      (desc nil)
  		      ((org-html-standalone-image-p destination info)
! 		       (format (org-html--translate (nth 2 org-html-numbered-link-format) info)
!                                (org-export-get-ordinal
!                                 (org-element-map destination 'link #'identity info t)
!                                 info '(link) 'org-html-standalone-image-p)))
  		      (t (org-export-get-ordinal
  			  destination info nil counter-predicate))))
                      (desc
  		     (cond (desc)
! 			   ((not numbered-ref) "No description for this link")
! 			   ((numberp numbered-ref) (number-to-string number))
!                            ((stringp numbered-ref) numbered-ref)
  			   (t (mapconcat #'number-to-string number ".")))))
!                (format "<a href=\"%s\"%s>%s</a>" ref attributes desc)))))))
       ;; Coderef: replace link with the reference name or the
       ;; equivalent line number.
       ((string= type "coderef")
***************
*** 3924,3930 ****
    "Transcode a TARGET object from Org to HTML.
  CONTENTS is nil.  INFO is a plist holding contextual
  information."
!   (let ((ref (org-html--reference target info)))
      (org-html--anchor ref nil nil info)))
  
  ;;;; Timestamp
--- 4397,4403 ----
    "Transcode a TARGET object from Org to HTML.
  CONTENTS is nil.  INFO is a plist holding contextual
  information."
!   (let ((ref (org-html--full-reference target info)))
      (org-html--anchor ref nil nil info)))
  
  ;;;; Timestamp
***************
*** 3984,3990 ****
      (delay-mode-hooks (set-auto-mode t))
      (when (plist-get info :html-indent)
        (indent-region (point-min) (point-max)))
!     (buffer-substring-no-properties (point-min) (point-max))))
  
  \f
  ;;; End-user functions
--- 4457,4470 ----
      (delay-mode-hooks (set-auto-mode t))
      (when (plist-get info :html-indent)
        (indent-region (point-min) (point-max)))
!     (if (plist-get info :multipage)
!         (let ((output-file (get-text-property
!                             0 :output-file
!                             (buffer-substring (point-min) (point-max)))))
!           (put-text-property
!            0 1 :output-file output-file
!            (buffer-substring-no-properties (point-min) (point-max))))
!       (buffer-substring-no-properties (point-min) (point-max)))))
  
  \f
  ;;; End-user functions
***************
*** 4092,4097 ****
--- 4572,5482 ----
  				  "html"))
  		      plist pub-dir))
  
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;;;
+ ;;; Code specific to the multipage backend
+ ;;;
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ 
+ (defun org-html-reverse-assoc-list (assoc-list)
+   (mapcar (lambda (entry) (cons (cdr entry) (car entry))) assoc-list))
+ 
+ (defun org-html-element-title (element)
+   (org-element-property :raw-value element))
+ 
+ (defun org-html-increment-string-idx (string)
+   (if (string-match "\\([0-9]+\\)$" string)
+       (replace-match (format "%s" (1+ (read (match-string 0 string)))) nil nil string)
+     (format "%s-1" string)))
+ 
+ (defun org-html-unique-filename (string filenames)
+   "return a unique filename by appending -<num> to the string with
+ <num> starting from 1 and incrementing until the string is
+ unique in filenames."
+   (if (member string filenames)
+       (org-html-unique-filename
+        (org-html-increment-string-idx string) filenames)
+     string))
+ 
+ (defun org-html-replace-chars-with-dash (chars string)
+   (cl-reduce (lambda (accum x) (replace-regexp-in-string (format "%s+" x) "-" accum))
+            chars
+            :initial-value string))
+ 
+ (defun org-html-remove-chars (chars string)
+   (cl-reduce (lambda (accum x) (replace-regexp-in-string (format "%s+" x) "" accum))
+            chars
+            :initial-value string))
+ 
+ (defun org-html-string-to-filename (string)
+    (replace-regexp-in-string
+     "-+"  "-"
+     (org-html-remove-chars
+      '("(" ")" "*" "," ";" "{" "}" "'" "\\" "?")
+      (org-html-replace-chars-with-dash
+       '(" " "_" ":" "/")
+       (replace-regexp-in-string
+        "\\\\ast{}" "*"
+        (downcase (string-trim string)))))))
+ 
+ (defun org-html-string-prepend-section-numbering (string levels maxlevel)
+   "Prepend the chapter outline numbers given in levels to
+ string. Truncate levels to maxlevel or pad with zeroes if
+ required."
+   (cl-loop
+    for i from (1- maxlevel) downto 0
+    with result = string
+    do (setq result (format "%02d_%s" (or (nth i levels) 0) result))
+    finally (return result)))
+ 
+ (defun org-html--get-multipage-page-url (element info)
+   "Return the url of the page containing ELEMENT."
+   (alist-get
+    (org-html-get-multipage-tl-headline element info)
+    (plist-get info :tl-url-lookup)))
+ 
+ (defun org-html--full-reference (destination info &optional page-only)
+   "Return an appropriate reference for DESTINATION. Like
+ org-html--reference, but generating an extended cross-page
+ reference for multipage.
+ 
+ DESTINATION is an element or a `target' type object.  INFO is the
+ current export state, as a plist.
+ 
+ When PAGE-ONLY is non-nil just return the page reference."
+   (if (plist-get info :multipage)
+       (concat (org-html--get-multipage-page-url destination info)
+               (if page-only ""
+                 (format "#%s" (org-export-get-reference destination info))))
+     (format "#%s" (org-export-get-reference destination info))))
+ 
+ (defun org-html-multipage-toc (depth info &optional scope)
+   "Build a table of contents for a page in multipage
+ export. `:tl-headline-number' and `:tl-headline' refer to the
+ current page and have to be supplied in INFO.
+ 
+ DEPTH is an integer specifying the depth of the table.  INFO is a
+ plist used as a communication channel.  Optional argument SCOPE
+ is an element defining the scope of the table.  Return the table
+ of contents as a string, or nil if it is empty."
+   (let* ((tl-headline-number (plist-get info :tl-headline-number))
+          (tl-headline (unless (plist-get info :full-toc) (plist-get info :tl-headline)))
+          (curr-number-ref tl-headline-number)
+          (toc-entries
+ 	  (cl-loop
+            for (entry . props) in (plist-get info :multipage-toc-lookup)
+            if (<= (length (plist-get props :toc-hl-number)) depth)
+            collect (let* ((tl-hl (plist-get props :tl-hl))
+                           (page-headline-number (plist-get props :page-hl-number)))
+                      (if (eq tl-hl tl-headline)
+                          (setf curr-number-ref page-headline-number))
+                      (cl-list*
+                       (org-html--format-mp-toc-headline
+                        (plist-get props :href)
+                        (plist-get props :toc-body)
+                        (equal (plist-get props :tl-hl) tl-headline)
+                        (plist-get info :full-toc))
+                       (unless (plist-get info :full-toc)
+                         (org-html--hidden-in-toc? page-headline-number
+                                                   curr-number-ref))
+                       (plist-get props :relative-level))))))
+     (when toc-entries
+       (let ((toc (concat "<div id=\"text-table-of-contents\" role=\"doc-toc\">"
+ 			 (org-html--toc-text toc-entries)
+ 			 "</div>\n")))
+ 	(if scope toc
+ 	  (let ((outer-tag (if (org-html--html5-fancy-p info)
+ 			       "nav"
+ 			     "div")))
+ 	    (concat (format "<%s id=\"table-of-contents\" role=\"doc-toc\">\n" outer-tag)
+ 		    (let ((top-level (plist-get info :html-toplevel-hlevel)))
+ 		      (format "<h%d>%s</h%d>\n"
+ 			      top-level
+ 			      (org-html--translate
+                                (or (plist-get info :html-toc-title)
+                                    org-html-toc-title)
+                                info)
+ 			      top-level))
+ 		    toc
+ 		    (format "</%s>\n" outer-tag))))))))
+ 
+ (defun org-html--get-toc-body (headline info)
+   "Return the body of the toc entry of HEADLINE. INFO is a plist
+ used as a communication channel."
+   (let* ((headline-number (org-html-get-multipage-headline-number headline info))
+ 	 (todo (and (plist-get info :with-todo-keywords)
+ 		    (let ((todo (org-element-property :todo-keyword headline)))
+ 		      (and todo (org-export-data todo info)))))
+ 	 (todo-type (and todo (org-element-property :todo-type headline)))
+ 	 (priority (and (plist-get info :with-priority)
+ 			(org-element-property :priority headline)))
+ 	 (text (org-export-data-with-backend
+ 		(org-export-get-alt-title headline info)
+ 		(org-export-toc-entry-backend 'html)
+ 		info))
+ 	 (tags (and (eq (plist-get info :with-tags) t)
+ 		    (org-export-get-tags headline info))))
+     ;; Body.
+     (concat
+      (and (not (org-export-low-level-p headline info))
+           (plist-get info :section-numbers)
+           (concat
+            (mapconcat #'number-to-string headline-number ".")
+            "&nbsp;&nbsp;"))
+      (apply (plist-get info :html-format-headline-function)
+             todo todo-type priority text tags :section-number nil))))
+ 
+ (defun org-html--format-mp-toc-headline (href body active full-toc)
+   "Return a table of contents entry for multipage output."
+   (format "<a %s>%s</a>"
+           ;; Target
+           (format "href=\"%s\"%s"
+                   href
+                   (concat
+                    "class=\""
+                    (if full-toc "inline-toc-entry"
+                      "toc-entry")
+                    (if active
+                        " toc-active" "")
+                    "\""))
+           
+           ;; Body.
+           body))
+ 
+ (defun org-html-multipage-ensure-export-dir (dir)
+   "get the full pathname of dir and ensure it exists."
+   (when (symbolp dir) (setq dir (format "%s" dir)))
+   (unless (= (aref dir 0) 47)
+     (setq dir (concat (file-name-directory (buffer-file-name)) dir)))
+   (unless (file-directory-p dir)
+     (make-directory dir :parents))
+   dir)
+ 
+ (defun org-html-multipage-split-tree (info)
+   (let ((split-ref (plist-get info :html-multipage-split-level))
+         (headline-numbering (plist-get info :headline-numbering)))
+     (cond
+      ((eq split-ref 'toc)
+       (let ((maxdepth (if (numberp (plist-get info :with-toc))
+                           (plist-get info :with-toc)
+                         (plist-get info :headline-levels))))
+         (plist-put info :export-depth maxdepth)
+         (org-html-page-headlines
+          (cl-remove-if (lambda (hl-num) (> (length hl-num) maxdepth))
+                        headline-numbering :key 'cdr)
+          info)))
+      ((numberp split-ref)
+       (plist-put info :export-depth split-ref)
+       (org-html-page-headlines
+        (cl-remove-if (lambda (hl-num) (> (length hl-num) split-ref))
+                      headline-numbering :key 'cdr)
+        info)))))
+ 
+ (defun org-html-transcode-multipage (info &optional body-only)
+   "Central routine transcoding to multipage output called by
+ `org-html-transcode-org-data' called from `org-export-as'.
+ 
+ The pages to be exported are in the :multipage-org-pages property
+ of info as a list of org-page pseudo elements. This function
+ transcodes the org-pages and returns a list of the transcoded
+ output strings with their filename as :output-file Text Property
+ to be further processed by the function calling `org-export-as'.
+ 
+ INFO is the communication channel.
+ "
+   (let ((async (plist-get info :async))
+         (post-process (plist-get info :post-process)))
+     (declare (indent 2))
+     (setq global-output
+           (cl-loop
+            for org-page in (plist-get info :multipage-org-pages)
+            collect (let ((file (org-element-property :output-file org-page)))
+                      (message "transcoding: %s" file)
+                      (let ((output (org-html-transcode-org-page org-page info)))
+                        (put-text-property 0 1 :output-file file output)
+                        output))))))
+ 
+ (defun org-html-multipage-split (data _backend info)
+   "Filter routine to collect all properties relevant to multipage
+ output. It is called in the context of calling all
+ :filter-parse-tree alist functions in `org-export-annotate-info'
+ after the parse-tree is completed and its properties
+ collected. The function takes care of splitting the parse-tree
+ into the subtrees for each page, creating org-page pseudo
+ elements, adding them in a list in the :multipage-org-pages
+ property of info. In addition lookup alists for the stripped
+ pages, for the page-urls, the navigation elements, the toc,
+ etc. are added to info, which are needed by the html transcoders.
+ 
+ DATA is the completed parse-tree of the document.
+ 
+ INFO is the communication channel.
+ "
+   (if (plist-get info :multipage)
+       (let ((dir (plist-get info :verified-export-directory))
+             (async (plist-get info :async))
+             (post-process (plist-get info :post-process)))
+         (declare (indent 2))
+         (plist-put info :headline-numbering
+                    (org-export--collect-headline-numbering
+                     (plist-get info :parse-tree)
+                     (cl-list* :section-numbers t info)))
+         (if (not (file-writable-p dir)) (error "Output dir not writable")
+           (let* ((encoding (or org-export-coding-system buffer-file-coding-system))
+                  (headline-numbering (plist-get info :headline-numbering))
+                  ;; each entry in exported-headline-numbering will become a
+                  ;; single page in multipage output.
+                  (exported-headline-numbering
+                   (let ((tmp (org-html-multipage-split-tree info)))
+                     (plist-put info :exported-headline-numbering tmp)
+                     tmp))
+                  (max-toc-depth (if (numberp (plist-get info :with-toc))
+                                     (plist-get info :with-toc)
+                                   (plist-get info :headline-levels)))
+                  ;; section-trees is a list of all sections which get
+                  ;; exported to a single page
+                  (section-trees
+                   (cl-loop
+                    for section-entry in exported-headline-numbering
+                    for keep-first-subhls = (plist-get info :keep-first-subhls) then (cdr keep-first-subhls)
+                    collect
+                    (let* ((section-number (cdr section-entry)))
+                      (if (< (length section-number) max-toc-depth)
+                          (org-html-element-remove-subheadlines
+                           (car section-entry)
+                           (car keep-first-subhls)
+                           max-toc-depth)
+                        (org-html-element-copy-element (car section-entry))))))
+                  ;; stripped-section-headline-numbering is the equivalent of
+                  ;; headline-numbering but replacing the car of its elements
+                  ;; with the stripped version of the headlines.
+                  (stripped-section-headline-numbering
+                   (cl-mapcar 'cons
+                              (cl-loop for section in section-trees
+                                       ;; collect all subheadlines to match
+                                       ;; headline-numbering:
+                                       append (org-element-map section 'headline
+                                                'identity))
+                              (mapcar 'cdr headline-numbering)))
+                  ;; lookup from all toc headline-numbers to the tl-headline.
+ )
+             ;; add stripped-section-headline-numbering to
+             ;; :headline-numbering, to make their headline-numbering
+             ;; accessible when generating the body of the individual
+             ;; pages.
+             (plist-put info :headline-numbering
+                        (append
+                         headline-numbering
+                         stripped-section-headline-numbering))
+             (plist-put info :section-trees section-trees)
+             (plist-put info :stripped-section-headline-numbering
+                        stripped-section-headline-numbering)
+             ;; tl-url-lookup associates the stripped section headlines
+             ;; with the names of the joined pages to export.
+             (plist-put info :tl-url-lookup (org-html--generate-tl-url-lookup info))
+             ;; lookup for the navigation elements of each page.
+             (plist-put info :section-nav-lookup
+                        (org-html--make-section-nav-lookup info))
+             (let ((section-filenames
+                    (mapcar
+                     (lambda (hl) (alist-get hl (plist-get info :tl-url-lookup)))
+                     section-trees)))
+               (plist-put info :section-filenames section-filenames)
+               ;; bidirectional lookup tables to map between the
+               ;; stripped-section headlines and their global
+               ;; parse-tree equvialent.
+               (plist-put
+                info :stripped-hl-to-parse-tree-hl
+                (append
+                 (cl-mapcar 'cons
+                            (mapcar 'car stripped-section-headline-numbering)
+                            (mapcar 'car headline-numbering))
+                 (cl-mapcar 'cons
+                            (mapcar 'car headline-numbering)
+                            (mapcar 'car stripped-section-headline-numbering))))
+               ;; collect the toc information to avoid repeated
+               ;; recalculation in the toc transcoder for the
+               ;; individual pages.
+               (plist-put info :multipage-toc-lookup
+                          (org-html--make-multipage-toc-lookup info))
+               ;; The url for the "top" link on each page.
+               (plist-put info :html-top-url
+                          (alist-get
+                           (car (plist-get info :section-trees))
+                           (plist-get info :tl-url-lookup)))
+               ;; The title for the "top" link on each page.
+               (plist-put info :html-top-title
+                          (org-html-element-title
+                           (car (plist-get info :section-trees))))
+               ;; collect all org-pages to be exported.
+               (plist-put info :multipage-org-pages
+                          (cl-loop
+                           for file in section-filenames
+                           for tl-headline in section-trees
+                           collect
+                           (list 'org-page
+                                 (list :output-file (format "%s/%s" dir file)
+                                       :tl-headline tl-headline
+                                       :tl-headline-number
+                                       (alist-get
+                                        tl-headline
+                                        stripped-section-headline-numbering))
+                                 nil))))))))
+   data)
+ 
+ (defun org-html--generate-tl-url-lookup (info)
+   "Return an assoc list for all headlines appearing in the toc
+ and the url names of the page they're on."
+   (let ((extension (plist-get info :html-extension))
+         (stripped-section-headline-numbering
+          (plist-get info :stripped-section-headline-numbering))
+         filenames)
+     (mapcar
+      (lambda (entry)
+        (let* ((tl-elem (org-html-element-get-top-level entry))
+               (title (org-html-element-title tl-elem)))
+          (cons
+           entry
+           (format "%s.%s"
+                   (car (push
+                         (org-html-unique-filename
+                          (if (plist-get info :html-multipage-numbered-filenames)
+                              (org-html-string-prepend-section-numbering
+                               (org-html-string-to-filename title)
+                               (cdr (assoc
+                                     tl-elem
+                                     stripped-section-headline-numbering))
+                               org-export-headline-levels)
+                            (org-html-string-to-filename title))
+                          filenames)
+                         filenames))
+                   extension))))
+      (plist-get info :section-trees))))
+ 
+ (defun org-html--make-section-nav-lookup (info)
+   "Return an assoc-list for the headlines of all
+ exported pages with a plist containing titles and urls for the
+ section and its navigation."
+   (let* ((stripped-section-headline-numbering (plist-get info :stripped-section-headline-numbering))
+          ;;; first collect navigation-info once for each page only
+          (nav (mapcar (lambda (hl)
+                         (let* ((hl-number (alist-get hl stripped-section-headline-numbering))
+                                (up (car (rassoc (butlast hl-number) stripped-section-headline-numbering))))
+                           (list hl
+                                 (org-html-element-title hl)
+                                 (org-html--full-reference hl info t)
+                                 (org-html-element-title up)
+                                 (and up (org-html--full-reference up info t)))))
+                       (plist-get info :section-trees))))
+     ;;; collect the info for prev, curr, next and up navigation for
+     ;;; each page by cdr-ing over nav.
+     (cl-labels ((inner (prev-entry curr-entry)
+                   (let ((prev (car prev-entry))
+                         (curr (car curr-entry))
+                         (next (cadr curr-entry)))
+                     (if curr
+                         (cons (list (car curr)
+                                     :prev-title (nth 1 prev)
+                                     :curr-title (nth 1 curr)
+                                     :next-title (nth 1 next)
+                                     :up-title (nth 3 curr)
+                                     :prev-url (nth 2 prev)
+                                     :curr-url (nth 2 curr)
+                                     :next-url (nth 2 next)
+                                     :up-url (nth 4 curr))
+                               (inner (cdr prev-entry) (cdr curr-entry)))))))
+       (inner (cons nil nav) nav))))
+ 
+ (defun org-html--make-multipage-toc-lookup (info)
+   "Return an assoc-list containing info for the headlines of all toc entries."
+   (mapcar
+    (lambda (hl)
+      (let* ((tl-hl (org-html-element-get-top-level hl)))
+        (list hl
+              :href (org-html--full-reference hl info (plist-get info :html-multipage-toc-to-top))
+              :tl-hl tl-hl
+              :relative-level (org-export-get-relative-level hl info)
+              :toc-body (org-html--get-toc-body hl info)
+              :toc-hl-number (alist-get hl (plist-get info :headline-numbering))
+              :page-hl-number (org-html-get-multipage-headline-number hl info))))
+    (org-html-collect-local-headlines info nil)))
+ 
+ (defun org-html-get-multipage-tl-headline (element info)
+   "return the headline of the page containing
+ element. This requires that :headline-numbering has already been
+ added to info (done in org-export--collect-tree-properties)."
+   (let* ((elem element)
+          (parent (org-element-property :parent elem)))
+     (while parent
+       (setf elem parent)
+       (setf parent (org-element-property :parent elem)))
+     elem))
+ 
+ (defun org-html-get-multipage-headline-numbering (element info)
+   "return the headline of the section containing
+ element. This requires that :headline-numbering has already been
+ added to info (done in org-export--collect-tree-properties)."
+   (let* ((elem element)
+          (parent (org-element-property :parent elem))
+          (hl-numbering (assoc elem (plist-get info :stripped-section-headline-numbering))))
+     (while (not hl-numbering)
+       (setf elem parent)
+       (setf parent (org-element-property :parent elem))
+       (setf hl-numbering (assoc elem (plist-get info :stripped-section-headline-numbering))))
+     hl-numbering))
+ 
+ (defun org-html-get-multipage-headline-number (element info)
+   "return the headline-number of the section containing
+ element. This requires that :headline-numbering has already been
+ added to info (done in org-export--collect-tree-properties)."
+   (cdr (org-html-get-multipage-headline-numbering element info)))
+ 
+ (defun org-html-element-get-top-level (element)
+   "Return the top-level element of ELEMENT by traversing the parse
+ tree upwards until the parent of element is nil."
+   (let ((elem element)
+         (parent (org-element-property :parent element)))
+     (while parent
+       (setq elem parent)
+       (setq parent (org-element-property :parent elem)))
+     elem))
+ 
+ (defun org-html-element-copy-element (org-node &optional keep-parent)
+   "copy ORG-NODE to a new org-node with elements not copied,
+ but referenced."
+   (let* (headline
+          (props (copy-sequence (nth 1 org-node)))
+          (new (list (car org-node) props)))
+     (unless keep-parent (setf (org-element-property :parent new) nil))
+     (apply 'org-element-adopt-elements new (org-element-contents org-node))))
+ 
+ (defun org-html-element-remove-subheadlines (org-node &optional
+                                                       keep-first-subheadlines max-toc-depth keep-parent)
+   "remove all elements starting with and including the first headline
+ in the children of ORG-NODE if JOIN_EMPTY_BODIES is nil. Returns a
+ new ast with all elements starting at START-CHILD-IDX copied into
+ it with the :parent property optionally removed in the top node."
+   (let* ((num-subheadlines 0)
+          contents-end
+          headline
+          (props (copy-sequence (nth 1 org-node)))
+          (new (list (car org-node) props))
+          (new-children (cl-loop
+                         for x in (org-element-contents org-node)
+                         with exit = nil
+                         do (if (and
+                                 (consp x)
+                                 (eq (org-element-type x) 'headline))
+                                (if (and (car keep-first-subheadlines) (zerop num-subheadlines))
+                                    (progn
+                                      (setf num-subheadlines (1+ num-subheadlines))
+                                      (if (< (org-element-property :level x) max-toc-depth)
+                                          (setq x (org-html-element-remove-subheadlines
+                                                   x (cdr keep-first-subheadlines) max-toc-depth))))
+                                  (progn
+                                    (setq contents-end (org-element-property :begin x))
+                                    (setq exit t))))
+                         until exit
+                         collect x)))
+     (unless keep-parent (setf (org-element-property :parent new) nil))
+     (apply 'org-element-adopt-elements new new-children)))
+ 
+ (defun org-html-find-headline (headline-number headline-numbering)
+   "return the headline in headline numbering for a given
+ headline-number."
+   (cond
+    ((null headline-numbering) nil)
+    ((equal headline-number (cdar headline-numbering))
+     (caar headline-numbering))
+    (t (org-html-find-headline headline-number (cdr headline-numbering)))))
+ 
+ (defun org-html-element-body-text (element info)
+   "check if transcoding of the contents of element until the next
+ subheadline returns an empty string."
+   (let ((strings
+          (cl-loop
+           for elem in (org-element-contents element)
+           while (not (eq 'headline (org-element-type elem)))
+           collect (org-export-data elem info))))
+     (string-trim
+      (apply 'concat
+             (with-temp-buffer
+               (mapcar 'insert strings)
+               (dom-strings (libxml-parse-html-region (point-min) (point-max))))))))
+ 
+ (defun org-html-element-body-text? (element info)
+   "check if transcoded element produces any text."
+   (not (eq "" (org-html-element-body-text element info))))
+ 
+ (defun org-html-page-headlines (headlines info)
+   "collect the headlines of all pages to export. In case of
+ html-multipage-join-empty-bodies don't collect the headlines to
+ be joined and keep track by collecting them for each page
+ headline in :keep-first-subhls.
+ `org-html-element-remove-subheadlines'"
+   (if (plist-get info :html-multipage-join-empty-bodies)
+       (cl-loop for (prev curr-headline) on (cons nil headlines)
+                with collect-hl = nil
+                with tmp = nil
+                with keep-shl = nil
+                while curr-headline
+                do (progn
+                     (setf
+                      collect-hl
+                      (or         ;; collect curr-headline either
+                       (not prev) ;; when it is the first headline
+                       (<= (length (cdr curr-headline))
+                           (length (cdr prev))) ;; when it is not a subheadline of prev.
+                       ;; or when the previous headline contains body text
+                       (org-html-element-body-text? (car prev) info)))
+                     (if collect-hl
+                         (progn (push (reverse tmp) keep-shl)
+                                (setf tmp nil))
+                       (push t tmp)))
+                if collect-hl collect curr-headline
+                finally (progn (push tmp keep-shl)
+                               (plist-put info :keep-first-subhls (cdr (reverse keep-shl)))))
+     headlines))
+ 
+ (defun org-html-transcode-org-page (page info)
+   "transcode the headline tree in the contents of the org-page
+ pseudo element PAGE into a string according to the backend and
+ return the string.
+ 
+ INFO is used as communication channel."
+   (let* ((body-only (org-element-property :body-only page))
+          (headline (org-element-property :tl-headline page))
+          (info (cl-list*
+                 :tl-headline headline
+                 :tl-headline-number (org-element-property :tl-headline-number page)
+                 info))
+          (body (org-element-normalize-string
+                 (or (org-export-data headline info)
+                     "")))
+ 	 (inner-template (if (plist-get info :multipage)
+                              (alist-get 'multipage-inner-template
+                                         (plist-get info :translate-alist))
+                            (alist-get 'inner-template
+                                         (plist-get info :translate-alist))))
+ 	 (full-body (org-export-filter-apply-functions
+ 		     (plist-get info :filter-body)
+ 		     (if (not (functionp inner-template)) body
+                          (funcall inner-template body info))
+ 		     info))
+ 	 (template (if (plist-get info :multipage)
+                        (cdr (assq 'multipage-template
+                                   (plist-get info :translate-alist)))
+                      (cdr (assq 'template
+                                   (plist-get info :translate-alist)))))
+          (output
+           (if (or (not (functionp template)) body-only) full-body
+ 	    (funcall template full-body info))))
+     ;; Call citation export finalizer.
+     (setq output (org-cite-finalize-export output info))
+     ;; Remove all text properties since they cannot be
+     ;; retrieved from an external process.  Finally call
+     ;; final-output filter and return result.
+     (org-no-properties
+      (org-export-filter-apply-functions
+       (plist-get info :filter-final-output)
+       output info))))
+ 
+ (defun org-html-export-to-multipage
+     (&optional async subtreep visible-only body-only ext-plist post-process)
+   "Export current buffer to multipage HTML files.
+ 
+ If narrowing is active in the current buffer, only export its
+ narrowed part.
+ 
+ If a region is active, export that region.
+ 
+ A non-nil optional argument ASYNC means the process should happen
+ asynchronously.  The resulting files should be accessible through
+ the `org-export-stack' interface.
+ 
+ When optional argument SUBTREEP is non-nil, export the sub-tree
+ at point, extracting information from the headline properties
+ first.
+ 
+ When optional argument VISIBLE-ONLY is non-nil, don't export
+ contents of hidden elements.
+ 
+ When optional argument BODY-ONLY is non-nil, only write code
+ between \"<body>\" and \"</body>\" tags.
+ 
+ EXT-PLIST, when provided, is a property list with external
+ parameters overriding Org default settings, but still inferior to
+ file-local settings.
+ 
+ Return output directory's name."
+   (interactive)
+   (let* ((extension (concat
+ 		     (when (> (length org-html-extension) 0) ".")
+ 		     (or (plist-get ext-plist :html-extension)
+ 			 org-html-extension
+ 			 "html")))
+          (backend 'html)
+          (encoding (or org-export-coding-system buffer-file-coding-system))
+ 	 (org-export-coding-system org-html-coding-system)
+          (environment (org-export-get-environment 'html nil nil))
+          (dir (org-html-multipage-ensure-export-dir
+                (plist-get environment :html-multipage-export-directory))))
+     (if (not (file-writable-p dir)) (error "Output dir not writable")
+       (progn
+         (message "collecting multipage output...")
+        (let ((output
+               (org-export-as backend subtreep visible-only body-only
+                              (cl-list*
+                               :async async
+                               :multipage t
+                               :verified-export-directory dir
+                               ext-plist))))
+          (when (plist-get environment :html-multipage-clear-export-directory)
+            (message "clearing export-directory.")
+            (dolist
+                (file (directory-files dir nil ".html$"))
+              (delete-file (format "%s/%s" dir file))))
+          (dolist (out output)
+            (if async
+                (org-export-async-start
+                    (lambda (file)
+                      (org-export-add-to-stack (expand-file-name file) backend))
+                  `(let ((file (get-text-property 0 :ouput-file out)))
+                     (setq file (org-export--write-output output ',encoding))
+                     (let ((post (lambda (f) (or (ignore-errors (funcall ',post-process f)) f))))
+                       (if (listp file) (mapcar post file) (funcall post file)))))
+              (let (file)
+                (setq file (org-export--write-output out encoding))
+                (when (and (org-export--copy-to-kill-ring-p) (org-string-nw-p output))
+                  (org-kill-new output))
+                ;; Get proper return value.
+                (let ((post (lambda (f)
+                              (or (and (functionp post-process)
+                                       (funcall post-process f))
+                                  f))))
+                  (if (listp file) (mapcar post file) (funcall post file))))))
+          (if (member system-type '(darwin gnu/linux gnu))
+              (shell-command (format "ln -s %s %s/index.html" (get-text-property 0 :output-file (car output)) dir)))
+          (message "done!\n")
+          (cl-case (plist-get environment :html-multipage-open)
+            ('browser (org-open-file (format "%s" (get-text-property 0 :output-file (car output)))))
+            ('buffer (find-file (format "%s" (get-text-property 0 :output-file (car output)))))))))))
+ 
+ (defun org-html--hidden-in-toc? (headline-number tl-headline-number)
+   "Check if the entry of HEADLINE-NUMBER should be hidden in the
+ toc of the page containing TL-HEADLINE-NUMBER."
+   (and
+    (> (length headline-number) 1)
+    (let ((l1 (length headline-number))
+          (l2 (length tl-headline-number)))
+      (cond
+       ((= l1 l2) (not (equal (butlast headline-number)
+                              (butlast tl-headline-number))))
+       ((> l1 l2) (not (equal tl-headline-number
+                              (butlast headline-number))))
+       (t (not (equal (butlast headline-number)
+                      (butlast (butlast tl-headline-number)))))))))
+ 
+ (defun org-html-collect-local-headlines (info scope)
+   "Collect all headlines of headline-numbering from their local
+ tl-headlines counterparts."
+   (let ((stripped-section-headline-numbering (plist-get info :stripped-section-headline-numbering))
+         (headline-numbering (plist-get info :headline-numbering)))
+     (mapcar
+      (lambda (global-headline)
+        (car
+         (rassoc (cdr (assoc global-headline headline-numbering))
+                 stripped-section-headline-numbering)))
+      (org-export-collect-headlines
+       info
+       (if (numberp (plist-get info :with-toc))
+           (plist-get info :with-toc)
+         (plist-get info :headline-levels))
+       scope))))
+ 
+ (defun org-html-nav-left (nav-lookup)
+   "Return nav string for multipage Navigation in page-main-body.
+ 
+ INFO is a plist used as a communication channel.
+ "
+   (let* ((prev-url (plist-get nav-lookup :prev-url))
+          (prev-title (plist-get nav-lookup :prev-title)))
+     (if prev-url
+         (format "<nav id=\"nav-left\"><a href=\"%s\" class=\"nav-left\"><i class=\"angle-left\"></i></a></nav>"
+                 prev-url)
+       (format "<nav id=\"nav-left\"><a href=\"%s\" class=\"nav-left\"><i class=\"angle-left-inactive\"></i></a></nav>"
+               ""))))
+ 
+ (defun org-html-nav-right (nav-lookup)
+   "Return nav string for multipage Navigation in page-main-body.
+ 
+ INFO is a plist used as a communication channel.
+ "
+   (let* ((next-url (plist-get nav-lookup :next-url))
+          (next-title (plist-get nav-lookup :next-title)))
+     (if next-url
+         (format "<nav id=\"nav-right\"><a href=\"%s\" class=\"nav-right\"><i class=\"angle-right\"></i></a></nav>"
+                 next-url)
+       (format "<nav id=\"nav-right\"><a href=\"%s\" class=\"nav-right\"><i class=\"angle-right-inactive\"></i></a></nav>"
+               ""))))
+ 
+ (defun org-html-multipage-nav (info)
+   "Return the string for the multipage navigation anchors.
+ 
+ INFO is a plist used as a communication channel.
+ "
+   (let ((section-nav-lookup
+           (alist-get
+            (plist-get info :tl-headline)
+            (plist-get info :section-nav-lookup)))
+          (nav-format (plist-get info :html-multipage-nav-format)))
+      (format (car nav-format)
+              (concat
+               (when (plist-get section-nav-lookup :next-url)
+                 (format (cadr nav-format)
+                         (plist-get section-nav-lookup :next-url)
+                         (plist-get section-nav-lookup :next-title)))
+               (when (plist-get section-nav-lookup :prev-url)
+                 (format (caddr nav-format)
+                         (plist-get section-nav-lookup :prev-url)
+                         (plist-get section-nav-lookup :prev-title)))
+               (when (plist-get section-nav-lookup :up-url)
+                     (format (cadddr nav-format)
+                             (plist-get section-nav-lookup :up-url)
+                             (plist-get section-nav-lookup :up-title)))
+               (when (plist-get info :html-top-url)
+                   (format (nth 4 nav-format)
+                           (plist-get info :html-top-url)
+                           (plist-get info :html-top-title)))))))
+ 
+ (defun org-html-multipage-template (contents info)
+   "Return complete document string after HTML conversion.
+ CONTENTS is the transcoded contents string.  INFO is a plist
+ holding export options."
+   (concat
+    (when (and (not (org-html-html5-p info)) (org-html-xhtml-p info))
+      (let* ((xml-declaration (plist-get info :html-xml-declaration))
+ 	    (decl (or (and (stringp xml-declaration) xml-declaration)
+ 		      (cdr (assoc (plist-get info :html-extension)
+ 				  xml-declaration))
+ 		      (cdr (assoc "html" xml-declaration))
+ 		      "")))
+        (when (not (or (not decl) (string= "" decl)))
+ 	 (format "%s\n"
+ 		 (format decl
+ 			 (or (and org-html-coding-system
+                                   ;; FIXME: Use Emacs 22 style here, see `coding-system-get'.
+ 				  (coding-system-get org-html-coding-system 'mime-charset))
+ 			     "iso-8859-1"))))))
+    (org-html-doctype info)
+    "\n"
+    (concat "<html"
+ 	   (cond ((org-html-xhtml-p info)
+ 		  (format
+ 		   " xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"%s\" xml:lang=\"%s\""
+ 		   (plist-get info :language) (plist-get info :language)))
+ 		 ((org-html-html5-p info)
+ 		  (format " lang=\"%s\"" (plist-get info :language))))
+ 	   ">\n")
+    "<head>\n"
+    (org-html--build-meta-info info)
+    (org-html--build-head info)
+    (org-html--build-mathjax-config info)
+    "</head>\n"
+    "<body>\n"
+    (when (eq org-html-multipage-preamble-position 'top)
+      (org-html--build-pre/postamble 'preamble info))
+    (org-html-multipage-nav info)
+      ;; Preamble.
+    (unless (eq org-html-multipage-preamble-position 'top)
+      (org-html--build-pre/postamble 'preamble info))
+    ;; Document contents.
+    (let ((div (assq 'content (plist-get info :html-divs))))
+      (format "<%s id=\"%s\" class=\"%s\">\n"
+              (nth 1 div)
+              (nth 2 div)
+              (plist-get info :html-content-class)))
+    ;; Table of contents.
+    (let ((depth (if (numberp (plist-get info :with-toc))
+                     (plist-get info :with-toc)
+                   (plist-get info :headline-levels))))
+      (when depth (org-html-multipage-toc depth info)))
+    ;; Document title.
+    (when (plist-get info :with-title)
+      (let ((title (and (plist-get info :with-title)
+ 		       (plist-get info :title)))
+ 	   (subtitle (plist-get info :subtitle))
+ 	   (html5-fancy (org-html--html5-fancy-p info)))
+        (when title
+ 	 (format
+ 	  (if html5-fancy
+ 	      "<header>\n<h1 class=\"title\">%s</h1>\n%s</header>"
+ 	    "<h1 class=\"title\">%s%s</h1>\n")
+ 	  (org-export-data title info)
+ 	  (if subtitle
+ 	      (format
+ 	       (if html5-fancy
+ 		   "<p class=\"subtitle\" role=\"doc-subtitle\">%s</p>\n"
+ 		 (concat "\n" (org-html-close-tag "br" nil info) "\n"
+ 			 "<span class=\"subtitle\">%s</span>\n"))
+ 	       (org-export-data subtitle info))
+ 	    "")))))
+    contents
+    (format "</%s>\n" (nth 1 (assq 'content (plist-get info :html-divs))))
+    ;; Possibly use the Klipse library live code blocks.
+    (when (plist-get info :html-klipsify-src)
+      (concat "<script>" (plist-get info :html-klipse-selection-script)
+ 	     "</script><script src=\""
+ 	     org-html-klipse-js
+ 	     "\"></script><link rel=\"stylesheet\" type=\"text/css\" href=\""
+ 	     org-html-klipse-css "\"/>"))
+    (when (eq org-html-multipage-postamble-position 'bottom)
+      (org-html--build-pre/postamble 'postamble info))
+    ;; Closing document.
+    "</body>\n</html>"))
+ 
+ (defun org-html-multipage-inner-template (contents info)
+   "Return body of document string after HTML conversion.
+ CONTENTS is the transcoded contents string.  INFO is a plist
+ holding export options.
+ 
+ DATA contains the subtree of the parse tree of the section to be
+ exported for multipage export.
+ "
+   ;; Navigation
+   (let* ((data (plist-get info :tl-headline))
+          (section-nav-lookup
+              (alist-get
+               data
+               (plist-get info :section-nav-lookup))))
+     (format "<div id=\"page-main-body\">%s\n<div id=\"page-text-body\">%s</div>%s</div>"
+             (org-html-nav-left section-nav-lookup)
+             (concat
+              ;; Document contents.
+              contents
+              ;; Footnotes section.
+              (or (org-html-footnote-section info) "")
+              ;; Postamble.
+              (unless (eq org-html-multipage-postamble-position 'bottom)
+                (org-html--build-pre/postamble 'postamble info)))
+             (org-html-nav-right section-nav-lookup))))
+ 
+ (defun org-html-transcode-org-data (data content info)
+   "Transcode the top org-data node of the org file to export.
+ 
+ It is called by `org-export-as' after all necessary information
+ has been added to info and the final parse-tree has been
+ generated. Multipage information has already been collected by
+ calling `org-html-multipage-filter' in `org-export-annotate-info'
+ using the :multipage-split property.
+ 
+ INFO is a plist used as a communication channel."
+   (message "transcoding data!")
+   (if (plist-get info :multipage)
+       ;;; for multipage output we don't need data and content as all
+       ;;; information is already collected in info.
+       (org-html-transcode-multipage info)
+     (org-export-transcode-org-data data content info)))
  
  (provide 'ox-html)
  
***************
*** 4100,4102 ****
--- 5485,5489 ----
  ;; End:
  
  ;;; ox-html.el ends here
+ 
+ 

[-- Attachment #5: org-manual.org.patch --]
[-- Type: text/plain, Size: 16184 bytes --]

*** org-mode/doc/org-manual.org	2024-08-05 17:15:57.585261838 +0200
--- org-mode-multipage/doc/org-manual.org	2024-08-05 15:40:24.679134249 +0200
***************
*** 772,781 ****
    where you can use the following keys to find your destination:
  
    #+attr_texinfo: :columns 0.3 0.7
!   | {{{kbd(TAB)}}}            | Cycle visibility.               |
    | {{{kbd(DOWN)}}} / {{{kbd(UP)}}} | Next/previous visible headline. |
!   | {{{kbd(RET)}}}            | Select this location.           |
!   | {{{kbd(/)}}}              | Do a Sparse-tree search         |
  
    #+texinfo: @noindent
    The following keys work if you turn off ~org-goto-auto-isearch~
--- 772,781 ----
    where you can use the following keys to find your destination:
  
    #+attr_texinfo: :columns 0.3 0.7
!   | {{{kbd(TAB)}}}                  | Cycle visibility.               |
    | {{{kbd(DOWN)}}} / {{{kbd(UP)}}} | Next/previous visible headline. |
!   | {{{kbd(RET)}}}                  | Select this location.           |
!   | {{{kbd(/)}}}                    | Do a Sparse-tree search         |
  
    #+texinfo: @noindent
    The following keys work if you turn off ~org-goto-auto-isearch~
***************
*** 783,791 ****
    #+attr_texinfo: :columns 0.3 0.7
    | {{{kbd(n)}}} / {{{kbd(p)}}}   | Next/previous visible headline.    |
    | {{{kbd(f)}}} / {{{kbd(b)}}}   | Next/previous headline same level. |
!   | {{{kbd(u)}}}            | One level up.                      |
    | {{{kbd(0)}}} ... {{{kbd(9)}}} | Digit argument.                    |
!   | {{{kbd(q)}}}            | Quit.                              |
  
    #+vindex: org-goto-interface
    #+texinfo: @noindent
--- 783,791 ----
    #+attr_texinfo: :columns 0.3 0.7
    | {{{kbd(n)}}} / {{{kbd(p)}}}   | Next/previous visible headline.    |
    | {{{kbd(f)}}} / {{{kbd(b)}}}   | Next/previous headline same level. |
!   | {{{kbd(u)}}}                  | One level up.                      |
    | {{{kbd(0)}}} ... {{{kbd(9)}}} | Digit argument.                    |
!   | {{{kbd(q)}}}                  | Quit.                              |
  
    #+vindex: org-goto-interface
    #+texinfo: @noindent
***************
*** 2044,2050 ****
  
  #+attr_texinfo: :columns 0.2 0.8
  | =$1..$3=      | first three fields in the current row                          |
! | =$P..$Q=      | range, using column names (see [[*Advanced features]])             |
  | =$<<<..$>>=   | start in third column, continue to the last but one            |
  | =@2$1..@4$3=  | nine fields between these two fields (same as =A2..C4=)        |
  | =@-1$-2..@-1= | 3 fields in the row above, starting from 2 columns on the left |
--- 2044,2050 ----
  
  #+attr_texinfo: :columns 0.2 0.8
  | =$1..$3=      | first three fields in the current row                          |
! | =$P..$Q=      | range, using column names (see [[*Advanced features]])         |
  | =$<<<..$>>=   | start in third column, continue to the last but one            |
  | =@2$1..@4$3=  | nine fields between these two fields (same as =A2..C4=)        |
  | =@-1$-2..@-1= | 3 fields in the row above, starting from 2 columns on the left |
***************
*** 2248,2255 ****
  | =$1+$2;%.2f=       | Same, format result to two decimals              |
  | =exp($2)+exp($1)=  | Math functions can be used                       |
  | =$0;%.1f=          | Reformat current cell to 1 decimal               |
! | =($3-32)*5/9=      | Degrees F \to C conversion                         |
! | =$c/$1/$cm=        | Hz \to cm conversion, using =constants.el=         |
  | =tan($1);Dp3s1=    | Compute in degrees, precision 3, display SCI 1   |
  | =sin($1);Dp3%.1e=  | Same, but use ~printf~ specifier for display     |
  | =vmean($2..$7)=    | Compute column range mean, using vector function |
--- 2248,2255 ----
  | =$1+$2;%.2f=       | Same, format result to two decimals              |
  | =exp($2)+exp($1)=  | Math functions can be used                       |
  | =$0;%.1f=          | Reformat current cell to 1 decimal               |
! | =($3-32)*5/9=      | Degrees F \to C conversion                       |
! | =$c/$1/$cm=        | Hz \to cm conversion, using =constants.el=       |
  | =tan($1);Dp3s1=    | Compute in degrees, precision 3, display SCI 1   |
  | =sin($1);Dp3%.1e=  | Same, but use ~printf~ specifier for display     |
  | =vmean($2..$7)=    | Compute column range mean, using vector function |
***************
*** 11995,12001 ****
    #+attr_texinfo: :columns 0.1 0.9
    | {{{kbd(s)}}} | Sort the footnote definitions by reference sequence.               |
    | {{{kbd(r)}}} | Renumber the simple =fn:N= footnotes.                              |
!   | {{{kbd(S)}}} | Short for first {{{kbd(r)}}}, then {{{kbd(s)}}} action.                        |
    | {{{kbd(n)}}} | Rename all footnotes into a =fn:1= ... =fn:n= sequence.            |
    | {{{kbd(d)}}} | Delete the footnote at point, including definition and references. |
  
--- 11995,12001 ----
    #+attr_texinfo: :columns 0.1 0.9
    | {{{kbd(s)}}} | Sort the footnote definitions by reference sequence.               |
    | {{{kbd(r)}}} | Renumber the simple =fn:N= footnotes.                              |
!   | {{{kbd(S)}}} | Short for first {{{kbd(r)}}}, then {{{kbd(s)}}} action.            |
    | {{{kbd(n)}}} | Rename all footnotes into a =fn:1= ... =fn:n= sequence.            |
    | {{{kbd(d)}}} | Delete the footnote at point, including definition and references. |
  
***************
*** 13283,13288 ****
--- 13283,13299 ----
  
    Exports to a temporary buffer.  Does not create a file.
  
+ - {{{kbd(C-c C-e h m)}}} (~org-html-export-to-multipage~) ::
+   #+kindex: C-c C-e h m
+   #+findex: org-html-export-to-multipage
+ 
+   Export as multiple HTML files with a =.html= extension.  The
+   exported files are written into a directory specified with the
+   customization variable =org-html-multipage-export-dir=.  If
+   =org-html-clear-export-directory= is non-nil, all files with a
+   =.html= extension will be removed before writing the files.  Files
+   with duplicate names will be overwritten without warning.
+ 
  *** HTML specific export settings
  :PROPERTIES:
  :DESCRIPTION: Settings for HTML export.
***************
*** 13823,13831 ****
  #+vindex: org-html-head-extra
  #+cindex: @samp{HTML_INCLUDE_STYLE}, keyword
  The HTML export backend includes a compact default style in each
! exported HTML file.  To override the default style with another style,
! use these keywords in the Org file.  They will replace the global
! defaults the HTML exporter uses.
  
  #+cindex: @samp{HTML_HEAD}, keyword
  #+cindex: @samp{HTML_HEAD_EXTRA}, keyword
--- 13834,13844 ----
  #+vindex: org-html-head-extra
  #+cindex: @samp{HTML_INCLUDE_STYLE}, keyword
  The HTML export backend includes a compact default style in each
! exported HTML file[fn:: The constant is called
! ~org-html-style-default~ for single page output and
! ~org-html-multipage-style-default~ for multipage output].  To override
! the default style with another style, use these keywords in the Org
! file.  They will replace the global defaults the HTML exporter uses.
  
  #+cindex: @samp{HTML_HEAD}, keyword
  #+cindex: @samp{HTML_HEAD_EXTRA}, keyword
***************
*** 13855,13861 ****
  a =CUSTOM_ID= property.  You can also assign a specific class to
  a headline with the =HTML_HEADLINE_CLASS= property.
  
! Never change the ~org-html-style-default~ constant.  Instead, use other
  simpler ways of customizing as described above.
  
  *** JavaScript supported display of web pages
--- 13868,13875 ----
  a =CUSTOM_ID= property.  You can also assign a specific class to
  a headline with the =HTML_HEADLINE_CLASS= property.
  
! Never change the ~org-html-style-default~ and
! ~org-html-multipage-style-default~ constants.  Instead, use other
  simpler ways of customizing as described above.
  
  *** JavaScript supported display of web pages
***************
*** 13944,13949 ****
--- 13958,14124 ----
  variable ~org-infojs-options~.  If you always want to apply the script
  to your pages, configure the variable ~org-export-html-use-infojs~.
  
+ *** Multipage HTML specific export options
+     The options and custom variables for HTML export also apply to
+     multipage export.  In addition the variables below are applying to
+     multipage export. They can be set using the listed variable name
+     or using an in buffer option using the name without the =org-= at
+     the beginning as in the following example:
+ #+begin_src
+     #+OPTIONS: html-multipage-clear-export-directory:t
+ #+end_src
+ 
+ - ~org-html-multipage-clear-export-directory~ ::
+ 
+   #+vindex: org-html-multipage-clear-export-directory
+   Whether to clear all =.html= files in the export directory before
+   writing.
+   
+ - ~org-html-multipage-export-directory~ ::
+ 
+   #+vindex: org-html-multipage-export-directory
+   The directory where the multiple files will be written. Relative to
+   the path of the Org document or absolute.
+   
+ - ~org-html-multipage-head-include-default-style~ ::
+ 
+   #+vindex: org-html-multipage-head-include-default-style
+   Whether to include the default CSS style
+   (=org-html-multipage-style-default=) into every exported file.
+ 
+ - ~org-html-multipage-join-empty-bodies~ ::
+ 
+   #+vindex: org-html-multipage-join-empty-bodies
+   Recursively join subheadlines, if a headline doesn't contain any
+   text before its subheadline.
+ 
+   Example:
+   #+begin_example
+ ,* Headline 1
+ ,** Subheadline 1.1
+ ,*** Subsubheadline 1.1.1
+     Text of Subsubheadline 1.1.1
+   #+end_example
+   will be put on the same HTML page if this option is set, otherwise
+   Headline 1 and Subheadline 1.1 will each be put on a separate HTML
+   page with empty content.
+ 
+ - ~org-html-multipage-nav-format~ ::
+ 
+   #+vindex: org-html-multipage-nav-format
+   The HTML format string for the four navigation elements in the top
+   navigation menu of each page. See explanation of the variable
+   ~org-html-multipage-nav-format~.
+   
+ - ~org-html-multipage-numbered-filenames~ ::
+ 
+   #+vindex: org-html-multipage-numbered-filenames
+   Boolean indicating whether filenames in multipage export should get
+   their headline-numbering prepended.  Note that this option is
+   independent of the =num:= option and that the backend guarantees
+   that filenames are unique in any case.
+   
+ - ~org-html-multipage-open~ ::
+ 
+   #+vindex: org-html-multipage-open
+   If and where to open the top page of the multipage html after
+   export.  Possible values are =browser=, =buffer= or =nil=. Note that
+   all files will always be written, even for the =buffer= case.
+ 
+ - ~org-html-multipage-postamble-position~ ::
+ 
+   #+vindex: org-html-multipage-postamble-position
+   The position of the postamble in the html output.
+   Possible choices are =bottom= or =text-content=.
+   See [[*Multipage HTML specific CSS support]]
+   
+ - ~org-html-multipage-preamble-position~ ::
+ 
+   #+vindex: org-html-multipage-preamble-position
+   The position of the postamble in the html output.
+   Possible choices are =top= or =text-content=.
+   See [[*Multipage HTML specific CSS support]]
+ 
+ - ~org-html-multipage-split-hooks~ ::
+ 
+   #+vindex: org-html-multipage-split-hooks
+   list of additional custom functions to be called during the export
+   after multipage splitting has taken place and before transcoding
+   with the =info= communication channel as input.
+   
+ - ~org-html-multipage-split-level~ ::
+ 
+   #+vindex: org-html-multipage-split-level
+   Where to split the ORG file into multiple HTML pages. Can be either
+   =toc= for splitting into a separate page for each toc entry or a
+   number defining the maximum headline level for splitting.
+   
+ - ~org-html-multipage-toc-to-top~ ::
+ 
+   #+vindex: org-html-multipage-toc-to-top
+   If t links in the table of contents will always point to the top of
+   the referenced page, otherwise it will link directly to the
+   referenced headline element.
+ 
+ *** Multipage HTML specific CSS support
+ :PROPERTIES:
+ :DESCRIPTION: Changing the appearance of the Multipage HTML output.
+ :END:
+ #+cindex: CSS, for Multipage HTML export
+ #+cindex: HTML Multipage export, CSS
+ 
+ #+vindex: org-html-multipage-preamble-position
+ #+vindex: org-html-multipage-preamble-position
+ #+vindex: org-html-multipage-postamble-position
+ In HTML multipage output each page will be generated with the
+ following structure:
+ 
+ #+begin_example
+ ,* html
+ ,** head
+ ,** body
+ ,*** preamble
+ ,*** org-div-nav-menu
+ ,*** content
+ ,**** table-of-contents
+ ,**** page-main-body
+ ,***** nav-left
+ ,***** page-text-body
+ ,***** nav-right
+ ,*** postamble
+ #+end_example
+ 
+ The default CSS shipped with org-mode will place a table of contents
+ to the left of the page content below the preamble and the top
+ navigation menu. This table of contents will contain /all/ headlines
+ according to the =toc= option, ignoring any =notoc= option within the
+ document to make every exported page of the document accessible.
+ 
+ Preamble and postamble can be moved inside the page text body at its
+ top and bottom using =org-html-multipage-preamble-position= and
+ =org-html-multipage-postamble-position= respectively. Elements to be
+ skipped can be hidden by setting their =display= property to =none= in
+ the CSS.  Note that the table of contents will only be generated if
+ 
+ In addition to the single page HTML CSS support (see [[*CSS support]])
+ the HTML Multipage exporter assigns the following special CSS classes
+ to appropriate parts of the document. They are mainly concerned with
+ navigation elements. The table of contents CSS below refers to the
+ table of contents generated for every page of the multipage HTML
+ output and /not/ to any additional toc inside the text body.
+ 
+ | ~#org-div-nav-menu~       | Top Navigation Menu                                                  |
+ | ~#table-of-contents~      | the Table of Contents generated for every output page                |
+ | ~#text-table-of-contents~ | the Table of Contents text area after its title                      |
+ | ~.ul-toc-level-N~         | the ul element of a toc entry with level N.                          |
+ | ~.toc-level-N~            | the li element of a toc entry with level N.                          |
+ | ~.toc-hidden~             | the li element of a toc entry to be (optionally) hidden              |
+ | ~.toc-entry~              | the a element of a toc entry.                                        |
+ | ~.toc-entry-active~       | The anchor of the toc entry currently active.                        |
+ | ~#nav-left~               | Navigation contained in the page-main-body div to the previous page. |
+ | ~#nav-right~              | Navigation contained in the page-main-body div to the next page      |
+ |                           |                                                                      |
+ 
  ** LaTeX Export
  :PROPERTIES:
  :DESCRIPTION: Exporting to @LaTeX{} and processing to PDF.
***************
*** 16655,16666 ****
  :UNNUMBERED: notoc
  :END:
  
! The Org export can filter not just for backends, but also for
! specific files through the =BIND= keyword.  Here is an example with
! two filters; one removes brackets from time stamps, and the other
! removes strike-through text.  The filter functions are defined in
! a code block in the same Org file, which is a handy location for
! debugging.
  
  #+begin_example
  ,#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp)
--- 16830,16842 ----
  :UNNUMBERED: notoc
  :END:
  
! The Org export can filter not just for backends, but also for specific
! files through the =BIND= keyword.  Here is an example with two
! filters; one removes brackets from time stamps, and the other removes
! strike-through text.  The filter functions are defined in a code block
! in the same Org file, which is a handy location for debugging.  Note
! that ~org-export-allow-bind-keywords~ has to be non-nil for this to
! work.
  
  #+begin_example
  ,#+BIND: org-export-filter-timestamp-functions (tmp-f-timestamp)

^ permalink raw reply	[relevance 1%]

Results 1-20 of 20 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2022-06-07  0:01     babel output seems to drop anything before % (in session) Felix Freeman via General discussions about Org-mode.
2022-06-18  3:20 11% ` [PATCH] " Ihor Radchenko
2022-10-13 15:14     Org 9.6-pre and Bash sessions Rudolf Adamkovič
2022-10-14  3:44     ` Ihor Radchenko
2022-10-15 20:56       ` Rudolf Adamkovič
2022-10-17  8:34         ` Ihor Radchenko
2022-10-21  5:29  6%       ` Ihor Radchenko
2022-11-17 22:18  6% Evaluate, execute, oh my! Rudolf Adamkovič
2023-02-06 19:39     [PATCH] Async evaluation in ob-shell Matt
2023-02-07 11:40     ` Ihor Radchenko
2023-02-09  4:33       ` Matt
2023-02-09 11:24         ` Ihor Radchenko
     [not found]           ` <m2sfdwuoxk.fsf@numbchild>
2023-03-23  4:21             ` [SUGGESTION] ob-shell async result output should not contains shell prompt Matt
2023-03-23 11:12 11%           ` Christopher M. Miles
2023-02-24 17:03     [PATCH] lisp/ob-screen.el: Support ~:var~ header args for babel blocks Ken Mankoff
2023-02-24 18:33     ` Ken Mankoff
2023-02-25  3:51       ` Max Nikulin
2023-02-25 15:14         ` Ken Mankoff
2023-02-25 16:05           ` Max Nikulin
2023-02-25 16:47             ` Ken Mankoff
2023-02-26 12:18               ` Ihor Radchenko
2023-02-27  1:59  9%             ` Ken Mankoff
2023-02-27 19:43  0%               ` Ihor Radchenko
2023-03-28 17:24     Font lock for org-babel shell scripts? Derek Chen-Becker
2023-03-28 21:53 12% ` [BUG] No font lock in src blocks for shells in org-babel-shell-names (was Re: Font lock for org-babel shell scripts?) Matt
2023-03-29  9:35       ` Ihor Radchenko
2023-03-29 17:04         ` Derek Chen-Becker
2023-03-29 20:17           ` Matt
2023-03-30  8:56 10%         ` Ihor Radchenko
2023-03-30 23:10  0%           ` Derek Chen-Becker
2023-04-01 23:21 10%           ` Matt
2023-04-03 17:42  0%             ` Derek Chen-Becker
2023-10-25 11:17     bash source code block: problem after ssh commands Alain.Cochard
2023-10-26 13:23     ` Alain.Cochard
2023-10-26 13:44       ` Ihor Radchenko
2023-10-27 18:26         ` Alain.Cochard
2023-10-30 10:50           ` Bruno Barbier
2023-11-06 13:32             ` Ihor Radchenko
2023-11-06 18:25               ` Matt
2023-11-07  8:55                 ` Ihor Radchenko
2023-11-08 19:41                   ` Matt
2023-11-09 12:14                     ` Ihor Radchenko
2023-11-09 17:48                       ` Matt
2023-11-15 16:32                         ` Matt
2023-11-16  9:32                           ` Ihor Radchenko
2023-11-16 19:03                             ` Matt
2023-11-16 19:46                               ` Alain.Cochard
2023-11-16 20:54                                 ` Matt
2023-11-17  9:22                                   ` Ihor Radchenko
2023-11-17  9:55                                     ` Alain.Cochard
2023-11-17 10:17                                       ` Ihor Radchenko
2023-11-17 15:47                                         ` Bruno Barbier
2023-11-18 10:37                                           ` Ihor Radchenko
2023-11-21 19:01                                             ` Bruno Barbier
2023-11-22 17:06  9%                                           ` Max Nikulin
2024-01-11 20:30 20% ob-shell: proposal to remove "posh" Matt
2024-01-12 10:04 12% ` Morgan Willcock
2024-01-12 15:49 11%   ` Matt
2024-01-13 10:43 26% ` Matt
2024-01-13 18:02 26% ` Ihor Radchenko
2024-01-15 20:11 25%   ` Matt
2024-01-15 21:16 12%     ` Ihor Radchenko
2024-07-23 11:35     multipage html output Orm Finnendahl
2024-07-23 14:13     ` Ihor Radchenko
     [not found]       ` <Zp_b2lL2SzDswa-w@orm-t14s>
2024-07-23 17:10         ` Ihor Radchenko
2024-07-23 20:35           ` Orm Finnendahl
2024-07-24 10:20             ` Ihor Radchenko
2024-07-25  9:57               ` Orm Finnendahl
2024-07-25 10:04                 ` Ihor Radchenko
2024-07-27 19:24                   ` Orm Finnendahl
2024-07-27 19:39                     ` Ihor Radchenko
2024-08-05 16:52  1%                   ` Orm Finnendahl

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).