diff --git a/.dir-locals.el b/.dir-locals.el index e0b6061..e526e3b 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -10,5 +10,4 @@ (org-with-point-at . 1) (magit-insert-section . defun) (magit-section-case . 0) - (->> . 1) (org-roam-with-file . 2))))) diff --git a/org-roam-mode.el b/org-roam-mode.el index 6646ebb..ca72415 100644 --- a/org-roam-mode.el +++ b/org-roam-mode.el @@ -48,6 +48,30 @@ Normally this node is `org-roam-buffer-current-node'." :group 'org-roam :type 'hook) +(defcustom org-roam-buffer-postrender-functions (list) + "Functions to run after the Org-roam buffer is rendered. +Each function accepts no arguments, and is run with the Org-roam +buffer as the current buffer." + :group 'org-roam + :type 'hook) + +(defcustom org-roam-preview-function #'org-roam-preview-default-function + "The preview function to use to populate the Org-roam buffer. + +The function takes no arguments, but the point is temporarily set +to the exact location of the backlink." + :group 'org-roam + :type 'function) + +(defcustom org-roam-preview-postprocess-functions (list #'org-roam-strip-comments) + "A list of functions to postprocess the preview content. + +Each function takes a single argument, the string for the preview +content, and returns the post-processed string. The functions are +applied in order of appearance in the list." + :group 'org-roam + :type 'hook) + ;;; Faces (defface org-roam-header-line `((((class color) (background light)) @@ -205,6 +229,7 @@ buffer." (magit-insert-section (org-roam) (magit-insert-heading) (run-hook-with-args 'org-roam-mode-section-functions org-roam-buffer-current-node)) + (run-hooks org-roam-buffer-postrender-functions) (goto-char 0))) (defun org-roam-buffer-set-header-line-format (string) @@ -398,81 +423,27 @@ In interactive calls OTHER-WINDOW is set with (when (org-invisible-p) (org-show-context)) buf)) +(defun org-roam-preview-default-function () + "Return the preview content at point. + +This function returns the all contents under the current +headline, up to the next headline." + (let ((beg (progn (org-roam-end-of-meta-data t) + (point))) + (end (progn (org-next-visible-heading 1) + (point)))) + (string-trim (buffer-substring-no-properties beg end)))) + (defun org-roam-preview-get-contents (file pt) "Get preview content for FILE at PT." (save-excursion (org-roam-with-temp-buffer file (org-with-wide-buffer (goto-char pt) - (let ((beg (progn (org-roam-end-of-meta-data t) - (point))) - (end (progn (org-next-visible-heading 1) - (point)))) - (string-trim (buffer-substring-no-properties beg end))))))) - -(defun org-roam-preview-get-entry-text (marker n-lines &optional indent) - "Extract entry text from MARKER, at most N-LINES lines. -This will ignore drawers etc, just get the text. -If INDENT is given, prefix every line with this string." - (let (txt ind) - (save-excursion - (with-current-buffer (marker-buffer marker) - (if (not (derived-mode-p 'org-mode)) - (setq txt "") - (org-with-wide-buffer - (goto-char marker) - (end-of-line 1) - (setq txt (buffer-substring - (min (1+ (point)) (point-max)) - (progn (outline-next-heading) (point)))) - (with-temp-buffer - (insert txt) - (goto-char (point-min)) - (while (org-activate-links (point-max)) - (goto-char (match-end 0))) - (goto-char (point-min)) - (while (re-search-forward org-link-bracket-re (point-max) t) - (set-text-properties (match-beginning 0) (match-end 0) - nil)) - (goto-char (point-min)) - (while (re-search-forward org-drawer-regexp nil t) - (delete-region - (match-beginning 0) - (progn (re-search-forward - "^[ \t]*:END:.*\n?" nil 'move) - (point)))) - (goto-char (point-min)) - (goto-char (point-max)) - (skip-chars-backward " \t\n") - (when (looking-at "[ \t\n]+\\'") (replace-match "")) - - ;; find and remove min common indentation - (goto-char (point-min)) - (untabify (point-min) (point-max)) - (setq ind (current-indentation)) - (while (not (eobp)) - (unless (looking-at "[ \t]*$") - (setq ind (min ind (current-indentation)))) - (beginning-of-line 2)) - (goto-char (point-min)) - (while (not (eobp)) - (unless (looking-at "[ \t]*$") - (move-to-column ind) - (delete-region (point-at-bol) (point))) - (beginning-of-line 2)) - (goto-char (point-min)) - (when indent - (while (and (not (eobp)) (re-search-forward "^" nil t)) - (replace-match indent t t))) - (goto-char (point-min)) - (while (looking-at "[ \t]*\n") (replace-match "")) - (goto-char (point-max)) - (when (> (org-current-line) - n-lines) - (org-goto-line (1+ n-lines)) - (backward-char 1)) - (setq txt (buffer-substring (point-min) (point)))))))) - txt)) + (let ((s (funcall org-roam-preview-function))) + (dolist (fn org-roam-preview-postprocess-functions) + (setq s (funcall fn s))) + s))))) ;;;; Backlinks (cl-defstruct (org-roam-backlink (:constructor org-roam-backlink-create) diff --git a/org-roam-utils.el b/org-roam-utils.el index 832c5eb..ec0999b 100644 --- a/org-roam-utils.el +++ b/org-roam-utils.el @@ -49,8 +49,8 @@ (defun org-roam-quote-string (s) "Quotes string S." (->> s - (org-roam-replace-string "\\" "\\\\") - (org-roam-replace-string "\"" "\\\""))) + (org-roam-replace-string "\\" "\\\\") + (org-roam-replace-string "\"" "\\\""))) (defun org-roam-string-equal (s1 s2) "Return t if S1 and S2 are equal. @@ -59,6 +59,17 @@ Like `string-equal', but case-insensitive." (or (string-equal s1 s2) (string-equal (downcase s1) (downcase s2))))) +(defun org-roam-strip-comments (s) + "Strip Org comments from string S." + (with-temp-buffer + (insert s) + (goto-char (point-min)) + (while (not (eobp)) + (if (org-at-comment-p) + (delete-region (point-at-bol) (progn (forward-line) (point))) + (forward-line))) + (buffer-string))) + ;;; List utilities (defun org-roam-plist-map! (fn plist) "Map FN over PLIST, modifying it in-place and returning it.