field_thought_slight

joined 1 year ago
 

When debugging some code, I learned that if you call pop-to-buffer and pop-to-buffer-same-window inside save-excursion or save-current-buffer, the original buffer will not be restored at the end of the save-. You can get around this by using save-window-excursion; however, I still feel like save-excursion ought to work. Does anyone know why it doesn't?

(You can check this by eval-ing the following in any buffer other than *Messages*: (save-excursion (pop-to-buffer-same-window "*Messages*")).

 

When debugging some code, I learned that if you call pop-to-buffer and pop-to-buffer-same-window inside save-excursion or save-current-buffer, the original buffer will not be restored at the end of the save-. You can get around this by using save-window-excursion; however, I still feel like save-excursion ought to work. Does anyone know why it doesn't?

(You can check this by eval-ing the following in any buffer other than *Messages*: (save-excursion (pop-to-buffer-same-window "*Messages*")).

[–] field_thought_slight@alien.top 1 points 11 months ago

It's a dealbreaker for certain applications (e.g., window management). It's not a dealbreaker for Emacs as a whole.

Actually, to be clear: most of the pain is with blocking I/O. But Emacs does have support for asynchronous I/O. The problem is that there is too much code that uses blocking I/O rather than asynchronous I/O.

[–] field_thought_slight@alien.top 1 points 11 months ago

In that case, if you have a new version of an old node, in that case you just write a new one. You can just start at the very beginning of that node to refer back to the old nodes.

If you keep your notes in version control, you can achieve a similar effect with git-auto-commit-mode.

[–] field_thought_slight@alien.top 1 points 11 months ago (1 children)

I use org-roam-timestamps; but, as you say, there are no query functions.

If you have org-roam-timestamps and just want to answer the question "which nodes did I modify on a given day", I think it would be very easy to write a function for that. But I don't think there's any harm in duplicating that data in the daily log, either.

 

I found myself wanting to automatically keep a log of every org-roam entry I work on. After struggling with the capture system for a while, I managed to make something work.

(setf (alist-get "u" org-roam-dailies-capture-templates nil nil #'equal)
      '("updated" plain nil
        :target (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n" ("Updated"))
        :unnarrowed t :prepend t))

(defmacro +save-current-buffer (&rest body)
  "Save current buffer; execute BODY; restore original buffer.
I have found that this macro works under some circumstances in
which ‘save-current-buffer’ does not."
  (declare (indent 0))
  `(let ((original-buffer (current-buffer)))
     (unwind-protect (progn ,@body)
       (when (buffer-name original-buffer)
         (switch-to-buffer original-buffer)))))

(defmacro +edit-to-string (&rest body)
  "Eval BODY in a temporary buffer and extract contents to a string."
  (declare (indent 0))
  `(with-temp-buffer
     ,@body
     (buffer-string)))

(defun +org-element-contents (element)
  "Extract contents of ELEMENT from current buffer."
  (buffer-substring (org-element-property :contents-begin element)
                    (org-element-property :contents-end element)))

(defun +org-roam-updated-on-save ()
  "Log current Org-roam buffer as modified."
  (when (org-roam-buffer-p)
    (let* ((original-buffer (current-buffer))
           (id (org-id-get (point-min)))
           (title (org-get-title))
           (link-text (format "%s\n" (+edit-to-string
                                       (org-insert-link nil id title)))))
      (save-excursion  ;; in case we are currently editing the daily note
        (+save-current-buffer
         (org-roam-dailies-goto-today "u")
         (unless (eq original-buffer (current-buffer))
           (let ((elt (org-element-context)))
             (if (not (eq 'plain-list (org-element-type elt)))
                 (insert "\n- " link-text)
               (org-down-element)
               (cl-loop
                for elt = (org-element-context)
                while (eq 'item (org-element-type elt))
                if (equal link-text (+org-element-contents elt)) return nil
                do (org-forward-element)
                finally (insert "- " link-text))))))))))

(add-hook 'after-save-hook #'+org-roam-updated-on-save)

I originally tried to do this using just capture templates (i.e., just an interpolated Lisp expression, no wrapper code), but I'm not sure that that's possible due to some flexibility problems with the Org-roam capture system.

One thing I'm not happy about is having to use my weird homespun +save-current-buffer macro, but the original save-current-buffer macro doesn't switch back for some reason.

I am kind of? happy about having gotten some experience with the loop macro. I'm still not sure I like it, but I understand better why it exists in a language that doesn't have other, more structure looping facilities.

 

I'm wondering if there's any way to make a variable automatically save its old value, so that I can, e.g., write a minor mode that will automatically restore the old values of variables when it's deactivated (without having to declare a bunch of -old-value variables).

What is wrong with just using org-roam?