Bladeren bron

Fix link search

* lisp/org.el (org-open-link-marker): Remove variable.
(org-open-at-point): Apply removal.
(org-link-search): Sanitize function.  Fix issue with internal link
encoding.
(org-search-not-self): Remove function.

* lisp/ox.el (org-export--inclusion-absolute-lines): Ensure INCLUDE
  keywords with locations can find named elements and targets.

* testing/lisp/test-org.el (test-org/return):
(test-org/coderef):
(test-org/custom-id): Update tests.
(test-org/fuzzy-links): Add tests.

Reported-by: Ivanov Dmitry <usr345@gmail.com>
<http://permalink.gmane.org/gmane.emacs.orgmode/99340>
Nicolas Goaziou 9 jaren geleden
bovenliggende
commit
cfe5bc97f8
4 gewijzigde bestanden met toevoegingen van 220 en 204 verwijderingen
  1. 159 156
      lisp/org.el
  2. 1 1
      lisp/ox.el
  3. 36 23
      testing/lisp/test-org.el
  4. 24 24
      testing/lisp/test-ox.el

+ 159 - 156
lisp/org.el

@@ -10603,9 +10603,6 @@ See the docstring of `org-open-file' for details."
   "The window configuration before following a link.
 This is saved in case the need arises to restore it.")
 
-(defvar org-open-link-marker (make-marker)
-  "Marker pointing to the location where `org-open-at-point' was called.")
-
 ;;;###autoload
 (defun org-open-at-point-global ()
   "Follow a link like Org-mode does.
@@ -10670,7 +10667,6 @@ link in a property drawer line."
   ;; On a code block, open block's results.
   (unless (call-interactively 'org-babel-open-src-block-result)
     (org-load-modules-maybe)
-    (move-marker org-open-link-marker (point))
     (setq org-window-config-before-follow-link (current-window-configuration))
     (org-remove-occur-highlights nil nil t)
     (unless (run-hook-with-args-until-success 'org-open-at-point-functions)
@@ -10858,7 +10854,6 @@ link in a property drawer line."
 			    (line-beginning-position)))))))
 	  (org-footnote-action))
 	 (t (user-error "No link found")))))
