how can I collapse all entries older than 3 months in my emacs org-mode journal file?
Asked Answered
E

4

3

I have a large journal file with date entries like this:

[2011-06-23 Thu]

some text

[2011-06-22 Wed]

some more text

[... 12MB of text later ...]

[2000-01-01 Sat]

first entry

I would like to be able to configure org-mode so that only the last 3 months are visible, whereas older entries are collapsed, and are only expanded when I need to. Is there a way of setting this up automatically so that every new day makes the 3 month + 1 day old entry be collapsed next time?

As it is now, it's impossible for me to use, because it takes more than a minute to load the document.

Escallop answered 23/6, 2011 at 8:3 Comment(1)
I can get quite close using a sparse tree search. C-c / m for match search, and something like Match: TIMESTAMP>"<-3m>" as the search expression. But in my tests, this will only match entries containing a TODO keyword. Having solved this last issue, the search can be assigned to a key binding, or a hook, so that you don't need to type it each time.Matthiew
S
3

With 12MB of text, that's got to be a huge number of date entry headings, so I would imagine buffer narrowing might still be a good way to go.

I'm an org-mode novice, so I may be missing an easier way to achieve this, but the following will automatically narrow the buffer to the entries made since three months prior to the current date.

(defvar my-org-journal "/path/to/file.org")

(add-hook 'org-mode-hook 'my-org-mode-hook)
(defun my-org-mode-hook ()
  (when (equal (expand-file-name (buffer-file-name))
               (expand-file-name my-org-journal))
    (my-org-narrow-to-month-of-entries)))

(defun my-org-narrow-to-month-of-entries ()
  "Narrow buffer to entries within the last three months."
  (interactive)
  (let ((minimum-date
         (with-temp-buffer
           (progn
             (org-insert-time-stamp (current-time) nil t)
             (org-timestamp-change -3 'month)
             (buffer-substring-no-properties
              (point-min) (point-max))))))
    (save-excursion
      (while (search-forward-regexp org-tsr-regexp-both nil t)
        (let ((end (point)))
          (backward-sexp)
          (let ((datestamp (buffer-substring-no-properties (point) end)))
            (if (string< datestamp minimum-date)
                (narrow-to-region (point-min) (point))
              (forward-sexp))))))))

And, of course, C-xnw to widen the buffer again to see all the entries.

If you wanted to apply this based on a Local Variable rather than by file name, you could use this approach instead:

(defvar my-org-narrow-to-month-of-entries nil)

(add-hook 'org-mode-hook 'my-org-mode-hook)
(defun my-org-mode-hook ()
  (add-hook 'hack-local-variables-hook
            (lambda () (when my-org-narrow-to-month-of-entries
                         (my-org-narrow-to-month-of-entries)))
            nil t))

with the following at the end of your file:

;;; Local Variables:
;;; my-org-narrow-to-month-of-entries: t
;;; End:

References:

edit:

I'm not sure if that will do anything about that long load time, to be honest. A sample org file of comparable size doesn't take remotely that long to load on my machine, but I don't know whether that's due to better hardware, or my simple dummy file being easier to process.

If the above doesn't improve things, we could look at making the narrowing happen before org-mode is initialised, and see if that makes any difference?

The following may not be the best way of doing this, but it should be worth trying out for performance reasons, just in case it makes a difference.

This would be in place of the org-mode-hook, and using the my-org-journal variable for the filename, as with the first example above.

(defadvice insert-file-contents (after my-insert-file-contents)
  (when (equal (expand-file-name (buffer-file-name))
               (expand-file-name my-org-journal))
    (require 'org)
    (my-org-narrow-to-month-of-entries)))
(ad-activate 'insert-file-contents)
Semasiology answered 24/6, 2011 at 14:30 Comment(0)
S
2

Create an agenda view with C-[ then look at the daily/weekly agenda with C-u 90 C-c a a. You can customise this and bind it to something, see http://www.gnu.org/software/emacs/manual/html_node/org/Custom-agenda-views.html#Custom-agenda-views .

[EDIT] Actually, this doesn't answer the question about collapsing older entries, but does allow you to view only the relevant entries.

Skysweeper answered 23/6, 2011 at 15:30 Comment(0)
A
2

I don't have a completely automated way to do what you're asking. I'm sure someone with some elisp/org-mode chops could automate it.

Here are some org-mode features that might help:

  • You can label headings with the Archive tag (via C-c C-x a) and that prevents them from expanding when you cycle visibility. See the org-mode manual on Archiving. I think that achieves what you want visibility-wise.
  • As @Juancho commented, you can search for Timestamps that match an expression. This generates a list of matches where you can easily write a keyboard macro to tag each as an Archive. Here's a good document on Advanced searches in org-mode.

One annoyance that I found when trying this on my system is that the search result ended up with a flat list of all heading levels. The way I organize entries, it would be better to limit the search to top-level headings (that's what I use for daily entries in my journal). I'm sure you could work around it by setting some property, or perhaps org-mode can filter searches at a particular level.

Ankle answered 23/6, 2011 at 19:12 Comment(0)
U
1

You have three options:

  1. set the VISIBILITY property to folded for all older entries. You can use C-c a < a to get the agenda restricted to the current file followed by marking the entries and setting the above property en masse.
  2. Move the older journal entries to an "Archive sibling" with C-c C-x A.
  3. Archive the older entries to an archive file with C-c C-x C-s.
Ulises answered 23/6, 2011 at 8:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.