From: Marc-Oliver Ihm <marc-oliver.ihm@online.de>
To: emacs-orgmode@gnu.org
Cc: Marc-Oliver Ihm <ihm@online.de>
Subject: Progress of org-find-timestamps
Date: Sun, 14 Aug 2011 17:00:49 +0200 [thread overview]
Message-ID: <4E47E321.7040505@online.de> (raw)
In-Reply-To: <87oc0e6d5n.fsf@altern.org>
Am 28.07.2011 09:54, schrieb Bastien:
> Hi Marc-Oliver,
>
> Marc-Oliver Ihm<marc-oliver.ihm@online.de> writes:
>
>> Thanx for testing again !
>
> You're welcome.
>
>> I will try to figure out, how to patch `org-sparse-tree'.
>
> Thanks -- let us know how it goes, and take the time to grasp
> Org's internals...
>
>> And I will add active timestamps. Which was a think, that I have
>> thought of before, but postponed until someone would suggest/request
>> this feature :-)
>
> Yep. It will make your `org-find-timestamps' function quite useful.
> Please be aware that I will spend some time and trying to create a cache
> for timestamps (see recent discussions about calfw), and that such a
> cache could help a lot in making your solution easier to implement.
>
> Best,
>
Hello Bastien,
Just to keep you and the newsgroup updated :-)
Down below you will find the current version of org-find-timestamps.
It is, as you did suggest, now capable of finding active timestamps as well as inactive ones.
However, studying the code of org-sparse-tree, I realized, that it would be beneficial, to be able to
find CLOSED, SCHEDULED and DEADLINE timestamps as well. Therefore I have started to implement these features as well.
Moreover I would like to make available some of the functionality of org-find-timestamps within org-sparse-tree.
As soon as I am done with this, I will post a patch to org.el.
with kind regards, Marc-Oliver Ihm
P.s.: I realized the the features of org-sparse-tree and org-find-timestamps overlap to a considerable degree,
although the do not share any code. This is probably a sign, that both functions should be reworked to use some
common helper functions. This might be a secound step, once org-find-timestamps has found its way into the code ...
(defun org-find-timestamps (&optional first-date last-date buffer-name which collect-method sort)
"Find inactive timestamps within a date-range and maybe sort them.
This function can help to bring the notes, that you take within
org-mode, into a chronological order, even if they are scattered
among many different nodes. The result is somewhat like a diary,
listing your notes for each successive day. Please be aware
however: This intended usage requires, that you routinely
insert inactive timestamps into the notes that you write.
org-find-timstamps works by creating a regular expression to
match a given range of dates, doing a search for it and
displaying the results either as a sparse tree or with the help
of occur. The original buffer is not modified.
Argument FIRST-DATE and LAST-DATE (yyyy-mm-dd) define the range
of timestamps to search for.
BUFFER-NAME specifies the name of the buffer to search. If nil, use
current buffer.
WHICH (`active', `inactive' or `both'), tells which timestamps to use.
COLLECT-METHOD can be one of `org-occur', `occur' and
`multi-occur', thus telling: Which buffers to search (current or
all org-mode buffers) and how to present matches.
Results will be sorted according to SORT (either the symbol `y'
or `n'); this is only possible, if results are presented with
`occur' or `multi-occur'.
All Arguments can be `nil' (or ommitted), in which case their values are
queried interactively.
"
(interactive)
(let ((occur-buffer-name "*Occur*")
(occur-header-regex "^[0-9]+ match\\(es\\)?") ;; regexp to match for header-lines in *Occur* buffer
description
swap-dates
(days 0)
date-regex
buff
org-buffers
)
(if buffer-name (switch-to-buffer buffer-name))
(save-window-excursion
;; ask for type of timestamp to search, if not supplied as an argument
(cond ((null which)
(setq which (intern-soft (car (split-string (org-icompleting-read "Please choose, which type of timestamp to search: " '("active" "inactive" "both") nil t nil nil "inactive"))))))
((not (member which '(active inactive both)))
(error "Argument `WHICH' can not be `%s'" which)))
;; ask for date-range, if not supplied as argument
(or last-date (setq last-date (org-read-date nil nil nil "End date (or start): " nil nil)))
(or first-date (setq first-date (org-read-date nil nil nil "Start date (or end): " nil nil)))
;; swap dates, if required
(when (string< last-date first-date)
(setq swap-dates last-date)
(setq last-date first-date)
(setq first-date swap-dates))
;; readable description of what we searched for
(setq description (format "%s timestamps from %s to %s in %s, %s"
(if (eq which 'both) "active and inactive" (symbol-name which))
first-date last-date
(if (eq collect-method 'multi-occur) "all org-buffers" (concat "buffer " (buffer-name)))
(if (and (eq sort 'yes) (not (eq collect-method 'org-occur))) "sorted" "not sorted")))
;; temporary buffer for date-manipulations
(with-temp-buffer
;; construct list of dates in working buffer, loop as long we did not reach end-date
(while (not (looking-at-p last-date))
(goto-char (point-max))
;; Type of timstamp (inactive) might be wrong, will be corrected below
(insert "[")
;; Day of week (Mo) might be wrong, will be corrected below
(insert first-date " Mo]\n")
(forward-line -1)
;; advance number of days and correct day of week
(org-timestamp-change days 'day)
(setq days (1+ days))
(when (eq which 'both)
;; double last timestamp
(let (start content)
(move-to-column 0)
(setq start (point))
(forward-line)
(setq content (delete-and-extract-region start (point)))
(insert content)
(insert content)
(forward-line -1)
)
)
(unless (eq which 'inactive)
;; inserted inactive timestamp above, now we correct this
(org-toggle-timestamp-type)
)
(move-to-column 1)
)
(goto-char (point-max))
;; transform constructed list of dates into a single, optimized regex
(setq date-regex (regexp-opt (split-string (buffer-string) "\n" t)))
)
)
;; If no argument supplied, ask user, which buffers to search and how to present results
(or collect-method (setq collect-method (intern (car (split-string (org-icompleting-read "Please choose, which buffers to search and how to present the matches: " '("occur -- this buffer, list" "multi-occur -- all org-buffers, list" "org-occur -- this-buffer, sparse tree") nil t nil nil "occur -- this buffer, list"))))))
;; Perform the actual search
(save-window-excursion
(cond ((eq collect-method 'occur)
(occur date-regex)
)
((eq collect-method 'org-occur)
(if (string= major-mode "org-mode")
(org-occur date-regex)
(error "Buffer not in org-mode"))
)
((eq collect-method 'multi-occur)
;; construct list of all org-buffers
(dolist (buff (buffer-list))
(set-buffer buff)
(if (string= major-mode "org-mode")
(setq org-buffers (cons buff org-buffers))))
(multi-occur org-buffers date-regex))
(t (error (format "Argument `COLLECT-METHOD' can not be `%s'" collect-method)))
)
)
;; Postprocessing: Optionally sort buffer with results
;; org-occur operates on the current buffer, so we cannot modify its results afterwards
(if (eq collect-method 'org-occur)
(message (concat "Sparse tree with " description))
;; switch to occur-buffer and modify it
(if (not (get-buffer occur-buffer-name))
(message (concat "Did not find any matches for " description))
(let ((original-inhibit-read-only inhibit-read-only))
(unwind-protect
(progn
;; next line might be risky, so we unwind-protect it
(setq inhibit-read-only t)
(set-buffer occur-buffer-name)
(goto-char (point-min))
;; beautify the occur-buffer by replacing the potentially long original regexp
(while (search-forward (concat " for \"" date-regex "\"") nil t)
(replace-match "" nil t))
(goto-char (point-min))
;; Sort results by matching date ?
(when (cond ((eq sort 'yes) t)
((eq sort 'no) nil)
((null sort) (y-or-n-p "Sort results by date ? "))
(t (error "Argument `SORT' can not be `%s'" sort)))
(when (eq collect-method 'multi-occur)
;; bring all header lines ('xx matches for ..') to top of buffer, all lines with matches to bottom
(sort-subr t
'forward-line
'end-of-line
;; search-key for this sort only differentiates between header-lines and matche-lines
(lambda () (if (looking-at-p occur-header-regex) 2 1))
nil)
)
;; goto first line of matches
(goto-char (point-max))
(search-backward-regexp occur-header-regex)
(forward-line)
;; sort all matches according to date, that matched the regex
(sort-subr t
'forward-line
'end-of-line
;; search-key for this sort is date
(lambda () (search-forward-regexp date-regex) (substring (match-string 0) 1 -1))
nil
'string<)
;; pretend, that we did not modify the occur-buffer
)
(insert (format "Searched for %s.\n" description))
(goto-char (point-min))
(set-buffer-modified-p nil)
)
(setq inhibit-read-only original-inhibit-read-only)
)
)
;; show result
(switch-to-buffer occur-buffer-name)
)
)
)
)
next prev parent reply other threads:[~2011-08-14 15:01 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-17 9:03 Possibly new function to view your notes in chronological order Marc-Oliver Ihm
2011-07-18 8:20 ` Bastien
2011-07-18 19:06 ` Marc-Oliver Ihm
2011-07-18 19:11 ` Marc-Oliver Ihm
2011-07-22 18:43 ` New version which is compatible with emacs 24: New " Marc-Oliver Ihm
2011-07-26 11:55 ` Bastien
2011-07-26 19:17 ` Marc-Oliver Ihm
2011-07-28 7:54 ` Bastien
2011-08-14 15:00 ` Marc-Oliver Ihm [this message]
2011-08-14 15:17 ` exporting to HTML: <strong> instead of <b> for *bold text* iminet
2011-08-14 16:06 ` Nicolas Goaziou
2011-08-14 17:18 ` iminet
2011-08-14 16:19 ` Bastien
2011-08-14 17:18 ` iminet
2011-08-14 15:22 ` *bold*text iminet
2011-08-14 16:20 ` *bold*text Bastien
2011-08-14 17:17 ` *bold*text iminet
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=4E47E321.7040505@online.de \
--to=marc-oliver.ihm@online.de \
--cc=emacs-orgmode@gnu.org \
--cc=ihm@online.de \
/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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public 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).