Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for property drawers (revisited) #62

Open
danielkrizian opened this issue Jan 28, 2025 · 3 comments
Open

Support for property drawers (revisited) #62

danielkrizian opened this issue Jan 28, 2025 · 3 comments

Comments

@danielkrizian
Copy link

danielkrizian commented Jan 28, 2025

Revisiting #27 (I don't have permissions to reopen it), which discusses interactive toggling of property drawers not being in the scope of org-appear, I thought perhaps supporting dynamic toggling instead of interactive toggling is aligned with the philosophy of org-appear - i.e. re-appear-ance of any already hidden property drawer when user:

  1. set the drawer(s) to be hidden at startup; and
  2. set org-appear-autodrawers to non-nil and org-hidden-drawers is non-nil; and
  3. has cursor/point near hidden property drawer, i.e. one or customizable number of lines above or below the drawer

Starting from functions that hide the properties drawers:
(copied here since the original is now buried in old version of Hitchhiker's-Rough-Guide-to-Org-roam-V2; slightly modified)

      (add-hook 'org-mode-hook (lambda () (setq-local org-drawers-hidden nil)))

      (defun org-hide-properties ()
        "Hide all org-mode headline property drawers in buffer. Could be slow if it has a lot of overlays."
        (interactive)
        (save-excursion
          (goto-char (point-min))
          (while (re-search-forward
                  "^ *:properties:\n\\( *:.+?:.*\n\\)+ *:end:\n" nil t)
            (let ((ov_this (make-overlay (match-beginning 0) (match-end 0))))
              (overlay-put ov_this 'display "")
              (overlay-put ov_this 'hidden-prop-drawer t))))
        (setq org-drawers-hidden t))

      (defun org-show-properties ()
        "Show all org-mode property drawers hidden by org-hide-properties."
        (interactive)
        (remove-overlays (point-min) (point-max) 'hidden-prop-drawer t)
        (setq org-drawers-hidden nil))

      (defun org-toggle-properties ()
        "Toggle visibility of property drawers."
        (interactive)
        (if org-drawers-hidden
            (org-show-properties)
          (org-hide-properties)))

I have this working prototype:

      (defcustom org-appear-autodrawers t
        "Non-nil enables automatic toggling of hidden property drawers.
      Does not have an effect if `org-drawers-hidden' is nil"
        :type 'boolean
        :group 'org-appear)

      (defvar-local org-appear-unhidden-drawers nil
        "List of currently unhidden property drawers in the buffer.")

      (defun hide-near-point-otherwise-unhide ()
        "Dynamically hide or unhide property drawers based on cursor proximity."
        (let ((unhidden-drawers-near-point
               (cl-loop for pos in '(-1 2)
                        for drawer-near-point = (org-find-overlays 'hidden-prop-drawer (line-beginning-position pos))
                        when drawer-near-point do (overlay-put (car drawer-near-point) 'display nil) ;; unhide drawer near point
                        append drawer-near-point)))
          (dolist (previously-unhidden-drawer org-appear-unhidden-drawers)
              (unless (member previously-unhidden-drawer unhidden-drawers-near-point)
                (overlay-put previously-unhidden-drawer 'display ""))) ;; hide previously unhidden drawer no longer near point
          (setq-local org-appear-unhidden-drawers unhidden-drawers-near-point)))

      (defun org-appear-dynamic-drawers-visibility--setup ()
        "Set up dynamic drawer visibility for Org-mode."
        (add-hook 'post-command-hook #'hide-near-point-otherwise-unhide nil t))

      (defun org-appear-dynamic-drawers-visibility--cleanup ()
        "Remove dynamic drawer visibility for Org-mode."
        (remove-hook 'post-command-hook #'hide-near-point-otherwise-unhide t))

      (add-hook 'org-mode-hook #'org-appear-dynamic-drawers-visibility--setup)
      (add-hook 'org-mode-hook
                (lambda () (add-hook 'kill-buffer-hook #'org-appear-dynamic-drawers-visibility--cleanup nil t)))

Of course it would be better to implement with org-elements rather than re-search-forward.

@krisbalintona
Copy link

Related are the packages:

@danielkrizian
Copy link
Author

these do not make a drawer automatically re-appear locally at point (when the cursor moves near the hidden overlay)

@krisbalintona
Copy link

these do not make a drawer automatically re-appear locally at point (when the cursor moves near the hidden overlay)

Yes, that's correct. I mentioned them because they are related packages.

But with respect to implementing a unhide-on-point functionality, I think org-hide-drawers could be retooled for that purpose, since it can hide (with overlays; though I suppose the code could be rewritten to use text properties like org-appear...) drawers when given a drawer element or region. I've done a bit of work integrating org-appear with hiding org-cite citations recently, and as far as I can tell, the above shouldn't be too much work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants