* overlay showing computed value of macro? @ 2018-11-22 18:19 Matt Price 2018-11-22 21:06 ` Matt Price 0 siblings, 1 reply; 7+ messages in thread From: Matt Price @ 2018-11-22 18:19 UTC (permalink / raw) To: Org Mode [-- Attachment #1: Type: text/plain, Size: 1115 bytes --] I use macros in my course syllabi to automate creation of timestamps It looksl ike this: # see bottom of this email for the defn of ~get-ts~ #+MACRO: ts (eval (get-ts+7)) ** Week {{{n}}} ({{{ts}}}): Time Scales in Rivers, Geology, and Human Relationships * Week {{{n}}} ({{{ts}}}): +READING WEEK: NO CLASS ** Week {{{n}}} ({{{ts}}}): Communities, States, and Water Governance This makes it much easier for me to re-arrange headings while I'm planning schedules. But it's a little hard to tell, for instance, if I have the right number of class meetings, or if the University holidays are in the right place, etc. It would be nice for me to overlay the macro invocations with the values that they will evaluate to on export. I guess I would have to figure out when to trigger recalculation of the values (maybe not too often, say only when the macro is first created, when it's edited or deleted/deformed, and perhaps on structure editing. I do not understand emacs overlays very well so this feels a little daunting to me. Does anyone out there have ideas about how to do it effectively? Thanks as always! [-- Attachment #2: Type: text/html, Size: 1478 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: overlay showing computed value of macro? 2018-11-22 18:19 overlay showing computed value of macro? Matt Price @ 2018-11-22 21:06 ` Matt Price 2018-11-22 22:37 ` Matt Price 0 siblings, 1 reply; 7+ messages in thread From: Matt Price @ 2018-11-22 21:06 UTC (permalink / raw) To: Org Mode [-- Attachment #1: Type: text/plain, Size: 1141 bytes --] On Thu, Nov 22, 2018 at 1:19 PM Matt Price <moptop99@gmail.com> wrote: > It would be nice for me to overlay the macro invocations with the values > that they will evaluate to on export. I guess I would have to figure out > when to trigger recalculation of the values (maybe not too often, say only > when the macro is first created, when it's edited or deleted/deformed, and > perhaps on structure editing. > > I do not understand emacs overlays very well so this feels a little > daunting to me. Does anyone out there have ideas about how to do it > effectively? > > This is what I've come up with; it feels somewhat close but not quite there yet. I can create, remove, and the overlays, which is great. What I miss is the awesomeness of the way that overlays work with org links. I love how the link target and the enclosing [[ ][ ]] are invisible until I delete one of the "[" elements. However, with my code, the whole macro expression {{{macroname}}} ius invisible until I delete the whole thing, at which point the overlay helpfully disappears. Is htere a way to get something like the link behaviour? > Thanks as always! > > [-- Attachment #2: Type: text/html, Size: 1837 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: overlay showing computed value of macro? 2018-11-22 21:06 ` Matt Price @ 2018-11-22 22:37 ` Matt Price 2018-11-23 9:08 ` Matt Price 0 siblings, 1 reply; 7+ messages in thread From: Matt Price @ 2018-11-22 22:37 UTC (permalink / raw) To: Org Mode [-- Attachment #1: Type: text/plain, Size: 4504 bytes --] On Thu, Nov 22, 2018 at 4:06 PM Matt Price <moptop99@gmail.com> wrote: > > > On Thu, Nov 22, 2018 at 1:19 PM Matt Price <moptop99@gmail.com> wrote: > >> It would be nice for me to overlay the macro invocations with the values >> that they will evaluate to on export. I guess I would have to figure out >> when to trigger recalculation of the values (maybe not too often, say only >> when the macro is first created, when it's edited or deleted/deformed, and >> perhaps on structure editing. >> >> I do not understand emacs overlays very well so this feels a little >> daunting to me. Does anyone out there have ideas about how to do it >> effectively? >> >> > This is what I've come up with; it feels somewhat close but not quite > there yet. I can create, remove, and the overlays, which is great. What I > miss is the awesomeness of the way that overlays work with org links. I > love how the link target and the enclosing [[ ][ ]] are invisible until I > delete one of the "[" elements. However, with my code, the whole macro > expression {{{macroname}}} ius invisible until I delete the whole thing, at > which point the overlay helpfully disappears. Is htere a way to get > something like the link behaviour? > Oops! Here is the actual code (a bit long actually! Largely stolen from org source code). #+begin_src emacs-lisp (defun mwp-show-macros () (interactive) (remove-overlays (point-min) (point-max) 'macro-ov-p t) (save-excursion (goto-char (point-min)) ;; keeping this properties/keywordsstuff b/c I don't quite understand it (let* ((keywords nil) (properties-regexp (format "\\`EXPORT_%s\\+?\\'" (regexp-opt keywords))) record) (while (re-search-forward "{{{[-A-Za-z0-9_]" nil t) (unless (save-match-data (org-in-commented-heading-p)) (let* ((datum (save-match-data (org-element-context))) (type (org-element-type datum)) (macro (cond ((eq type 'macro) datum) ;; In parsed keywords and associated node ;; properties, force macro recognition. ((or (and (eq type 'keyword) (member (org-element-property :key datum) keywords)) (and (eq type 'node-property) (string-match-p properties-regexp (org-element-property :key datum)))) (save-excursion (goto-char (match-beginning 0)) (org-element-macro-parser)))))) (when macro (let* ((key (org-element-property :key macro)) (value (org-macro-expand macro org-macro-templates)) (begin (org-element-property :begin macro)) (end (save-excursion (goto-char (org-element-property :end macro)) (skip-chars-backward " \t") (point))) (signature (list begin macro (org-element-property :args macro)))) ;; Avoid circular dependencies by checking if the same ;; macro with the same arguments is expanded at the ;; same position twice. (cond ((member signature record) (error "Circular macro expansion: %s" key)) (value (push signature record) (let ((ov (make-overlay begin end))) (overlay-put ov 'invisible t) (overlay-put ov 'evaporate t) (overlay-put ov 'macro-ov-p t) (overlay-put ov 'before-string value ))) ;; Special "results" macro: if it is not defined, ;; simply leave it as-is. It will be expanded in ;; a second phase. ((equal key "results")) (t ;; (error "Undefined Org macro: %s; aborting" ;; (org-element-property :key macro)) ))))))))) (org-macro--counter-initialize) (setq-local mwp-macro-overlays t) ) (defun mwp-hide-macros () (interactive) (remove-overlays (point-min) (point-max) 'macro-ov-p t) (setq-local mwp-macro-overlays nil) ;; (cl-loop for o in (overlays-in (point-min) (point-max)) ;; if (overlay-get o 'macro-ov-p) ;; ()) ) (defun mwp-toggle-macros () (interactive) (if mwp-macro-overlays (mwp-hide-macros) (mwp-show-macros)) ) (defvar-local mwp-macro-overlays nil) #+end_src [-- Attachment #2: Type: text/html, Size: 6350 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: overlay showing computed value of macro? 2018-11-22 22:37 ` Matt Price @ 2018-11-23 9:08 ` Matt Price 2018-11-23 9:32 ` Eric S Fraga 0 siblings, 1 reply; 7+ messages in thread From: Matt Price @ 2018-11-23 9:08 UTC (permalink / raw) To: emacs-orgmode [-- Attachment #1: Type: text/plain, Size: 5848 bytes --] 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. [-- Attachment #2: Type: text/html, Size: 8004 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: overlay showing computed value of macro? 2018-11-23 9:08 ` Matt Price @ 2018-11-23 9:32 ` Eric S Fraga 2018-11-23 12:49 ` Matt Price 0 siblings, 1 reply; 7+ messages in thread From: Eric S Fraga @ 2018-11-23 9:32 UTC (permalink / raw) To: Matt Price; +Cc: emacs-orgmode Matt, you might like to have a look at how the n() macro was implemented as it has some similar goals. Check out org-macro-initialize-templates and org-macro--counter-increment. -- Eric S Fraga via Emacs 27.0.50, Org release_9.1.14-1035-gfeb442 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: overlay showing computed value of macro? 2018-11-23 9:32 ` Eric S Fraga @ 2018-11-23 12:49 ` Matt Price 2018-11-23 14:15 ` Eric S Fraga 0 siblings, 1 reply; 7+ messages in thread From: Matt Price @ 2018-11-23 12:49 UTC (permalink / raw) To: Org Mode [-- Attachment #1: Type: text/plain, Size: 454 bytes --] On Fri, Nov 23, 2018 at 4:32 AM Eric S Fraga <esflists@gmail.com> wrote: > Matt, > > you might like to have a look at how the n() macro was implemented as it > has some similar goals. Check out org-macro-initialize-templates and > org-macro--counter-increment. > ah. no stupid searching backwards through the buffer. just track everyting in a variable. that... is smarter. > -- > Eric S Fraga via Emacs 27.0.50, Org release_9.1.14-1035-gfeb442 > [-- Attachment #2: Type: text/html, Size: 916 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: overlay showing computed value of macro? 2018-11-23 12:49 ` Matt Price @ 2018-11-23 14:15 ` Eric S Fraga 0 siblings, 0 replies; 7+ messages in thread From: Eric S Fraga @ 2018-11-23 14:15 UTC (permalink / raw) To: Matt Price; +Cc: Org Mode On Friday, 23 Nov 2018 at 07:49, Matt Price wrote: > ah. no stupid searching backwards through the buffer. just track > everyting in a variable. > > that... is smarter. I hadn't looked to see how it was done but I do know that I can usually learn something from what Nicolas has done! -- Eric S Fraga via Emacs 27.0.50, Org release_9.1.14-1035-gfeb442 ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2018-11-23 14:15 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2018-11-22 18:19 overlay showing computed value of macro? Matt Price 2018-11-22 21:06 ` Matt Price 2018-11-22 22:37 ` Matt Price 2018-11-23 9:08 ` Matt Price 2018-11-23 9:32 ` Eric S Fraga 2018-11-23 12:49 ` Matt Price 2018-11-23 14:15 ` Eric S Fraga
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.