Browse Source

Prevent flagging drawers in example blocks

* lisp/org.el (org-flag-drawer): Rewrite function using Elements.
  Also prevents flagging drawers within example blocks.
* testing/lisp/test-org.el (test-org/flag-drawer): Add test.
Nicolas Goaziou 11 years ago
parent
commit
b392750108
2 changed files with 58 additions and 12 deletions
  1. 15 12
      lisp/org.el
  2. 43 0
      testing/lisp/test-org.el

+ 15 - 12
lisp/org.el

@@ -7058,18 +7058,21 @@ specifying which drawers should not be hidden."
 	     org-inlinetask-min-level)
     (hide-sublevels (1- org-inlinetask-min-level))))
 
-(defun org-flag-drawer (flag)
-  "When FLAG is non-nil, hide the drawer we are within.
-Otherwise make it visible."
-  (save-excursion
-    (beginning-of-line 1)
-    (when (looking-at "^[ \t]*:[a-zA-Z][a-zA-Z0-9]*:")
-      (let ((b (match-end 0)))
-	(if (re-search-forward
-	     "^[ \t]*:END:"
-	     (save-excursion (outline-next-heading) (point)) t)
-	    (outline-flag-region b (point-at-eol) flag)
-	  (user-error ":END: line missing at position %s" b))))))
+(defun org-flag-drawer (flag &optional element)
+  "When FLAG is non-nil, hide the drawer we are at.
+Otherwise make it visible.  When optional argument ELEMENT is
+a parsed drawer, as returned by `org-element-at-point', hide or
+show that drawer instead."
+  (let ((drawer (or element (org-element-at-point))))
+    (when (memq (org-element-type drawer) '(drawer property-drawer))
+      (save-excursion
+	(goto-char (org-element-property :post-affiliated drawer))
+	(outline-flag-region
+	 (line-end-position)
+	 (progn (goto-char (org-element-property :end drawer))
+		(skip-chars-backward " \r\t\n")
+		(line-end-position))
+	 flag)))))
 
 (defun org-subtree-end-visible-p ()
   "Is the end of the current subtree visible?"

+ 43 - 0
testing/lisp/test-org.el

@@ -1294,6 +1294,49 @@ Text.
 	  (org-test-with-temp-text "<<target>> <<<radio-target>>>"
 	    (org-all-targets t)))))
 
+
+;;; Visibility
+
+(ert-deftest test-org/flag-drawer ()
+  "Test `org-flag-drawer' specifications."
+  ;; Hide drawer.
+  (should
+   (org-test-with-temp-text ":DRAWER:\ncontents\n:END:"
+     (org-flag-drawer t)
+     (get-char-property (line-end-position) 'invisible)))
+  ;; Show drawer.
+  (should-not
+   (org-test-with-temp-text ":DRAWER:\ncontents\n:END:"
+     (org-flag-drawer t)
+     (org-flag-drawer nil)
+     (get-char-property (line-end-position) 'invisible)))
+  ;; Test optional argument.
+  (should
+   (org-test-with-temp-text ":D1:\nc1\n:END:\n\n:D2:\nc2\n:END:"
+     (let ((drawer (save-excursion (search-forward ":D2")
+				   (org-element-at-point))))
+       (org-flag-drawer t drawer)
+       (get-char-property (progn (search-forward ":D2") (line-end-position))
+			  'invisible))))
+  (should-not
+   (org-test-with-temp-text ":D1:\nc1\n:END:\n\n:D2:\nc2\n:END:"
+     (let ((drawer (save-excursion (search-forward ":D2")
+				   (org-element-at-point))))
+       (org-flag-drawer t drawer)
+       (get-char-property (line-end-position) 'invisible))))
+  ;; Do not hide fake drawers.
+  (should-not
+   (org-test-with-temp-text "#+begin_example\n:D:\nc\n:END:\n#+end_example"
+     (forward-line 1)
+     (org-flag-drawer t)
+     (get-char-property (line-end-position) 'invisible)))
+  ;; Do not hide incomplete drawers.
+  (should-not
+   (org-test-with-temp-text ":D:\nparagraph"
+     (forward-line 1)
+     (org-flag-drawer t)
+     (get-char-property (line-end-position) 'invisible))))
+
 
 (provide 'test-org)