├── .dir-locals.el ├── .github └── workflows │ └── check.yml ├── .gitignore ├── LICENSE ├── README.org ├── demo.gif └── org-appear.el /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;;; Directory Local Variables 2 | ;;; For more information see (info "(emacs) Directory Variables") 3 | 4 | ((emacs-lisp-mode . ((indent-tabs-mode . t)))) 5 | -------------------------------------------------------------------------------- /.github/workflows/check.yml: -------------------------------------------------------------------------------- 1 | name: check 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | check: 6 | runs-on: ubuntu-latest 7 | strategy: 8 | matrix: 9 | emacs-version: 10 | - 29.1 11 | - snapshot 12 | elisp-check: 13 | - melpa 14 | - load-file 15 | - byte-compile 16 | - checkdoc 17 | - package-lint 18 | steps: 19 | - uses: actions/checkout@v2 20 | - uses: purcell/setup-emacs@master 21 | with: 22 | version: ${{ matrix.emacs-version }} 23 | - uses: leotaku/elisp-check@master 24 | with: 25 | check: ${{ matrix.elisp-check }} 26 | file: org-appear.el 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /testing 2 | *.elc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Alice Istleyeva 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | [[https://melpa.org/#/org-appear][file:https://melpa.org/packages/org-appear-badge.svg]] 2 | [[https://github.com/awth13/org-appear/actions/workflows/check.yml][file:https://github.com/awth13/org-appear/actions/workflows/check.yml/badge.svg?branch=master]] 3 | 4 | * ~org-appear~ 5 | 6 | Make invisible parts of Org elements appear visible. 7 | 8 | ** About 9 | 10 | [[https://orgmode.org/][Org mode]] provides a way to toggle visibility of hidden elements such as emphasis markers, links, etc. by customising specific variables, e.g., ~org-hide-emphasis-markers~. However, it is currently not possible to do this interactively and on an element-by-element basis. This package, inspired by [[https://github.com/io12/org-fragtog][org-fragtog]], enables automatic visibility toggling depending on cursor position. Hidden element parts appear when the cursor enters an element and disappear when it leaves. 11 | 12 | [[file:demo.gif]] 13 | 14 | ** Installation 15 | 16 | The easiest way to install ~org-appear~ is from MELPA, using your favourite package manager or ~package-install~. For Guix users, ~org-appear~ is also available in the official GNU Guix channel. 17 | 18 | ** Manual installation 19 | 20 | With [[https://github.com/raxod502/straight.el][straight.el]], simply put the following line in ~init.el~: 21 | 22 | #+begin_src emacs-lisp 23 | 24 | (straight-use-package '(org-appear :type git :host github :repo "awth13/org-appear")) 25 | 26 | #+end_src 27 | 28 | Alternatively, git clone this repository and point Emacs to it using the ~:load-path~ keyword of ~use-package~ or ~require~. 29 | 30 | ** Usage 31 | 32 | The package can be enabled interactively or automatically on Org mode start-up: 33 | 34 | #+begin_src emacs-lisp 35 | 36 | (add-hook 'org-mode-hook 'org-appear-mode) 37 | 38 | #+end_src 39 | 40 | By default, toggling is instantaneous and only emphasis markers are toggled. The following custom variables can be changed to enable additional functionality. 41 | 42 | - org-appear-autoemphasis :: if non-nil and ~org-hide-emphasis-markers~ is on, toggle emphasis markers 43 | - org-appear-autolinks :: if non-nil and ~org-link-descriptive~ is on, toggle links 44 | - org-appear-autosubmarkers :: if non-nil and ~org-pretty-entities~ is on, toggle subscripts and superscripts 45 | - org-appear-autoentities :: if non-nil and ~org-pretty-entities~ is on, toggle Org entitites 46 | - org-appear-autokeywords :: if non-nil and ~org-hidden-keywords~ is on, toggle keywords in ~org-hidden-keywords~ 47 | - org-appear-inside-latex :: if non-nil, toggle entities and sub/superscripts in LaTeX fragments 48 | - org-appear-delay :: seconds of delay before toggling 49 | - org-appear-trigger :: when to toggle elements 50 | 51 | If Org mode custom variables that control visibility of elements are configured to show hidden parts, the respective ~org-appear~ settings do not have an effect. 52 | 53 | ~org-appear-trigger~ can be set to ~always~, ~on-change~, or ~manual~. With ~on-change~, elements will be toggled only when the buffer is modified or on mouse click. This option disables delayed toggling. With ~manual~, toggling must be enabled by calling ~org-appear-manual-start~. ~org-appear-manual-stop~ is used to disable toggling with this option. 54 | 55 | The ~manual~ option is useful for, e.g., integrating ~org-appear~ with ~evil-mode~. Below is an example configuration for toggling elements in Insert mode only. Note that ~org-appear~ expects to be enabled in Org mode buffers only, which is why the example attaches ~evil-mode~ hooks to the Org mode startup hook. 56 | 57 | #+begin_src emacs-lisp 58 | 59 | (setq org-appear-trigger 'manual) 60 | (add-hook 'org-mode-hook (lambda () 61 | (add-hook 'evil-insert-state-entry-hook 62 | #'org-appear-manual-start 63 | nil 64 | t) 65 | (add-hook 'evil-insert-state-exit-hook 66 | #'org-appear-manual-stop 67 | nil 68 | t))) 69 | 70 | #+end_src 71 | 72 | ** Acknowledgements 73 | 74 | Special thanks to [[https://github.com/SPFabGerman][SPFabGerman]], who came up with the idea and extended ~org-appear~ beyond emphasis marker toggling, and [[https://github.com/daviwil][daviwil]], who proposed the ~org-appear~ name. 75 | 76 | ** Known Issues 77 | 78 | ~org-appear~ does not handle overlapping emphasis elements correctly, e.g., 79 | 80 | #+begin_example 81 | *Why would someone /nest emphasis* like that?/ 82 | #+end_example 83 | 84 | In the above example, ~org-appear~ can only detect and reveal the first (bold) element. This is due to the reliance on the ~org-element~ API -- ~org-element-context~ in particular -- which also fails to detect the second (italic) element. 85 | 86 | ~org-appear~ will fail to detect elements nested inside certain other elements, such as comments or document titles. 87 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awth13/org-appear/32ee50f8fdfa449bbc235617549c1bccb503cb09/demo.gif -------------------------------------------------------------------------------- /org-appear.el: -------------------------------------------------------------------------------- 1 | ;;; org-appear.el --- Auto-toggle Org elements -*- lexical-binding: t; -*- 2 | 3 | ;; Portions of code in this file are taken from org-fragtog https://github.com/io12/org-fragtog 4 | ;; org-fragtog Copyright (C) 2020 Benjamin Levy - MIT/X11 License 5 | ;; org-appear Copyright (C) 2021 Alice Istleyeva - MIT License 6 | ;; Author: Alice Istleyeva 7 | ;; Version: 0.3.1 8 | ;; Description: Toggle Org mode element visibility upon entering and leaving 9 | ;; Homepage: https://github.com/awth13/org-appear 10 | ;; Package-Requires: ((emacs "29.1") (org "9.3")) 11 | 12 | ;; Permission is hereby granted, free of charge, to any person obtaining a copy 13 | ;; of this software and associated documentation files (the "Software"), to deal 14 | ;; in the Software without restriction, including without limitation the rights 15 | ;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | ;; copies of the Software, and to permit persons to whom the Software is 17 | ;; furnished to do so, subject to the following conditions: 18 | ;; 19 | ;; The above copyright notice and this permission notice shall be included in all 20 | ;; copies or substantial portions of the Software. 21 | ;; 22 | ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | ;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | ;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | ;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | ;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | ;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | ;; SOFTWARE. 29 | 30 | ;;; Commentary: 31 | 32 | ;; This package enables automatic visibility toggling of various Org elements depending on cursor position. 33 | ;; It supports automatic toggling of emphasis markers, links, subscripts and 34 | ;; superscripts, entities, and keywords. By default, toggling is instantaneous 35 | ;; and only affects emphasis markers. If Org mode custom variables that control 36 | ;; visibility of elements are configured to show hidden parts, the respective 37 | ;; `org-appear' settings do not have an effect. 38 | 39 | ;;; Code: 40 | 41 | (require 'org) 42 | (require 'org-element) 43 | (require 'subr-x) ; Compatibility 44 | 45 | (defgroup org-appear nil 46 | "Auto-toggle Org elements." 47 | :group 'org) 48 | 49 | (defcustom org-appear-trigger 'always 50 | "Method of triggering element toggling. 51 | `always' means that elements are toggled every time they are under the cursor. 52 | `on-change' means that elements are toggled only when the buffer is modified 53 | or when the element under the cursor is clicked with a mouse. 54 | `manual' means that toggling starts on call to `org-appear-manual-start' 55 | and stops on call to `org-appear-manual-stop'." 56 | :type '(choice (const :tag "Always" always) 57 | (const :tag "Only on change" on-change) 58 | (const :tag "Manual" manual)) 59 | :group 'org-appear) 60 | 61 | (defcustom org-appear-autoemphasis t 62 | "Non-nil enables automatic toggling of emphasised and verbatim markers. 63 | Does not have an effect if `org-hide-emphasis-markers' is nil." 64 | :type 'boolean 65 | :group 'org-appear) 66 | 67 | (defcustom org-appear-autosubmarkers nil 68 | "Non-nil enables automatic toggling of subscript and superscript markers. 69 | Does not have an effect if `org-pretty-entities' is nil." 70 | :type 'boolean 71 | :group 'org-appear) 72 | 73 | (defcustom org-appear-autoentities nil 74 | "Non-nil enables automatic toggling of org entities. 75 | Does not have an effect if `org-pretty-entities' is nil." 76 | :type 'boolean 77 | :group 'org-appear) 78 | 79 | (defcustom org-appear-autolinks nil 80 | "Non-nil enables automatic toggling of links. 81 | If set to the symbol `just-brackets', links will be shown with 82 | brackets around them without showing the link target. Does not 83 | have an effect if `org-link-descriptive' is nil." 84 | :type '(choice (const :tag "Ignore links" nil) 85 | (const :tag "Toggle full link" t) 86 | (const :tag "Toggle brackets" just-brackets)) 87 | :group 'org-appear) 88 | 89 | (defcustom org-appear-autokeywords nil 90 | "Non-nil enables automatic toggling of keywords. 91 | Does not have an effect if `org-hidden-keywords' is nil." 92 | :type 'boolean 93 | :group 'org-appear) 94 | 95 | (defcustom org-appear-inside-latex nil 96 | "Also applies toggling inside Latex fragments and environments. 97 | Sub- and superscript markers are toggled if `org-appear-autosubmarkers' is 98 | non-nil. Entities are toggled if `org-appear-autoentities' is non-nil." 99 | :type 'boolean 100 | :group 'org-appear) 101 | 102 | (defcustom org-appear-delay 0.0 103 | "Seconds of delay before toggling an element." 104 | :type 'number 105 | :group 'org-appear) 106 | 107 | (defcustom org-appear-manual-linger nil 108 | "Whether to hide the element on manual stop. 109 | If true, hide upon navigating away." 110 | :type 'boolean 111 | :group 'org-appear) 112 | 113 | (defvar-local org-appear--timer nil 114 | "Current active timer.") 115 | 116 | ;;;###autoload 117 | (define-minor-mode org-appear-mode 118 | "A minor mode that automatically toggles elements in Org mode." 119 | :init-value nil 120 | :lighter nil 121 | :keymap nil 122 | 123 | (cond 124 | (org-appear-mode 125 | (org-appear--set-elements) 126 | (add-hook 'post-command-hook #'org-appear--post-cmd nil t) 127 | (add-hook 'pre-command-hook #'org-appear--pre-cmd nil t) 128 | (when (eq org-appear-trigger 'on-change) 129 | (add-hook 'mouse-leave-buffer-hook #'org-appear--after-change nil t) 130 | (add-hook 'after-change-functions #'org-appear--after-change nil t))) 131 | (t 132 | ;; Clean up current element when disabling the mode 133 | (when-let ((current-elem (org-appear--current-elem))) 134 | (org-appear--hide-invisible current-elem) 135 | (when org-appear--timer 136 | (cancel-timer org-appear--timer) 137 | (setq org-appear--timer nil))) 138 | (remove-hook 'post-command-hook #'org-appear--post-cmd t) 139 | (remove-hook 'pre-command-hook #'org-appear--pre-cmd t) 140 | (when (eq org-appear-trigger 'on-change) 141 | (remove-hook 'mouse-leave-buffer-hook #'org-appear--after-change t) 142 | (remove-hook 'after-change-functions #'org-appear--after-change t))))) 143 | 144 | (defvar org-appear-elements nil 145 | "List of Org elements to toggle.") 146 | 147 | (defvar-local org-appear--prev-elem nil 148 | "Previous element that surrounded the cursor. 149 | nil if the cursor was not on an element.") 150 | 151 | (defvar-local org-appear--do-buffer nil 152 | "Non-nil when `org-appear-mode' is notified to start toggling.") 153 | 154 | (defvar-local org-appear--elem-toggled nil 155 | "Non-nil if the last encountered element has been toggled.") 156 | 157 | (defun org-appear--set-elements () 158 | "Add elements to toggle to `org-appear-elements'." 159 | (let ((emphasis-elements '(bold 160 | italic 161 | underline 162 | strike-through 163 | verbatim 164 | code)) 165 | (script-elements '(subscript 166 | superscript)) 167 | (entity-elements '(entity)) 168 | (link-elements '(link)) 169 | (keyword-elements '(keyword)) 170 | (latex-elements '(latex-fragment latex-environment))) 171 | 172 | ;; HACK: is there a better way to do this? 173 | (setq-local org-appear--prev-elem nil) 174 | (setq org-appear-elements nil) ; reset 175 | (when (and org-hide-emphasis-markers org-appear-autoemphasis) 176 | (setq org-appear-elements (append org-appear-elements emphasis-elements))) 177 | (when (and org-pretty-entities org-appear-autosubmarkers) 178 | (setq org-appear-elements (append org-appear-elements script-elements))) 179 | (when (and org-pretty-entities org-appear-autoentities) 180 | (setq org-appear-elements (append org-appear-elements entity-elements))) 181 | (when (and org-link-descriptive org-appear-autolinks) 182 | (setq org-appear-elements (append org-appear-elements link-elements))) 183 | (when (and org-hidden-keywords org-appear-autokeywords) 184 | (setq org-appear-elements (append org-appear-elements keyword-elements))) 185 | (when org-appear-inside-latex 186 | (setq org-appear-elements (append org-appear-elements latex-elements))))) 187 | 188 | (defun org-appear--post-cmd () 189 | "This function is executed by `post-command-hook' in `org-appear-mode'. 190 | It handles toggling elements depending on whether the cursor entered or exited them." 191 | (let* ((prev-elem org-appear--prev-elem) 192 | (prev-elem-start (org-element-property :begin prev-elem)) 193 | (current-elem (org-appear--current-elem)) 194 | (current-elem-start (org-element-property :begin current-elem))) 195 | 196 | ;; After leaving an element 197 | (when (and prev-elem 198 | org-appear--elem-toggled 199 | (not (equal prev-elem-start current-elem-start))) 200 | 201 | ;; Forget element 202 | (setq org-appear--elem-toggled nil) 203 | 204 | ;; If timer for prev-elem fired and was expired 205 | (if (not org-appear--timer) 206 | (save-excursion 207 | (goto-char prev-elem-start) 208 | ;; Reevaluate `org-element-context' in case the bounds 209 | ;; of the previous element changed 210 | (org-appear--hide-invisible (org-element-context))) 211 | (cancel-timer org-appear--timer) 212 | (setq org-appear--timer nil))) 213 | 214 | ;; Inside an element 215 | (when (and current-elem (or (eq org-appear-trigger 'always) 216 | org-appear--do-buffer 217 | org-appear--elem-toggled)) 218 | 219 | ;; Mark element as toggled to continue toggling and ignore buffer state 220 | (setq org-appear--elem-toggled t) 221 | 222 | ;; New element, delay first unhiding 223 | (when (and (eq org-appear-trigger 'always) 224 | (> org-appear-delay 0) 225 | (not (eq prev-elem-start current-elem-start))) 226 | (setq org-appear--timer (run-with-idle-timer org-appear-delay 227 | nil 228 | #'org-appear--show-with-lock 229 | current-elem 230 | t))) 231 | 232 | ;; Not a new element 233 | (when (not org-appear--timer) 234 | (org-appear--show-with-lock current-elem))) 235 | 236 | (setq org-appear--prev-elem current-elem) 237 | (when (not (eq org-appear-trigger 'manual)) 238 | (setq org-appear--do-buffer nil)))) 239 | 240 | (defun org-appear--after-change (&rest _args) 241 | "This function is executed by `after-change-functions' in `org-appear-mode'. 242 | It signals that elements in the current buffer must be toggled." 243 | (setq org-appear--do-buffer 't)) 244 | 245 | (defun org-appear-manual-start () 246 | "Signal that elements in the current buffer must be toggled." 247 | (setq org-appear--do-buffer 't)) 248 | 249 | (defun org-appear-manual-stop () 250 | "Signal that elements in the current buffer must no longer be toggled." 251 | (when (not org-appear-manual-linger) 252 | (when-let ((current-elem (org-appear--current-elem))) 253 | (org-appear--hide-invisible current-elem)) 254 | (setq org-appear--elem-toggled nil)) 255 | (setq org-appear--do-buffer nil)) 256 | 257 | (defun org-appear--pre-cmd () 258 | "This function is executed by `pre-command-hook' in `org-appear-mode'. 259 | It hides elements before commands that modify the buffer based on column width." 260 | (when (memq this-command '(org-fill-paragraph 261 | org-ctrl-c-ctrl-c)) 262 | (when-let ((current-elem (org-appear--current-elem))) 263 | (org-appear--hide-invisible current-elem)))) 264 | 265 | (defun org-appear--current-elem () 266 | "Return element at point. 267 | Return nil if element is not supported by `org-appear-mode'." 268 | (when-let ((elem (org-element-context))) 269 | (let* ((elem-type (car elem)) 270 | (elem-end (- (org-element-property :end elem) 271 | (1- (org-element-property :post-blank elem)))) 272 | (link-ignore-p (and (eq elem-type 'link) 273 | (or (string-match-p "[Cc]ite" 274 | (org-element-property :type elem)) 275 | (memq (org-element-property :format elem) 276 | '(plain angle))))) 277 | (key-ignore-p (and (eq elem-type 'keyword) 278 | (not (memq (intern (downcase 279 | (org-element-property :key elem))) 280 | org-hidden-keywords)))) 281 | (script-ignore-p (and (or (eq elem-type 'subscript) 282 | (eq elem-type 'superscript)) 283 | (not (org-element-property :use-brackets-p elem)) 284 | (not (eq org-use-sub-superscripts t))))) 285 | (if (and (memq elem-type org-appear-elements) 286 | (< (point) elem-end) ; Ignore post-element whitespace 287 | (not link-ignore-p) ; Ignore plain and org-ref links 288 | (not key-ignore-p) ; Ignore unhidden keywords 289 | (not script-ignore-p)) ; Ignore sub/supercripts ignored by Org 290 | elem 291 | nil)))) 292 | 293 | (defun org-appear--parse-elem (elem) 294 | "Return bounds of element ELEM. 295 | Return nil if element cannot be parsed." 296 | (let* ((elem-type (car elem)) 297 | (elem-tag (cond ((memq elem-type '(bold 298 | italic 299 | underline 300 | strike-through 301 | verbatim 302 | code)) 303 | 'emph) 304 | ((memq elem-type '(subscript 305 | superscript)) 306 | 'script) 307 | ((eq elem-type 'entity) 308 | 'entity) 309 | ((eq elem-type 'link) 310 | 'link) 311 | ((eq elem-type 'keyword) 312 | 'keyword) 313 | ((memq elem-type '(latex-fragment latex-environment)) 314 | 'latex-fragment) 315 | (t nil))) 316 | (elem-start (org-element-property :begin elem)) 317 | (elem-end (org-element-property :end elem)) 318 | (elem-content-start (org-element-property :contents-begin elem)) 319 | (elem-content-end (org-element-property :contents-end elem)) 320 | ;; Some elements have extra spaces at the end 321 | ;; The number of spaces is stored in the post-blank property 322 | (post-elem-spaces (org-element-property :post-blank elem)) 323 | (elem-end-real (- elem-end post-elem-spaces))) 324 | ;; Only sub/superscript elements are guaranteed to have 325 | ;; contents-begin and contents-end properties 326 | (when elem-tag 327 | `(:start ,elem-start 328 | :end ,elem-end-real 329 | :visible-start ,(pcase elem-tag 330 | ('emph (1+ elem-start)) 331 | ('script elem-content-start) 332 | ('link (or elem-content-start (+ elem-start 2)))) 333 | :visible-end ,(pcase elem-tag 334 | ('emph (1- elem-end-real)) 335 | ('script elem-content-end) 336 | ('link (or elem-content-end (- elem-end-real 2)))))))) 337 | 338 | (defun org-appear--show-invisible (elem) 339 | "Silently remove invisible property from invisible parts of element ELEM." 340 | (let* ((elem-at-point (org-appear--parse-elem elem)) 341 | (elem-type (car elem)) 342 | (start (plist-get elem-at-point :start)) 343 | (end (plist-get elem-at-point :end)) 344 | (visible-start (plist-get elem-at-point :visible-start)) 345 | (visible-end (plist-get elem-at-point :visible-end))) 346 | (when (and (eq org-appear-autolinks 'just-brackets) 347 | (eq elem-type 'link)) 348 | (setq start (1- visible-start)) 349 | (setq end (1+ visible-end))) 350 | (with-silent-modifications 351 | (cond ((eq elem-type 'entity) 352 | (decompose-region start end)) 353 | ((memq elem-type '(latex-fragment latex-environment)) 354 | (when org-appear-autosubmarkers 355 | (remove-text-properties start end '(invisible))) 356 | (when org-appear-autoentities 357 | (decompose-region start end))) 358 | ((eq elem-type 'keyword) 359 | (remove-text-properties start end '(invisible org-link))) 360 | ((and (featurep 'org-fold) 361 | (eq elem-type 'link) 362 | (eq org-fold-core-style 'text-properties)) 363 | (remove-text-properties start 364 | visible-start 365 | (list (org-fold-core--property-symbol-get-create 'org-link) nil)) 366 | (remove-text-properties visible-end 367 | end 368 | (list (org-fold-core--property-symbol-get-create 'org-link) nil))) 369 | (t 370 | (remove-text-properties start visible-start '(invisible org-link)) 371 | (remove-text-properties visible-end end '(invisible org-link))))))) 372 | 373 | (defun org-appear--show-with-lock (elem &optional renew) 374 | "Show invisible parts of element ELEM. 375 | When RENEW is non-nil, obtain element at point instead." 376 | ;; When called with timer, element might be different upon arrival 377 | (when renew 378 | (setq elem (org-appear--current-elem)) 379 | (setq org-appear--prev-elem elem) 380 | (setq org-appear--timer nil)) 381 | 382 | (when-let ((elem-start (org-element-property :begin elem)) 383 | (elem-end (org-element-property :end elem))) 384 | ;; Call `font-lock-ensure' before unhiding to prevent `jit-lock-mode' 385 | ;; from refontifying the element region after changes in buffer 386 | (font-lock-ensure elem-start elem-end) 387 | (org-appear--show-invisible elem))) 388 | 389 | (defun org-appear--hide-invisible (elem) 390 | "Silently add invisible property to invisible parts of element ELEM." 391 | (let* ((elem-at-point (org-appear--parse-elem elem)) 392 | (elem-type (car elem)) 393 | (start (plist-get elem-at-point :start)) 394 | (end (plist-get elem-at-point :end)) 395 | (visible-start (plist-get elem-at-point :visible-start)) 396 | (visible-end (plist-get elem-at-point :visible-end))) 397 | (when elem-at-point 398 | (when (and (eq org-appear-autolinks 'just-brackets) 399 | (eq elem-type 'link)) 400 | (setq start (1- visible-start)) 401 | (setq end (1+ visible-end))) 402 | (with-silent-modifications 403 | (cond ((eq elem-type 'entity) 404 | (compose-region start end (org-element-property :utf-8 elem)) 405 | (font-lock-flush start end)) 406 | ((memq elem-type '(keyword latex-fragment latex-environment)) 407 | (font-lock-flush start end)) 408 | ((and (featurep 'org-fold) 409 | (eq elem-type 'link) 410 | (eq org-fold-core-style 'text-properties)) 411 | (put-text-property start 412 | visible-start 413 | (org-fold-core--property-symbol-get-create 'org-link) 414 | 'org-link) 415 | (put-text-property visible-end 416 | end 417 | (org-fold-core--property-symbol-get-create 'org-link) 418 | 'org-link)) 419 | (t 420 | (put-text-property start visible-start 'invisible 'org-link) 421 | (put-text-property visible-end end 'invisible 'org-link) 422 | (font-lock-flush start end)))) 423 | ;; Call `font-lock-ensure' after flushing to prevent `jit-lock-mode' 424 | ;; from refontifying the next element entered 425 | (font-lock-ensure start end)))) 426 | 427 | (provide 'org-appear) 428 | ;;; org-appear.el ends here 429 | --------------------------------------------------------------------------------