mirror of
https://github.com/org-roam/org-roam
synced 2025-08-03 12:27:23 -05:00
(internal): org-roam.el formatting (#687)
Organize org-roam.el: - Move functions so they are defined before they are referenced - Move defcustoms to appropriate section, sort alphabetically - Move interactive commands to appropriate section, autoload, sort. Should not change any behavior, but make review easier.
This commit is contained in:
736
org-roam.el
736
org-roam.el
@ -33,34 +33,38 @@
|
|||||||
;;
|
;;
|
||||||
;;
|
;;
|
||||||
;;; Code:
|
;;; Code:
|
||||||
;;;; Library Requires
|
;;;; Dependencies
|
||||||
(require 'org)
|
(require 'org)
|
||||||
(require 'org-element)
|
(require 'org-element)
|
||||||
(require 'ob-core) ;for org-babel-parse-header-arguments
|
(require 'ob-core) ;for org-babel-parse-header-arguments
|
||||||
(eval-when-compile (require 'subr-x))
|
(require 'org-ref nil t) ; To detect cite: links
|
||||||
(require 'dash)
|
|
||||||
(require 's)
|
|
||||||
(require 'f)
|
|
||||||
(require 'cl-lib)
|
(require 'cl-lib)
|
||||||
|
(require 'dash)
|
||||||
|
(require 'f)
|
||||||
|
(require 's)
|
||||||
(require 'seq)
|
(require 'seq)
|
||||||
|
(eval-when-compile (require 'subr-x))
|
||||||
|
|
||||||
;;;; org-roam features
|
;;;; Features
|
||||||
(require 'org-roam-compat)
|
(require 'org-roam-compat)
|
||||||
(require 'org-roam-macs)
|
(require 'org-roam-macs)
|
||||||
(require 'org-roam-db)
|
;; These features should be able to be loaded order independently.
|
||||||
|
;; @TODO: implement something akin to `org-modules' that allows
|
||||||
|
;; selectively loading different sets of features.
|
||||||
|
;; ~NV [2020-05-22 Fri]
|
||||||
(require 'org-roam-buffer)
|
(require 'org-roam-buffer)
|
||||||
(require 'org-roam-capture)
|
|
||||||
(require 'org-roam-graph)
|
|
||||||
(require 'org-roam-completion)
|
(require 'org-roam-completion)
|
||||||
|
(require 'org-roam-capture)
|
||||||
(require 'org-roam-dailies)
|
(require 'org-roam-dailies)
|
||||||
|
(require 'org-roam-db)
|
||||||
(require 'org-roam-doctor)
|
(require 'org-roam-doctor)
|
||||||
|
(require 'org-roam-graph)
|
||||||
|
|
||||||
;; To detect cite: links
|
;;;; Declarations
|
||||||
(require 'org-ref nil t)
|
|
||||||
(defvar org-ref-cite-types) ;; from org-ref-core.el
|
(defvar org-ref-cite-types) ;; from org-ref-core.el
|
||||||
(declare-function org-ref-split-and-strip-string "ext:org-ref-utils" (string))
|
(declare-function org-ref-split-and-strip-string "ext:org-ref-utils" (string))
|
||||||
|
|
||||||
;;;; Customizable Variables
|
;;;; Customizable variables
|
||||||
(defgroup org-roam nil
|
(defgroup org-roam nil
|
||||||
"Roam Research replica in Org-mode."
|
"Roam Research replica in Org-mode."
|
||||||
:group 'org
|
:group 'org
|
||||||
@ -75,29 +79,15 @@
|
|||||||
|
|
||||||
(defcustom org-roam-directory (expand-file-name "~/org-roam/")
|
(defcustom org-roam-directory (expand-file-name "~/org-roam/")
|
||||||
"Default path to Org-roam files.
|
"Default path to Org-roam files.
|
||||||
|
|
||||||
All Org files, at any level of nesting, are considered part of the Org-roam."
|
All Org files, at any level of nesting, are considered part of the Org-roam."
|
||||||
:type 'directory
|
:type 'directory
|
||||||
:group 'org-roam)
|
:group 'org-roam)
|
||||||
|
|
||||||
(defcustom org-roam-link-title-format "%s"
|
|
||||||
"The formatter used when inserting Org-roam links that use their title.
|
|
||||||
Formatter may be a function that takes title as its only argument."
|
|
||||||
:type '(choice
|
|
||||||
(string :tag "String Format" "%s")
|
|
||||||
(function :tag "Custom function"))
|
|
||||||
:group 'org-roam)
|
|
||||||
|
|
||||||
(defcustom org-roam-encrypt-files nil
|
(defcustom org-roam-encrypt-files nil
|
||||||
"Whether to encrypt new files. If true, create files with .gpg extension."
|
"Whether to encrypt new files. If true, create files with .gpg extension."
|
||||||
:type 'boolean
|
:type 'boolean
|
||||||
:group 'org-roam)
|
:group 'org-roam)
|
||||||
|
|
||||||
(defcustom org-roam-verbose t
|
|
||||||
"Echo messages that are not errors."
|
|
||||||
:type 'boolean
|
|
||||||
:group 'org-roam)
|
|
||||||
|
|
||||||
(defcustom org-roam-file-extensions '("org")
|
(defcustom org-roam-file-extensions '("org")
|
||||||
"Detected file extensions to include in the Org-roam ecosystem.
|
"Detected file extensions to include in the Org-roam ecosystem.
|
||||||
The first item in the list is used as the default file extension.
|
The first item in the list is used as the default file extension.
|
||||||
@ -107,6 +97,101 @@ ensure that."
|
|||||||
:type '(repeat string)
|
:type '(repeat string)
|
||||||
:group 'org-roam)
|
:group 'org-roam)
|
||||||
|
|
||||||
|
(defcustom org-roam-include-type-in-ref-path-completions nil
|
||||||
|
"When t, include the type in ref-path completions.
|
||||||
|
Note that this only affects interactive calls.
|
||||||
|
See `org-roam--get-ref-path-completions' for details."
|
||||||
|
:type 'boolean
|
||||||
|
:group 'org-roam)
|
||||||
|
|
||||||
|
(defcustom org-roam-index-file "index.org"
|
||||||
|
"Path to the Org-roam index file.
|
||||||
|
The path can be a string or a function. If it is a string, it
|
||||||
|
should be the path (absolute or relative to `org-roam-directory')
|
||||||
|
to the index file. If it is is a function, the function should
|
||||||
|
return the path to the index file. Otherwise, the index is
|
||||||
|
assumed to be a note in `org-roam-directory' whose title is
|
||||||
|
'Index'."
|
||||||
|
:type '(choice
|
||||||
|
(string :tag "Path to index" "%s")
|
||||||
|
(function :tag "Function to generate the path"))
|
||||||
|
:group 'org-roam)
|
||||||
|
|
||||||
|
(defcustom org-roam-link-title-format "%s"
|
||||||
|
"The formatter used when inserting Org-roam links that use their title.
|
||||||
|
Formatter may be a function that takes title as its only argument."
|
||||||
|
:type '(choice
|
||||||
|
(string :tag "String Format" "%s")
|
||||||
|
(function :tag "Custom function"))
|
||||||
|
:group 'org-roam)
|
||||||
|
|
||||||
|
(defcustom org-roam-list-files-commands '(find rg)
|
||||||
|
"Commands that will be used to find Org-roam files.
|
||||||
|
|
||||||
|
It should be a list of symbols or cons cells representing any of the following
|
||||||
|
supported file search methods.
|
||||||
|
|
||||||
|
The commands will be tried in order until an executable for a command is found.
|
||||||
|
The Elisp implementation is used if no command in the list is found.
|
||||||
|
|
||||||
|
`rg'
|
||||||
|
Use ripgrep as the file search method.
|
||||||
|
Example command: rg /path/to/dir/ --files -g \"*.org\" -g \"*.org.gpg\"
|
||||||
|
|
||||||
|
`find'
|
||||||
|
Use find as the file search method.
|
||||||
|
Example command:
|
||||||
|
find /path/to/dir -type f \( -name \"*.org\" -o -name \"*.org.gpg\" \)
|
||||||
|
|
||||||
|
By default, `executable-find' will be used to look up the path to the
|
||||||
|
executable. If a custom path is required, it can be specified together with the
|
||||||
|
method symbol as a cons cell. For example: '(find (rg . \"/path/to/rg\"))."
|
||||||
|
:type '(set (const :tag "find" find)
|
||||||
|
(const :tag "rg" rg)))
|
||||||
|
|
||||||
|
(defcustom org-roam-tag-separator ","
|
||||||
|
"String to use to separate tags when `org-roam-tag-sources' is non-nil."
|
||||||
|
:type 'string
|
||||||
|
:group 'org-roam)
|
||||||
|
|
||||||
|
(defcustom org-roam-tag-sort nil
|
||||||
|
"When non-nil, sort the tags in the completions.
|
||||||
|
When t, sort the tags alphabetically, regardless of case.
|
||||||
|
`org-roam-tag-sort' can also be a list of arguments to be applied
|
||||||
|
to `cl-sort'. For example, these are the arguments used when
|
||||||
|
`org-roam-tag-sort' is set to t:
|
||||||
|
\('string-lessp :key 'downcase)
|
||||||
|
Only relevant when `org-roam-tag-sources' is non-nil."
|
||||||
|
:type '(choice
|
||||||
|
(boolean)
|
||||||
|
(list :tag "Arguments to cl-loop"))
|
||||||
|
:group 'org-roam)
|
||||||
|
|
||||||
|
(defcustom org-roam-tag-sources '(prop)
|
||||||
|
"Sources to obtain tags from.
|
||||||
|
|
||||||
|
It should be a list of symbols representing any of the following
|
||||||
|
extraction methods:
|
||||||
|
|
||||||
|
`prop'
|
||||||
|
Extract tags from the #+ROAM_TAGS property.
|
||||||
|
Tags are space delimited.
|
||||||
|
Tags may contain spaces if they are double-quoted.
|
||||||
|
e.g. #+ROAM_TAGS: tag \"tag with spaces\"
|
||||||
|
|
||||||
|
`all-directories'
|
||||||
|
Extract sub-directories relative to `org-roam-directory'.
|
||||||
|
That is, if a file is located at relative path foo/bar/file.org,
|
||||||
|
the file will have tags \"foo\" and \"bar\".
|
||||||
|
|
||||||
|
`last-directory'
|
||||||
|
Extract the last directory relative to `org-roam-directory'.
|
||||||
|
That is, if a file is located at relative path foo/bar/file.org,
|
||||||
|
the file will have tag \"bar\"."
|
||||||
|
:type '(set (const :tag "#+ROAM_TAGS" prop)
|
||||||
|
(const :tag "sub-directories" all-directories)
|
||||||
|
(const :tag "parent directory" last-directory)))
|
||||||
|
|
||||||
(defcustom org-roam-title-sources '((title headline) alias)
|
(defcustom org-roam-title-sources '((title headline) alias)
|
||||||
"The list of sources from which to retrieve a note title.
|
"The list of sources from which to retrieve a note title.
|
||||||
Each element in the list is either:
|
Each element in the list is either:
|
||||||
@ -135,61 +220,21 @@ space-delimited strings.
|
|||||||
(symbol)))
|
(symbol)))
|
||||||
:group 'org-roam)
|
:group 'org-roam)
|
||||||
|
|
||||||
(defcustom org-roam-tag-sources '(prop)
|
(defcustom org-roam-verbose t
|
||||||
"Sources to obtain tags from.
|
"Echo messages that are not errors."
|
||||||
|
:type 'boolean
|
||||||
It should be a list of symbols representing any of the following
|
:group 'org-roam)
|
||||||
extraction methods:
|
|
||||||
|
|
||||||
`prop'
|
|
||||||
Extract tags from the #+ROAM_TAGS property.
|
|
||||||
Tags are space delimited.
|
|
||||||
Tags may contain spaces if they are double-quoted.
|
|
||||||
e.g. #+ROAM_TAGS: tag \"tag with spaces\"
|
|
||||||
|
|
||||||
`all-directories'
|
|
||||||
Extract sub-directories relative to `org-roam-directory'.
|
|
||||||
That is, if a file is located at relative path foo/bar/file.org,
|
|
||||||
the file will have tags \"foo\" and \"bar\".
|
|
||||||
|
|
||||||
`last-directory'
|
|
||||||
Extract the last directory relative to `org-roam-directory'.
|
|
||||||
That is, if a file is located at relative path foo/bar/file.org,
|
|
||||||
the file will have tag \"bar\"."
|
|
||||||
:type '(set (const :tag "#+ROAM_TAGS" prop)
|
|
||||||
(const :tag "sub-directories" all-directories)
|
|
||||||
(const :tag "parent directory" last-directory)))
|
|
||||||
|
|
||||||
(defcustom org-roam-list-files-commands '(find rg)
|
|
||||||
"Commands that will be used to find Org-roam files.
|
|
||||||
|
|
||||||
It should be a list of symbols or cons cells representing any of the following
|
|
||||||
supported file search methods.
|
|
||||||
|
|
||||||
The commands will be tried in order until an executable for a command is found.
|
|
||||||
The Elisp implementation is used if no command in the list is found.
|
|
||||||
|
|
||||||
`rg'
|
|
||||||
Use ripgrep as the file search method.
|
|
||||||
Example command: rg /path/to/dir/ --files -g \"*.org\" -g \"*.org.gpg\"
|
|
||||||
|
|
||||||
`find'
|
|
||||||
Use find as the file search method.
|
|
||||||
Example command:
|
|
||||||
find /path/to/dir -type f \( -name \"*.org\" -o -name \"*.org.gpg\" \)
|
|
||||||
|
|
||||||
By default, `executable-find' will be used to look up the path to the
|
|
||||||
executable. If a custom path is required, it can be specified together with the
|
|
||||||
method symbol as a cons cell. For example: '(find (rg . \"/path/to/rg\"))."
|
|
||||||
:type '(set (const :tag "find" find)
|
|
||||||
(const :tag "rg" rg)))
|
|
||||||
|
|
||||||
;;;; Dynamic variables
|
;;;; Dynamic variables
|
||||||
(defvar org-roam-last-window nil
|
(defvar org-roam-last-window nil
|
||||||
"Last window `org-roam' was called from.")
|
"Last window `org-roam' was called from.")
|
||||||
|
|
||||||
;;; Utilities
|
(defvar org-roam--org-link-file-bracket-re
|
||||||
;;;; General Utilities
|
"\\[\\[file:\\(\\(?:[^][\\]\\|\\\\\\(?:\\\\\\\\\\)*[][]\\|\\\\+[^][]\\)+\\)]\\(?:\\[\\(\\(?:.\\|
|
||||||
|
\\)+?\\)]\\)?]"
|
||||||
|
"Matches a 'file:' link in double brackets.")
|
||||||
|
|
||||||
|
;;;; Utilities
|
||||||
(defun org-roam--plist-to-alist (plist)
|
(defun org-roam--plist-to-alist (plist)
|
||||||
"Return an alist of the property-value pairs in PLIST."
|
"Return an alist of the property-value pairs in PLIST."
|
||||||
(let (res)
|
(let (res)
|
||||||
@ -248,7 +293,7 @@ Like `file-name-extension', but does not strip version number."
|
|||||||
"Return t if FILE is part of Org-roam system, nil otherwise.
|
"Return t if FILE is part of Org-roam system, nil otherwise.
|
||||||
If FILE is not specified, use the current buffer's file-path."
|
If FILE is not specified, use the current buffer's file-path."
|
||||||
(if-let ((path (or file
|
(if-let ((path (or file
|
||||||
(buffer-file-name))))
|
(buffer-file-name))))
|
||||||
(save-match-data
|
(save-match-data
|
||||||
(and
|
(and
|
||||||
(org-roam--org-file-p path)
|
(org-roam--org-file-p path)
|
||||||
@ -302,8 +347,8 @@ Use external shell commands if defined in `org-roam-list-files-commands'."
|
|||||||
exe (symbol-name cmd)))
|
exe (symbol-name cmd)))
|
||||||
(wrong-type
|
(wrong-type
|
||||||
(signal 'wrong-type-argument
|
(signal 'wrong-type-argument
|
||||||
`((consp symbolp)
|
`((consp symbolp)
|
||||||
,wrong-type))))
|
,wrong-type))))
|
||||||
(when path (cl-return)))
|
(when path (cl-return)))
|
||||||
(if path
|
(if path
|
||||||
(let ((fn (intern (concat "org-roam--list-files-" exe))))
|
(let ((fn (intern (concat "org-roam--list-files-" exe))))
|
||||||
@ -330,11 +375,6 @@ The search terminates when the first property is encountered."
|
|||||||
(push (cons prop p) res)))
|
(push (cons prop p) res)))
|
||||||
res))
|
res))
|
||||||
|
|
||||||
(defvar org-roam--org-link-file-bracket-re
|
|
||||||
"\\[\\[file:\\(\\(?:[^][\\]\\|\\\\\\(?:\\\\\\\\\\)*[][]\\|\\\\+[^][]\\)+\\)]\\(?:\\[\\(\\(?:.\\|
|
|
||||||
\\)+?\\)]\\)?]"
|
|
||||||
"Matches a 'file:' link in double brackets.")
|
|
||||||
|
|
||||||
(defun org-roam--expand-links (content path)
|
(defun org-roam--expand-links (content path)
|
||||||
"Crawl CONTENT for relative links and expand them.
|
"Crawl CONTENT for relative links and expand them.
|
||||||
PATH should be the root from which to compute the relativity."
|
PATH should be the root from which to compute the relativity."
|
||||||
@ -475,19 +515,6 @@ The final directory component is used as a tag."
|
|||||||
(let* ((prop (org-roam--extract-global-props '("ROAM_TAGS"))))
|
(let* ((prop (org-roam--extract-global-props '("ROAM_TAGS"))))
|
||||||
(org-roam--parse-tags (cdr (assoc "ROAM_TAGS" prop)))))
|
(org-roam--parse-tags (cdr (assoc "ROAM_TAGS" prop)))))
|
||||||
|
|
||||||
(defcustom org-roam-tag-sort nil
|
|
||||||
"When non-nil, sort the tags in the completions.
|
|
||||||
When t, sort the tags alphabetically, regardless of case.
|
|
||||||
`org-roam-tag-sort' can also be a list of arguments to be applied
|
|
||||||
to `cl-sort'. For example, these are the arguments used when
|
|
||||||
`org-roam-tag-sort' is set to t:
|
|
||||||
\('string-lessp :key 'downcase)
|
|
||||||
Only relevant when `org-roam-tag-sources' is non-nil."
|
|
||||||
:type '(choice
|
|
||||||
(boolean)
|
|
||||||
(list :tag "Arguments to cl-loop"))
|
|
||||||
:group 'org-roam)
|
|
||||||
|
|
||||||
(defun org-roam--extract-tags (&optional file)
|
(defun org-roam--extract-tags (&optional file)
|
||||||
"Extract tags from the current buffer.
|
"Extract tags from the current buffer.
|
||||||
If file-path FILE, use it to determine the directory tags.
|
If file-path FILE, use it to determine the directory tags.
|
||||||
@ -511,10 +538,28 @@ Tags are obtained via:
|
|||||||
`((booleanp (list symbolp …))
|
`((booleanp (list symbolp …))
|
||||||
,wrong-type))))))
|
,wrong-type))))))
|
||||||
|
|
||||||
(defun org-roam--ref-type-p (type)
|
(defun org-roam--cite-prefix (ref)
|
||||||
"Return t if the ref from current buffer is TYPE."
|
"Return the citation prefix of REF, or nil otherwise.
|
||||||
(let ((current (car (org-roam--extract-ref))))
|
The prefixes are defined in `org-ref-cite-types`.
|
||||||
(eq current type)))
|
Examples:
|
||||||
|
(org-roam--cite-prefix \"cite:foo\") -> \"cite:\"
|
||||||
|
(org-roam--cite-prefix \"https://google.com\") -> nil"
|
||||||
|
(when (require 'org-ref nil t)
|
||||||
|
(seq-find
|
||||||
|
(lambda (prefix) (s-prefix? prefix ref))
|
||||||
|
(-map (lambda (type) (concat type ":"))
|
||||||
|
org-ref-cite-types))))
|
||||||
|
|
||||||
|
(defun org-roam--ref-type (ref)
|
||||||
|
"Determine the type of the REF from the prefix."
|
||||||
|
(let* ((cite-prefix (org-roam--cite-prefix ref))
|
||||||
|
(is-website (seq-some
|
||||||
|
(lambda (prefix) (s-prefix? prefix ref))
|
||||||
|
'("http" "https")))
|
||||||
|
(type (cond (cite-prefix "cite")
|
||||||
|
(is-website "website")
|
||||||
|
(t "roam"))))
|
||||||
|
type))
|
||||||
|
|
||||||
(defun org-roam--extract-ref ()
|
(defun org-roam--extract-ref ()
|
||||||
"Extract the ref from current buffer and return the type and the key of the ref."
|
"Extract the ref from current buffer and return the type and the key of the ref."
|
||||||
@ -530,28 +575,10 @@ Tags are obtained via:
|
|||||||
(t ref))))
|
(t ref))))
|
||||||
(cons type key)))))
|
(cons type key)))))
|
||||||
|
|
||||||
(defun org-roam--ref-type (ref)
|
(defun org-roam--ref-type-p (type)
|
||||||
"Determine the type of the REF from the prefix."
|
"Return t if the ref from current buffer is TYPE."
|
||||||
(let* ((cite-prefix (org-roam--cite-prefix ref))
|
(let ((current (car (org-roam--extract-ref))))
|
||||||
(is-website (seq-some
|
(eq current type)))
|
||||||
(lambda (prefix) (s-prefix? prefix ref))
|
|
||||||
'("http" "https")))
|
|
||||||
(type (cond (cite-prefix "cite")
|
|
||||||
(is-website "website")
|
|
||||||
(t "roam"))))
|
|
||||||
type))
|
|
||||||
|
|
||||||
(defun org-roam--cite-prefix (ref)
|
|
||||||
"Return the citation prefix of REF, or nil otherwise.
|
|
||||||
The prefixes are defined in `org-ref-cite-types`.
|
|
||||||
Examples:
|
|
||||||
(org-roam--cite-prefix \"cite:foo\") -> \"cite:\"
|
|
||||||
(org-roam--cite-prefix \"https://google.com\") -> nil"
|
|
||||||
(when (require 'org-ref nil t)
|
|
||||||
(seq-find
|
|
||||||
(lambda (prefix) (s-prefix? prefix ref))
|
|
||||||
(-map (lambda (type) (concat type ":"))
|
|
||||||
org-ref-cite-types))))
|
|
||||||
|
|
||||||
;;;; Title/Path/Slug conversion
|
;;;; Title/Path/Slug conversion
|
||||||
(defun org-roam--path-to-slug (path)
|
(defun org-roam--path-to-slug (path)
|
||||||
@ -581,7 +608,6 @@ Examples:
|
|||||||
(slug (-reduce-from #'cl-replace (strip-nonspacing-marks title) pairs)))
|
(slug (-reduce-from #'cl-replace (strip-nonspacing-marks title) pairs)))
|
||||||
(downcase slug))))
|
(downcase slug))))
|
||||||
|
|
||||||
;;; Interactive Commands
|
|
||||||
(defun org-roam--format-link-title (title)
|
(defun org-roam--format-link-title (title)
|
||||||
"Return the link title, given the file TITLE."
|
"Return the link title, given the file TITLE."
|
||||||
(if (functionp org-roam-link-title-format)
|
(if (functionp org-roam-link-title-format)
|
||||||
@ -602,61 +628,6 @@ Examples:
|
|||||||
target))
|
target))
|
||||||
description)))
|
description)))
|
||||||
|
|
||||||
(defun org-roam-insert (&optional lowercase completions filter-fn description)
|
|
||||||
"Find an Org-roam file, and insert a relative org link to it at point.
|
|
||||||
If LOWERCASE, downcase the title before insertion.
|
|
||||||
COMPLETIONS is a list of completions to be used instead of
|
|
||||||
`org-roam--get-title-path-completions`.
|
|
||||||
FILTER-FN is the name of a function to apply on the candidates
|
|
||||||
which takes as its argument an alist of path-completions.
|
|
||||||
If DESCRIPTION is provided, use this as the link label. See
|
|
||||||
`org-roam--get-title-path-completions' for details."
|
|
||||||
(interactive "P")
|
|
||||||
(let* ((region (and (region-active-p)
|
|
||||||
;; following may lose active region, so save it
|
|
||||||
(cons (region-beginning) (region-end))))
|
|
||||||
(region-text (when region
|
|
||||||
(buffer-substring-no-properties
|
|
||||||
(car region) (cdr region))))
|
|
||||||
(completions (--> (or completions
|
|
||||||
(org-roam--get-title-path-completions))
|
|
||||||
(if filter-fn
|
|
||||||
(funcall filter-fn it)
|
|
||||||
it)))
|
|
||||||
(title-with-tags (org-roam-completion--completing-read "File: " completions
|
|
||||||
:initial-input region-text))
|
|
||||||
(res (cdr (assoc title-with-tags completions)))
|
|
||||||
(title (or (plist-get res :title)
|
|
||||||
title-with-tags))
|
|
||||||
(target-file-path (plist-get res :path))
|
|
||||||
(description (or description region-text title))
|
|
||||||
(link-description (org-roam--format-link-title (if lowercase
|
|
||||||
(downcase description)
|
|
||||||
description))))
|
|
||||||
(if (and target-file-path
|
|
||||||
(file-exists-p target-file-path))
|
|
||||||
(progn
|
|
||||||
(when region ;; Remove previously selected text.
|
|
||||||
(delete-region (car region) (cdr region)))
|
|
||||||
(insert (org-roam--format-link target-file-path link-description)))
|
|
||||||
(when (org-roam-capture--in-process-p)
|
|
||||||
(user-error "Nested Org-roam capture processes not supported"))
|
|
||||||
(let ((org-roam-capture--info `((title . ,title-with-tags)
|
|
||||||
(slug . ,(org-roam--title-to-slug title-with-tags))))
|
|
||||||
(org-roam-capture--context 'title))
|
|
||||||
(add-hook 'org-capture-after-finalize-hook #'org-roam-capture--insert-link-h)
|
|
||||||
(setq org-roam-capture-additional-template-props (list :region region
|
|
||||||
:link-description link-description
|
|
||||||
:capture-fn 'org-roam-insert))
|
|
||||||
(org-roam--with-template-error 'org-roam-capture-templates
|
|
||||||
(org-roam-capture--capture))))))
|
|
||||||
|
|
||||||
(defcustom org-roam-tag-separator ","
|
|
||||||
"String to use to separate tags.
|
|
||||||
Only relevant when `org-roam-tag-sources' is non-nil."
|
|
||||||
:type 'string
|
|
||||||
:group 'org-roam)
|
|
||||||
|
|
||||||
(defun org-roam--get-title-path-completions ()
|
(defun org-roam--get-title-path-completions ()
|
||||||
"Return an alist for completion.
|
"Return an alist for completion.
|
||||||
The car is the displayed title for completion, and the cdr is the
|
The car is the displayed title for completion, and the cdr is the
|
||||||
@ -682,53 +653,6 @@ to the file."
|
|||||||
(v (list :path file-path :title title)))
|
(v (list :path file-path :title title)))
|
||||||
(push (cons k v) completions))))))))
|
(push (cons k v) completions))))))))
|
||||||
|
|
||||||
(defun org-roam-find-file (&optional initial-prompt completions filter-fn)
|
|
||||||
"Find and open an Org-roam file.
|
|
||||||
INITIAL-PROMPT is the initial title prompt.
|
|
||||||
COMPLETIONS is a list of completions to be used instead of
|
|
||||||
`org-roam--get-title-path-completions`.
|
|
||||||
FILTER-FN is the name of a function to apply on the candidates
|
|
||||||
which takes as its argument an alist of path-completions. See
|
|
||||||
`org-roam--get-title-path-completions' for details."
|
|
||||||
(interactive)
|
|
||||||
(let* ((completions (--> (or completions
|
|
||||||
(org-roam--get-title-path-completions))
|
|
||||||
(if filter-fn
|
|
||||||
(funcall filter-fn it)
|
|
||||||
it)))
|
|
||||||
(title-with-tags (org-roam-completion--completing-read "File: " completions
|
|
||||||
:initial-input initial-prompt))
|
|
||||||
(res (cdr (assoc title-with-tags completions)))
|
|
||||||
(file-path (plist-get res :path)))
|
|
||||||
(if file-path
|
|
||||||
(find-file file-path)
|
|
||||||
(if (org-roam-capture--in-process-p)
|
|
||||||
(user-error "Org-roam capture in process")
|
|
||||||
(let ((org-roam-capture--info `((title . ,title-with-tags)
|
|
||||||
(slug . ,(org-roam--title-to-slug title-with-tags))))
|
|
||||||
(org-roam-capture--context 'title))
|
|
||||||
(add-hook 'org-capture-after-finalize-hook #'org-roam-capture--find-file-h)
|
|
||||||
(org-roam--with-template-error 'org-roam-capture-templates
|
|
||||||
(org-roam-capture--capture)))))))
|
|
||||||
|
|
||||||
(defun org-roam-find-directory ()
|
|
||||||
"Find and open `org-roam-directory'."
|
|
||||||
(interactive)
|
|
||||||
(find-file org-roam-directory))
|
|
||||||
|
|
||||||
(defcustom org-roam-index-file "index.org"
|
|
||||||
"Path to the Org-roam index file.
|
|
||||||
The path can be a string or a function. If it is a string, it
|
|
||||||
should be the path (absolute or relative to `org-roam-directory')
|
|
||||||
to the index file. If it is is a function, the function should
|
|
||||||
return the path to the index file. Otherwise, the index is
|
|
||||||
assumed to be a note in `org-roam-directory' whose title is
|
|
||||||
'Index'."
|
|
||||||
:type '(choice
|
|
||||||
(string :tag "Path to index" "%s")
|
|
||||||
(function :tag "Function to generate the path"))
|
|
||||||
:group 'org-roam)
|
|
||||||
|
|
||||||
(defun org-roam--get-index-path ()
|
(defun org-roam--get-index-path ()
|
||||||
"Return the path to the index in `org-roam-directory'.
|
"Return the path to the index in `org-roam-directory'.
|
||||||
The path to the index can be defined in `org-roam-index-file'.
|
The path to the index can be defined in `org-roam-index-file'.
|
||||||
@ -746,28 +670,7 @@ whose title is 'Index'."
|
|||||||
(concat (file-truename org-roam-directory) path)
|
(concat (file-truename org-roam-directory) path)
|
||||||
index)))
|
index)))
|
||||||
|
|
||||||
(defun org-roam-jump-to-index ()
|
|
||||||
"Find the index file in `org-roam-directory'.
|
|
||||||
The path to the index can be defined in `org-roam-index-file'.
|
|
||||||
Otherwise, the function will look in your `org-roam-directory'
|
|
||||||
for a note whose title is 'Index'. If it does not exist, the
|
|
||||||
command will offer you to create one."
|
|
||||||
(interactive)
|
|
||||||
(let ((index (org-roam--get-index-path)))
|
|
||||||
(if (and index
|
|
||||||
(file-exists-p index))
|
|
||||||
(find-file index)
|
|
||||||
(when (y-or-n-p "Index file does not exist. Would you like to create it? ")
|
|
||||||
(org-roam-find-file "Index")))))
|
|
||||||
|
|
||||||
;;;; org-roam-find-ref
|
;;;; org-roam-find-ref
|
||||||
(defcustom org-roam-include-type-in-ref-path-completions nil
|
|
||||||
"When t, include the type in ref-path completions.
|
|
||||||
Note that this only affects interactive calls.
|
|
||||||
See `org-roam--get-ref-path-completions' for details."
|
|
||||||
:type 'boolean
|
|
||||||
:group 'org-roam)
|
|
||||||
|
|
||||||
(defun org-roam--get-ref-path-completions (&optional interactive filter)
|
(defun org-roam--get-ref-path-completions (&optional interactive filter)
|
||||||
"Return a alist of refs to absolute path of Org-roam files.
|
"Return a alist of refs to absolute path of Org-roam files.
|
||||||
When `org-roam-include-type-in-ref-path-completions' and
|
When `org-roam-include-type-in-ref-path-completions' and
|
||||||
@ -815,26 +718,6 @@ Return nil if the file does not exist."
|
|||||||
(file (plist-get (cdr (assoc ref completions)) :path)))
|
(file (plist-get (cdr (assoc ref completions)) :path)))
|
||||||
(find-file file)))
|
(find-file file)))
|
||||||
|
|
||||||
(defun org-roam-find-ref (arg &optional filter)
|
|
||||||
"Find and open an Org-roam file from a ref.
|
|
||||||
ARG is used to forward interactive calls to
|
|
||||||
`org-roam--get-ref-path-completions'
|
|
||||||
FILTER can either be a string or a function:
|
|
||||||
- If it is a string, it should be the type of refs to include as
|
|
||||||
candidates (e.g. \"cite\" ,\"website\" ,etc.)
|
|
||||||
- If it is a function, it should be the name of a function that
|
|
||||||
takes three arguments: the type, the ref, and the file of the
|
|
||||||
current candidate. It should return t if that candidate is to be
|
|
||||||
included as a candidate."
|
|
||||||
(interactive "p")
|
|
||||||
(let* ((completions (org-roam--get-ref-path-completions arg filter))
|
|
||||||
(ref (org-roam-completion--completing-read "Ref: "
|
|
||||||
completions
|
|
||||||
:require-match t))
|
|
||||||
(file (-> (cdr (assoc ref completions))
|
|
||||||
(plist-get :path))))
|
|
||||||
(find-file file)))
|
|
||||||
|
|
||||||
(defun org-roam--get-roam-buffers ()
|
(defun org-roam--get-roam-buffers ()
|
||||||
"Return a list of buffers that are Org-roam files."
|
"Return a list of buffers that are Org-roam files."
|
||||||
(--filter (and (with-current-buffer it (derived-mode-p 'org-mode))
|
(--filter (and (with-current-buffer it (derived-mode-p 'org-mode))
|
||||||
@ -842,27 +725,11 @@ included as a candidate."
|
|||||||
(org-roam--org-roam-file-p (buffer-file-name it)))
|
(org-roam--org-roam-file-p (buffer-file-name it)))
|
||||||
(buffer-list)))
|
(buffer-list)))
|
||||||
|
|
||||||
(defun org-roam-switch-to-buffer ()
|
|
||||||
"Switch to an existing Org-roam buffer."
|
|
||||||
(interactive)
|
|
||||||
(let* ((roam-buffers (org-roam--get-roam-buffers))
|
|
||||||
(names-and-buffers (mapcar (lambda (buffer)
|
|
||||||
(cons (or (org-roam--get-title-or-slug
|
|
||||||
(buffer-file-name buffer))
|
|
||||||
(buffer-name buffer))
|
|
||||||
buffer))
|
|
||||||
roam-buffers)))
|
|
||||||
(unless roam-buffers
|
|
||||||
(user-error "No roam buffers"))
|
|
||||||
(when-let ((name (org-roam-completion--completing-read "Buffer: " names-and-buffers
|
|
||||||
:require-match t)))
|
|
||||||
(switch-to-buffer (cdr (assoc name names-and-buffers))))))
|
|
||||||
|
|
||||||
(defun org-roam--file-path-from-id (id)
|
(defun org-roam--file-path-from-id (id)
|
||||||
"The file path for an Org-roam file, with identifier ID."
|
"The file path for an Org-roam file, with identifier ID."
|
||||||
(file-truename
|
(file-truename
|
||||||
(let* ((ext (or (car org-roam-file-extensions)
|
(let* ((ext (or (car org-roam-file-extensions)
|
||||||
"org"))
|
"org"))
|
||||||
(file (concat id "." ext)))
|
(file (concat id "." ext)))
|
||||||
(expand-file-name
|
(expand-file-name
|
||||||
(if org-roam-encrypt-files
|
(if org-roam-encrypt-files
|
||||||
@ -991,51 +858,7 @@ for Org-ref cite links."
|
|||||||
:link (format "file:%s" (abbreviate-file-name buffer-file-name))
|
:link (format "file:%s" (abbreviate-file-name buffer-file-name))
|
||||||
:description title))))
|
:description title))))
|
||||||
|
|
||||||
;;;###autoload
|
|
||||||
(defalias 'org-roam 'org-roam-buffer-toggle-display)
|
|
||||||
|
|
||||||
;;; The global minor org-roam-mode
|
;;; The global minor org-roam-mode
|
||||||
|
|
||||||
;;;###autoload
|
|
||||||
(define-minor-mode org-roam-mode
|
|
||||||
"Minor mode for Org-roam.
|
|
||||||
|
|
||||||
This mode sets up several hooks, to ensure that the cache is updated on file
|
|
||||||
changes, renames and deletes. It is also in charge of graceful termination of
|
|
||||||
the database connection.
|
|
||||||
|
|
||||||
When called interactively, toggle `org-roam-mode'. with prefix
|
|
||||||
ARG, enable `org-roam-mode' if ARG is positive, otherwise disable
|
|
||||||
it.
|
|
||||||
|
|
||||||
When called from Lisp, enable `org-roam-mode' if ARG is omitted,
|
|
||||||
nil, or positive. If ARG is `toggle', toggle `org-roam-mode'.
|
|
||||||
Otherwise, behave as if called interactively."
|
|
||||||
:lighter " Org-roam"
|
|
||||||
:keymap (let ((map (make-sparse-keymap))) map)
|
|
||||||
:group 'org-roam
|
|
||||||
:require 'org-roam
|
|
||||||
:global t
|
|
||||||
(cond
|
|
||||||
(org-roam-mode
|
|
||||||
(add-hook 'find-file-hook #'org-roam--find-file-hook-function)
|
|
||||||
(add-hook 'kill-emacs-hook #'org-roam-db--close-all)
|
|
||||||
(advice-add 'rename-file :after #'org-roam--rename-file-advice)
|
|
||||||
(advice-add 'delete-file :before #'org-roam--delete-file-advice)
|
|
||||||
(org-roam-db-build-cache))
|
|
||||||
(t
|
|
||||||
(remove-hook 'find-file-hook #'org-roam--find-file-hook-function)
|
|
||||||
(remove-hook 'kill-emacs-hook #'org-roam-db--close-all)
|
|
||||||
(advice-remove 'rename-file #'org-roam--rename-file-advice)
|
|
||||||
(advice-remove 'delete-file #'org-roam--delete-file-advice)
|
|
||||||
(org-roam-db--close-all)
|
|
||||||
;; Disable local hooks for all org-roam buffers
|
|
||||||
(dolist (buf (org-roam--get-roam-buffers))
|
|
||||||
(with-current-buffer buf
|
|
||||||
(org-link-set-parameters "file" :face 'org-link)
|
|
||||||
(remove-hook 'post-command-hook #'org-roam-buffer--update-maybe t)
|
|
||||||
(remove-hook 'after-save-hook #'org-roam-db--update-file t))))))
|
|
||||||
|
|
||||||
(defun org-roam--find-file-hook-function ()
|
(defun org-roam--find-file-hook-function ()
|
||||||
"Called by `find-file-hook' when mode symbol `org-roam-mode' is on."
|
"Called by `find-file-hook' when mode symbol `org-roam-mode' is on."
|
||||||
(when (org-roam--org-roam-file-p)
|
(when (org-roam--org-roam-file-p)
|
||||||
@ -1061,27 +884,27 @@ update with NEW-DESC."
|
|||||||
(find-file-noselect file))
|
(find-file-noselect file))
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(let ((link-markers (org-element-map (org-element-parse-buffer) 'link
|
(let ((link-markers (org-element-map (org-element-parse-buffer) 'link
|
||||||
(lambda (l)
|
(lambda (l)
|
||||||
(let ((type (org-element-property :type l))
|
(let ((type (org-element-property :type l))
|
||||||
(path (org-element-property :path l)))
|
(path (org-element-property :path l)))
|
||||||
(when (and (equal "file" type)
|
(when (and (equal "file" type)
|
||||||
(string-equal (file-truename path)
|
(string-equal (file-truename path)
|
||||||
old-path))
|
old-path))
|
||||||
(set-marker (make-marker) (org-element-property :begin l))))))))
|
(set-marker (make-marker) (org-element-property :begin l))))))))
|
||||||
(dolist (m link-markers)
|
(dolist (m link-markers)
|
||||||
(goto-char m)
|
(goto-char m)
|
||||||
(save-match-data
|
(save-match-data
|
||||||
(unless (org-in-regexp org-link-bracket-re 1)
|
(unless (org-in-regexp org-link-bracket-re 1)
|
||||||
(user-error "No link at point"))
|
(user-error "No link at point"))
|
||||||
(let* ((label (if (match-end 2)
|
(let* ((label (if (match-end 2)
|
||||||
(match-string-no-properties 2)
|
(match-string-no-properties 2)
|
||||||
(org-link-unescape (match-string-no-properties 1))))
|
(org-link-unescape (match-string-no-properties 1))))
|
||||||
(new-label (if (string-equal label old-desc)
|
(new-label (if (string-equal label old-desc)
|
||||||
new-desc
|
new-desc
|
||||||
label)))
|
label)))
|
||||||
(replace-match (org-link-make-string
|
(replace-match (org-link-make-string
|
||||||
(concat "file:" (file-relative-name new-path (file-name-directory (buffer-file-name))))
|
(concat "file:" (file-relative-name new-path (file-name-directory (buffer-file-name))))
|
||||||
new-label)))))))
|
new-label)))))))
|
||||||
(save-buffer)))
|
(save-buffer)))
|
||||||
|
|
||||||
(defun org-roam--fix-relative-links (old-path)
|
(defun org-roam--fix-relative-links (old-path)
|
||||||
@ -1153,23 +976,49 @@ replaced links are made relative to the current buffer."
|
|||||||
(save-buffer)))
|
(save-buffer)))
|
||||||
(org-roam-db--update-file new-path)))))
|
(org-roam-db--update-file new-path)))))
|
||||||
|
|
||||||
;;;; Diagnostics
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun org-roam-version (&optional message)
|
(define-minor-mode org-roam-mode
|
||||||
"Return `org-roam' version.
|
"Minor mode for Org-roam.
|
||||||
Interactively, or when MESSAGE is non-nil, show in the echo area."
|
|
||||||
(interactive)
|
This mode sets up several hooks, to ensure that the cache is updated on file
|
||||||
(let* ((version
|
changes, renames and deletes. It is also in charge of graceful termination of
|
||||||
(with-temp-buffer
|
the database connection.
|
||||||
(insert-file-contents-literally (locate-library "org-roam.el"))
|
|
||||||
(goto-char (point-min))
|
When called interactively, toggle `org-roam-mode'. with prefix
|
||||||
(save-match-data
|
ARG, enable `org-roam-mode' if ARG is positive, otherwise disable
|
||||||
(if (re-search-forward "\\(?:;; Version: \\([^z-a]*?$\\)\\)" nil nil)
|
it.
|
||||||
(substring-no-properties (match-string 1))
|
|
||||||
"N/A")))))
|
When called from Lisp, enable `org-roam-mode' if ARG is omitted,
|
||||||
(if (or message (called-interactively-p 'interactive))
|
nil, or positive. If ARG is `toggle', toggle `org-roam-mode'.
|
||||||
(message "%s" version)
|
Otherwise, behave as if called interactively."
|
||||||
version)))
|
:lighter " Org-roam"
|
||||||
|
:keymap (let ((map (make-sparse-keymap))) map)
|
||||||
|
:group 'org-roam
|
||||||
|
:require 'org-roam
|
||||||
|
:global t
|
||||||
|
(cond
|
||||||
|
(org-roam-mode
|
||||||
|
(add-hook 'find-file-hook #'org-roam--find-file-hook-function)
|
||||||
|
(add-hook 'kill-emacs-hook #'org-roam-db--close-all)
|
||||||
|
(advice-add 'rename-file :after #'org-roam--rename-file-advice)
|
||||||
|
(advice-add 'delete-file :before #'org-roam--delete-file-advice)
|
||||||
|
(org-roam-db-build-cache))
|
||||||
|
(t
|
||||||
|
(remove-hook 'find-file-hook #'org-roam--find-file-hook-function)
|
||||||
|
(remove-hook 'kill-emacs-hook #'org-roam-db--close-all)
|
||||||
|
(advice-remove 'rename-file #'org-roam--rename-file-advice)
|
||||||
|
(advice-remove 'delete-file #'org-roam--delete-file-advice)
|
||||||
|
(org-roam-db--close-all)
|
||||||
|
;; Disable local hooks for all org-roam buffers
|
||||||
|
(dolist (buf (org-roam--get-roam-buffers))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(org-link-set-parameters "file" :face 'org-link)
|
||||||
|
(remove-hook 'post-command-hook #'org-roam-buffer--update-maybe t)
|
||||||
|
(remove-hook 'after-save-hook #'org-roam-db--update-file t))))))
|
||||||
|
|
||||||
|
;;; Interactive Commands
|
||||||
|
;;;###autoload
|
||||||
|
(defalias 'org-roam 'org-roam-buffer-toggle-display)
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun org-roam-diagnostics ()
|
(defun org-roam-diagnostics ()
|
||||||
@ -1187,5 +1036,160 @@ Interactively, or when MESSAGE is non-nil, show in the echo area."
|
|||||||
(insert (format "- Org: %s\n" (org-version nil 'full)))
|
(insert (format "- Org: %s\n" (org-version nil 'full)))
|
||||||
(insert (format "- Org-roam: %s" (org-roam-version)))))
|
(insert (format "- Org-roam: %s" (org-roam-version)))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-roam-find-file (&optional initial-prompt completions filter-fn)
|
||||||
|
"Find and open an Org-roam file.
|
||||||
|
INITIAL-PROMPT is the initial title prompt.
|
||||||
|
COMPLETIONS is a list of completions to be used instead of
|
||||||
|
`org-roam--get-title-path-completions`.
|
||||||
|
FILTER-FN is the name of a function to apply on the candidates
|
||||||
|
which takes as its argument an alist of path-completions. See
|
||||||
|
`org-roam--get-title-path-completions' for details."
|
||||||
|
(interactive)
|
||||||
|
(let* ((completions (--> (or completions
|
||||||
|
(org-roam--get-title-path-completions))
|
||||||
|
(if filter-fn
|
||||||
|
(funcall filter-fn it)
|
||||||
|
it)))
|
||||||
|
(title-with-tags (org-roam-completion--completing-read "File: " completions
|
||||||
|
:initial-input initial-prompt))
|
||||||
|
(res (cdr (assoc title-with-tags completions)))
|
||||||
|
(file-path (plist-get res :path)))
|
||||||
|
(if file-path
|
||||||
|
(find-file file-path)
|
||||||
|
(if (org-roam-capture--in-process-p)
|
||||||
|
(user-error "Org-roam capture in process")
|
||||||
|
(let ((org-roam-capture--info `((title . ,title-with-tags)
|
||||||
|
(slug . ,(org-roam--title-to-slug title-with-tags))))
|
||||||
|
(org-roam-capture--context 'title))
|
||||||
|
(add-hook 'org-capture-after-finalize-hook #'org-roam-capture--find-file-h)
|
||||||
|
(org-roam--with-template-error 'org-roam-capture-templates
|
||||||
|
(org-roam-capture--capture)))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-roam-find-directory ()
|
||||||
|
"Find and open `org-roam-directory'."
|
||||||
|
(interactive)
|
||||||
|
(find-file org-roam-directory))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-roam-find-ref (arg &optional filter)
|
||||||
|
"Find and open an Org-roam file from a ref.
|
||||||
|
ARG is used to forward interactive calls to
|
||||||
|
`org-roam--get-ref-path-completions'
|
||||||
|
FILTER can either be a string or a function:
|
||||||
|
- If it is a string, it should be the type of refs to include as
|
||||||
|
candidates (e.g. \"cite\" ,\"website\" ,etc.)
|
||||||
|
- If it is a function, it should be the name of a function that
|
||||||
|
takes three arguments: the type, the ref, and the file of the
|
||||||
|
current candidate. It should return t if that candidate is to be
|
||||||
|
included as a candidate."
|
||||||
|
(interactive "p")
|
||||||
|
(let* ((completions (org-roam--get-ref-path-completions arg filter))
|
||||||
|
(ref (org-roam-completion--completing-read "Ref: "
|
||||||
|
completions
|
||||||
|
:require-match t))
|
||||||
|
(file (-> (cdr (assoc ref completions))
|
||||||
|
(plist-get :path))))
|
||||||
|
(find-file file)))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-roam-insert (&optional lowercase completions filter-fn description)
|
||||||
|
"Find an Org-roam file, and insert a relative org link to it at point.
|
||||||
|
If LOWERCASE, downcase the title before insertion.
|
||||||
|
COMPLETIONS is a list of completions to be used instead of
|
||||||
|
`org-roam--get-title-path-completions`.
|
||||||
|
FILTER-FN is the name of a function to apply on the candidates
|
||||||
|
which takes as its argument an alist of path-completions.
|
||||||
|
If DESCRIPTION is provided, use this as the link label. See
|
||||||
|
`org-roam--get-title-path-completions' for details."
|
||||||
|
(interactive "P")
|
||||||
|
(let* ((region (and (region-active-p)
|
||||||
|
;; following may lose active region, so save it
|
||||||
|
(cons (region-beginning) (region-end))))
|
||||||
|
(region-text (when region
|
||||||
|
(buffer-substring-no-properties (car region) (cdr region))))
|
||||||
|
(completions (--> (or completions
|
||||||
|
(org-roam--get-title-path-completions))
|
||||||
|
(if filter-fn
|
||||||
|
(funcall filter-fn it)
|
||||||
|
it)))
|
||||||
|
(title-with-tags (org-roam-completion--completing-read "File: " completions
|
||||||
|
:initial-input region-text))
|
||||||
|
(res (cdr (assoc title-with-tags completions)))
|
||||||
|
(title (or (plist-get res :title)
|
||||||
|
title-with-tags))
|
||||||
|
(target-file-path (plist-get res :path))
|
||||||
|
(description (or description region-text title))
|
||||||
|
(link-description (org-roam--format-link-title (if lowercase
|
||||||
|
(downcase description)
|
||||||
|
description))))
|
||||||
|
(if (and target-file-path
|
||||||
|
(file-exists-p target-file-path))
|
||||||
|
(progn
|
||||||
|
(when region ;; Remove previously selected text.
|
||||||
|
(delete-region (car region) (cdr region)))
|
||||||
|
(insert (org-roam--format-link target-file-path link-description)))
|
||||||
|
(when (org-roam-capture--in-process-p)
|
||||||
|
(user-error "Nested Org-roam capture processes not supported"))
|
||||||
|
(let ((org-roam-capture--info `((title . ,title-with-tags)
|
||||||
|
(slug . ,(org-roam--title-to-slug title-with-tags))))
|
||||||
|
(org-roam-capture--context 'title))
|
||||||
|
(add-hook 'org-capture-after-finalize-hook #'org-roam-capture--insert-link-h)
|
||||||
|
(setq org-roam-capture-additional-template-props (list :region region
|
||||||
|
:link-description link-description
|
||||||
|
:capture-fn 'org-roam-insert))
|
||||||
|
(org-roam--with-template-error 'org-roam-capture-templates
|
||||||
|
(org-roam-capture--capture))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-roam-jump-to-index ()
|
||||||
|
"Find the index file in `org-roam-directory'.
|
||||||
|
The path to the index can be defined in `org-roam-index-file'.
|
||||||
|
Otherwise, the function will look in your `org-roam-directory'
|
||||||
|
for a note whose title is 'Index'. If it does not exist, the
|
||||||
|
command will offer you to create one."
|
||||||
|
(interactive)
|
||||||
|
(let ((index (org-roam--get-index-path)))
|
||||||
|
(if (and index
|
||||||
|
(file-exists-p index))
|
||||||
|
(find-file index)
|
||||||
|
(when (y-or-n-p "Index file does not exist. Would you like to create it? ")
|
||||||
|
(org-roam-find-file "Index")))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-roam-switch-to-buffer ()
|
||||||
|
"Switch to an existing Org-roam buffer."
|
||||||
|
(interactive)
|
||||||
|
(let* ((roam-buffers (org-roam--get-roam-buffers))
|
||||||
|
(names-and-buffers (mapcar (lambda (buffer)
|
||||||
|
(cons (or (org-roam--get-title-or-slug
|
||||||
|
(buffer-file-name buffer))
|
||||||
|
(buffer-name buffer))
|
||||||
|
buffer))
|
||||||
|
roam-buffers)))
|
||||||
|
(unless roam-buffers
|
||||||
|
(user-error "No roam buffers"))
|
||||||
|
(when-let ((name (org-roam-completion--completing-read "Buffer: " names-and-buffers
|
||||||
|
:require-match t)))
|
||||||
|
(switch-to-buffer (cdr (assoc name names-and-buffers))))))
|
||||||
|
|
||||||
|
;;;###autoload
|
||||||
|
(defun org-roam-version (&optional message)
|
||||||
|
"Return `org-roam' version.
|
||||||
|
Interactively, or when MESSAGE is non-nil, show in the echo area."
|
||||||
|
(interactive)
|
||||||
|
(let* ((version
|
||||||
|
(with-temp-buffer
|
||||||
|
(insert-file-contents-literally (locate-library "org-roam.el"))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(save-match-data
|
||||||
|
(if (re-search-forward "\\(?:;; Version: \\([^z-a]*?$\\)\\)" nil nil)
|
||||||
|
(substring-no-properties (match-string 1))
|
||||||
|
"N/A")))))
|
||||||
|
(if (or message (called-interactively-p 'interactive))
|
||||||
|
(message "%s" version)
|
||||||
|
version)))
|
||||||
|
|
||||||
(provide 'org-roam)
|
(provide 'org-roam)
|
||||||
;;; org-roam.el ends here
|
;;; org-roam.el ends here
|
||||||
|
Reference in New Issue
Block a user