emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/denote 8e6e2736dc 174/355: Add generic denote-link-find


From: ELPA Syncer
Subject: [elpa] externals/denote 8e6e2736dc 174/355: Add generic denote-link-find-file
Date: Sun, 26 Jun 2022 23:58:20 -0400 (EDT)

branch: externals/denote
commit 8e6e2736dcc539f54a87879dd0908e76962fa2cd
Author: Protesilaos Stavrou <info@protesilaos.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>

    Add generic denote-link-find-file
---
 README.org     |  84 +++++++++++++++++++++-----------------------
 denote-link.el | 108 +++++++++++++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 132 insertions(+), 60 deletions(-)

diff --git a/README.org b/README.org
index 5484472d84..fe38dfa360 100644
--- a/README.org
+++ b/README.org
@@ -540,55 +540,49 @@ participate in the development of Denote.
 :CUSTOM_ID: h:fc913d54-26c8-4c41-be86-999839e8ad31
 :END:
 
-The linking facility is subject to review and there will likely be
-breaking changes.  This is the only area that needs to be fixed before
-we release the first stable version of the package.  *What follows is
-not up-to-date as of 2022-06-14 17:01 +0300.*
+*The linking facility is the area that needs refinements before
+releasing the first stable version of Denote.*
+
+Denote aims to have a simple-yet-effective linking facility to quickly
+establish connections between notes.
 
 #+findex: denote-link
-Denote has a basic linking facility to quickly establish connections
-between notes.  The command ~denote-link~ prompts for a file name in the
-~denote-directory~ (only regular files are considered, not directories).
-It then retrieves the path of the given note, inserts it at point using
-the appropriate link notation, and creates a backlink entry in the
-target file (again using the appropriate notation).
+The command ~denote-link~ prompts for a file in the ~denote-directory~
+(only regular files are considered, not directories).  It then retrieves
+the identifier of the given note and inserts it at point using the
+appropriate link notation.
 
 What constitutes "appropriate link notation" depends on the file type of
-the given entry per ~denote-file-type~ 
([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file naming scheme]]).  For
-example when linking from an Org file to a Markdown file, the link in
-the former will follow Org syntax while the backlink in the latter will
-use that of Markdown.  Org links use =[[file:TARGET][DESCRIPTION]]=,
-those of Markdown are =[DESCRIPTION](file:TARGET)=, while for plain text
-we implement our own scheme of =<TYPE: TARGET> [DESCRIPTION]=, where
-=TYPE= is either =LINK= or =BACKLINK= (capitalization in the latter two
-is literal, because plain text lacks other means of emphasis).
-
-Plain text links can benefit from Emacs' notion of "future history",
-else its ability to read the thing at point for relevant commands.  With
-point over the =TARGET=, =M-x find-file= followed by =M-n= will fill the
-path to that file (this also works with point over just the identifier
-of a note).
-
-#+vindex: denote-link-insert-functions
-#+findex: denote-link-backlink
-Backlinks are optionally recorded at the end of a note under the heading
-with the title =Denote backlinks=.  This is an opt-in feature that has
-to be set up by adding ~denote-link-backlinks~ to the special hook
-~denote-link-insert-functions~.
-
-The reason backlinks are off by default is because we might still make
-breaking changes on how they are implemented.  For the time being,
-Denote expects that users do not edit the section with the backlinks: it
-is controlled by Denote, such as to delete duplicate links (in the
-future it might also handle stuff like alphabetic sorting).  Suggestions
-to improve backlinking are most welcome!
-
-The section with the backlinks is formatted according to the note's file
-type.
-
-#+findex: denote-link-clear-stale-backlinks
-Backlinks that no longer point to available notes can be removed from
-the current buffer with the command ~denote-link-clear-stale-backlinks~.
+the given entry, per ~denote-file-type~ 
([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file naming scheme]]):
+
++ Org: =[[denote:IDENTIFIER][TITLE]]=
++ Markdown: =[TITLE](denote:IDENTIFIER)=
++ Plain text: =[[IDENTIFIER] [TITLE]]=
+
+The special specifier =denote:= is experimental.  The idea is to reserve
+for possible integration with Org/Markdown, though we might switch to
+another method.
+
+As a general feature of Emacs, any identifier that appears in a note,
+can be expanded into the corresponding file name at the same directory
+by leveraging Emacs' notion of "future history" (predicting what the
+user wants).  With point over the identifier, =M-x find-file= followed
+by =M-n= will fill the path to that file.
+
+#+findex: denote-link-find-file
+Based on this principle, Denote has a major-mode-agnostic mechanism to
+collects all linked file references in the current buffer and return
+them as an appropriately formatted list.  This list can then be used in
+interactive commands.  The ~denote-link-find-file~ is one such command.
+It uses minibuffer completion to visit a file that is linked to from the
+current note.  The candidates have the correct metadata, meaning that a
+package such as =marginalia= will display the correct annotations.
+
+** TODO Finalise first version of denote-link.el [1/3]
+*** DONE Add generic linking mechanism
+*** TODO Check if denote: is the right link type for Org/Markdown
+*** TODO Flesh out the ~denote-link-backlinks~ prototype
+*** TODO Document use of Embark with ~denote-link-find-file~
 
 * Fontification in Dired
 :PROPERTIES:
diff --git a/denote-link.el b/denote-link.el
index 7ab015d722..4059556053 100644
--- a/denote-link.el
+++ b/denote-link.el
@@ -38,25 +38,65 @@
 
 ;;;; Link to note
 
