0

From agenda view, is it possible to execute functions on specific .org files?

Example setup: foo.org and bar.org are source files for agenda

Example working function from : Sort entire hierarchy in an Org mode buffer

(defun sort-all-org-entries ()
  (interactive)
  (let ((fun #'(lambda nil
                 (condition-case nil
                     (org-sort-entries nil ?d)
                   (user-error t)))))
    (org-map-entries fun)))
(add-hook 'org-agenda-mode-hook 
    (lambda()
        (local-set-key (kbd "g") 'sort-all-org-entries)))

The example function sort-all-org-entries works correctly if M-x sort-all-org-entries is activated in the buffer for either foo.org or bar.org.

However, when g is pressed in the agenda buffer, the function is presumably executed only in the agenda as it presumably does not have a target .org file.

edit

Is there a way to define g to execute sort-all-org-entries at the beginning of foo.org, even though g is activated from the agenda buffer?

6
  • 1
    You are not asking anything different than what you asked in your other question and so the answer remains the same: even if you can determine that the entry in the agenda came from foo.org (which I'm sure you can), you also need to somehow tell it WHERE in that buffer to execute the function. You have added nothing here to specify that crucial piece of information.
    – NickD
    Sep 17, 2021 at 23:47
  • Does this answer your question? Org Mode: Sort specific tree and refresh agenda
    – NickD
    Sep 17, 2021 at 23:47
  • The other question was location dependent for activation of the function, as the result would change depending on pointer location within the buffer relative. This question is an attempt to be more generic with functions that execute similarly regardless of pointer position. For simplicity, I edited to execute at the beginning of the buffer if location is specified.
    – XLIII
    Sep 19, 2021 at 14:57
  • It's still location dependent if I judge from your answer: your answer does not necessarily execute the function at the beginning of the buffer. Instead, it depends on the position you were at, before switching to the agenda to call the function.
    – NickD
    Sep 23, 2021 at 12:29
  • Based on testing, the sorting code appears to sort a tree correctly, whether point was at the beginning of the buffer before the tree or at the end of the buffer, after the sort tree.
    – XLIII
    Sep 24, 2021 at 19:41

1 Answer 1

1

Edit: New solution based on comment recommendations

with-current-buffer is a useful command for temporarily working within a buffer. This can be used to execute the function without leaving the agenda buffer.

(defun sort-all-org-entries ()
  (interactive)
  (with-current-buffer "foo.org" 
    (let ((fun #'(lambda nil
                 (condition-case nil
                     (org-sort-entries nil ?d)
                   (user-error t)))))
    (org-map-entries fun)) 
  (org-agenda-redo())) 
(add-hook 'org-agenda-mode-hook 
    (lambda()
        (local-set-key (kbd "g") 'sort-all-org-entries)))

Following code also works, but is susceptible to errors as detailed in comments.

switch-to-buffer allows selection of a buffer. However, intended use is not for temporary functions.

(defun sort-all-org-entries ()
  (interactive)
  (switch-to-buffer "foo.org") ## active buffer to execute function
  (let ((fun #'(lambda nil
                 (condition-case nil
                     (org-sort-entries nil ?d)
                   (user-error t)))))
    (org-map-entries fun))
   (switch-to-buffer())  ## returns to previous buffer (agenda)
   (org-agenda-redo())) ## refreshes agenda to reflect function effect
(add-hook 'org-agenda-mode-hook 
    (lambda()
        (local-set-key (kbd "g") 'sort-all-org-entries)))
6
  • switch-to-buffer is not the way to do that - see its doc string with C-h f switch-to-buffer which says: WARNING: This is NOT the way to work on another buffer temporarily within a Lisp program! Use ‘set-buffer’ instead. That avoids messing with the window-buffer correspondences.. I advocated for with-current-buffer in my answer to your original question.
    – NickD
    Sep 23, 2021 at 12:21
  • You still have the problem I mentioned in my comment to your question: switching to the buffer and running the sorting code depends on where in the buffer you were before switching to the agenda and pressing g. If point was at the beginning, your function would behave as you expect, but if point was anywhere else, that's where your function would be applied after the switch-to-buffer producing unpredictable and unexpected results.
    – NickD
    Sep 23, 2021 at 12:26
  • I misunderstood the use of 'with-current-buffer'. It's use should be more elegant as the buffer work is designed to be temporary. However replacement of (switch-to-buffer "foo.org") with (with-current-buffer "foo.org") does not work. I am currently troubleshooting the correct use of with-current-buffer.
    – XLIII
    Sep 24, 2021 at 19:49
  • My second comment above does not apply in this case (as you pointed out in your last comment under the question) because you are calling org-map-entries without a matcher. That makes it apply the function to every headline in the buffer. My comment would apply if you limited the matcher so that it would only match e.g the current subtree. In that case, the position is important.
    – NickD
    Sep 24, 2021 at 19:54
  • The usage of with-current-buffer (check with C-h f with-current-buffer) is (with-current-buffer BUFFER-OR-NAME &rest BODY) where the BODY is the lisp code that you want to execute in the context of that buffer (in your case, the (let ..) form that defines the auxiliary function and calls org-map-entry with it).
    – NickD
    Sep 24, 2021 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.