Prevent flagging drawers in example blocks
authorNicolas Goaziou <n.goaziou@gmail.com>
Sat, 2 Nov 2013 14:48:36 +0000 (2 15:48 +0100)
committerNicolas Goaziou <n.goaziou@gmail.com>
Sat, 2 Nov 2013 14:50:29 +0000 (2 15:50 +0100)
* 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.

lisp/org.el
testing/lisp/test-org.el

index a432806..7016d5a 100644 (file)
@@ -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?"
index d603971..0e068dd 100644 (file)
@@ -1294,6 +1294,49 @@ Text.
          (org-test-with-temp-text "<<target>> <<<radio-target>>>"
            (org-all-targets t)))))
 
+\f
+;;; 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)