[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)
- [elpa] externals/denote 561553db8e 132/355: fix: Use the correct match subgroup in `denote-link--find-value`, (continued)
- [elpa] externals/denote 561553db8e 132/355: fix: Use the correct match subgroup in `denote-link--find-value`, ELPA Syncer, 2022/06/27
- [elpa] externals/denote e1c18f5f57 136/355: Remove potentially bad advice from the manual, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 7b719e6274 152/355: Add user option to disable multi-word keywords, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 25fa79e8d9 146/355: Refine denote-retrieve internals, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 0165b00ddb 145/355: Use only denote-retrieve functions in denote-link, ELPA Syncer, 2022/06/27
- [elpa] externals/denote f57e9c5c9f 165/355: Change internal variable symbols for consistency, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 8565d36e7d 161/355: Add note in the manual about journal/diary, ELPA Syncer, 2022/06/27
- [elpa] externals/denote be58aec5db 163/355: Include journal sample that prompts for TITLE, ELPA Syncer, 2022/06/27
- [elpa] externals/denote d66312e517 172/355: Fix regression in file extension caused by f57e9c5, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 553c10a9cc 178/355: Tweak doc string, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 8e6e2736dc 174/355: Add generic denote-link-find-file,
ELPA Syncer <=
- [elpa] externals/denote b54dd3404d 186/355: Tweak doc string, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 5195f13f55 197/355: Add optional absolute for denote--directory-files, ELPA Syncer, 2022/06/27
- [elpa] externals/denote a160d9f147 196/355: Fix typo in the manual, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 3654f902e6 210/355: Accept optional group in denote-retrieve--search, ELPA Syncer, 2022/06/27
- [elpa] externals/denote aab21a74dd 194/355: Register 'denote:' custom Org hyperlink type, ELPA Syncer, 2022/06/27
- [elpa] externals/denote 4dc46d1b68 185/355: Set denote-link-fontify-backlinks to t by default, ELPA Syncer, 2022/06/27
- [elpa] externals/denote d5b62c4e58 220/355: Add denote-date command (notes for past date), ELPA Syncer, 2022/06/27
- [elpa] externals/denote f193199c88 228/355: Insert generic format links with prefix argument, ELPA Syncer, 2022/06/27
- [elpa] externals/denote e1c45e25f4 219/355: Optionally no current in files in dir regexp match, ELPA Syncer, 2022/06/27
- [elpa] externals/denote a1d315ff84 237/355: Reword statement about metanotes, ELPA Syncer, 2022/06/27