branch: externals/org
commit 004ac14a5bacf311e3d0f14a7cd8345a49980bef
Author: Ihor Radchenko <yanta...@gmail.com>
Commit: Ihor Radchenko <yanta...@gmail.com>

    Fix compatibility with Emacs 26
    
    * lisp/org-compat.el (org-file-name-concat): Do not use
    `string-empty-p'.
    (combine-change-calls): Create a stub when `combine-change-calls' were
    not yet available.
    (org-replace-buffer-contents): Add compatibility function for
    `replace-buffer-contents'.
    
    * lisp/org-element.el (org-element--current-element): Do not use
    `if-let'.
    * lisp/org-persist.el (org-persist-gc): Do not use `when-let'.
    * lisp/org-plot.el (org-plot/gnuplot): Do not use `if-let'.
    * lisp/org-src.el (org-edit-src-save, org-edit-src-exit): Use
    `org-replace-buffer-contents'.
    
    * lisp/org.el (org-narrow-to-subtree, org--property-local-values,
    org-entry-get-with-inheritance, org-in-commented-heading-p,
    org-up-heading-safe, org-goto-first-child): Do not use
    `if-let'/`when-let'.
    
    * testing/org-test.el (org-test-at-time): Fallback to old
    `decode-time' specification in older Emacs.
---
 lisp/org-compat.el  |  13 +-
 lisp/org-element.el | 365 ++++++++++++++++++++++++++--------------------------
 lisp/org-persist.el |  21 +--
 lisp/org-plot.el    |   7 +-
 lisp/org-src.el     |   8 +-
 lisp/org.el         | 322 ++++++++++++++++++++++-----------------------
 testing/org-test.el |   9 +-
 7 files changed, 385 insertions(+), 360 deletions(-)

diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 737f628..4019b06 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -90,7 +90,7 @@ inserted before contatenating."
        (delq nil
              (mapcar
               (lambda (str)
-                (when (and str (not (string-empty-p str))
+                (when (and str (not (seq-empty-p str))
                            (string-match "\\(.+\\)/?" str))
                   (match-string 1 str)))
               (cons directory components)))
@@ -106,6 +106,17 @@ inserted before contatenating."
 
 ;;; Emacs < 27.1 compatibility
 
+(unless (fboundp 'combine-change-calls)
+  ;; A stub when `combine-change-calls' was not yet there.
+  (defmacro combine-change-calls (_beg _end &rest body)
+    (declare (debug (form form def-body)) (indent 2))
+    `(progn ,@body)))
+
+(if (version< emacs-version "27.1")
+    (defsubst org-replace-buffer-contents (source &optional _max-secs 
_max-costs)
+      (replace-buffer-contents source))
+  (defalias 'org-replace-buffer-contents #'replace-buffer-contents))
+
 (unless (fboundp 'proper-list-p)
   ;; `proper-list-p' was added in Emacs 27.1.  The function below is
   ;; taken from Emacs subr.el 200195e824b^.
diff --git a/lisp/org-element.el b/lisp/org-element.el
index bcf5c62..42f97b4 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -4138,189 +4138,190 @@ not checked.
 
 This function assumes point is always at the beginning of the
 element it has to parse."
-  (if-let* ((element (and (not (buffer-narrowed-p))
-                          (org-element--cache-active-p)
-                          (not org-element--cache-sync-requests)
-                          (org-element--cache-find (point) t)))
-            (element (progn (while (and element
-                                        (not (and (eq (point) 
(org-element-property :begin element))
-                                                (eq mode (org-element-property 
:mode element)))))
-                              (setq element (org-element-property :parent 
element)))
-                            element))
-            (old-element element)
-            (element (when
-                         (pcase (org-element-property :granularity element)
-                           (`nil t)
-                           (`object t)
-                           (`element (not (memq granularity '(nil object))))
-                           (`greater-element (not (memq granularity '(nil 
object element))))
-                           (`headline (eq granularity 'headline)))
-                       element)))
-      element
-    (save-excursion
-      (let ((case-fold-search t)
-           ;; Determine if parsing depth allows for secondary strings
-           ;; parsing.  It only applies to elements referenced in
-           ;; `org-element-secondary-value-alist'.
-           (raw-secondary-p (and granularity (not (eq granularity 'object))))
-            result)
-        (setq
-         result
-         (cond
-          ;; Item.
-          ((eq mode 'item)
-          (org-element-item-parser limit structure raw-secondary-p))
-          ;; Table Row.
-          ((eq mode 'table-row) (org-element-table-row-parser limit))
-          ;; Node Property.
-          ((eq mode 'node-property) (org-element-node-property-parser limit))
-          ;; Headline.
-          ((org-with-limited-levels (org-at-heading-p))
-           (org-element-headline-parser limit raw-secondary-p))
-          ;; Sections (must be checked after headline).
-          ((eq mode 'section) (org-element-section-parser limit))
-          ((eq mode 'first-section)
-          (org-element-section-parser
-           (or (save-excursion (org-with-limited-levels 
(outline-next-heading)))
-               limit)))
-          ;; Comments.
-          ((looking-at "^[ \t]*#\\(?: \\|$\\)")
-          (org-element-comment-parser limit))
-          ;; Planning.
-          ((and (eq mode 'planning)
-               (eq ?* (char-after (line-beginning-position 0)))
-               (looking-at org-planning-line-re))
-          (org-element-planning-parser limit))
-          ;; Property drawer.
-          ((and (pcase mode
-                 (`planning (eq ?* (char-after (line-beginning-position 0))))
-                 ((or `property-drawer `top-comment)
-                  (save-excursion
-                    (beginning-of-line 0)
-                    (not (looking-at "[[:blank:]]*$"))))
-                 (_ nil))
-               (looking-at org-property-drawer-re))
-          (org-element-property-drawer-parser limit))
-          ;; When not at bol, point is at the beginning of an item or
-          ;; a footnote definition: next item is always a paragraph.
-          ((not (bolp)) (org-element-paragraph-parser limit (list (point))))
-          ;; Clock.
-          ((looking-at org-clock-line-re) (org-element-clock-parser limit))
-          ;; Inlinetask.
-          ((looking-at "^\\*+ ")
-          (org-element-inlinetask-parser limit raw-secondary-p))
-          ;; From there, elements can have affiliated keywords.
-          (t (let ((affiliated (org-element--collect-affiliated-keywords
-                               limit (memq granularity '(nil object)))))
-              (cond
-               ;; Jumping over affiliated keywords put point off-limits.
-               ;; Parse them as regular keywords.
-               ((and (cdr affiliated) (>= (point) limit))
-                (goto-char (car affiliated))
-                (org-element-keyword-parser limit nil))
-               ;; LaTeX Environment.
-               ((looking-at org-element--latex-begin-environment)
-                (org-element-latex-environment-parser limit affiliated))
-               ;; Drawer.
-               ((looking-at org-drawer-regexp)
-                (org-element-drawer-parser limit affiliated))
-               ;; Fixed Width
-               ((looking-at "[ \t]*:\\( \\|$\\)")
-                (org-element-fixed-width-parser limit affiliated))
-               ;; Inline Comments, Blocks, Babel Calls, Dynamic Blocks and
-               ;; Keywords.
-               ((looking-at "[ \t]*#\\+")
-                (goto-char (match-end 0))
+  (let* ((element (and (not (buffer-narrowed-p))
+                       (org-element--cache-active-p)
+                       (not org-element--cache-sync-requests)
+                       (org-element--cache-find (point) t)))
+         (element (progn (while (and element
+                                     (not (and (eq (point) 
(org-element-property :begin element))
+                                             (eq mode (org-element-property 
:mode element)))))
+                           (setq element (org-element-property :parent 
element)))
+                         element))
+         (old-element element)
+         (element (when
+                      (pcase (org-element-property :granularity element)
+                        (`nil t)
+                        (`object t)
+                        (`element (not (memq granularity '(nil object))))
+                        (`greater-element (not (memq granularity '(nil object 
element))))
+                        (`headline (eq granularity 'headline)))
+                    element)))
+    (if element
+        element
+      (save-excursion
+        (let ((case-fold-search t)
+             ;; Determine if parsing depth allows for secondary strings
+             ;; parsing.  It only applies to elements referenced in
+             ;; `org-element-secondary-value-alist'.
+             (raw-secondary-p (and granularity (not (eq granularity 'object))))
+              result)
+          (setq
+           result
+           (cond
+            ;; Item.
+            ((eq mode 'item)
+            (org-element-item-parser limit structure raw-secondary-p))
+            ;; Table Row.
+            ((eq mode 'table-row) (org-element-table-row-parser limit))
+            ;; Node Property.
+            ((eq mode 'node-property) (org-element-node-property-parser limit))
+            ;; Headline.
+            ((org-with-limited-levels (org-at-heading-p))
+             (org-element-headline-parser limit raw-secondary-p))
+            ;; Sections (must be checked after headline).
+            ((eq mode 'section) (org-element-section-parser limit))
+            ((eq mode 'first-section)
+            (org-element-section-parser
+             (or (save-excursion (org-with-limited-levels 
(outline-next-heading)))
+                 limit)))
+            ;; Comments.
+            ((looking-at "^[ \t]*#\\(?: \\|$\\)")
+            (org-element-comment-parser limit))
+            ;; Planning.
+            ((and (eq mode 'planning)
+                 (eq ?* (char-after (line-beginning-position 0)))
+                 (looking-at org-planning-line-re))
+            (org-element-planning-parser limit))
+            ;; Property drawer.
+            ((and (pcase mode
+                   (`planning (eq ?* (char-after (line-beginning-position 0))))
+                   ((or `property-drawer `top-comment)
+                    (save-excursion
+                      (beginning-of-line 0)
+                      (not (looking-at "[[:blank:]]*$"))))
+                   (_ nil))
+                 (looking-at org-property-drawer-re))
+            (org-element-property-drawer-parser limit))
+            ;; When not at bol, point is at the beginning of an item or
+            ;; a footnote definition: next item is always a paragraph.
+            ((not (bolp)) (org-element-paragraph-parser limit (list (point))))
+            ;; Clock.
+            ((looking-at org-clock-line-re) (org-element-clock-parser limit))
+            ;; Inlinetask.
+            ((looking-at "^\\*+ ")
+            (org-element-inlinetask-parser limit raw-secondary-p))
+            ;; From there, elements can have affiliated keywords.
+            (t (let ((affiliated (org-element--collect-affiliated-keywords
+                                 limit (memq granularity '(nil object)))))
                 (cond
-                 ((looking-at "BEGIN_\\(\\S-+\\)")
-                  (beginning-of-line)
-                  (funcall (pcase (upcase (match-string 1))
-                             ("CENTER"  #'org-element-center-block-parser)
-                             ("COMMENT" #'org-element-comment-block-parser)
-                             ("EXAMPLE" #'org-element-example-block-parser)
-                             ("EXPORT"  #'org-element-export-block-parser)
-                             ("QUOTE"   #'org-element-quote-block-parser)
-                             ("SRC"     #'org-element-src-block-parser)
-                             ("VERSE"   #'org-element-verse-block-parser)
-                             (_         #'org-element-special-block-parser))
-                           limit
-                           affiliated))
-                 ((looking-at "CALL:")
-                  (beginning-of-line)
-                  (org-element-babel-call-parser limit affiliated))
-                 ((looking-at "BEGIN:? ")
-                  (beginning-of-line)
-                  (org-element-dynamic-block-parser limit affiliated))
-                 ((looking-at "\\S-+:")
-                  (beginning-of-line)
-                  (org-element-keyword-parser limit affiliated))
-                 (t
-                  (beginning-of-line)
-                  (org-element-paragraph-parser limit affiliated))))
-               ;; Footnote Definition.
-               ((looking-at org-footnote-definition-re)
-                (org-element-footnote-definition-parser limit affiliated))
-               ;; Horizontal Rule.
-               ((looking-at "[ \t]*-\\{5,\\}[ \t]*$")
-                (org-element-horizontal-rule-parser limit affiliated))
-               ;; Diary Sexp.
-               ((looking-at "%%(")
-                (org-element-diary-sexp-parser limit affiliated))
-               ;; Table.
-               ((or (looking-at "[ \t]*|")
-                    ;; There is no strict definition of a table.el
-                    ;; table.  Try to prevent false positive while being
-                    ;; quick.
-                    (let ((rule-regexp
-                           (rx (zero-or-more (any " \t"))
-                               "+"
-                               (one-or-more (one-or-more "-") "+")
-                               (zero-or-more (any " \t"))
-                               eol))
-                          (non-table.el-line
-                           (rx bol
-                               (zero-or-more (any " \t"))
-                               (or eol (not (any "+| \t")))))
-                          (next (line-beginning-position 2)))
-                      ;; Start with a full rule.
-                      (and
-                       (looking-at rule-regexp)
-                       (< next limit)  ;no room for a table.el table
-                       (save-excursion
-                         (end-of-line)
-                         (cond
-                          ;; Must end with a full rule.
-                          ((not (re-search-forward non-table.el-line limit 
'move))
-                           (if (bolp) (forward-line -1) (beginning-of-line))
-                           (looking-at rule-regexp))
-                          ;; Ignore pseudo-tables with a single
-                          ;; rule.
-                          ((= next (line-beginning-position))
-                           nil)
-                          ;; Must end with a full rule.
-                          (t
-                           (forward-line -1)
-                           (looking-at rule-regexp)))))))
-                (org-element-table-parser limit affiliated))
-               ;; List.
-               ((looking-at (org-item-re))
-                (org-element-plain-list-parser
-                 limit affiliated
-                 (or structure (org-element--list-struct limit))))
-               ;; Default element: Paragraph.
-               (t (org-element-paragraph-parser limit affiliated)))))))
-        (when result
-          (org-element-put-property result :mode mode)
-          (org-element-put-property result :granularity granularity))
-        (when (and (not (buffer-narrowed-p))
-                   (org-element--cache-active-p)
-                   (not org-element--cache-sync-requests)
-                   add-to-cache)
-          (if (not old-element)
-              (setq result (org-element--cache-put result))
-            (org-element-set-element old-element result)
-            (setq result old-element)))
-        result))))
+                 ;; Jumping over affiliated keywords put point off-limits.
+                 ;; Parse them as regular keywords.
+                 ((and (cdr affiliated) (>= (point) limit))
+                  (goto-char (car affiliated))
+                  (org-element-keyword-parser limit nil))
+                 ;; LaTeX Environment.
+                 ((looking-at org-element--latex-begin-environment)
+                  (org-element-latex-environment-parser limit affiliated))
+                 ;; Drawer.
+                 ((looking-at org-drawer-regexp)
+                  (org-element-drawer-parser limit affiliated))
+                 ;; Fixed Width
+                 ((looking-at "[ \t]*:\\( \\|$\\)")
+                  (org-element-fixed-width-parser limit affiliated))
+                 ;; Inline Comments, Blocks, Babel Calls, Dynamic Blocks and
+                 ;; Keywords.
+                 ((looking-at "[ \t]*#\\+")
+                  (goto-char (match-end 0))
+                  (cond
+                   ((looking-at "BEGIN_\\(\\S-+\\)")
+                    (beginning-of-line)
+                    (funcall (pcase (upcase (match-string 1))
+                               ("CENTER"  #'org-element-center-block-parser)
+                               ("COMMENT" #'org-element-comment-block-parser)
+                               ("EXAMPLE" #'org-element-example-block-parser)
+                               ("EXPORT"  #'org-element-export-block-parser)
+                               ("QUOTE"   #'org-element-quote-block-parser)
+                               ("SRC"     #'org-element-src-block-parser)
+                               ("VERSE"   #'org-element-verse-block-parser)
+                               (_         #'org-element-special-block-parser))
+                             limit
+                             affiliated))
+                   ((looking-at "CALL:")
+                    (beginning-of-line)
+                    (org-element-babel-call-parser limit affiliated))
+                   ((looking-at "BEGIN:? ")
+                    (beginning-of-line)
+                    (org-element-dynamic-block-parser limit affiliated))
+                   ((looking-at "\\S-+:")
+                    (beginning-of-line)
+                    (org-element-keyword-parser limit affiliated))
+                   (t
+                    (beginning-of-line)
+                    (org-element-paragraph-parser limit affiliated))))
+                 ;; Footnote Definition.
+                 ((looking-at org-footnote-definition-re)
+                  (org-element-footnote-definition-parser limit affiliated))
+                 ;; Horizontal Rule.
+                 ((looking-at "[ \t]*-\\{5,\\}[ \t]*$")
+                  (org-element-horizontal-rule-parser limit affiliated))
+                 ;; Diary Sexp.
+                 ((looking-at "%%(")
+                  (org-element-diary-sexp-parser limit affiliated))
+                 ;; Table.
+                 ((or (looking-at "[ \t]*|")
+                      ;; There is no strict definition of a table.el
+                      ;; table.  Try to prevent false positive while being
+                      ;; quick.
+                      (let ((rule-regexp
+                             (rx (zero-or-more (any " \t"))
+                                 "+"
+                                 (one-or-more (one-or-more "-") "+")
+                                 (zero-or-more (any " \t"))
+                                 eol))
+                            (non-table.el-line
+                             (rx bol
+                                 (zero-or-more (any " \t"))
+                                 (or eol (not (any "+| \t")))))
+                            (next (line-beginning-position 2)))
+                        ;; Start with a full rule.
+                        (and
+                         (looking-at rule-regexp)
+                         (< next limit)        ;no room for a table.el table
+                         (save-excursion
+                           (end-of-line)
+                           (cond
+                            ;; Must end with a full rule.
+                            ((not (re-search-forward non-table.el-line limit 
'move))
+                             (if (bolp) (forward-line -1) (beginning-of-line))
+                             (looking-at rule-regexp))
+                            ;; Ignore pseudo-tables with a single
+                            ;; rule.
+                            ((= next (line-beginning-position))
+                             nil)
+                            ;; Must end with a full rule.
+                            (t
+                             (forward-line -1)
+                             (looking-at rule-regexp)))))))
+                  (org-element-table-parser limit affiliated))
+                 ;; List.
+                 ((looking-at (org-item-re))
+                  (org-element-plain-list-parser
+                   limit affiliated
+                   (or structure (org-element--list-struct limit))))
+                 ;; Default element: Paragraph.
+                 (t (org-element-paragraph-parser limit affiliated)))))))
+          (when result
+            (org-element-put-property result :mode mode)
+            (org-element-put-property result :granularity granularity))
+          (when (and (not (buffer-narrowed-p))
+                     (org-element--cache-active-p)
+                     (not org-element--cache-sync-requests)
+                     add-to-cache)
+            (if (not old-element)
+                (setq result (org-element--cache-put result))
+              (org-element-set-element old-element result)
+              (setq result old-element)))
+          result)))))
 
 
 ;; Most elements can have affiliated keywords.  When looking for an
diff --git a/lisp/org-persist.el b/lisp/org-persist.el
index 6c054c2..78347e6 100644
--- a/lisp/org-persist.el
+++ b/lisp/org-persist.el
@@ -249,16 +249,17 @@ When BUFFER is `all', unregister VAR in all buffers."
   "Remove stored data for not existing files or unregistered variables."
   (let (new-index)
     (dolist (index org-persist--index)
-      (when-let ((file (plist-get index :path))
-                 (persist-file (org-file-name-concat
-                                org-persist-path
-                                (plist-get index :persist-file))))
-        (if (file-exists-p file)
-            (push index new-index)
-          (when (file-exists-p persist-file)
-            (delete-file persist-file)
-            (when (org-directory-empty-p (file-name-directory persist-file))
-              (delete-directory (file-name-directory persist-file)))))))
+      (let ((file (plist-get index :path))
+            (persist-file (org-file-name-concat
+                           org-persist-path
+                           (plist-get index :persist-file))))
+        (when (and file persist-file)
+          (if (file-exists-p file)
+              (push index new-index)
+            (when (file-exists-p persist-file)
+              (delete-file persist-file)
+              (when (org-directory-empty-p (file-name-directory persist-file))
+                (delete-directory (file-name-directory persist-file))))))))
     (setq org-persist--index (nreverse new-index))))
 
 (add-hook 'kill-emacs-hook #'org-persist-gc)
diff --git a/lisp/org-plot.el b/lisp/org-plot.el
index 4f14c7d..815cc6f 100644
--- a/lisp/org-plot.el
+++ b/lisp/org-plot.el
@@ -682,9 +682,10 @@ line directly before or after the table."
                                  (looking-at "[[:space:]]*#\\+"))
                        (setf params (org-plot/collect-options params))))
       ;; Dump table to datafile
-      (if-let ((dump-func (plist-get type :data-dump)))
-         (funcall dump-func table data-file num-cols params)
-       (org-plot/gnuplot-to-data table data-file params))
+      (let ((dump-func (plist-get type :data-dump)))
+        (if dump-func
+           (funcall dump-func table data-file num-cols params)
+         (org-plot/gnuplot-to-data table data-file params)))
       ;; Check type of ind column (timestamp? text?)
       (when (plist-get params :check-ind-type)
        (let* ((ind (1- (plist-get params :ind)))
diff --git a/lisp/org-src.el b/lisp/org-src.el
index 23e1964..f1948bf 100644
--- a/lisp/org-src.el
+++ b/lisp/org-src.el
@@ -1241,7 +1241,7 @@ EVENT is passed to `mouse-set-point'."
                   (insert (with-current-buffer write-back-buf 
(buffer-string))))
          (save-restriction
            (narrow-to-region beg end)
-           (replace-buffer-contents write-back-buf 0.1 nil)
+           (org-replace-buffer-contents write-back-buf 0.1 nil)
            (goto-char (point-max))))
        (when (and expecting-bol (not (bolp))) (insert "\n")))
       (kill-buffer write-back-buf)
@@ -1278,8 +1278,8 @@ EVENT is passed to `mouse-set-point'."
     (org-with-wide-buffer
      (when (and write-back
                 (not (equal (buffer-substring beg end)
-                           (with-current-buffer write-back-buf
-                              (buffer-string)))))
+                         (with-current-buffer write-back-buf
+                            (buffer-string)))))
        (undo-boundary)
        (goto-char beg)
        (let ((expecting-bol (bolp)))
@@ -1289,7 +1289,7 @@ EVENT is passed to `mouse-set-point'."
                               (buffer-string))))
           (save-restriction
             (narrow-to-region beg end)
-            (replace-buffer-contents write-back-buf 0.1 nil)
+            (org-replace-buffer-contents write-back-buf 0.1 nil)
             (goto-char (point-max))))
         (when (and expecting-bol (not (bolp))) (insert "\n")))))
     (when write-back-buf (kill-buffer write-back-buf))
diff --git a/lisp/org.el b/lisp/org.el
index 75ddfa8..1b8f0e6 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -7918,14 +7918,15 @@ If yes, remember the marker and the distance to BEG."
   "Narrow buffer to the current subtree."
   (interactive)
   (if (org-element--cache-active-p)
-      (if-let* ((heading (org-element-lineage
-                          (or element (org-element-at-point))
-                          '(headline) t))
-                (end (org-element-property :end heading)))
-          (narrow-to-region (org-element-property :begin heading)
-                            (if (= end (point-max))
-                                end (1- end)))
-        (signal 'outline-before-first-heading nil))
+      (let* ((heading (org-element-lineage
+                       (or element (org-element-at-point))
+                       '(headline) t))
+             (end (org-element-property :end heading)))
+        (if (and heading end)
+            (narrow-to-region (org-element-property :begin heading)
+                              (if (= end (point-max))
+                                  end (1- end)))
+          (signal 'outline-before-first-heading nil)))
     (save-excursion
       (save-match-data
         (org-with-limited-levels
@@ -13153,34 +13154,35 @@ Value is a list whose car is the base value for 
PROPERTY and cdr
 a list of accumulated values.  Return nil if neither is found in
 the entry.  Also return nil when PROPERTY is set to \"nil\",
 unless LITERAL-NIL is non-nil."
-  (if-let ((element (or element
-                        (and (org-element--cache-active-p)
-                             (org-element-at-point nil 'cached)))))
-      (let* ((element (org-element-lineage element '(headline org-data 
inlinetask) 'with-self))
-             (base-value (org-element-property (intern (concat ":" (upcase 
property))) element))
-             (base-value (if literal-nil base-value (org-not-nil base-value)))
-             (extra-value (org-element-property (intern (concat ":" (upcase 
property) "+")) element))
-             (extra-value (if (listp extra-value) extra-value (list 
extra-value)))
-             (value (cons base-value extra-value)))
-        (and (not (equal value '(nil))) value))
-    (let ((range (org-get-property-block)))
-      (when range
-        (goto-char (car range))
-        (let* ((case-fold-search t)
-              (end (cdr range))
-              (value
-               ;; Base value.
-               (save-excursion
-                 (let ((v (and (re-search-forward
-                                (org-re-property property nil t) end t)
-                               (match-string-no-properties 3))))
-                   (list (if literal-nil v (org-not-nil v)))))))
-         ;; Find additional values.
-         (let* ((property+ (org-re-property (concat property "+") nil t)))
-           (while (re-search-forward property+ end t)
-             (push (match-string-no-properties 3) value)))
-         ;; Return final values.
-         (and (not (equal value '(nil))) (nreverse value)))))))
+  (let ((element (or element
+                     (and (org-element--cache-active-p)
+                          (org-element-at-point nil 'cached)))))
+    (if element
+        (let* ((element (org-element-lineage element '(headline org-data 
inlinetask) 'with-self))
+               (base-value (org-element-property (intern (concat ":" (upcase 
property))) element))
+               (base-value (if literal-nil base-value (org-not-nil 
base-value)))
+               (extra-value (org-element-property (intern (concat ":" (upcase 
property) "+")) element))
+               (extra-value (if (listp extra-value) extra-value (list 
extra-value)))
+               (value (cons base-value extra-value)))
+          (and (not (equal value '(nil))) value))
+      (let ((range (org-get-property-block)))
+        (when range
+          (goto-char (car range))
+          (let* ((case-fold-search t)
+                (end (cdr range))
+                (value
+                 ;; Base value.
+                 (save-excursion
+                   (let ((v (and (re-search-forward
+                                  (org-re-property property nil t) end t)
+                                 (match-string-no-properties 3))))
+                     (list (if literal-nil v (org-not-nil v)))))))
+           ;; Find additional values.
+           (let* ((property+ (org-re-property (concat property "+") nil t)))
+             (while (re-search-forward property+ end t)
+               (push (match-string-no-properties 3) value)))
+           ;; Return final values.
+           (and (not (equal value '(nil))) (nreverse value))))))))
 
 (defun org--property-global-or-keyword-value (property literal-nil)
   "Return value for PROPERTY as defined by global properties or by keyword.
@@ -13328,59 +13330,60 @@ However, if LITERAL-NIL is set, return the string 
value \"nil\" instead."
   (org-with-wide-buffer
    (let (value at-bob-no-heading)
      (catch 'exit
-       (if-let ((element (or element
-                             (and (org-element--cache-active-p)
-                                  (org-element-at-point nil 'cached)))))
-           (let ((element (org-element-lineage element '(headline org-data 
inlinetask) 'with-self)))
-             (while t
-               (let* ((v (org--property-local-values property literal-nil 
element))
-                      (v (if (listp v) v (list v))))
-                 (when v
-                   (setq value
-                         (concat (mapconcat #'identity (delq nil v) " ")
-                                 (and value " ")
-                                 value)))
-                 (cond
-                 ((car v)
-                  (move-marker org-entry-property-inherited-from 
(org-element-property :begin element))
-                  (throw 'exit nil))
-                 ((org-element-property :parent element)
-                   (setq element (org-element-property :parent element)))
-                 (t
-                  (let ((global (org--property-global-or-keyword-value 
property literal-nil)))
-                    (cond ((not global))
-                          (value (setq value (concat global " " value)))
-                          (t (setq value global))))
-                  (throw 'exit nil))))))
-         (while t
-          (let ((v (org--property-local-values property literal-nil)))
-            (when v
-              (setq value
-                    (concat (mapconcat #'identity (delq nil v) " ")
-                            (and value " ")
-                            value)))
-            (cond
-             ((car v)
-              (org-back-to-heading-or-point-min t)
-              (move-marker org-entry-property-inherited-from (point))
-              (throw 'exit nil))
-             ((or (org-up-heading-safe)
-                   (and (not (bobp))
-                        (goto-char (point-min))
-                        nil)
-                   ;; `org-up-heading-safe' returned nil.  We are at low
-                   ;; level heading or bob.  If there is headline
-                   ;; there, do not try to fetch its properties.
-                   (and (bobp)
-                        (not at-bob-no-heading)
-                        (not (org-at-heading-p))
-                        (setq at-bob-no-heading t))))
-             (t
-              (let ((global (org--property-global-or-keyword-value property 
literal-nil)))
-                (cond ((not global))
-                      (value (setq value (concat global " " value)))
-                      (t (setq value global))))
-              (throw 'exit nil)))))))
+       (let ((element (or element
+                          (and (org-element--cache-active-p)
+                               (org-element-at-point nil 'cached)))))
+         (if element
+             (let ((element (org-element-lineage element '(headline org-data 
inlinetask) 'with-self)))
+               (while t
+                 (let* ((v (org--property-local-values property literal-nil 
element))
+                        (v (if (listp v) v (list v))))
+                   (when v
+                     (setq value
+                           (concat (mapconcat #'identity (delq nil v) " ")
+                                   (and value " ")
+                                   value)))
+                   (cond
+                   ((car v)
+                    (move-marker org-entry-property-inherited-from 
(org-element-property :begin element))
+                    (throw 'exit nil))
+                   ((org-element-property :parent element)
+                     (setq element (org-element-property :parent element)))
+                   (t
+                    (let ((global (org--property-global-or-keyword-value 
property literal-nil)))
+                      (cond ((not global))
+                            (value (setq value (concat global " " value)))
+                            (t (setq value global))))
+                    (throw 'exit nil))))))
+           (while t
+            (let ((v (org--property-local-values property literal-nil)))
+              (when v
+                (setq value
+                      (concat (mapconcat #'identity (delq nil v) " ")
+                              (and value " ")
+                              value)))
+              (cond
+               ((car v)
+                (org-back-to-heading-or-point-min t)
+                (move-marker org-entry-property-inherited-from (point))
+                (throw 'exit nil))
+               ((or (org-up-heading-safe)
+                     (and (not (bobp))
+                          (goto-char (point-min))
+                          nil)
+                     ;; `org-up-heading-safe' returned nil.  We are at low
+                     ;; level heading or bob.  If there is headline
+                     ;; there, do not try to fetch its properties.
+                     (and (bobp)
+                          (not at-bob-no-heading)
+                          (not (org-at-heading-p))
+                          (setq at-bob-no-heading t))))
+               (t
+                (let ((global (org--property-global-or-keyword-value property 
literal-nil)))
+                  (cond ((not global))
+                        (value (setq value (concat global " " value)))
+                        (t (setq value global))))
+                (throw 'exit nil))))))))
      (if literal-nil value (org-not-nil value)))))
 
 (defvar org-property-changed-functions nil
@@ -20711,25 +20714,26 @@ unless optional argument NO-INHERITANCE is non-nil.
 
 Optional argument ELEMENT contains element at point."
   (save-match-data
-    (if-let ((el (or element (org-element-at-point nil 'cached))))
-        (catch :found
-          (setq el (org-element-lineage el '(headline) 'include-self))
-          (if no-inheritance
-              (org-element-property :commentedp el)
-            (while el
-              (when (org-element-property :commentedp el)
-                (throw :found t))
-              (setq el (org-element-property :parent el)))))
-      (cond
-       ((org-before-first-heading-p) nil)
-       ((let ((headline (nth 4 (org-heading-components))))
-          (and headline
-              (let ((case-fold-search nil))
-                (string-match-p (concat "^" org-comment-string "\\(?: \\|$\\)")
-                                headline)))))
-       (no-inheritance nil)
-       (t
-        (save-excursion (and (org-up-heading-safe) 
(org-in-commented-heading-p))))))))
+    (let ((el (or element (org-element-at-point nil 'cached))))
+      (if el
+          (catch :found
+            (setq el (org-element-lineage el '(headline) 'include-self))
+            (if no-inheritance
+                (org-element-property :commentedp el)
+              (while el
+                (when (org-element-property :commentedp el)
+                  (throw :found t))
+                (setq el (org-element-property :parent el)))))
+        (cond
+         ((org-before-first-heading-p) nil)
+         ((let ((headline (nth 4 (org-heading-components))))
+            (and headline
+                (let ((case-fold-search nil))
+                  (string-match-p (concat "^" org-comment-string "\\(?: 
\\|$\\)")
+                                  headline)))))
+         (no-inheritance nil)
+         (t
+          (save-excursion (and (org-up-heading-safe) 
(org-in-commented-heading-p)))))))))
 
 (defun org-in-archived-heading-p (&optional no-inheritance element)
   "Non-nil if point is under an archived heading.
@@ -20809,42 +20813,43 @@ headline found, or nil if no higher level is found.
 Also, this function will be a lot faster than `outline-up-heading',
 because it relies on stars being the outline starters.  This can really
 make a significant difference in outlines with very many siblings."
-  (if-let ((element (and (org-element--cache-active-p)
-                         (org-element-at-point nil t))))
-      (let* ((current-heading (org-element-lineage element '(headline) 
'with-self))
-             (parent (org-element-lineage current-heading '(headline))))
-        (if (and parent
-                 (<= (point-min) (org-element-property :begin parent)))
-            (progn
-              (goto-char (org-element-property :begin parent))
-              (org-element-property :level parent))
-          (when (and current-heading
-                     (<= (point-min) (org-element-property :begin 
current-heading)))
-            (goto-char (org-element-property :begin current-heading))
-            nil)))
-    (when (ignore-errors (org-back-to-heading t))
-      (let (level-cache)
-        (unless org--up-heading-cache
-          (setq org--up-heading-cache (make-hash-table)))
-        (if (and (eq (buffer-chars-modified-tick) org--up-heading-cache-tick)
-                 (setq level-cache (gethash (point) org--up-heading-cache)))
-            (when (<= (point-min) (car level-cache) (point-max))
-              ;; Parent is inside accessible part of the buffer.
-              (progn (goto-char (car level-cache))
-                     (cdr level-cache)))
-          ;; Buffer modified.  Invalidate cache.
-          (unless (eq (buffer-chars-modified-tick) org--up-heading-cache-tick)
-            (setq-local org--up-heading-cache-tick
-                        (buffer-chars-modified-tick))
-            (clrhash org--up-heading-cache))
-          (let* ((level-up (1- (funcall outline-level)))
-                 (pos (point))
-                 (result (and (> level-up 0)
-                             (re-search-backward
-                               (format "^\\*\\{1,%d\\} " level-up) nil t)
-                             (funcall outline-level))))
-            (when result (puthash pos (cons (point) result) 
org--up-heading-cache))
-            result))))))
+  (let ((element (and (org-element--cache-active-p)
+                      (org-element-at-point nil t))))
+    (if element
+        (let* ((current-heading (org-element-lineage element '(headline) 
'with-self))
+               (parent (org-element-lineage current-heading '(headline))))
+          (if (and parent
+                   (<= (point-min) (org-element-property :begin parent)))
+              (progn
+                (goto-char (org-element-property :begin parent))
+                (org-element-property :level parent))
+            (when (and current-heading
+                       (<= (point-min) (org-element-property :begin 
current-heading)))
+              (goto-char (org-element-property :begin current-heading))
+              nil)))
+      (when (ignore-errors (org-back-to-heading t))
+        (let (level-cache)
+          (unless org--up-heading-cache
+            (setq org--up-heading-cache (make-hash-table)))
+          (if (and (eq (buffer-chars-modified-tick) org--up-heading-cache-tick)
+                   (setq level-cache (gethash (point) org--up-heading-cache)))
+              (when (<= (point-min) (car level-cache) (point-max))
+                ;; Parent is inside accessible part of the buffer.
+                (progn (goto-char (car level-cache))
+                       (cdr level-cache)))
+            ;; Buffer modified.  Invalidate cache.
+            (unless (eq (buffer-chars-modified-tick) 
org--up-heading-cache-tick)
+              (setq-local org--up-heading-cache-tick
+                          (buffer-chars-modified-tick))
+              (clrhash org--up-heading-cache))
+            (let* ((level-up (1- (funcall outline-level)))
+                   (pos (point))
+                   (result (and (> level-up 0)
+                               (re-search-backward
+                                 (format "^\\*\\{1,%d\\} " level-up) nil t)
+                               (funcall outline-level))))
+              (when result (puthash pos (cons (point) result) 
org--up-heading-cache))
+              result)))))))
 
 (defun org-up-heading-or-point-min ()
   "Move to the heading line of which the present is a subheading, or point-min.
@@ -20906,20 +20911,21 @@ move point."
 Return t when a child was found.  Otherwise don't move point and
 return nil."
   (if (org-element--cache-active-p)
-      (when-let ((heading (org-element-lineage
-                           (or element (org-element-at-point))
-                           '(headline inlinetask org-data)
-                           t)))
-        (unless (or (eq 'inlinetask (org-element-type heading))
-                    (not (org-element-property :contents-begin heading)))
-          (let ((pos (point)))
-            (goto-char (org-element-property :contents-begin heading))
-            (if (re-search-forward
-                 org-outline-regexp-bol
-                 (org-element-property :end heading)
-                 t)
-                (progn (goto-char (match-beginning 0)) t)
-              (goto-char pos) nil))))
+      (let ((heading (org-element-lineage
+                      (or element (org-element-at-point))
+                      '(headline inlinetask org-data)
+                      t)))
+        (when heading
+          (unless (or (eq 'inlinetask (org-element-type heading))
+                      (not (org-element-property :contents-begin heading)))
+            (let ((pos (point)))
+              (goto-char (org-element-property :contents-begin heading))
+              (if (re-search-forward
+                   org-outline-regexp-bol
+                   (org-element-property :end heading)
+                   t)
+                  (progn (goto-char (match-beginning 0)) t)
+                (goto-char pos) nil)))))
     (let (level (pos (point)) (re org-outline-regexp-bol))
       (when (org-back-to-heading-or-point-min t)
         (setq level (org-outline-level))
diff --git a/testing/org-test.el b/testing/org-test.el
index 30adb97..ae4f32b 100644
--- a/testing/org-test.el
+++ b/testing/org-test.el
@@ -466,8 +466,13 @@ TIME can be a non-nil Lisp time value, or a string 
specifying a date and time."
               (apply ,(symbol-function 'current-time-zone)
                      (or time ,at) args)))
            ((symbol-function 'decode-time)
-            (lambda (&optional time zone form) (funcall ,(symbol-function 
'decode-time)
-                                                   (or time ,at) zone form)))
+            (lambda (&optional time zone form)
+               (condition-case err
+                   (funcall ,(symbol-function 'decode-time)
+                           (or time ,at) zone form)
+                 ;; Fallback for Emacs <27.1.
+                 (error (funcall ,(symbol-function 'decode-time)
+                                (or time ,at) zone)))))
            ((symbol-function 'encode-time)
             (lambda (time &rest args)
               (apply ,(symbol-function 'encode-time) (or time ,at) args)))

Reply via email to