-(defconst denote-link--link-format-org "[[file:%s][%s (%s)]]"
+;; FIXME 2022-06-14 16:58:24 +0300: Plain text links will use the
+;; identifier only.  But for Org we need to figure out a better way of
+;; integrating with Org/Markdown in a standard way.  Relying on
+;; org-id.el may be the right course of action for Org.  What does
+;; markdown-mode require?
+;;
+;; Whatever we do, we need to consider the implications very carefully.
+;; This is not something we can undo once the package gets its first
+;; stable release.
+;;
+;; My principle is to avoid dependencies as much as possible.  The
+;; `denote-link-find-file' exemplifies this idea.
+;;
+;; Discussions on the GitHub mirror:
+;;
+;; * https://github.com/protesilaos/denote/issues/8
+;; * https://github.com/protesilaos/denote/issues/13
+;;
+;; And on the mailing list:
+;;
+;; * 
https://lists.sr.ht/~protesilaos/denote/%3C9ac1913b-7e8f-7d38-b547-771861a8d641%40eh-is.de%3E
+;; * https://lists.sr.ht/~protesilaos/denote/%3C87edzvd5oz.fsf%40cassou.me%3E
+
+;; Arguments are: FILE-ID FILE-TITLE
+(defconst denote-link--format-org "[[denote:%s][%s]]"
   "Format of Org link to note.")
 
-(defconst denote-link--link-format-markdown "[%2$s (%3$s)](file:%1$s)"
+(defconst denote-link--format-markdown "[%2$s](denote:%1$s)"
   "Format of Markdown link to note.")
 
-(defconst denote-link--link-format-text "<LINK: %s> [NAME %s (%s)]"
+(defconst denote-link--format-text "[[%s] [%s]]"
   "Format of plain text link to note.")
 
+(defconst denote-link--regexp-org
+  (concat "\\[\\[" "denote:"  "\\(?1:" denote--id-regexp "\\)" "]" "\\[.*?]]"))
+
+(defconst denote-link--regexp-markdown
+  (concat "\\[.*?]" "(denote:"  "\\(?1:" denote--id-regexp "\\)" ")"))
+
+(defconst denote-link--regexp-text
+  (concat "\\[\\[" "\\(?1:" denote--id-regexp "\\)" "]" "\s?" "\\[.*?]]"))
+
 (defun denote-link--file-type-format (file)
-  "Return link pattern based on FILE format."
+  "Return link format based on FILE format."
+  (pcase (file-name-extension file)
+    ("md" denote-link--format-markdown)
+    ("txt" denote-link--format-text)
+    (_ denote-link--format-org))) ; Includes backup files.  Maybe we can 
remove them?
+
+(defun denote-link--file-type-regexp (file)
+  "Return link regexp based on FILE format."
   (pcase (file-name-extension file)
-    ("md" denote-link--link-format-markdown)
-    ("txt" denote-link--link-format-text)
-    (_ denote-link--link-format-org))) ; Includes backup files.  Maybe we can 
remove them?
+    ("md" denote-link--regexp-markdown)
+    ("txt" denote-link--regexp-text)
+    (_ denote-link--regexp-org)))
 
 (defun denote-link--format-link (file pattern)
   "Prepare link to FILE using PATTERN."
-  (let* ((file-id (denote-retrieve--value file 
denote-retrieve--identifier-regexp))
+  (let* ((file-id (denote-retrieve--filename-identifier file))
          (file-title (denote-retrieve--value file 
denote-retrieve--title-front-matter-regexp)))
     (format pattern file-id file-title)))
 
@@ -65,14 +105,52 @@
   "Create Org link to TARGET note in variable `denote-directory'.
 Run `denote-link-insert-functions' afterwards."
   (interactive (list (denote-retrieve--read-file-prompt)))
-  (let* ((origin (buffer-file-name))
-         (link (denote-link--format-link target (denote-link--file-type-format 
origin))))
-    (insert link)))
+  (insert
+   (denote-link--format-link
+    target
+    (denote-link--file-type-format (buffer-file-name)))))
+
+(defun denote-link--collect-identifiers (regexp)
+  "Return collection of identifiers in buffer matching REGEXP."
+  (let (matches)
+    (save-excursion
+      (goto-char (point-min))
+      (while (re-search-forward regexp nil t)
+        (push (match-string-no-properties 1) matches)))
+    matches))
+
+(defun denote-link--expand-identifiers (regexp)
+  "Expend identifiers matching REGEXP into file paths."
+  (delq nil (mapcar (lambda (i)
+                      (file-name-completion i (denote-directory)))
+                    (denote-link--collect-identifiers regexp))))
+
+(defvar denote-link--find-file-history nil
+  "History for `denote-link-find-file'.")
+
+(defun denote-link--find-file-prompt (files)
+  "Prompt for linked file among FILES."
+  (completing-read "Find linked file "
+                   (denote--completion-table 'file files)
+                   nil t
+                   nil 'denote-link--find-file-history))
+
+;; TODO 2022-06-14: We should document the use of Embark for
+;; `denote-link-find-file'.  Users are gonna love it!
+
+;; TODO 2022-06-14: Do we need to add any sort of extension to better
+;; integrate with Embark?  For the minibuffer interaction it is not
+;; necessary, but maybe it can be done to immediately recognise the
+;; identifiers are links to files?
 
-;; TODO 2022-06-14: Write `denote-link-find-file' command.  It should be
-;; able to enhance this core idea:
-;;
-;; (file-name-completion file-id dir)
+;;;###autoload
+(defun denote-link-find-file ()
+  "Use minibuffer completion to visit linked file."
+  (interactive)
+  (if-let* ((regexp (denote-link--file-type-regexp (buffer-file-name)))
+            (files (denote-link--expand-identifiers regexp)))
+      (find-file (denote-link--find-file-prompt files))
+    (user-error "No links found in the current buffer")))
 
 ;;;; Backlinks' buffer (WORK-IN-PROGRESS)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]