diff options
author | Nicolas Goaziou <mail@nicolasgoaziou.fr> | 2020-04-18 12:29:43 +0200 |
---|---|---|
committer | Nicolas Goaziou <mail@nicolasgoaziou.fr> | 2020-04-18 18:34:56 +0200 |
commit | 692f191f840bed6fc1482268fb000027a7ada8c2 (patch) | |
tree | 621b297fa6bbd1354c76c03c7e251d3522fcae28 | |
parent | 4fbc36a0576a0eab1210e66534d81a5daf5e494b (diff) | |
download | org-mode-692f191f840bed6fc1482268fb000027a7ada8c2.tar.gz |
Refactor block and drawer visibility toggling
* lisp/org.el (org--hide-wrapper-toggle): New function.
(org-hide-block-toggle):
(org-hide-drawer-toggle): Use new function.
-rw-r--r-- | lisp/org.el | 145 |
1 files changed, 66 insertions, 79 deletions
diff --git a/lisp/org.el b/lisp/org.el index ae9ea5b..34c0f7d 100644 --- a/lisp/org.el +++ b/lisp/org.el @@ -5958,7 +5958,57 @@ heading to appear." (org-flag-region (point) (save-excursion (org-end-of-subtree t t)) nil 'outline)) -;;;; Blocks visibility +;;;; Blocks and drawers visibility + +(defun org--hide-wrapper-toggle (element category force no-error) + "Toggle visibility for ELEMENT. + +ELEMENT is a block or drawer type parsed element. CATEGORY is +either `block' or `drawer'. When FORCE is `off', show the block +or drawer. If it is non-nil, hide it unconditionally. Throw an +error when not at a block or drawer, unless NO-ERROR is non-nil. + +Return a non-nil value when toggling is successful." + (cond + ((memq (org-element-type element) + (pcase category + (`drawer '(drawer property-drawer)) + (`block '(center-block + comment-block dynamic-block example-block export-block + quote-block special-block src-block verse-block)) + (_ (error "Unknown category: %S" category)))) + (let* ((post (org-element-property :post-affiliated element)) + (start (save-excursion + (goto-char post) + (line-end-position))) + (end (save-excursion + (goto-char (org-element-property :end element)) + (skip-chars-backward " \t\n") + (line-end-position)))) + ;; Do nothing when not before or at the block opening line or at + ;; the block closing line. + (unless (let ((eol (line-end-position))) + (and (> eol start) (/= eol end))) + (let* ((spec (if (eq category 'drawer) + 'org-hide-drawer + 'org-hide-block)) + (flag + (cond ((eq force 'off) nil) + (force t) + ((eq (get-char-property start 'invisible) spec) nil) + (t t)))) + (org-flag-region start end flag spec)) + ;; When the block is hidden away, make sure point is left in + ;; a visible part of the buffer. + (when (invisible-p (max (1- (point)) (point-min))) + (goto-char post)) + ;; Signal success. + t))) + (no-error nil) + (t + (user-error (if (eq category 'drawer) + "Not at a drawer" + "Not at a block"))))) (defun org-hide-block-toggle (&optional force no-error element) "Toggle the visibility of the current block. @@ -5970,40 +6020,21 @@ ELEMENT is provided, consider it instead of the current block. Return a non-nil value when toggling is successful." (interactive) - (let ((element (or element (org-element-at-point)))) - (cond - ((memq (org-element-type element) - '(center-block comment-block dynamic-block example-block - export-block quote-block special-block src-block - verse-block)) - (let* ((post (org-element-property :post-affiliated element)) - (start (save-excursion - (goto-char post) - (line-end-position))) - (end (save-excursion - (goto-char (org-element-property :end element)) - (skip-chars-backward " \t\n") - (line-end-position)))) - ;; Do nothing when not before or at the block opening line or at - ;; the block closing line. - (unless (let ((eol (line-end-position))) - (and (> eol start) (/= eol end))) - (let ((flag - (cond ((eq force 'off) nil) - (force t) - ((eq (get-char-property start 'invisible) - 'org-hide-drawer) - nil) - (t t)))) - (org-flag-region start end flag 'org-hide-block)) - ;; When the block is hidden away, make sure point is left in - ;; a visible part of the buffer. - (when (invisible-p (max (1- (point)) (point-min))) - (goto-char post)) - ;; Signal success. - t))) - (no-error nil) - (t (user-error "Not at a block"))))) + (org--hide-wrapper-toggle + (or element (org-element-at-point)) 'block force no-error)) + +(defun org-hide-drawer-toggle (&optional force no-error element) + "Toggle the visibility of the current drawer. + +When optional argument FORCE is `off', make drawer visible. If +it is non-nil, hide it unconditionally. Throw an error when not +at a drawer, unless NO-ERROR is non-nil. When optional argument +ELEMENT is provided, consider it instead of the current drawer. + +Return a non-nil value when toggling is successful." + (interactive) + (org--hide-wrapper-toggle + (or element (org-element-at-point)) 'drawer force no-error)) (defun org-hide-block-all () "Fold all blocks in the current buffer." @@ -6011,8 +6042,6 @@ Return a non-nil value when toggling is successful." (org-show-all '(blocks)) (org-block-map 'org-hide-block-toggle)) -;;;; Drawers visibility - (defun org-cycle-hide-drawers (state &optional exceptions) "Re-hide all drawers after a visibility state change. STATE should be one of the symbols listed in the docstring of @@ -6038,48 +6067,6 @@ a list of strings specifying which drawers should not be hidden." ;; `org-drawer-regexp'. (goto-char (org-element-property :end drawer)))))))))) -(defun org-hide-drawer-toggle (&optional force no-error element) - "Toggle the visibility of the current drawer. - -When optional argument FORCE is `off', make drawer visible. If -it is non-nil, hide it unconditionally. Throw an error when not -at a drawer, unless NO-ERROR is non-nil. When optional argument -ELEMENT is provided, consider it instead of the current drawer. - -Return a non-nil value when toggling is successful." - (interactive) - (let ((element (or element (org-element-at-point)))) - (cond - ((memq (org-element-type element) '(drawer property-drawer)) - (let* ((post (org-element-property :post-affiliated element)) - (start (save-excursion - (goto-char post) - (line-end-position))) - (end (save-excursion - (goto-char (org-element-property :end element)) - (skip-chars-backward " \t\n") - (line-end-position)))) - ;; Do nothing when not before or at the block opening line or at - ;; the block closing line. - (unless (let ((eol (line-end-position))) - (and (> eol start) (/= eol end))) - (let ((flag - (cond ((eq force 'off) nil) - (force t) - ((eq (get-char-property start 'invisible) - 'org-hide-drawer) - nil) - (t t)))) - (org-flag-region start end flag 'org-hide-drawer)) - ;; When the drawer is hidden away, make sure point is left - ;; in a visible part of the buffer. - (when (invisible-p (max (1- (point)) (point-min))) - (goto-char post)) - ;; Signal success. - t))) - (no-error nil) - (t (user-error "Not at a drawer"))))) - ;;;; Visibility cycling (defvar-local org-cycle-global-status nil) |