[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/denote 6bb6da0882 1/6: feat: project.el integration & b
From: |
ELPA Syncer |
Subject: |
[elpa] externals/denote 6bb6da0882 1/6: feat: project.el integration & backlinks refactoring with xref |
Date: |
Mon, 21 Nov 2022 22:57:30 -0500 (EST) |
branch: externals/denote
commit 6bb6da088211324cdd1ad35396c2988ccb2eccb7
Author: Noboru Ota <me@nobiot.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>
feat: project.el integration & backlinks refactoring with xref
The main intent of the patch is as follows:
- To simplify the implementations of functions related to backlinks that
rely on the Xref library
- To add minimal implementations to integrate Denote with project.el
This is necessary for simplification of Xref/backlinks mentioned
above.
It has given an opportunity to refactor 'denote-file-prompt' to let
you search notes under all sub-directories of 'denote-directory'. The
original 'read-file-name' could only search within only single
'denote-directory'.
This enhances the following commands: 'denote-open-or-create',
'denote-link', 'denote-link-or-create', and 'denote-link-ol-complete'.
The project.el integration also lets users set something like this
below in their configuration. This way, they can generically use
project.el facilities for Denote such as 'project-find-file' and
'project-find-regexp' without a version management tool (e.g. Git)
(add-hook 'project-find-functions #'denote-project-find)
Following is more detail of changes for each function:
* denote.el
(denote-file-prompt): Refactored
- To use the same completion function as 'project-find-file' does.
- The main benefit is that it can let you search notes under all
sub-directories of 'denote-directory'. The original 'read-file-name'
could only search within only single 'denote-directory'
- Note the impact on commands that use 'denote-file-prompt';
i.e. 'denote-open-or-create', 'denote-link', 'denote-link-or-create',
and 'denote-link-ol-complete'
- One minor annoyance may be that the prompt now requires a confirmation
if the user enters text that does not match any of the candidate and
tries to exit
- 'denote--title-history' is directly updated from the minibuffer
completion function. This eliminates the need for
'denote--push-extracted-title-to-history'. The original used
'file-name-history' as the intermediate storage of titles, which are
not really file names, thus resulted in polluting the history for file
names
(denote--retrieve-xrefs): Removed
- No longer used. It was only used by 'denote--retrieve-process-grep',
which has now been removed.
(denote--retrieve-files-in-xrefs): Refactored
- To take IDENTIFIER as the argument. No change to the returned
values. This is for this function to be compatible with the removal of
'denote--retrieve-xrefs'. Retrieving files do not need to use the
intermediate xref-alist, which is a duplicate of work. This change
lets this function directly retrieve file name (group) from xrefs (not
xref-alist) with using Xref public methods
(denote--retrieve-process-grep): Removed
- No longer used. It was only used by 'denote-link--prepare-backlinks'
to retrieve xref-alist for the purpose of creating the backlinks
buffer. Creation of the backlinks buffer has now been refactored to
get closer to the built-in Xref. See 'denote-link-find-backlink' and
'denote-link--prepare-backlinks'
(denote--push-extracted-title-to-history): Removed
- No longer used. See commit message fro 'denote-file-prompt' above
(denote-open-or-create): Refactored
- To not use 'denote--push-extracted-title-to-history', which has been
removed
(denote-link-find-backlink): Refactored
- To not use 'denote--retrieve-xrefs', which has been removed
(denote-link-or-create): Refactored
- To not use 'denote--push-extracted-title-to-history', which has been
removed
(denote-backlinks-mode): Refactored
- To locally set 'denote-project-find'. This is be compatible with the
new project.el integration. The change is necessary for the backlinks
buffer to correctly revert by identifying the denote project root
(denote-link--prepare-backlinks): Refactored
- To set the correct revert function with using the new way
(denote-link-backlinks): Refactored
- To use 'xref--show-xrefs' to create and show backlinks buffer. The
double-hyphen in the name 'xref--show-xrefs' suggests it is a private
function; however, in the current development branch of Xref, there is
a new public function 'xref-show-xrefs'. It is a wrapper function
with the same arguments used in this patch, thus we are further
aligning Denote with the direction of Xref development
(project-root): (project-files): (denote-project-find): Added
- These are Denote specific implementations of generic functions defined
in project.el and a function for a hook to let Denote use them. This
patch contains many built-in Xref functions, which rely on project.el
to identify the "root" of the project. Denote explicitly defines its
root with 'denote-directory'. These newly created methods and function
connect Denote and project.el generic. This way, users without a
version management tool (e.g. Git) for their notes can benefit from
project.el. See one of such major benefits with 'denote-file-prompt'
and the related Denote commands above.
- This change also let users set something like this below in their
configuration to generically use project.el facilities such as
'project-find-file'.
(add-hook 'project-find-functions #'denote-project-find)
* denote-org-dblock.el
(org-dblock-write:denote-backlinks): Refactored
- To align with the change in 'denote--retrieve-files-in-xrefs' as
above
---
denote-org-dblock.el | 3 +-
denote.el | 155 ++++++++++++++++++++++++++-------------------------
2 files changed, 80 insertions(+), 78 deletions(-)
diff --git a/denote-org-dblock.el b/denote-org-dblock.el
index ce1026ab65..0f10456a1d 100644
--- a/denote-org-dblock.el
+++ b/denote-org-dblock.el
@@ -139,8 +139,7 @@ Used by `org-dblock-update' with PARAMS provided by the
dynamic block."
Used by `org-dblock-update' with PARAMS provided by the dynamic block."
(when-let* ((file (buffer-file-name))
(id (denote-retrieve-filename-identifier file))
- (files (denote--retrieve-files-in-xrefs
- (denote--retrieve-process-grep id))))
+ (files (delete file (denote--retrieve-files-in-xrefs id)))))
(insert (denote-link--prepare-links files file nil))
(join-line))) ;; remove trailing empty line
diff --git a/denote.el b/denote.el
index a6c26fe7d1..b472d207d7 100644
--- a/denote.el
+++ b/denote.el
@@ -719,10 +719,13 @@ whatever matches `denote-excluded-directories-regexp'."
(defun denote-file-prompt (&optional initial-text)
"Prompt for file with identifier in variable `denote-directory'.
With optional INITIAL-TEXT, use it to prepopulate the minibuffer."
- (read-file-name "Select note: " (denote-directory) nil nil initial-text
- (lambda (f)
- (or (denote-file-has-identifier-p f)
- (denote-file-directory-p f)))))
+ (let* ((project-find-functions #'denote-project-find)
+ (project (project-current nil (denote-directory)))
+ (dirs (list (project-root project)))
+ (all-files (project-files project dirs))
+ (completion-ignore-case read-file-name-completion-ignore-case))
+ (funcall project-read-file-name-function
+ "Select note: " all-files nil 'denote--title-history
initial-text)))
(define-obsolete-function-alias
'denote--retrieve-read-file-prompt
@@ -1245,50 +1248,16 @@ Run `denote-desluggify' on title if the extraction is
sucessful."
title
(denote-retrieve-filename-title file)))
-(defun denote--retrieve-xrefs (identifier &optional file)
- "Return xrefs of IDENTIFIER in variable `denote-directory'.
-The xrefs are returned as an alist of the form:
-
- ((GROUP . (XREF ...)) ...)
-
-GROUP is an absolute file name as retrieved by Xref facility.
-
-When FILE is present, remove its GROUP from the alist."
- (let ((alist
- (xref--alistify
- (xref-matches-in-files identifier (denote-directory-text-only-files))
- (lambda (x)
- (xref-location-group (xref-item-location x))))))
- (if file (assoc-delete-all file alist) alist)))
-
-(defun denote--retrieve-files-in-xrefs (xref-alist)
- "Return sorted, deduplicated file names from XREF-ALIST."
+(defun denote--retrieve-files-in-xrefs (identifier)
+ "Return sorted, deduplicated file names from IDENTIFIER."
(sort
- (delete-dups (mapcar #'car xref-alist))
+ (delete-dups
+ (mapcar #'xref-location-group
+ (mapcar #'xref-match-item-location
+ (xref-matches-in-files identifier
+
(denote-directory-text-only-files)))))
#'string-lessp))
-(defun denote--retrieve-process-grep (identifier)
- "Process lines matching IDENTIFIER and return list of xref-alist.
-
-The alist is of the form ((GROUP . (XREF ...)) ...).
-
-The alist excludes GROUP for the file that current buffer is
-visiting so that only its backlinks are colleced.
-
-In addition, GROUP is a transformed to filename relative to
-variable `denote-directory', which is the string displayed in the
-backlinks' buffer."
- ;;; This `mapcar' form is doing what function `xref--analyze' would
- ;;; do. `xref--analyze' can be flexibly configured but is not used
- ;;; directly here because it assumes that the current directory is in
- ;;; a "project" as defined in project.el. For Denote, this is not the
- ;;; case (at least as at the time of this writing).
- (mapcar
- (lambda (xref)
- (cons (denote-get-file-name-relative-to-denote-directory (car xref))
- (cdr xref)))
- (denote--retrieve-xrefs identifier (buffer-file-name))))
-
;;;; New note
;;;;; Common helpers for new notes
@@ -1726,13 +1695,6 @@ set to \\='(template title keywords)."
(string-match (denote-directory) title)
(substring title (match-end 0))))
-(defun denote--push-extracted-title-to-history ()
- "Add `denote--extract-title-from-file-history' to `denote--title-history'."
- (when-let* ((last-input (denote--extract-title-from-file-history))
- ((not (string-empty-p last-input)))
- ((not (string-blank-p last-input))))
- (push last-input denote--title-history)))
-
;;;###autoload
(defun denote-open-or-create (target)
"Visit TARGET file in variable `denote-directory'.
@@ -1747,7 +1709,6 @@ note's actual title. At the `denote-title-prompt' type
(interactive (list (denote-file-prompt)))
(if (file-exists-p target)
(find-file target)
- (denote--push-extracted-title-to-history)
(call-interactively #'denote)))
;;;###autoload
@@ -2635,9 +2596,7 @@ Like `denote-link-find-file', but select backlink to
follow."
(interactive)
(if-let* ((file (buffer-file-name))
(id (denote-retrieve-filename-identifier file))
- (files
- (denote--retrieve-files-in-xrefs
- (denote--retrieve-xrefs id (buffer-file-name)))))
+ (files (delete file (denote--retrieve-files-in-xrefs id))))
(find-file
(denote-get-path-by-id
(denote-extract-id-from-string
@@ -2694,7 +2653,6 @@ file's title. This has the same meaning as in
`denote-link'."
(interactive (list (denote-file-prompt) current-prefix-arg))
(if (file-exists-p target)
(denote-link target id-only)
- (denote--push-extracted-title-to-history)
(call-interactively #'denote-link-after-creating)))
(defalias 'denote-link-to-existing-or-new-note (symbol-function
'denote-link-or-create))
@@ -2823,24 +2781,37 @@ nil)."
(define-derived-mode denote-backlinks-mode xref--xref-buffer-mode "Backlinks"
"Major mode for backlinks buffers."
(unless denote-backlinks-show-context
- (font-lock-add-keywords nil denote-faces-file-name-keywords-for-backlinks
t)))
+ (font-lock-add-keywords nil denote-faces-file-name-keywords-for-backlinks
t))
+ (add-hook 'project-find-functions #'denote-project-find nil t))
(make-obsolete-variable 'denote-backlink-mode 'denote-backlinks-mode "0.6.0")
-(defun denote-link--prepare-backlinks (id xref-alist &optional title)
- "Create backlinks' buffer for ID using XREF-ALIST.
-Use optional TITLE for a prettier heading."
- (let ((inhibit-read-only t)
- (buf (format "*denote-backlinks to %s*" id))
- (file (buffer-file-name)))
+(defun denote-link--prepare-backlinks (fetcher _alist)
+ "Create backlinks' buffer for the current note.
+FETCHER is a function that fetches a list of xrefs. It is called
+with `funcall' with no argument like `xref--fetcher'.
+
+In the case of `denote', `apply-partially' is used to create a
+function that has already applied another function to multiple
+arguments.
+
+ALIST is not used in favour of using
+`denote-link-backlinks-display-buffer-action'."
+ (let* ((inhibit-read-only t)
+ (file (buffer-file-name))
+ (file-type (denote-filetype-heuristics file))
+ (id (denote-retrieve-filename-identifier file))
+ (buf (format "*denote-backlinks to %s*" id))
+ (xref-alist (xref--analyze (funcall fetcher))))
(with-current-buffer (get-buffer-create buf)
(setq-local default-directory (denote-directory))
(erase-buffer)
+ (setq overlay-arrow-position nil)
(denote-backlinks-mode)
(goto-char (point-min))
- (when-let* ((title)
- (heading (format "Backlinks to %S (%s)" title id))
- (l (length heading)))
+ (when-let* ((title (denote-retrieve-title-value file file-type))
+ (heading (format "Backlinks to %S (%s)" title id))
+ (l (length heading)))
(insert (format "%s\n%s\n\n" heading (make-string l ?-))))
(if denote-backlinks-show-context
(xref--insert-xrefs xref-alist)
@@ -2852,9 +2823,11 @@ Use optional TITLE for a prettier heading."
(goto-char (point-min))
(setq-local revert-buffer-function
(lambda (_ignore-auto _noconfirm)
- (when-let ((buffer-file-name file)
- (xref-alist (denote--retrieve-process-grep id)))
- (denote-link--prepare-backlinks id xref-alist title)))))
+ (when-let ((buffer-file-name file))
+ (denote-link--prepare-backlinks
+ (apply-partially #'xref-matches-in-files id
+ (delete file
(denote-directory-text-only-files)))
+ nil)))))
(denote-link--display-buffer buf)))
;;;###autoload
@@ -2875,12 +2848,14 @@ default, it will show up below the current window."
(let ((file (buffer-file-name)))
(when (denote-file-is-writable-and-supported-p file)
(let* ((id (denote-retrieve-filename-identifier file))
- (file-type (denote-filetype-heuristics file))
- (title (denote-retrieve-title-value file file-type)))
- (if-let ((xref-alist (denote--retrieve-process-grep id)))
- (progn (xref--push-markers)
- (denote-link--prepare-backlinks id xref-alist title))
- (user-error "No links to the current note"))))))
+ (xref-show-xrefs-function #'denote-link--prepare-backlinks)
+ (project-find-functions #'denote-project-find))
+ (xref--show-xrefs
+ (apply-partially #'xref-matches-in-files id
+ ;; remove the current buffer file from the
+ ;; backlinks
+ (delete file (denote-directory-text-only-files)))
+ nil)))))
(defalias 'denote-link-show-backlinks-buffer (symbol-function
'denote-link-backlinks))
@@ -3181,5 +3156,33 @@ Consult the manual for template samples."
(make-obsolete 'denote-migrate-old-org-filetags nil "1.1.0")
(make-obsolete 'denote-migrate-old-markdown-yaml-tags nil "1.1.0")
+
+;;;; project.el integration
+;; This is also used by xref integration
+
+(cl-defmethod project-root ((project (head denote)))
+ "Denote's implementation of `project-root' method from `project'.
+Return current variable `denote-directory' as the root of the
+current denote PROJECT."
+ (cdr project))
+
+(cl-defmethod project-files ((_project (head denote)) &optional _dirs)
+ "Denote's implementation of `project-files' method from `project'.
+Return all files that have an identifier for the current denote
+PROJECT. The return value may thus include file types that are
+not implied by `denote-file-type'. To limit the return value to
+text files, use the function `denote-directory-text-only-files'."
+ (denote-directory-files))
+
+(defun denote-project-find (dir)
+ "Return project instance if DIR is part of variable `denote-directory'.
+The format of project instance is aligned with `project-try-vc'
+defined in `project'."
+ (let ((dir (expand-file-name dir)) ; canonicalize current directory name
+ (root (denote-directory)))
+ (when (or (file-equal-p dir root) ; currently at `denote-directory'
+ (string-prefix-p root dir)) ; or its subdirectory
+ (cons 'denote root))))
+
(provide 'denote)
;;; denote.el ends here
- [elpa] externals/denote updated (69824125b9 -> 0665a1e367), ELPA Syncer, 2022/11/21
- [elpa] externals/denote 3e074afb4b 2/6: feat: follow-symlinks, ELPA Syncer, 2022/11/21
- [elpa] externals/denote 22829d8541 5/6: Remove reference to non-existing function, ELPA Syncer, 2022/11/21
- [elpa] externals/denote 93971de099 3/6: fix: denote-get-path-by-id to send only denote notes file, ELPA Syncer, 2022/11/21
- [elpa] externals/denote 6bb6da0882 1/6: feat: project.el integration & backlinks refactoring with xref,
ELPA Syncer <=
- [elpa] externals/denote 0a94f3e3c3 4/6: feat: xref-backend facility to enable xref integration, ELPA Syncer, 2022/11/21
- [elpa] externals/denote 0665a1e367 6/6: Merge branch 'xref-refinement-project-integration', ELPA Syncer, 2022/11/21