Function: org-cite-adjust-note
org-cite-adjust-note is a byte-compiled function defined in oc.el.gz.
Signature
(org-cite-adjust-note CITATION INFO &optional RULE PUNCT)
Documentation
Adjust note number location for CITATION object, and punctuation around it.
INFO is the export state, as a property list.
Optional argument RULE is the punctuation rule used, as a triplet. When nil,
rule is determined according to org-cite-note-rules, which see.
Optional argument PUNCT is a list of punctuation marks to be considered.
When nil, it defaults to org-cite-punctuation-marks.
Parse tree is modified by side-effect.
Note: when calling both org-cite-adjust-note and org-cite-wrap-citation on
the same object, call org-cite-adjust-note first.
Source Code
;; Defined in /usr/src/emacs/lisp/org/oc.el.gz
(defun org-cite-adjust-note (citation info &optional rule punct)
"Adjust note number location for CITATION object, and punctuation around it.
INFO is the export state, as a property list.
Optional argument RULE is the punctuation rule used, as a triplet. When nil,
rule is determined according to `org-cite-note-rules', which see.
Optional argument PUNCT is a list of punctuation marks to be considered.
When nil, it defaults to `org-cite-punctuation-marks'.
Parse tree is modified by side-effect.
Note: when calling both `org-cite-adjust-note' and `org-cite-wrap-citation' on
the same object, call `org-cite-adjust-note' first."
(when org-cite-adjust-note-numbers
(pcase-let* ((rule (or rule (org-cite--get-note-rule info)))
(punct-re (regexp-opt (or punct org-cite-punctuation-marks)))
;; with Emacs <27.1. Argument of `regexp' form (PUNCT-RE this case)
;; must be a string literal.
(previous-punct-re
(rx-to-string `(seq (opt (group (regexp ,(rx (0+ (any blank ?\n))))
(regexp ,punct-re)))
(regexp ,(rx (opt (0+ (any blank ?\n)) (group ?\"))
(opt (group (1+ (any blank ?\n))))
string-end)))
t))
(next-punct-re
(rx-to-string `(seq string-start
(group (0+ (any blank ?\n)) (regexp ,punct-re)))
t))
(next (org-export-get-next-element citation info))
(final-punct
(and (stringp next)
(string-match next-punct-re next)
(match-string 1 next)))
(previous
;; Find the closest terminal object. Consider
;; citation, subscript and superscript objects as
;; terminal.
(org-last
(org-element-map (org-export-get-previous-element citation info)
'(citation code entity export-snippet footnote-reference
line-break latex-fragment link plain-text
radio-target statistics-cookie timestamp
verbatim)
#'identity info nil '(citation subscript superscript))))
(`(,punct ,quote ,spacing)
(and (stringp previous)
(string-match previous-punct-re previous)
(list (match-string 1 previous)
(match-string 2 previous)
(match-string 3 previous)))))
;; Bail you when there is no quote and either no punctuation, or
;; punctuation on both sides.
(when (or quote (org-xor punct final-punct))
;; Phase 1: handle punctuation rule.
(pcase rule
((guard (not quote)) nil)
;; Move punctuation inside.
(`(,(or `inside (and `adaptive (guard (not spacing)))) . ,_)
;; This only makes sense if there is a quotation before the
;; citation that does not end with some punctuation.
(when (and (not punct) final-punct)
;; Quote guarantees there is a string object before
;; citation. Likewise, any final punctuation guarantees
;; there is a string object following citation.
(let ((new-prev
(replace-regexp-in-string
previous-punct-re
(concat final-punct "\"") previous nil nil 2))
(new-next
(replace-regexp-in-string
;; Before Emacs-27.1 `literal' `rx' form with a variable
;; as an argument is not available.
(rx-to-string `(seq string-start ,final-punct) t)
"" next)))
(org-element-set-element previous new-prev)
(org-element-set-element next new-next)
(setq previous new-prev)
(setq next new-next)
(setq punct final-punct)
(setq final-punct nil))))
;; Move punctuation outside.
(`(,(or `outside (and `adaptive (guard spacing))) . ,_)
;; This is only meaningful if there is some inner
;; punctuation and no final punctuation already.
(when (and punct (not final-punct))
;; Inner punctuation guarantees there is text object
;; before the citation. However, there is no information
;; about the object following citation, if any.
;; Therefore, we handle all the possible cases (string,
;; other type, or none).
(let ((new-prev
(replace-regexp-in-string
previous-punct-re "" previous nil nil 1))
(new-next (if (stringp next) (concat punct next) punct)))
(org-element-set-element previous new-prev)
(cond
((stringp next)
(org-element-set-element next new-next))
(next
(org-element-insert-before new-next next))
(t
(org-element-adopt-elements
(org-element-property :parent citation)
new-next)))
(setq previous new-prev)
(setq next new-next)
(setq final-punct punct)
(setq punct nil))))
(_
(error "Invalid punctuation rule: %S" rule))))
;; Phase 2: move citation to its appropriate location.
;;
;; First transform relative citation location into a definitive
;; location, according to the surrounding punctuation.
(pcase rule
(`(,punctuation same ,order)
(setf rule
(list punctuation
(cond
;; When there is punctuation on both sides, the
;; citation is necessarily on the outside.
((and punct final-punct) 'outside)
(punct 'inside)
(final-punct 'outside)
;; No punctuation: bail out on next step.
(t nil))
order))))
(pcase rule
(`(,_ nil ,_) nil)
(`(,_ inside after)
;; Citation has to be moved after punct, if there is
;; a quotation mark, or after final punctuation.
(cond
(quote
(org-cite--insert-at-split previous citation 2 previous-punct-re))
(final-punct
(org-cite--move-punct-before final-punct citation next info))
;; There is only punct, and we're already after it.
(t nil)))
(`(,_ inside before)
;; Citation is already behind final-punct, so only consider
;; other locations.
(when (or punct quote)
(org-cite--insert-at-split previous citation 0 previous-punct-re)))
(`(,_ outside after)
;; Citation is already after any punct or quote. It can only
;; move past final punctuation, if there is one.
(when final-punct
(org-cite--move-punct-before final-punct citation next info)))
(`(,_ outside before)
;; The only non-trivial case is when citation follows punct
;; without a quote.
(when (and punct (not quote))
(org-cite--insert-at-split previous citation 0 previous-punct-re)))
(_
(error "Invalid punctuation rule: %S" rule))))))