-    (move-marker org-open-link-marker nil)
     (run-hook-with-args 'org-follow-link-hook)))
 
 (defun org-offer-links-in-entry (buffer marker &optional nth zero)
@@ -10977,170 +10972,178 @@ the window configuration before `org-open-at-point' was called using:
     (set-window-configuration org-window-config-before-follow-link)")
 
 (defun org-link-search (s &optional type avoid-pos stealth)
-  "Search for a link search option.
-If S is surrounded by forward slashes, it is interpreted as a
-regular expression.  In org-mode files, this will create an `org-occur'
-sparse tree.  In ordinary files, `occur' will be used to list matches.
-If the current buffer is in `dired-mode', grep will be used to search
-in all files.  If AVOID-POS is given, ignore matches near that position.
+  "Search for a search string S.
+
+If S starts with \"#\", it triggers a custom ID search.
+
+If S is enclosed within parenthesis, it initiates a coderef
+search.
+
+If S is surrounded by forward slashes, it is interpreted as
+a regular expression.  In Org mode files, this will create an
+`org-occur' sparse tree.  In ordinary files, `occur' will be used
+to list matches.  If the current buffer is in `dired-mode', grep
+will be used to search in all files.
+
+When optional argument TYPE is `org-occur', call this function on
+a regexp matching S.  If it is `occur', call Emacs' `occur'
+function instead.
+
+When AVOID-POS is given, ignore matches near that position.
 
 When optional argument STEALTH is non-nil, do not modify
 visibility around point, thus ignoring `org-show-context-detail'
-variable."
-  (let ((case-fold-search t)
-	(s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
-	(markers (concat "\\(?:" (mapconcat (lambda (x) (regexp-quote (car x)))
-					    (append '(("") (" ") ("\t") ("\n"))
-						    org-emphasis-alist)
-					    "\\|") "\\)"))
-	(pos (point))
-	words re0 re2 re4_ re4 re5 re2a re2a_ reall)
+variable.
+
+Search is case-insensitive and ignores white spaces."
+  (unless (org-string-nw-p s) (error "Invalid search string \"%s\"" s))
+  (let* ((case-fold-search t)
+	 (origin (point))
+	 (normalized (replace-regexp-in-string "\n[ \t]*" " " s))
+	 (words (org-split-string s "[ \t\n]+"))
+	 (s-multi-re (mapconcat #'regexp-quote words "[ \t]+\\(?:\n[ \t]*\\)?"))
+	 (s-single-re (mapconcat #'regexp-quote words "[ \t]+")))
     (cond
-     ;; First check if there are any special search functions
+     ;; Check if there are any special search functions.
      ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
-     ;; Now try the builtin stuff
-     ((and (eq (aref s0 0) ?#)
-	   (> (length s0) 1)
-	   (let ((match (org-find-property "CUSTOM_ID" (substring s0 1))))
-	     (and match (goto-char match) (setf type 'dedicated)))))
-     ((save-excursion
-	(goto-char (point-min))
-	(and
-	 (re-search-forward
-	  (concat "<<" (regexp-quote s0) ">>") nil t)
-	 (setq type 'dedicated
-	       pos (match-beginning 0))))
-      ;; There is an exact target for this
-      (goto-char pos))
-     ((save-excursion
+     ((eq (string-to-char s) ?#)
+      ;; Look for a custom ID S if S starts with "#".
+      (let* ((id (substring normalized 1))
+	     (match (org-find-property "CUSTOM_ID" id)))
+	(if match (progn (goto-char match) (setf type 'dedicated))
+	  (error "No match for custom ID: %s" id))))
+     ((string-match "\\`(\\(.*\\))\\'" normalized)
+      ;; Look for coderef targets if S is enclosed within parenthesis.
+      (let ((coderef (match-string-no-properties 1 normalized))
+	    (re (substring s-single-re 1 -1)))
 	(goto-char (point-min))
-	(and
-	 (re-search-forward
-	  (format "^[ \t]*#\\+NAME: %s" (regexp-quote s0)) nil t)
-	 (setq type 'dedicated pos (match-beginning 0))))
-      ;; Found an element with a matching #+name affiliated keyword.
-      (goto-char pos))
-     ((and (string-match "^(\\(.*\\))$" s0)
-	   (save-excursion
-	     (goto-char (point-min))
-	     (and
-	      (re-search-forward
-	       (concat "[^[]" (regexp-quote
-			       (format org-coderef-label-format
-				       (match-string 1 s0))))
-	       nil t)
-	      (setq type 'dedicated
-		    pos (1+ (match-beginning 0))))))
-      ;; There is a coderef target for this
-      (goto-char pos))
-     ((string-match "^/\\(.*\\)/$" s)
-      ;; A regular expression
+	(catch :coderef-match
+	  (while (re-search-forward re nil t)
+	    (let ((element (org-element-at-point)))
+	      (when (and (memq (org-element-type element)
+			       '(example-block src-block))
+			 ;; Build proper regexp according to current
+			 ;; block's label format.
+			 (let ((label-fmt
+				(regexp-quote
+				 (or (org-element-property :label-fmt element)
+				     org-coderef-label-format))))
+			   (save-excursion
+			     (beginning-of-line)
+			     (looking-at (format ".*?\\(%s\\)[ \t]*$"
+						 (format label-fmt coderef))))))
+		(setq type 'dedicated)
+		(goto-char (match-beginning 1))
+		(throw :coderef-match nil))))
+	  (goto-char origin)
+	  (error "No match for coderef: %s" coderef))))
+     ((string-match "\\`/\\(.*\\)/\\'" normalized)
+      ;; Look for a regular expression.
       (cond
        ((derived-mode-p 'org-mode)
 	(org-occur (match-string 1 s)))
        (t (org-do-occur (match-string 1 s)))))
-     ((and (derived-mode-p 'org-mode)
-	   (or (and (equal (string-to-char s) ?*) (setq s (substring s 1)))
-	       org-link-search-must-match-exact-headline))
-      ;; Headline search.
-      (goto-char (point-min))
-      (cond
-       ((let (case-fold-search)
-	  (re-search-forward
-	   (let* ((wspace "[ \t]")
-		  (wspaceopt (concat wspace "*"))
-		  (cookie (concat "\\(?:"
-				  wspaceopt
-				  "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]"
-				  wspaceopt
-				  "\\)"))
-		  (sep (concat "\\(?:" wspace "+\\|" cookie "+\\)")))
-	     (concat
-	      org-outline-regexp-bol
-	      "\\(?:" org-todo-regexp "[ \t]+\\)?"
-	      "\\(?:\\[#.\\][ \t]+\\)?"
-	      "\\(?:" org-comment-string "[ \t]+\\)?"
-	      sep "*"
-	      (mapconcat #'identity
-			 (org-split-string (regexp-quote s))
-			 (concat sep "+"))
-	      sep "*"
-	      (org-re "\\(?:[ \t]+:[[:alnum:]_@#%%:]+:\\)?")
-	      "[ \t]*$"))
-	   nil t))
-	;; OK, found a match
-	(setq type 'dedicated)
-	(goto-char (match-beginning 0)))
-       ((and (not org-link-search-inhibit-query)
-	     (eq org-link-search-must-match-exact-headline 'query-to-create)
-	     (y-or-n-p "No match - create this as a new heading? "))
-	(goto-char (point-max))
-	(unless (bolp) (newline))
-	(org-insert-heading nil t t)
-	(insert s "\n")
-	(beginning-of-line 0))
-       (t
-	(goto-char pos)
-	(error "No match"))))
+     ;; Fuzzy links.
      (t
-      ;; A normal search string
-      (remove-text-properties
-       0 (length s)
-       '(face nil mouse-face nil keymap nil fontified nil) s)
-      ;; Make a series of regular expressions to find a match
-      (setq words (org-split-string s "[ \n\r\t]+")
-
-	    re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
-	    re2 (concat markers "\\(" (mapconcat 'downcase words "[ \t]+")
-			"\\)" markers)
-	    re2a_ (concat "\\(" (mapconcat 'downcase words
-					   "[ \t\r\n]+") "\\)[ \t\r\n]")
-	    re2a (concat "[ \t\r\n]" re2a_)
-	    re4_ (concat "\\(" (mapconcat 'downcase words
-					  "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
-	    re4 (concat "[^a-zA-Z_]" re4_)
-
-	    re5 (concat ".*" re4)
-	    reall (concat "\\(" re0 "\\)\\|\\(" re2 "\\)\\|\\(" re4
-			  "\\)\\|\\(" re5 "\\)"))
-      (cond
-       ((eq type 'org-occur) (org-occur reall))
-       ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
-       (t (goto-char (point-min))
-	  (setq type 'fuzzy)
-	  (if (or (and (org-search-not-self 1 re0 nil t)
-		       (setq type 'dedicated))
-		  (org-search-not-self 1 re2 nil t)
-		  (org-search-not-self 1 re2a nil t)
-		  (org-search-not-self 1 re4 nil t)
-		  (org-search-not-self 1 re5 nil t))
-	      (goto-char (match-beginning 1))
-	    (goto-char pos)
-	    (error "No match"))))))
-    (and (derived-mode-p 'org-mode)
-	 (not stealth)
-	 (org-show-context 'link-search))
+      (let* ((starred (eq (string-to-char normalized) ?*))
+	     (headline-search (and (derived-mode-p 'org-mode)
+				   (or org-link-search-must-match-exact-headline
+				       starred))))
+	(cond
+	 ;; Look for targets, only if not in a headline search.
+	 ((and (not headline-search)
+	       (let ((target (format "<<%s>>" s-multi-re)))
+		 (catch :target-match
+		   (goto-char (point-min))
+		   (while (re-search-forward target nil t)
+		     (backward-char)
+		     (let ((context (org-element-context)))
+		       (when (eq (org-element-type context) 'target)
+			 (setq type 'dedicated)
+			 (goto-char (org-element-property :begin context))
+			 (throw :target-match t))))
+		   nil))))
+	 ;; Look for elements named after S, only if not in a headline
+	 ;; search.
+	 ((and (not headline-search)
+	       (let ((name (format "^[ \t]*#\\+NAME: +%s[ \t]*$" s-single-re)))
+		 (catch :name-match
+		   (goto-char (point-min))
+		   (while (re-search-forward name nil t)
+		     (let ((element (org-element-at-point)))
+		       (when (equal (org-split-string
+				     (org-element-property :name element)
+				     "[ \t]+")
+				    words)
+			 (setq type 'dedicated)
+			 (beginning-of-line)
+			 (throw :name-match t))))
+		   nil))))
+	 ;; Regular text search.  Prefer headlines in Org mode
+	 ;; buffers.
+	 ((and (derived-mode-p 'org-mode)
+	       (let* ((wspace "[ \t]")
+		      (wspaceopt (concat wspace "*"))
+		      (cookie (concat "\\(?:"
+				      wspaceopt
+				      "\\[[0-9]*\\(?:%\\|/[0-9]*\\)\\]"
+				      wspaceopt
+				      "\\)"))
+		      (sep (concat "\\(?:" wspace "+\\|" cookie "+\\)"))
+		      (re (concat
+			   org-outline-regexp-bol
+			   "\\(?:" org-todo-regexp "[ \t]+\\)?"
+			   "\\(?:\\[#.\\][ \t]+\\)?"
+			   "\\(?:" org-comment-string "[ \t]+\\)?"
+			   sep "*"
+			   (let ((title (mapconcat #'regexp-quote
+						   words
+						   (concat sep "+"))))
+			     (if starred (substring title 1) title))
+			   sep "*"
+			   (org-re "\\(?:[ \t]+:[[:alnum:]_@#%%:]+:\\)?")
+			   "[ \t]*$")))
+		 (goto-char (point-min))
+		 (re-search-forward re nil t)))
+	  (goto-char (match-beginning 0))
+	  (setq type 'dedicated))
+	 ;; Offer to create non-existent headline depending on
+	 ;; `org-link-search-must-match-exact-headline'.
+	 ((and headline-search
+	       (not org-link-search-inhibit-query)
+	       (eq org-link-search-must-match-exact-headline 'query-to-create)
+	       (yes-or-no-p "No match - create this as a new heading? "))
+	  (goto-char (point-max))
+	  (unless (bolp) (newline))
+	  (org-insert-heading nil t t)
+	  (insert s "\n")
+	  (beginning-of-line 0))
+	 ;; Only headlines are looked after.  No need to process
+	 ;; further: throw an error.
+	 (headline-search
+	  (goto-char origin)
+	  (error "No match for fuzzy expression: %s" normalized))
+	 ;; Regular text search or occur, depending on TYPE.
+	 ((eq type 'org-occur) (org-occur s-multi-re))
+	 ((eq type 'occur) (org-do-occur s-multi-re 'cleanup))
+	 ((catch :fuzzy-match
+	    (goto-char (point-min))
+	    (while (re-search-forward s-multi-re nil t)
+	      (unless (and avoid-pos
+			   (>= (match-beginning 0) avoid-pos)
+			   (< (match-end 0) avoid-pos))
+		(goto-char (match-beginning 0))
+		(setq type 'fuzzy)
+		(throw :fuzzy-match t)))
+	    nil))
+	 ;; All failed.  Throw an error.
+	 (t (goto-char origin)
+	    (error "No match for fuzzy expression: %s" normalized))))))
+    ;; Disclose surroundings of match, if appropriate.
+    (when (and (derived-mode-p 'org-mode) (not stealth))
+      (org-show-context 'link-search))
     type))
 
-(defun org-search-not-self (group &rest args)
-  "Execute `re-search-forward', but only accept matches that do not
-enclose the position of `org-open-link-marker'."
-  (let ((m org-open-link-marker))
-    (catch 'exit
-      (while (apply 're-search-forward args)
-	(unless (get-text-property (match-end group) 'intangible) ; Emacs 21
-	  (goto-char (match-end group))
-	  (if (and (or (not (eq (marker-buffer m) (current-buffer)))
-		       (> (match-beginning 0) (marker-position m))
-		       (< (match-end 0) (marker-position m)))
-		   (save-match-data
-		     (or (not (org-in-regexp
-			       org-bracket-link-analytic-regexp 1))
-			 (not (match-end 4))  ; no description
-			 (and (<= (match-beginning 4) (point))
-			      (>= (match-end 4) (point))))))
-	      (throw 'exit (point))))))))
-
 (defun org-get-buffer-for-internal-link (buffer)
   "Return a buffer to be used for displaying the link target of internal links."
   (cond

+ 1 - 1
lisp/ox.el

@@ -3297,7 +3297,7 @@ Return a string of lines to be included in the format expected by
       (let ((org-inhibit-startup t)) (org-mode)))
     (condition-case err
 	;; Enforce consistent search.
-	(let ((org-link-search-must-match-exact-headline t))
+	(let ((org-link-search-must-match-exact-headline nil))
 	  (org-link-search location))
       (error
        (error "%s for %s::%s" (error-message-string err) file location)))

+ 36 - 23
testing/lisp/test-org.el

@@ -886,7 +886,8 @@
   ;; is non-nil.
   (should
    (org-test-with-temp-text "Link [[target<point>]] <<target>>"
-     (let ((org-return-follows-link t)) (org-return))
+     (let ((org-return-follows-link t)
+	   (org-link-search-must-match-exact-headline nil)) (org-return))
      (org-looking-at-p "<<target>>")))
   (should-not
    (org-test-with-temp-text "Link [[target<point>]] <<target>>"
@@ -1422,10 +1423,18 @@
 #+BEGIN_SRC emacs-lisp
 \(+ 1 1)                  (ref:sc)
 #+END_SRC
-\[[(sc)]]"
-     (goto-char (point-max))
+\[[(sc)]]<point>"
+     (org-open-at-point)
+     (looking-at "(ref:sc)")))
+  ;; Find coderef even with alternate label format.
+  (should
+   (org-test-with-temp-text "
+#+BEGIN_SRC emacs-lisp -l \"{ref:%s}\"
+\(+ 1 1)                  {ref:sc}
+#+END_SRC
+\[[(sc)]]<point>"
      (org-open-at-point)
-     (looking-at "(ref:sc)"))))
+     (looking-at "{ref:sc}"))))
 
 ;;;; Custom ID
 
@@ -1433,16 +1442,14 @@
   "Test custom ID links specifications."
   (should
    (org-test-with-temp-text
-       "* H1\n:PROPERTIES:\n:CUSTOM_ID: custom\n:END:\n* H2\n[[#custom]]"
-     (goto-char (point-max))
+       "* H1\n:PROPERTIES:\n:CUSTOM_ID: custom\n:END:\n* H2\n[[#custom]]<point>"
      (org-open-at-point)
      (org-looking-at-p "\\* H1")))
-  ;; Ignore false positives.
-  (should-not
+  ;; Throw an error on false positives.
+  (should-error
    (org-test-with-temp-text
        "* H1\n:DRAWER:\n:CUSTOM_ID: custom\n:END:\n* H2\n[[#custom]]<point>"
-     (goto-char (point-max))
-     (let (org-link-search-must-match-exact-headline) (org-open-at-point))
+     (org-open-at-point)
      (org-looking-at-p "\\* H1"))))
 
 ;;;; Fuzzy Links
@@ -1454,27 +1461,24 @@
   "Test fuzzy links specifications."
   ;; Fuzzy link goes in priority to a matching target.
   (should
-   (org-test-with-temp-text "#+NAME: Test\n|a|b|\n<<Test>>\n* Test\n[[Test]]"
-     (goto-line 5)
-     (org-open-at-point)
+   (org-test-with-temp-text
+       "#+NAME: Test\n|a|b|\n<<Test>>\n* Test\n<point>[[Test]]"
+     (let ((org-link-search-must-match-exact-headline nil)) (org-open-at-point))
      (looking-at "<<Test>>")))
   ;; Then fuzzy link points to an element with a given name.
   (should
-   (org-test-with-temp-text "Test\n#+NAME: Test\n|a|b|\n* Test\n[[Test]]"
-     (goto-line 5)
-     (org-open-at-point)
+   (org-test-with-temp-text "Test\n#+NAME: Test\n|a|b|\n* Test\n<point>[[Test]]"
+     (let ((org-link-search-must-match-exact-headline nil)) (org-open-at-point))
      (looking-at "#\\+NAME: Test")))
   ;; A target still lead to a matching headline otherwise.
   (should
-   (org-test-with-temp-text "* Head1\n* Head2\n*Head3\n[[Head2]]"
-     (goto-line 4)
-     (org-open-at-point)
+   (org-test-with-temp-text "* Head1\n* Head2\n*Head3\n<point>[[Head2]]"
+     (let ((org-link-search-must-match-exact-headline nil)) (org-open-at-point))
      (looking-at "\\* Head2")))
   ;; With a leading star in link, enforce heading match.
   (should
-   (org-test-with-temp-text "* Test\n<<Test>>\n[[*Test]]"
-     (goto-line 3)
-     (org-open-at-point)
+   (org-test-with-temp-text "* Test\n<<Test>>\n<point>[[*Test]]"
+     (let ((org-link-search-must-match-exact-headline nil)) (org-open-at-point))
      (looking-at "\\* Test")))
   ;; With a leading star in link, enforce exact heading match, even
   ;; with `org-link-search-must-match-exact-headline' set to nil.
@@ -1482,7 +1486,16 @@
    (org-test-with-temp-text "* Test 1\nFoo Bar\n<point>[[*Test]]"
      (let ((org-link-search-must-match-exact-headline nil))
        (org-open-at-point))))
-  ;; Heading match should not care about spaces, cookies, todo
+  ;; Handle non-nil `org-link-search-must-match-exact-headline'.
+  (should
+   (org-test-with-temp-text "* Test\nFoo Bar\n<point>[[Test]]"
+     (let ((org-link-search-must-match-exact-headline t)) (org-open-at-point))
+     (looking-at "\\* Test")))
+  (should
+   (org-test-with-temp-text "* Test\nFoo Bar\n<point>[[*Test]]"
+     (let ((org-link-search-must-match-exact-headline t)) (org-open-at-point))
+     (looking-at "\\* Test")))
+  ;; Heading match should not care about spaces, cookies, TODO
   ;; keywords, priorities, and tags.
   (should
    (let ((first-line

+ 24 - 24
testing/lisp/test-ox.el

@@ -911,40 +911,40 @@ text
    (equal
     "#+BEGIN_EXAMPLE\nSmall Org file with an include keyword.\n#+END_EXAMPLE\n"
     (org-test-with-temp-text
-     (format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\" EXAMPLE"
-	     org-test-dir)
-     (org-export-expand-include-keyword)
-     (buffer-string))))
+	(format "#+INCLUDE: \"%s/examples/include.org\" :lines \"1-2\" EXAMPLE"
+		org-test-dir)
+      (org-export-expand-include-keyword)
+      (buffer-string))))
   ;; Inclusion within a src-block.
   (should
    (equal
     "#+BEGIN_SRC emacs-lisp\n(+ 2 1)\n#+END_SRC\n"
     (org-test-with-temp-text
-     (format
-      "#+INCLUDE: \"%s/examples/include.org\" :lines \"4-5\" SRC emacs-lisp"
-      org-test-dir)
-     (org-export-expand-include-keyword)
-     (buffer-string))))
+	(format
+	 "#+INCLUDE: \"%s/examples/include.org\" :lines \"4-5\" SRC emacs-lisp"
+	 org-test-dir)
+      (org-export-expand-include-keyword)
+      (buffer-string))))
   ;; Inclusion within an html export-block.
   (should
    (equal
     "#+BEGIN_HTML\n<p>HTML!</p>\n#+END_HTML\n"
     (org-test-with-temp-text
-     (format
-      "#+INCLUDE: \"%s/examples/include.html\" HTML"
-      org-test-dir)
-     (org-export-expand-include-keyword)
-     (buffer-string))))
+	(format
+	 "#+INCLUDE: \"%s/examples/include.html\" HTML"
+	 org-test-dir)
+      (org-export-expand-include-keyword)
+      (buffer-string))))
   ;; Inclusion within an center paragraph
   (should
    (equal
     "#+BEGIN_CENTER\nSuccess!\n#+END_CENTER\n"
     (org-test-with-temp-text
-     (format
-      "#+INCLUDE: \"%s/examples/include2.org\" CENTER"
-      org-test-dir)
-     (org-export-expand-include-keyword)
-     (buffer-string))))
+	(format
+	 "#+INCLUDE: \"%s/examples/include2.org\" CENTER"
+	 org-test-dir)
+      (org-export-expand-include-keyword)
+      (buffer-string))))
   ;; Footnotes labels are local to each included file.
   (should
    (= 6
@@ -1016,15 +1016,15 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
    (equal
     "body\n"
     (org-test-with-temp-text
-     (concat
-      (format "#+INCLUDE: \"%s/examples/include.org::*Heading\" " org-test-dir)
-      ":only-contents t")
+	(concat
+	 (format "#+INCLUDE: \"%s/examples/include.org::*Heading\" " org-test-dir)
+	 ":only-contents t")
       (org-export-expand-include-keyword)
       (buffer-string))))
   ;; Headings can be included via CUSTOM_ID.
   (should
    (org-test-with-temp-text
-	(format "#+INCLUDE: \"%s/examples/include.org::#ah\"" org-test-dir)
+       (format "#+INCLUDE: \"%s/examples/include.org::#ah\"" org-test-dir)
      (org-export-expand-include-keyword)
      (goto-char (point-min))
      (looking-at "* Another heading")))
@@ -1039,7 +1039,7 @@ Footnotes[fn:2], foot[fn:test], digit only[3], and [fn:inline:anonymous footnote
   ;; Including non-existing elements should result in an error.
   (should-error
    (org-test-with-temp-text
-	(format "#+INCLUDE: \"%s/examples/include.org::*non-existing heading\"" org-test-dir)
+       (format "#+INCLUDE: \"%s/examples/include.org::*non-existing heading\"" org-test-dir)
      (org-export-expand-include-keyword)))
   ;; Lines work relatively to an included element.
   (should