From: Ihor Radchenko <yantar92@gmail.com> To: Bastien <bzg@gnu.org>, Kyle Meyer <kyle@kyleam.com>, Nicolas Goaziou <mail@nicolasgoaziou.fr>, Karl Voit <devnull@Karl-Voit.at>, Christian Heinrich <christian@gladbachcity.de>, emacs-orgmode@gnu.org Cc: Ihor Radchenko <yantar92@gmail.com> Subject: [PATCH 02/35] Separate folding functions from org.el into new library: org-fold Date: Sat, 29 Jan 2022 19:37:54 +0800 [thread overview] Message-ID: <a36ac8670ea6eda6b25b0be5ff1ee4afdd46e34a.1643454546.git.yantar92@gmail.com> (raw) In-Reply-To: <cover.1643454545.git.yantar92@gmail.com> [-- Attachment #1: Type: text/plain, Size: 150 bytes --] --- lisp/org-fold.el | 1135 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1135 insertions(+) create mode 100644 lisp/org-fold.el [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: 0002-Separate-folding-functions-from-org.el-into-new-libr.patch --] [-- Type: text/x-patch; name="0002-Separate-folding-functions-from-org.el-into-new-libr.patch", Size: 49902 bytes --] diff --git a/lisp/org-fold.el b/lisp/org-fold.el new file mode 100644 index 000000000..52717fd86 --- /dev/null +++ b/lisp/org-fold.el @@ -0,0 +1,1135 @@ +;;; org-fold.el --- Folding of Org entries -*- lexical-binding: t; -*- +;; +;; Copyright (C) 2020-2020 Free Software Foundation, Inc. +;; +;; Author: Ihor Radchenko <yantar92 at gmail dot com> +;; Keywords: folding, invisible text +;; Homepage: https://orgmode.org +;; +;; This file is part of GNU Emacs. +;; +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: + +;; This file contains code handling temporary invisibility (folding +;; and unfolding) of text in org buffers. + +;; The folding is implemented using generic org-fold-core library. This file +;; contains org-specific implementation of the folding. Also, various +;; useful functions from org-fold-core are aliased under shorted `org-fold' +;; prefix. + +;; The following features are implemented: +;; - Folding/unfolding various Org mode elements and regions of Org buffers: +;; + Region before first heading; +;; + Org headings, their text, children (subtree), siblings, parents, etc; +;; + Org blocks and drawers +;; - Revealing Org structure around invisible point location +;; - Revealing folded Org elements broken by user edits + +;;; Code: + +(require 'org-macs) +(require 'org-fold-core) + +(defvar org-inlinetask-min-level) +(defvar org-link--link-folding-spec) +(defvar org-link--description-folding-spec) +(defvar org-odd-levels-only) +(defvar org-drawer-regexp) +(defvar org-property-end-re) +(defvar org-link-descriptive) +(defvar org-outline-regexp-bol) +(defvar org-custom-properties-hidden-p) +(defvar org-archive-tag) + +;; Needed for overlays only +(defvar org-custom-properties-overlays) + +(declare-function isearch-filter-visible "isearch" (beg end)) +(declare-function org-element-type "org-element" (element)) +(declare-function org-element-at-point "org-element" (&optional pom cached-only)) +(declare-function org-element-property "org-element" (property element)) +(declare-function org-element--current-element "org-element" (limit &optional granularity mode structure)) +(declare-function org-element--cache-active-p "org-element" ()) +(declare-function org-toggle-custom-properties-visibility "org" ()) +(declare-function org-item-re "org-list" ()) +(declare-function org-up-heading-safe "org" ()) +(declare-function org-get-tags "org" (&optional pos local fontify)) +(declare-function org-get-valid-level "org" (level &optional change)) +(declare-function org-before-first-heading-p "org" ()) +(declare-function org-goto-sibling "org" (&optional previous)) +(declare-function org-block-map "org" (function &optional start end)) +(declare-function org-map-region "org" (fun beg end)) +(declare-function org-end-of-subtree "org" (&optional invisible-ok to-heading)) +(declare-function org-back-to-heading-or-point-min "org" (&optional invisible-ok)) +(declare-function org-back-to-heading "org" (&optional invisible-ok)) +(declare-function org-at-heading-p "org" (&optional invisible-not-ok)) +(declare-function org-cycle-hide-drawers "org-cycle" (state)) + +(declare-function outline-show-branches "outline" ()) +(declare-function outline-hide-sublevels "outline" (levels)) +(declare-function outline-get-next-sibling "outline" ()) +(declare-function outline-invisible-p "outline" (&optional pos)) +(declare-function outline-next-heading "outline" ()) + +;;; Customization + +(defgroup org-fold-reveal-location nil + "Options about how to make context of a location visible." + :tag "Org Reveal Location" + :group 'org-structure) + +(defcustom org-fold-show-context-detail '((agenda . local) + (bookmark-jump . lineage) + (isearch . lineage) + (default . ancestors)) + "Alist between context and visibility span when revealing a location. + +\\<org-mode-map>Some actions may move point into invisible +locations. As a consequence, Org always exposes a neighborhood +around point. How much is shown depends on the initial action, +or context. Valid contexts are + + agenda when exposing an entry from the agenda + org-goto when using the command `org-goto' (`\\[org-goto]') + occur-tree when using the command `org-occur' (`\\[org-sparse-tree] /') + tags-tree when constructing a sparse tree based on tags matches + link-search when exposing search matches associated with a link + mark-goto when exposing the jump goal of a mark + bookmark-jump when exposing a bookmark location + isearch when exiting from an incremental search + default default for all contexts not set explicitly + +Allowed visibility spans are + + minimal show current headline; if point is not on headline, + also show entry + + local show current headline, entry and next headline + + ancestors show current headline and its direct ancestors; if + point is not on headline, also show entry + + ancestors-full show current subtree and its direct ancestors + + lineage show current headline, its direct ancestors and all + their children; if point is not on headline, also show + entry and first child + + tree show current headline, its direct ancestors and all + their children; if point is not on headline, also show + entry and all children + + canonical show current headline, its direct ancestors along with + their entries and children; if point is not located on + the headline, also show current entry and all children + +As special cases, a nil or t value means show all contexts in +`minimal' or `canonical' view, respectively. + +Some views can make displayed information very compact, but also +make it harder to edit the location of the match. In such +a case, use the command `org-fold-reveal' (`\\[org-fold-reveal]') to show +more context." + :group 'org-fold-reveal-location + :version "26.1" + :package-version '(Org . "9.0") + :type '(choice + (const :tag "Canonical" t) + (const :tag "Minimal" nil) + (repeat :greedy t :tag "Individual contexts" + (cons + (choice :tag "Context" + (const agenda) + (const org-goto) + (const occur-tree) + (const tags-tree) + (const link-search) + (const mark-goto) + (const bookmark-jump) + (const isearch) + (const default)) + (choice :tag "Detail level" + (const minimal) + (const local) + (const ancestors) + (const ancestors-full) + (const lineage) + (const tree) + (const canonical)))))) + +(defvar org-fold-reveal-start-hook nil + "Hook run before revealing a location.") + +(defcustom org-fold-catch-invisible-edits 'smart + "Check if in invisible region before inserting or deleting a character. +Valid values are: + +nil Do not check, so just do invisible edits. +error Throw an error and do nothing. +show Make point visible, and do the requested edit. +show-and-error Make point visible, then throw an error and abort the edit. +smart Make point visible, and do insertion/deletion if it is + adjacent to visible text and the change feels predictable. + Never delete a previously invisible character or add in the + middle or right after an invisible region. Basically, this + allows insertion and backward-delete right before ellipses. + FIXME: maybe in this case we should not even show?" + :group 'org-edit-structure + :version "24.1" + :type '(choice + (const :tag "Do not check" nil) + (const :tag "Throw error when trying to edit" error) + (const :tag "Unhide, but do not do the edit" show-and-error) + (const :tag "Show invisible part and do the edit" show) + (const :tag "Be smart and do the right thing" smart))) + +;;; Core functionality + +;;; API + +;;;; Modifying folding specs + +(defalias 'org-fold-folding-spec-p #'org-fold-core-folding-spec-p) +(defalias 'org-fold-add-folding-spec #'org-fold-core-add-folding-spec) +(defalias 'org-fold-remove-folding-spec #'org-fold-core-remove-folding-spec) + +(defun org-fold-initialize (ellipsis) + "Setup folding in current Org buffer." + (setq-local org-fold-core-isearch-open-function #'org-fold--isearch-reveal) + (setq-local org-fold-core-extend-changed-region-functions (list #'org-fold--extend-changed-region)) + ;; FIXME: Converting org-link + org-description to overlays when + ;; search matches hidden "[[" part of the link, reverses priority of + ;; link and description and hides the whole link. Working around + ;; this until there will be no need to convert text properties to + ;; overlays for isearch. + (setq-local org-fold-core--isearch-special-specs '(org-link)) + (org-fold-core-initialize `((org-fold-outline + (:ellipsis . ,ellipsis) + (:fragile . ,#'org-fold--reveal-outline-maybe) + (:isearch-open . t) + ;; This is needed to make sure that inserting a + ;; new planning line in folded heading is not + ;; revealed. + (:front-sticky . t) + (:rear-sticky . t) + (:font-lock-skip . t) + (:alias . (headline heading outline inlinetask plain-list))) + (org-fold-block + (:ellipsis . ,ellipsis) + (:fragile . ,#'org-fold--reveal-drawer-or-block-maybe) + (:isearch-open . t) + (:front-sticky . t) + (:alias . ( block center-block comment-block + dynamic-block example-block export-block + quote-block special-block src-block + verse-block))) + (org-fold-drawer + (:ellipsis . ,ellipsis) + (:fragile . ,#'org-fold--reveal-drawer-or-block-maybe) + (:isearch-open . t) + (:front-sticky . t) + (:alias . (drawer property-drawer))) + ,org-link--description-folding-spec + ,org-link--link-folding-spec))) + +;;;; Searching and examining folded text + +(defalias 'org-fold-folded-p #'org-fold-core-folded-p) +(defalias 'org-fold-get-folding-spec #'org-fold-core-get-folding-spec) +(defalias 'org-fold-get-folding-specs-in-region #'org-fold-core-get-folding-specs-in-region) +(defalias 'org-fold-get-region-at-point #'org-fold-core-get-region-at-point) +(defalias 'org-fold-next-visibility-change #'org-fold-core-next-visibility-change) +(defalias 'org-fold-previous-visibility-change #'org-fold-core-previous-visibility-change) +(defalias 'org-fold-next-folding-state-change #'org-fold-core-next-folding-state-change) +(defalias 'org-fold-previous-folding-state-change #'org-fold-core-previous-folding-state-change) +(defalias 'org-fold-search-forward #'org-fold-core-search-forward) + +;;;;; Macros + +(defmacro org-fold-save-outline-visibility--overlays (use-markers &rest body) + "Save and restore outline visibility around BODY. +If USE-MARKERS is non-nil, use markers for the positions. This +means that the buffer may change while running BODY, but it also +means that the buffer should stay alive during the operation, +because otherwise all these markers will point to nowhere." + (declare (debug (form body)) (indent 1)) + (org-with-gensyms (data invisible-types markers?) + `(let* ((,invisible-types '(org-hide-block outline)) + (,markers? ,use-markers) + (,data + (mapcar (lambda (o) + (let ((beg (overlay-start o)) + (end (overlay-end o)) + (type (overlay-get o 'invisible))) + (and beg end + (> end beg) + (memq type ,invisible-types) + (list (if ,markers? (copy-marker beg) beg) + (if ,markers? (copy-marker end t) end) + type)))) + (org-with-wide-buffer + (overlays-in (point-min) (point-max)))))) + (unwind-protect (progn ,@body) + (org-with-wide-buffer + (dolist (type ,invisible-types) + (remove-overlays (point-min) (point-max) 'invisible type)) + (pcase-dolist (`(,beg ,end ,type) (delq nil ,data)) + (org-fold-region beg end t type) + (when ,markers? + (set-marker beg nil) + (set-marker end nil)))))))) +(defmacro org-fold-save-outline-visibility--text-properties (use-markers &rest body) + "Save and restore outline visibility around BODY. +If USE-MARKERS is non-nil, use markers for the positions. This +means that the buffer may change while running BODY, but it also +means that the buffer should stay alive during the operation, +because otherwise all these markers will point to nowhere." + (declare (debug (form body)) (indent 1)) + (org-with-gensyms (data specs markers?) + `(let* ((,specs ',(org-fold-core-folding-spec-list)) + (,markers? ,use-markers) + (,data + (org-with-wide-buffer + (let ((pos (point-min)) + data-val) + (while (< pos (point-max)) + (dolist (spec (org-fold-get-folding-spec 'all pos)) + (let ((region (org-fold-get-region-at-point spec pos))) + (if ,markers? + (push (list (copy-marker (car region)) + (copy-marker (cdr region) t) + spec) + data-val) + (push (list (car region) (cdr region) spec) + data-val)))) + (setq pos (org-fold-next-folding-state-change nil pos))))))) + (unwind-protect (progn ,@body) + (org-with-wide-buffer + (dolist (spec ,specs) + (org-fold-region (point-min) (point-max) nil spec)) + (pcase-dolist (`(,beg ,end ,spec) (delq nil ,data)) + (org-fold-region beg end t spec) + (when ,markers? + (set-marker beg nil) + (set-marker end nil)))))))) +(defmacro org-fold-save-outline-visibility (use-markers &rest body) + "Save and restore outline visibility around BODY. +If USE-MARKERS is non-nil, use markers for the positions. This +means that the buffer may change while running BODY, but it also +means that the buffer should stay alive during the operation, +because otherwise all these markers will point to nowhere." + (declare (debug (form body)) (indent 1)) + `(when (eq org-fold-core-style 'text-properties) + (org-fold-save-outline-visibility--text-properties ,use-markers ,@body) + (org-fold-save-outline-visibility--overlays ,use-markers ,@body))) + +;;;; Changing visibility (regions, blocks, drawers, headlines) + +;;;;; Region visibility + +;; (defalias 'org-fold-region #'org-fold-core-region) +(defun org-fold-region--overlays (from to flag spec) + "Hide or show lines from FROM to TO, according to FLAG. +SPEC is the invisibility spec, as a symbol." + (remove-overlays from to 'invisible spec) + ;; Use `front-advance' since text right before to the beginning of + ;; the overlay belongs to the visible line than to the contents. + (when flag + (let ((o (make-overlay from to nil 'front-advance))) + (overlay-put o 'evaporate t) + (overlay-put o 'invisible spec) + (overlay-put o + 'isearch-open-invisible + (lambda (&rest _) (org-fold-show-context 'isearch)))))) +(defsubst org-fold-region (from to flag &optional spec) + "Hide or show lines from FROM to TO, according to FLAG. +SPEC is the invisibility spec, as a symbol." + (if (eq org-fold-core-style 'text-properties) + (org-fold-core-region from to flag spec) + (org-fold-region--overlays from to flag spec))) + +(defun org-fold-show-all--text-properties (&optional types) + "Show all contents in the visible part of the buffer. +By default, the function expands headings, blocks and drawers. +When optional argument TYPES is a list of symbols among `blocks', +`drawers' and `headings', to only expand one specific type." + (interactive) + (dolist (type (or types '(blocks drawers headings))) + (org-fold-region (point-min) (point-max) nil + (pcase type + (`blocks 'block) + (`drawers 'drawer) + (`headings 'headline) + (_ (error "Invalid type: %S" type)))))) +(defun org-fold-show-all--overlays (&optional types) + "Show all contents in the visible part of the buffer. +By default, the function expands headings, blocks and drawers. +When optional argument TYPE is a list of symbols among `blocks', +`drawers' and `headings', to only expand one specific type." + (interactive) + (let ((types (or types '(blocks drawers headings)))) + (when (memq 'blocks types) + (org-fold-region (point-min) (point-max) nil 'org-hide-block)) + (cond + ;; Fast path. Since headings and drawers share the same + ;; invisible spec, clear everything in one go. + ((and (memq 'headings types) + (memq 'drawers types)) + (org-fold-region (point-min) (point-max) nil 'outline)) + ((memq 'headings types) + (org-fold-region (point-min) (point-max) nil 'outline) + (org-cycle-hide-drawers 'all)) + ((memq 'drawers types) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward org-drawer-regexp nil t) + (let* ((pair (get-char-property-and-overlay (line-beginning-position) + 'invisible)) + (o (cdr-safe pair))) + (if (overlayp o) (goto-char (overlay-end o)) + (pcase (get-char-property-and-overlay (point) 'invisible) + (`(outline . ,o) + (goto-char (overlay-end o)) + (delete-overlay o)) + (_ nil)))))))))) +(defsubst org-fold-show-all (&optional types) + "Show all contents in the visible part of the buffer. +By default, the function expands headings, blocks and drawers. +When optional argument TYPES is a list of symbols among `blocks', +`drawers' and `headings', to only expand one specific type." + (interactive) + (if (eq org-fold-core-style 'text-properties) + (org-fold-show-all--text-properties types) + (org-fold-show-all--overlays types))) + +(defun org-fold-flag-above-first-heading (&optional arg) + "Hide from bob up to the first heading. +Move point to the beginning of first heading or end of buffer." + (goto-char (point-min)) + (unless (org-at-heading-p) + (outline-next-heading)) + (unless (bobp) + (org-fold-region 1 (1- (point)) (not arg) 'outline))) + +;;;;; Heading visibility + +(defun org-fold-heading (flag &optional entry) + "Fold/unfold the current heading. FLAG non-nil means make invisible. +When ENTRY is non-nil, show the entire entry." + (save-excursion + (org-back-to-heading t) + ;; Check if we should show the entire entry + (if (not entry) + (org-fold-region + (line-end-position 0) (line-end-position) flag 'outline) + (org-fold-show-entry) + (save-excursion + ;; FIXME: potentially catches inlinetasks + (and (outline-next-heading) + (org-fold-heading nil)))))) + +(defun org-fold-hide-entry () + "Hide the body directly following this heading." + (interactive) + (save-excursion + (org-back-to-heading-or-point-min t) + (when (org-at-heading-p) (forward-line)) + (unless (eobp) ; Current headline is empty and ends at the end of buffer. + (org-fold-region + (line-end-position 0) + (save-excursion + (if (re-search-forward + (concat "[\r\n]" (org-get-limited-outline-regexp)) nil t) + (line-end-position 0) + (point-max))) + t + 'outline)))) + +(defun org-fold-subtree (flag) + (save-excursion + (org-back-to-heading t) + (org-fold-region (line-end-position) + (progn (org-end-of-subtree t) (point)) + flag + 'outline))) + +;; Replaces `outline-hide-subtree'. +(defun org-fold-hide-subtree () + "Hide everything after this heading at deeper levels." + (interactive) + (org-fold-subtree t)) + +;; Replaces `outline-hide-sublevels' +(defun org-fold-hide-sublevels (levels) + "Hide everything but the top LEVELS levels of headers, in whole buffer. +This also unhides the top heading-less body, if any. + +Interactively, the prefix argument supplies the value of LEVELS. +When invoked without a prefix argument, LEVELS defaults to the level +of the current heading, or to 1 if the current line is not a heading." + (interactive (list + (cond + (current-prefix-arg (prefix-numeric-value current-prefix-arg)) + ((save-excursion (beginning-of-line) + (looking-at outline-regexp)) + (funcall outline-level)) + (t 1)))) + (if (< levels 1) + (error "Must keep at least one level of headers")) + (save-excursion + (let* ((beg (progn + (goto-char (point-min)) + ;; Skip the prelude, if any. + (unless (org-at-heading-p) (outline-next-heading)) + (point))) + (end (progn + (goto-char (point-max)) + ;; Keep empty last line, if available. + (max (point-min) (if (bolp) (1- (point)) (point)))))) + (if (< end beg) + (setq beg (prog1 end (setq end beg)))) + ;; First hide everything. + (org-fold-region beg end t 'headline) + ;; Then unhide the top level headers. + (org-map-region + (lambda () + (when (<= (funcall outline-level) levels) + (org-fold-heading nil))) + beg end) + ;; Finally unhide any trailing newline. + (goto-char (point-max)) + (if (and (bolp) (not (bobp)) (outline-invisible-p (1- (point)))) + (org-fold-region (max (point-min) (1- (point))) (point) nil))))) + +(defun org-fold-show-entry () + "Show the body directly following its heading. +Show the heading too, if it is currently invisible." + (interactive) + (save-excursion + (org-back-to-heading-or-point-min t) + (org-fold-region + (line-end-position 0) + (save-excursion + (if (re-search-forward + (concat "[\r\n]\\(" (org-get-limited-outline-regexp) "\\)") nil t) + (match-beginning 1) + (point-max))) + nil + 'outline) + (org-cycle-hide-drawers 'children))) + +(defalias 'org-fold-show-hidden-entry #'org-fold-show-entry + "Show an entry where even the heading is hidden.") + +(defun org-fold-show-siblings () + "Show all siblings of the current headline." + (save-excursion + (while (org-goto-sibling) (org-fold-heading nil))) + (save-excursion + (while (org-goto-sibling 'previous) + (org-fold-heading nil)))) + +(defun org-fold-show-children (&optional level) + "Show all direct subheadings of this heading. +Prefix arg LEVEL is how many levels below the current level +should be shown. Default is enough to cause the following +heading to appear." + (interactive "p") + (unless (org-before-first-heading-p) + (save-excursion + (org-with-limited-levels (org-back-to-heading t)) + (let* ((current-level (funcall outline-level)) + (max-level (org-get-valid-level + current-level + (if level (prefix-numeric-value level) 1))) + (end (save-excursion (org-end-of-subtree t t))) + (regexp-fmt "^\\*\\{%d,%s\\}\\(?: \\|$\\)") + (past-first-child nil) + ;; Make sure to skip inlinetasks. + (re (format regexp-fmt + current-level + (cond + ((not (featurep 'org-inlinetask)) "") + (org-odd-levels-only (- (* 2 org-inlinetask-min-level) + 3)) + (t (1- org-inlinetask-min-level)))))) + ;; Display parent heading. + (org-fold-heading nil) + (forward-line) + ;; Display children. First child may be deeper than expected + ;; MAX-LEVEL. Since we want to display it anyway, adjust + ;; MAX-LEVEL accordingly. + (while (re-search-forward re end t) + (unless past-first-child + (setq re (format regexp-fmt + current-level + (max (funcall outline-level) max-level))) + (setq past-first-child t)) + (org-fold-heading nil)))))) + +(defun org-fold-show-subtree () + "Show everything after this heading at deeper levels." + (interactive) + (org-fold-region + (point) (save-excursion (org-end-of-subtree t t)) nil 'outline)) + +(defun org-fold-show-branches () + "Show all subheadings of this heading, but not their bodies." + (interactive) + (org-fold-show-children 1000)) + +(defun org-fold-show-branches-buffer--text-properties () + "Show all branches in the buffer." + (org-fold-flag-above-first-heading) + (org-fold-hide-sublevels 1) + (unless (eobp) + (org-fold-show-branches) + (while (outline-get-next-sibling) + (org-fold-show-branches))) + (goto-char (point-min))) +(defun org-fold-show-branches-buffer--overlays () + "Show all branches in the buffer." + (org-fold-flag-above-first-heading) + (outline-hide-sublevels 1) + (unless (eobp) + (outline-show-branches) + (while (outline-get-next-sibling) + (outline-show-branches))) + (goto-char (point-min))) +(defsubst org-fold-show-branches-buffer () + "Show all branches in the buffer." + (if (eq org-fold-core-style 'text-properties) + (org-fold-show-branches-buffer--text-properties) + (org-fold-show-branches-buffer--overlays))) + +;;;;; Blocks and drawers visibility + +(defun org-fold--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." + (let ((type (org-element-type element))) + (cond + ((memq type + (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 org-fold-core-style 'text-properties) + category + (if (eq category 'block) 'org-hide-block 'outline))) + (flag + (cond ((eq force 'off) nil) + (force t) + ((if (eq org-fold-core-style 'text-properties) + (org-fold-folded-p start spec) + (eq spec (get-char-property start 'invisible))) + nil) + (t t)))) + (org-fold-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 (format "%s@%s: %s" + (buffer-file-name (buffer-base-buffer)) + (point) + (if (eq category 'drawer) + "Not at a drawer" + "Not at a block"))))))) + +(defun org-fold-hide-block-toggle (&optional force no-error element) + "Toggle the visibility of the current block. + +When optional argument FORCE is `off', make block visible. If it +is non-nil, hide it unconditionally. Throw an error when not at +a block, unless NO-ERROR is non-nil. When optional argument +ELEMENT is provided, consider it instead of the current block. + +Return a non-nil value when toggling is successful." + (interactive) + (org-fold--hide-wrapper-toggle + (or element (org-element-at-point)) 'block force no-error)) + +(defun org-fold-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-fold--hide-wrapper-toggle + (or element (org-element-at-point)) 'drawer force no-error)) + +(defun org-fold-hide-block-all () + "Fold all blocks in the current buffer." + (interactive) + (org-block-map (apply-partially #'org-fold-hide-block-toggle 'hide))) + +(defun org-fold-hide-drawer-all () + "Fold all drawers in the current buffer." + (let ((begin (point-min)) + (end (point-max))) + (org-fold--hide-drawers begin end))) + +(defun org-fold--hide-drawers--overlays (begin end) + "Hide all drawers between BEGIN and END." + (save-excursion + (goto-char begin) + (while (re-search-forward org-drawer-regexp end t) + (let* ((pair (get-char-property-and-overlay (line-beginning-position) + 'invisible)) + (o (cdr-safe pair))) + (if (overlayp o) (goto-char (overlay-end o)) ;invisible drawer + (pcase (get-char-property-and-overlay (point) 'invisible) + (`(outline . ,o) (goto-char (overlay-end o))) ;already folded + (_ + (let* ((drawer (org-element-at-point)) + (type (org-element-type drawer))) + (when (memq type '(drawer property-drawer)) + (org-fold-hide-drawer-toggle t nil drawer) + ;; Make sure to skip drawer entirely or we might flag it + ;; another time when matching its ending line with + ;; `org-drawer-regexp'. + (goto-char (org-element-property :end drawer))))))))))) +(defun org-fold--hide-drawers--text-properties (begin end) + "Hide all drawers between BEGIN and END." + (save-excursion + (goto-char begin) + (while (and (< (point) end) + (re-search-forward org-drawer-regexp end t)) + ;; Skip folded drawers + (if (org-fold-folded-p nil 'drawer) + (goto-char (org-fold-next-folding-state-change 'drawer nil end)) + (let* ((drawer (org-element-at-point)) + (type (org-element-type drawer))) + (when (memq type '(drawer property-drawer)) + (org-fold-hide-drawer-toggle t nil drawer) + ;; Make sure to skip drawer entirely or we might flag it + ;; another time when matching its ending line with + ;; `org-drawer-regexp'. + (goto-char (org-element-property :end drawer)))))))) +(defun org-fold--hide-drawers (begin end) + "Hide all drawers between BEGIN and END." + (if (eq org-fold-core-style 'text-properties) + (org-fold--hide-drawers--text-properties begin end) + (org-fold--hide-drawers--overlays begin end))) + +(defun org-fold-hide-archived-subtrees (beg end) + "Re-hide all archived subtrees after a visibility state change." + (org-with-wide-buffer + (let ((case-fold-search nil) + (re (concat org-outline-regexp-bol ".*:" org-archive-tag ":"))) + (goto-char beg) + ;; Include headline point is currently on. + (beginning-of-line) + (while (and (< (point) end) (re-search-forward re end t)) + (when (member org-archive-tag (org-get-tags nil t)) + (org-fold-subtree t) + (org-end-of-subtree t)))))) + +;;;;; Reveal point location + +(defun org-fold-show-context (&optional key) + "Make sure point and context are visible. +Optional argument KEY, when non-nil, is a symbol. See +`org-fold-show-context-detail' for allowed values and how much is to +be shown." + (org-fold-show-set-visibility + (cond ((symbolp org-fold-show-context-detail) org-fold-show-context-detail) + ((cdr (assq key org-fold-show-context-detail))) + (t (cdr (assq 'default org-fold-show-context-detail)))))) + +(defun org-fold-show-set-visibility--overlays (detail) + "Set visibility around point according to DETAIL. +DETAIL is either nil, `minimal', `local', `ancestors', +`ancestors-full', `lineage', `tree', `canonical' or t. See +`org-show-context-detail' for more information." + ;; Show current heading and possibly its entry, following headline + ;; or all children. + (if (and (org-at-heading-p) (not (eq detail 'local))) + (org-fold-heading nil) + (org-fold-show-entry) + ;; If point is hidden within a drawer or a block, make sure to + ;; expose it. + (dolist (o (overlays-at (point))) + (when (memq (overlay-get o 'invisible) '(org-hide-block outline)) + (delete-overlay o))) + (unless (org-before-first-heading-p) + (org-with-limited-levels + (cl-case detail + ((tree canonical t) (org-fold-show-children)) + ((nil minimal ancestors ancestors-full)) + (t (save-excursion + (outline-next-heading) + (org-fold-heading nil))))))) + ;; Show whole subtree. + (when (eq detail 'ancestors-full) (org-fold-show-subtree)) + ;; Show all siblings. + (when (eq detail 'lineage) (org-fold-show-siblings)) + ;; Show ancestors, possibly with their children. + (when (memq detail '(ancestors ancestors-full lineage tree canonical t)) + (save-excursion + (while (org-up-heading-safe) + (org-fold-heading nil) + (when (memq detail '(canonical t)) (org-fold-show-entry)) + (when (memq detail '(tree canonical t)) (org-fold-show-children)))))) +(defvar org-hide-emphasis-markers); Defined in org.el +(defvar org-pretty-entities); Defined in org.el +(defun org-fold-show-set-visibility--text-properties (detail) + "Set visibility around point according to DETAIL. +DETAIL is either nil, `minimal', `local', `ancestors', +`ancestors-full', `lineage', `tree', `canonical' or t. See +`org-show-context-detail' for more information." + ;; Show current heading and possibly its entry, following headline + ;; or all children. + (if (and (org-at-heading-p) (not (eq detail 'local))) + (org-fold-heading nil) + (org-fold-show-entry) + ;; If point is hidden make sure to expose it. + (when (org-invisible-p) + ;; FIXME: No clue why, but otherwise the following might not work. + (redisplay) + (let ((region (org-fold-get-region-at-point))) + ;; Reveal emphasis markers. + (let (org-hide-emphasis-markers + org-link-descriptive + org-pretty-entities + (region (or (org-find-text-property-region (point) 'org-emphasis) + (org-find-text-property-region (point) 'invisible) + region))) + (when region + (org-with-point-at (car region) + (beginning-of-line) + (let (font-lock-extend-region-functions) + (font-lock-fontify-region (1- (car region)) (cdr region)))))) + (when region + (org-fold-region (car region) (cdr region) nil)))) + (unless (org-before-first-heading-p) + (org-with-limited-levels + (cl-case detail + ((tree canonical t) (org-fold-show-children)) + ((nil minimal ancestors ancestors-full)) + (t (save-excursion + (outline-next-heading) + (org-fold-heading nil))))))) + ;; Show whole subtree. + (when (eq detail 'ancestors-full) (org-fold-show-subtree)) + ;; Show all siblings. + (when (eq detail 'lineage) (org-fold-show-siblings)) + ;; Show ancestors, possibly with their children. + (when (memq detail '(ancestors ancestors-full lineage tree canonical t)) + (save-excursion + (while (org-up-heading-safe) + (org-fold-heading nil) + (when (memq detail '(canonical t)) (org-fold-show-entry)) + (when (memq detail '(tree canonical t)) (org-fold-show-children)))))) +(defun org-fold-show-set-visibility (detail) + "Set visibility around point according to DETAIL. +DETAIL is either nil, `minimal', `local', `ancestors', `lineage', +`tree', `canonical' or t. See `org-fold-show-context-detail' for more +information." + (if (eq org-fold-core-style 'text-properties) + (org-fold-show-set-visibility--text-properties detail) + (org-fold-show-set-visibility--overlays detail))) + +(defun org-fold-reveal (&optional siblings) + "Show current entry, hierarchy above it, and the following headline. + +This can be used to show a consistent set of context around +locations exposed with `org-fold-show-context'. + +With optional argument SIBLINGS, on each level of the hierarchy all +siblings are shown. This repairs the tree structure to what it would +look like when opened with hierarchical calls to `org-cycle'. + +With a \\[universal-argument] \\[universal-argument] prefix, \ +go to the parent and show the entire tree." + (interactive "P") + (run-hooks 'org-fold-reveal-start-hook) + (cond ((equal siblings '(4)) (org-fold-show-set-visibility 'canonical)) + ((equal siblings '(16)) + (save-excursion + (when (org-up-heading-safe) + (org-fold-show-subtree) + (run-hook-with-args 'org-cycle-hook 'subtree)))) + (t (org-fold-show-set-visibility 'lineage)))) + +;;; Make isearch search in some text hidden via text propertoes + +(defun org-fold--isearch-reveal (&rest _) + "Reveal text at POS found by isearch." + (org-fold-show-set-visibility 'isearch)) + +;;; Handling changes in folded elements + +(defun org-fold--extend-changed-region (from to) + "Consider folded regions in the next/previous line when fixing +region visibility. +This function is intended to be used as a member of +`org-fold-core-extend-changed-region-functions'." + ;; If the edit is done in the first line of a folded drawer/block, + ;; the folded text is only starting from the next line and needs to + ;; be checked. + (setq to (save-excursion (goto-char to) (line-beginning-position 2))) + ;; If the ":END:" line of the drawer is deleted, the folded text is + ;; only ending at the previous line and needs to be checked. + (setq from (save-excursion (goto-char from) (line-beginning-position 0))) + (cons from to)) + +(defun org-fold--reveal-outline-maybe (region _) + "Reveal folded outline in REGION when needed. + +This function is intended to be used as :fragile property of +`org-fold-outline' spec. See `org-fold-core--specs' for details." + (save-match-data + (save-excursion + (goto-char (car region)) + ;; The line before beginning of the fold should be either a + ;; headline or a list item. + (backward-char) + (beginning-of-line) + ;; Make sure that headline is not partially hidden + (unless (org-fold-folded-p nil 'headline) (org-fold-region (max (point-min) (1- (point))) (line-end-position) nil 'headline)) + ;; Check the validity of headline + (unless (let ((case-fold-search t)) + (looking-at (rx-to-string `(or (regex ,(org-item-re)) + (regex ,org-outline-regexp-bol))))) ; the match-data will be used later + t)))) + +(defun org-fold--reveal-drawer-or-block-maybe (region spec) + "Reveal folded drawer/block (according to SPEC) in REGION when needed. + +This function is intended to be used as :fragile property of +`org-fold-drawer' or `org-fold-block' spec." + (let ((begin-re (cond + ((eq spec (org-fold-core-get-folding-spec-from-alias 'drawer)) + org-drawer-regexp) + ;; Group one below contains the type of the block. + ((eq spec (org-fold-core-get-folding-spec-from-alias 'block)) + (rx bol (zero-or-more (any " " "\t")) + "#+begin" + (or ":" + (seq "_" + (group (one-or-more (not (syntax whitespace)))))))))) + ;; To be determined later. May depend on `begin-re' match (i.e. for blocks). + end-re) + (save-match-data ; we should not clobber match-data in after-change-functions + (let ((fold-begin (car region)) + (fold-end (cdr region))) + (let (unfold?) + (catch :exit + ;; The line before folded text should be beginning of + ;; the drawer/block. + (save-excursion + (goto-char fold-begin) + ;; The line before beginning of the fold should be the + ;; first line of the drawer/block. + (backward-char) + (beginning-of-line) + (unless (let ((case-fold-search t)) + (looking-at begin-re)) ; the match-data will be used later + (throw :exit (setq unfold? t)))) + ;; Set `end-re' for the current drawer/block. + (setq end-re + (cond + ((eq spec (org-fold-core-get-folding-spec-from-alias 'drawer)) + org-property-end-re) + ((eq spec (org-fold-core-get-folding-spec-from-alias 'block)) + (let ((block-type (match-string 1))) ; the last match is from `begin-re' + (concat (rx bol (zero-or-more (any " " "\t")) "#+end") + (if block-type + (concat "_" + (regexp-quote block-type) + (rx (zero-or-more (any " " "\t")) eol)) + (rx (opt ":") (zero-or-more (any " " "\t")) eol))))))) + ;; The last line of the folded text should match `end-re'. + (save-excursion + (goto-char fold-end) + (beginning-of-line) + (unless (let ((case-fold-search t)) + (looking-at end-re)) + (throw :exit (setq unfold? t)))) + ;; There should be no `end-re' or + ;; `org-outline-regexp-bol' anywhere in the + ;; drawer/block body. + (save-excursion + (goto-char fold-begin) + (when (save-excursion + (let ((case-fold-search t)) + (re-search-forward (rx-to-string `(or (regex ,end-re) + (regex ,org-outline-regexp-bol))) + (max (point) + (1- (save-excursion + (goto-char fold-end) + (line-beginning-position)))) + t))) + (throw :exit (setq unfold? t))))) + unfold?))))) + +;; Catching user edits inside invisible text +(defun org-fold-check-before-invisible-edit--overlays (kind) + "Check if editing KIND is dangerous with invisible text around. +The detailed reaction depends on the user option +`org-fold-catch-invisible-edits'." + ;; First, try to get out of here as quickly as possible, to reduce overhead + (when (and org-fold-catch-invisible-edits + (or (not (boundp 'visible-mode)) (not visible-mode)) + (or (get-char-property (point) 'invisible) + (get-char-property (max (point-min) (1- (point))) 'invisible))) + ;; OK, we need to take a closer look. Do not consider + ;; invisibility obtained through text properties (e.g., link + ;; fontification), as it cannot be toggled. + (let* ((invisible-at-point + (pcase (get-char-property-and-overlay (point) 'invisible) + (`(,_ . ,(and (pred overlayp) o)) o))) + ;; Assume that point cannot land in the middle of an + ;; overlay, or between two overlays. + (invisible-before-point + (and (not invisible-at-point) + (not (bobp)) + (pcase (get-char-property-and-overlay (1- (point)) 'invisible) + (`(,_ . ,(and (pred overlayp) o)) o)))) + (border-and-ok-direction + (or + ;; Check if we are acting predictably before invisible + ;; text. + (and invisible-at-point + (memq kind '(insert delete-backward))) + ;; Check if we are acting predictably after invisible text + ;; This works not well, and I have turned it off. It seems + ;; better to always show and stop after invisible text. + ;; (and (not invisible-at-point) invisible-before-point + ;; (memq kind '(insert delete))) + ))) + (when (or invisible-at-point invisible-before-point) + (when (eq org-fold-catch-invisible-edits 'error) + (user-error "Editing in invisible areas is prohibited, make them visible first")) + (if (and org-custom-properties-overlays + (y-or-n-p "Display invisible properties in this buffer? ")) + (org-toggle-custom-properties-visibility) + ;; Make the area visible + (save-excursion + (when invisible-before-point + (goto-char + (previous-single-char-property-change (point) 'invisible))) + ;; Remove whatever overlay is currently making yet-to-be + ;; edited text invisible. Also remove nested invisibility + ;; related overlays. + (delete-overlay (or invisible-at-point invisible-before-point)) + (let ((origin (if invisible-at-point (point) (1- (point))))) + (while (pcase (get-char-property-and-overlay origin 'invisible) + (`(,_ . ,(and (pred overlayp) o)) + (delete-overlay o) + t))))) + (cond + ((eq org-fold-catch-invisible-edits 'show) + ;; That's it, we do the edit after showing + (message + "Unfolding invisible region around point before editing") + (sit-for 1)) + ((and (eq org-fold-catch-invisible-edits 'smart) + border-and-ok-direction) + (message "Unfolding invisible region around point before editing")) + (t + ;; Don't do the edit, make the user repeat it in full visibility + (user-error "Edit in invisible region aborted, repeat to confirm with text visible")))))))) +(defun org-fold-check-before-invisible-edit--text-properties (kind) + "Check if editing KIND is dangerous with invisible text around. +The detailed reaction depends on the user option +`org-fold-catch-invisible-edits'." + ;; First, try to get out of here as quickly as possible, to reduce overhead + (when (and org-fold-catch-invisible-edits + (or (not (boundp 'visible-mode)) (not visible-mode)) + (or (org-invisible-p) + (org-invisible-p (max (point-min) (1- (point)))))) + ;; OK, we need to take a closer look. Only consider invisibility + ;; caused by folding. + (let* ((invisible-at-point (org-invisible-p)) + (invisible-before-point + (and (not (bobp)) + (org-invisible-p (1- (point))))) + (border-and-ok-direction + (or + ;; Check if we are acting predictably before invisible + ;; text. + (and invisible-at-point (not invisible-before-point) + (memq kind '(insert delete-backward))) + (and (not invisible-at-point) invisible-before-point + (memq kind '(insert delete)))))) + (when (or invisible-at-point invisible-before-point) + (when (eq org-fold-catch-invisible-edits 'error) + (user-error "Editing in invisible areas is prohibited, make them visible first")) + (if (and org-custom-properties-hidden-p + (y-or-n-p "Display invisible properties in this buffer? ")) + (org-toggle-custom-properties-visibility) + ;; Make the area visible + (save-excursion + (org-fold-show-set-visibility 'local)) + (when invisible-before-point + (org-with-point-at (1- (point)) (org-fold-show-set-visibility 'local))) + (cond + ((eq org-fold-catch-invisible-edits 'show) + ;; That's it, we do the edit after showing + (message + "Unfolding invisible region around point before editing") + (sit-for 1)) + ((and (eq org-fold-catch-invisible-edits 'smart) + border-and-ok-direction) + (message "Unfolding invisible region around point before editing")) + (t + ;; Don't do the edit, make the user repeat it in full visibility + (user-error "Edit in invisible region aborted, repeat to confirm with text visible")))))))) +(defsubst org-fold-check-before-invisible-edit (kind) + "Check if editing KIND is dangerous with invisible text around. +The detailed reaction depends on the user option +`org-fold-catch-invisible-edits'." + ;; First, try to get out of here as quickly as possible, to reduce overhead + (if (eq org-fold-core-style 'text-properties) + (org-fold-check-before-invisible-edit--text-properties kind) + (org-fold-check-before-invisible-edit--overlays kind))) + +(provide 'org-fold) + +;;; org-fold.el ends here
next prev parent reply other threads:[~2022-01-29 11:36 UTC|newest] Thread overview: 192+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-04-24 6:55 [patch suggestion] Mitigating the poor Emacs performance on huge org files: Do not use overlays for PROPERTY and LOGBOOK drawers Ihor Radchenko 2020-04-24 8:02 ` Nicolas Goaziou 2020-04-25 0:29 ` stardiviner 2020-04-26 16:04 ` Ihor Radchenko 2020-05-04 16:56 ` Karl Voit 2020-05-07 7:18 ` Karl Voit 2020-05-09 15:43 ` Ihor Radchenko 2020-05-07 11:04 ` Christian Heinrich 2020-05-09 15:46 ` Ihor Radchenko 2020-05-08 16:38 ` Nicolas Goaziou 2020-05-09 13:58 ` Nicolas Goaziou 2020-05-09 16:22 ` Ihor Radchenko 2020-05-09 17:21 ` Nicolas Goaziou 2020-05-10 5:25 ` Ihor Radchenko 2020-05-10 9:47 ` Nicolas Goaziou 2020-05-10 13:29 ` Ihor Radchenko 2020-05-10 14:46 ` Nicolas Goaziou 2020-05-10 16:21 ` Ihor Radchenko 2020-05-10 16:38 ` Nicolas Goaziou 2020-05-10 17:08 ` Ihor Radchenko 2020-05-10 19:38 ` Nicolas Goaziou 2020-05-09 15:40 ` Ihor Radchenko 2020-05-09 16:30 ` Ihor Radchenko 2020-05-09 17:32 ` Nicolas Goaziou 2020-05-09 18:06 ` Ihor Radchenko 2020-05-10 14:59 ` Nicolas Goaziou 2020-05-10 15:15 ` Kyle Meyer 2020-05-10 16:30 ` Ihor Radchenko 2020-05-10 19:32 ` Nicolas Goaziou 2020-05-12 10:03 ` Nicolas Goaziou 2020-05-17 15:00 ` Ihor Radchenko 2020-05-17 15:40 ` Ihor Radchenko 2020-05-18 14:35 ` Nicolas Goaziou 2020-05-18 16:52 ` Ihor Radchenko 2020-05-19 13:07 ` Nicolas Goaziou 2020-05-23 13:52 ` Ihor Radchenko 2020-05-23 13:53 ` Ihor Radchenko 2020-05-23 15:26 ` Ihor Radchenko 2020-05-26 8:33 ` Nicolas Goaziou 2020-06-02 9:21 ` Ihor Radchenko 2020-06-02 9:23 ` Ihor Radchenko 2020-06-02 12:10 ` Bastien 2020-06-02 13:12 ` Ihor Radchenko 2020-06-02 13:23 ` Bastien 2020-06-02 13:30 ` Ihor Radchenko 2020-06-02 9:25 ` Ihor Radchenko 2020-06-05 7:26 ` Nicolas Goaziou 2020-06-05 8:18 ` Ihor Radchenko 2020-06-05 13:50 ` Nicolas Goaziou 2020-06-08 5:05 ` Ihor Radchenko 2020-06-08 5:06 ` Ihor Radchenko 2020-06-08 5:08 ` Ihor Radchenko 2020-06-10 17:14 ` Nicolas Goaziou 2020-06-21 9:52 ` Ihor Radchenko 2020-06-21 15:01 ` Nicolas Goaziou 2020-08-11 6:45 ` Ihor Radchenko 2020-08-11 23:07 ` Kyle Meyer 2020-08-12 6:29 ` Ihor Radchenko 2020-09-20 5:53 ` Ihor Radchenko 2020-09-20 11:45 ` Kévin Le Gouguec 2020-09-22 9:05 ` Ihor Radchenko 2020-09-22 10:00 ` Ihor Radchenko 2020-09-23 6:16 ` Kévin Le Gouguec 2020-09-23 6:48 ` Ihor Radchenko 2020-09-23 7:09 ` Bastien 2020-09-23 7:30 ` Ihor Radchenko 2020-09-24 18:07 ` Kévin Le Gouguec 2020-09-25 2:16 ` Ihor Radchenko 2020-12-15 17:38 ` [9.4] Fixing logbook visibility during isearch Kévin Le Gouguec 2020-12-16 3:15 ` Ihor Radchenko 2020-12-16 18:05 ` Kévin Le Gouguec 2020-12-17 3:18 ` Ihor Radchenko 2020-12-17 14:50 ` Kévin Le Gouguec 2020-12-18 2:23 ` Ihor Radchenko 2020-12-24 23:37 ` Kévin Le Gouguec 2020-12-25 2:51 ` Ihor Radchenko 2020-12-25 10:59 ` Kévin Le Gouguec 2020-12-25 12:32 ` Ihor Radchenko 2020-12-25 21:35 ` Kévin Le Gouguec 2020-12-26 4:14 ` Ihor Radchenko 2020-12-26 11:44 ` Kévin Le Gouguec 2020-12-26 12:22 ` Ihor Radchenko 2020-12-04 5:58 ` [patch suggestion] Mitigating the poor Emacs performance on huge org files: Do not use overlays for PROPERTY and LOGBOOK drawers Ihor Radchenko 2021-03-21 9:09 ` Ihor Radchenko 2021-05-03 17:28 ` Bastien 2021-09-21 13:32 ` Timothy 2021-10-26 17:25 ` Matt Price 2021-10-27 6:27 ` Ihor Radchenko 2022-01-29 11:37 ` [PATCH 00/35] Merge org-fold feature branch Ihor Radchenko 2022-01-29 11:37 ` [PATCH 01/35] Add org-fold-core: new folding engine Ihor Radchenko 2022-01-29 11:37 ` Ihor Radchenko [this message] 2022-01-29 11:37 ` [PATCH 03/35] Separate cycling functions from org.el into new library: org-cycle Ihor Radchenko 2022-01-29 11:37 ` [PATCH 04/35] Remove functions from org.el that are now moved elsewhere Ihor Radchenko 2022-01-29 11:37 ` [PATCH 05/35] Disable native-comp in agenda Ihor Radchenko 2022-01-29 11:37 ` [PATCH 06/35] org-macs: New function org-find-text-property-region Ihor Radchenko 2022-01-29 11:37 ` [PATCH 07/35] org-at-heading-p: Accept optional argument Ihor Radchenko 2022-01-29 11:38 ` [PATCH 08/35] org-string-width: Reimplement to work with new folding Ihor Radchenko 2022-01-29 11:38 ` [PATCH 09/35] Rename old function call to use org-fold Ihor Radchenko 2022-01-29 11:38 ` [PATCH 10/35] Implement link folding Ihor Radchenko 2022-05-04 6:13 ` [BUG] 67275f4 broke evil-search " Tom Gillespie 2022-05-04 6:38 ` Ihor Radchenko 2022-05-28 2:17 ` Tom Gillespie 2022-05-28 2:37 ` Ihor Radchenko 2022-05-28 2:42 ` Tom Gillespie 2022-05-28 3:09 ` Ihor Radchenko 2022-05-28 3:11 ` Ihor Radchenko 2022-01-29 11:38 ` [PATCH 11/35] Implement overlay- and text-property-based versions of some functions Ihor Radchenko 2022-01-29 11:38 ` [PATCH 12/35] org-fold: Handle indirect buffer visibility Ihor Radchenko 2022-01-29 11:38 ` [PATCH 13/35] Fix subtle differences between overlays and invisible text properties Ihor Radchenko 2022-01-29 11:38 ` [PATCH 14/35] Support extra org-fold optimisations for huge buffers Ihor Radchenko 2022-01-29 11:38 ` [PATCH 15/35] Alias new org-fold functions to their old shorter names Ihor Radchenko 2022-01-29 11:38 ` [PATCH 16/35] Obsolete old function names that are now in org-fold Ihor Radchenko 2022-01-29 11:38 ` [PATCH 17/35] org-compat: Work around some third-party packages using outline-* functions Ihor Radchenko 2022-01-29 11:38 ` [PATCH 18/35] Move `org-buffer-list' to org-macs.el Ihor Radchenko 2022-01-29 11:38 ` [PATCH 19/35] Restore old visibility behaviour of org-refile Ihor Radchenko 2022-01-29 11:38 ` [PATCH 20/35] Add org-fold-related tests Ihor Radchenko 2022-01-29 11:38 ` [PATCH 21/35] org-manual: Update to new org-fold function names Ihor Radchenko 2022-01-29 11:38 ` [PATCH 22/35] ORG-NEWS: Add list of changes Ihor Radchenko 2022-01-29 20:31 ` New folding backend & outline (was: [PATCH 22/35] ORG-NEWS: Add list of changes) Kévin Le Gouguec 2022-01-30 2:15 ` Ihor Radchenko 2022-01-29 11:38 ` [PATCH 23/35] Backport contributed commits Ihor Radchenko 2022-01-29 11:38 ` [PATCH 24/35] Fix typo: delete-duplicates → delete-dups Ihor Radchenko 2022-01-29 11:38 ` [PATCH 25/35] Fix bug in org-get-heading Ihor Radchenko 2022-01-29 11:38 ` [PATCH 26/35] Rename remaining org-force-cycle-archived → org-cycle-force-archived Ihor Radchenko 2022-01-29 11:38 ` [PATCH 27/35] Fix org-fold--hide-drawers--overlays Ihor Radchenko 2022-01-29 11:38 ` [PATCH 28/35] org-string-width: Handle undefined behaviour in older Emacs Ihor Radchenko 2022-01-29 11:38 ` [PATCH 29/35] org-string-width: Work around `window-pixel-width' bug in old Emacs Ihor Radchenko 2022-01-29 11:38 ` [PATCH 30/35] org-fold-show-set-visibility: Fix edge case when folded region is at BOB Ihor Radchenko 2022-01-29 11:38 ` [PATCH 31/35] org-fold-core: Fix fontification inside folded regions Ihor Radchenko 2022-01-29 11:38 ` [PATCH 32/35] test-org/string-width: Add tests for strings with prefix properties Ihor Radchenko 2022-01-29 11:38 ` [PATCH 33/35] org--string-from-props: Fix handling folds in Emacs <28 Ihor Radchenko 2022-01-29 11:38 ` [PATCH 34/35] org-link-make-string: Throw error when both LINK and DESCRIPTION are empty Ihor Radchenko 2022-01-29 11:38 ` [PATCH 35/35] test-ol/org-toggle-link-display: Fix compatibility with old Emacs Ihor Radchenko 2022-02-03 6:27 ` [PATCH 00/35] Merge org-fold feature branch Bastien 2022-02-03 7:07 ` Ihor Radchenko 2022-04-20 13:23 ` [PATCH v2 00/38] Final call for comments: " Ihor Radchenko 2022-04-20 13:23 ` [PATCH v2 01/38] Add org-fold-core: new folding engine--- Ihor Radchenko 2022-04-20 13:24 ` [PATCH v2 02/38] Separate folding functions from org.el into new library: org-fold Ihor Radchenko 2022-04-20 13:24 ` [PATCH v2 03/38] Separate cycling functions from org.el into new library: org-cycle Ihor Radchenko 2022-04-20 13:24 ` [PATCH v2 04/38] Remove functions from org.el that are now moved elsewhere Ihor Radchenko 2022-04-20 13:24 ` [PATCH v2 05/38] Disable native-comp in agendaIt caused cryptic bugs in the past Ihor Radchenko 2022-04-20 13:24 ` [PATCH v2 06/38] org-macs: New function org-find-text-property-region--- Ihor Radchenko 2022-04-20 13:24 ` [PATCH v2 07/38] org-at-heading-p: Accept optional argument* lisp/org.el (org-at-heading-p): Use second argument to allow Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 08/38] org-string-width: Reimplement to work with new folding Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 09/38] Rename old function call to use org-fold--- Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 10/38] Implement link folding* lisp/ol.el (org-link--link-folding-spec): Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 11/38] Implement overlay- and text-property-based versions of some functions Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 12/38] org-fold: Handle indirect buffer visibility--- Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 13/38] Fix subtle differences between overlays and invisible text properties Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 14/38] Support extra org-fold optimisations for huge buffers Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 15/38] Alias new org-fold functions to their old shorter names Ihor Radchenko 2022-04-20 13:25 ` [PATCH v2 16/38] Obsolete old function names that are now in org-fold--- Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 17/38] org-compat: Work around some third-party packages using outline-* functions Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 18/38] Move `org-buffer-list' to org-macs.el--- Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 19/38] Restore old visibility behaviour of org-refile--- Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 20/38] Add org-fold-related tests--- Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 21/38] org-manual: Update to new org-fold function names--- Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 22/38] ORG-NEWS: Add list of changes--- Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 23/38] Backport contributed commits--- Ihor Radchenko 2022-04-20 13:26 ` [PATCH v2 24/38] Fix typo: delete-duplicates → delete-dups Anders Johansson 2022-04-20 13:26 ` [PATCH v2 25/38] Fix bug in org-get-headingFixes #26, where fontification could make the matching and extraction of heading Anders Johansson 2022-04-20 13:27 ` [PATCH v2 26/38] Rename remaining org-force-cycle-archived Anders Johansson 2022-04-20 13:27 ` [PATCH v2 27/38] Fix org-fold--hide-drawers--overlays--- Ihor Radchenko 2022-04-20 13:27 ` [PATCH v2 28/38] org-string-width: Handle undefined behaviour in older Emacs Ihor Radchenko 2022-04-20 13:27 ` [PATCH v2 29/38] org-string-width: Work around `window-pixel-width' bug in old Emacs Ihor Radchenko 2022-04-20 13:27 ` [PATCH v2 30/38] org-fold-show-set-visibility: Fix edge case when folded region is at BOB Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 31/38] org-fold-core: Fix fontification inside folded regions Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 32/38] test-org/string-width: Add tests for strings with prefix properties Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 33/38] org--string-from-props: Fix handling folds in Emacs <28 Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 34/38] org-link-make-string: Throw error when both LINK and DESCRIPTION are empty Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 35/38] test-ol/org-toggle-link-display: Fix compatibility with old Emacs Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 36/38] org-macs.el: Fix fontification checks take 2--- Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 37/38] org-fold-core-fontify-region: Fix cases when fontification is not registered Ihor Radchenko 2022-04-20 13:28 ` [PATCH v2 38/38] org-agenda.el: Re-enable native compilation* lisp/org-agenda.el: Re-enable native compilation as it does not Ihor Radchenko 2022-04-20 14:47 ` [PATCH v2 00/38] Final call for comments: Merge org-fold feature branch Bastien 2022-04-20 15:38 ` Ihor Radchenko 2022-04-20 16:22 ` Bastien 2022-04-21 6:01 ` Ihor Radchenko 2022-04-21 6:55 ` Bastien 2022-04-21 9:27 ` Ihor Radchenko 2022-04-21 9:43 ` Bastien 2022-04-22 18:54 ` Kévin Le Gouguec 2022-04-25 11:44 ` Ihor Radchenko 2022-04-25 13:02 ` Bastien 2022-04-25 13:25 ` Ihor Radchenko 2022-04-25 14:05 ` Bastien 2022-04-26 11:48 ` Ihor Radchenko 2022-04-25 11:45 ` Ihor Radchenko 2022-04-26 6:10 ` Kévin Le Gouguec 2022-05-03 4:44 ` [ISSUE] org-fold does not support auto-reveal for some external package commands Christopher M. Miles [not found] ` <6270b43a.1c69fb81.835d4.54a6SMTPIN_ADDED_BROKEN@mx.google.com> 2022-05-03 6:33 ` Ihor Radchenko 2022-05-03 10:19 ` [DONE] " Christopher M. Miles
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style List information: https://www.orgmode.org/ * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=a36ac8670ea6eda6b25b0be5ff1ee4afdd46e34a.1643454546.git.yantar92@gmail.com \ --to=yantar92@gmail.com \ --cc=bzg@gnu.org \ --cc=christian@gladbachcity.de \ --cc=devnull@Karl-Voit.at \ --cc=emacs-orgmode@gnu.org \ --cc=kyle@kyleam.com \ --cc=mail@nicolasgoaziou.fr \ --subject='Re: [PATCH 02/35] Separate folding functions from org.el into new library: org-fold' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Code repositories for project(s) associated with this inbox: https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).