OH man, I know this is a lot of replies to my own thread.  Sorry for the
noise. I just wanted to point out something I somehow failed to see as I
was pretending to cook Thanksgiving dinner while working on this project
(!!) -- my code does just fine producing overlays, which might be useful to
some people, but it does not really help with my own need, which is to
calculate timestamp values based on the position of the macro call in the
buffer.  That's because I'm using a function that searches backwards for
previous timestames, and the overlays are of course *not part of the buffer
string*, so they don't get picked up by regexp-search-backward.

To fix this I replaced my original function with a group of functions that
searches the buffer string *and* the overlays, looking for a timestamp
regep.  For the overlays, I endedu p writing a recursive function cause I
oculdn't think howelse to do it.

This is all much more verbose than my original function and I think pretty
inelegant but I would be interested to hear what others htink.

Here's the original function, which doesn't look for overlays:

(defun get-ts+7 (&optional weekly-times)
  "Return a string of the form <%Y-%m-d %a> where the date
elements are 7 days later than the (n - WEEKLY-TIMES timestamp)
in the buffer. That is, if WEEKLY-TIMES is nil or 1, return a
date one week later than the *PREVIOUS* timestamp. If
WEEKLY-TIMES is 2, return a time one week later than the
*SECOND-TO-LAST* timestamp above the previous location.

If there are not enough timestamps, right now it returns the last
found timestamp. "
  (interactive)
  (setq weekly-times (or weekly-times 1))
  (defun ts-search ()
    (save-match-data
      (goto-char (re-search-backward
                  (org-re-timestamp 'all) nil t))
      (let ((thismatch  (match-string 0)))
        (message "match: %s" thismatch)
        thismatch)))
  (let* (r
         (base-date (save-excursion
                     (cl-dotimes (time weekly-times r)
                       (condition-case nil
                           (progn (setq  r (or (ts-search) r))
                                  (message "r is %s" r))
                         (error
                          (message "Drat, there were %s timestamps, using
the last one I found."
                                   (if (= 0 time) "no" time))
                          (return r))))))

        (result nil))
    (message "base-time is %s" base-date)
    (if base-date
        (format-time-string "<%Y-%m-%d %a>"
                            (time-add
                             (date-to-time base-date) (days-to-time (1+
7))))
      "NO PREVIOUS TIMESTAMP") ))
-------------------------

and here are the several functions I felt I needed to solve the problem of
searching in 2 dimmensions:


(defun ts-search-both ()
  (save-match-data
    (let* ((bufts
            (save-match-data
              (set-match-data nil)
              (save-excursion
                (re-search-backward
                 (org-re-timestamp 'all) nil t)
                (if (match-beginning 0)
                    `(,(match-beginning 0) ,(match-string 0))
                  nil))))
           (ovts (save-match-data (save-excursion  (ts-search-ov)))))
      (cond
       ((and bufts ovts)
        (if (> (car bufts) (car ovts))
            (goto-char (car bufts))
            (cadr bufts)
          (cadr ovts)))
       (bufts
        (goto-char (car bufts))
        (cadr bufts))
       (ovts
        (goto-char (car ovts))
        (cadr ovts))
       (t
        (goto-char (point-min)) nil)
       )
      )))

(defun ts-search-ov ()
  (let* ((ovend   (previous-single-char-property-change (point)
'macro-ov-p))
         (ovs (overlays-at ovend))
         (m  (cl-loop for o in ovs
                      if (string-match (org-re-timestamp 'all) (overlay-get
o 'before-string))
                      ;;(goto-char (overlay-start o))
                      return (match-string 0 (overlay-get o
'before-string)))))
    (cond
     (m `(,(point) ,m))
     ((>= (point-min) ovend )
      (goto-char ovend)
      nil)
     (t
      (goto-char ovend)
      (ts-search-ov))
      )))

(defun get-ts+7-inc-ov (&optional weekly-times)
  "Return a string of the form <%Y-%m-d %a> where the date
elements are 7 days later than the (n - WEEKLY-TIMES timestamp)
in the buffer. That is, if WEEKLY-TIMES is nil or 1, return a
date one week later than the *PREVIOUS* timestamp. If
WEEKLY-TIMES is 2, return a time one week later than the
*SECOND-TO-LAST* timestamp above the previous location.

If there are not enough timestamps, right now it returns the last
found timestamp. "
  (interactive)
  (setq weekly-times (or weekly-times 1))

  (let* (r
         (base-date (save-excursion
                     (cl-dotimes (time weekly-times r)
                       (condition-case nil
                           (let ((s (ts-search-both)))
                             (if s
                                 (setq r s)
                               (message "Drat, there were %s timestamps,
using the last one I found."
                                        (if (= 0 time) "no" time))
                               (return r)))

                         ;; (error
                         ;;  (message "Drat, there were %s timestamps,
using the last one I found."
                         ;;           (if (= 0 time) "no" time))
                         ;;  (return r))
                         ))))

        (result nil))
    (message "base-time is %s" base-date)
    (if base-date
        (format-time-string "<%Y-%m-%d %a>"
                            (time-add
                             (date-to-time base-date) (days-to-time (1+
7))))
      "NO PREVIOUS TIMESTAMP") ))


-------------------------------

I'd be interested in feedback if others have some interest i nthe problem.

Reply via email to