Create `org-link-parameters'

* lisp/org-element.el: Replace `org-link-types' variable with
  `org-link-types' function.

* lisp/org.el: Replace the `org-link-types' variable with
  `org-link-types' function. Create `org-link-get-parameter' and
  `org-link-set-parameters' functions. Remove `org-add-link-type'. Add
  `org-store-link-functions' function and remove
  `org-store-link-functions' variable. Add `org--open-file-link' for use
  as a :follow function for file type links.

* lisp/org.el: Set :follow functions for file links in `org-link-parameters.
Define `org-open-file-link' that opens a file link with an app.

* testing/lisp/test-ox.el: Remove usage of the `org-link-types'
  variable.

* lisp/org-compat.el: Move `org-add-link-type' and mark it as obsolete.

* lisp/ox.el: Change org-add-link-type comment in ox.el.
This commit is contained in:
John Kitchin 2016-07-07 09:58:29 -04:00 committed by Nicolas Goaziou
parent 481709e11b
commit 9bc2940034
5 changed files with 157 additions and 66 deletions

View File

@ -195,6 +195,37 @@ is, use SPECS to define the face."
specs))
(make-obsolete 'org-compatible-face "you can remove it." "Org 9.0")
(defun org-add-link-type (type &optional follow export)
"Add a new TYPE link.
FOLLOW and EXPORT are two functions.
FOLLOW should take the link path as the single argument and do whatever
is necessary to follow the link, for example find a file or display
a mail message.
EXPORT should format the link path for export to one of the export formats.
It should be a function accepting three arguments:
path the path of the link, the text after the prefix (like \"http:\")
desc the description of the link, if any
format the export format, a symbol like `html' or `latex' or `ascii'.
The function may use the FORMAT information to return different values
depending on the format. The return value will be put literally into
the exported file. If the return value is nil, this means Org should
do what it normally does with links which do not have EXPORT defined.
Org mode has a built-in default for exporting links. If you are happy with
this default, there is no need to define an export function for the link
type. For a simple example of an export function, see `org-bbdb.el'.
If TYPE already exists, update it with the arguments.
See `org-link-parameters' for documentation on the other parameters."
(org-link-set-parameters type :follow follow :export export)
(message "Created %s link." type))
(make-obsolete 'org-add-link-type "org-link-add." "Org 9.0")
;;; Miscellaneous functions

View File

@ -185,7 +185,7 @@ specially in `org-element--object-lex'.")
"\\)\\)")
org-element--object-regexp
(mapconcat #'identity
(let ((link-types (regexp-opt org-link-types)))
(let ((link-types (regexp-opt (org-link-types))))
(list
;; Sub/superscript.
"\\(?:[_^][-{(*+.,[:alnum:]]\\)"
@ -3108,7 +3108,7 @@ Assume point is at the beginning of the link."
(string-match "\\`\\.\\.?/" raw-link))
(setq type "file")
(setq path raw-link))
;; Explicit type (http, irc, bbdb...). See `org-link-types'.
;; Explicit type (http, irc, bbdb...).
((string-match org-link-types-re raw-link)
(setq type (match-string 1 raw-link))
(setq path (substring raw-link (match-end 0))))

View File

@ -1758,6 +1758,73 @@ calls `table-recognize-table'."
"Buffer-local version of `org-link-abbrev-alist', which see.
The value of this is taken from the #+LINK lines.")
(defcustom org-link-parameters
'(("file" :complete org-file-complete-link)
("file+emacs" :follow (lambda (path) (org--open-file-link path '(4))))
("file+sys" :follow (lambda (path) (org--open-file-link path 'system)))
("http") ("https") ("ftp") ("mailto")
("news") ("shell") ("elisp")
("doi") ("message") ("help"))
"An alist of properties that defines all the links in Org mode.
The key in each association is a string of the link type.
Subsequent optional elements make up a p-list of link properties.
:follow - A function that takes the link path as an argument.
:export - A function that takes the link path, description and
export-backend as arguments.
:store - A function responsible for storing the link. See the
function `org-store-link-functions'.
:complete - A function that inserts a link with completion. The
function takes one optional prefix arg.
:face - A face for the link, or a function that returns a face.
The function takes one argument which is the link path. The
default face is `org-link'.
:mouse-face - The mouse-face. The default is `highlight'.
:display - `full' will not fold the link in descriptive
display. Default is `org-link'.
:help-echo - A string or function that takes (window object position)
as arguments and returns a string.
:keymap - A keymap that is active on the link. The default is
`org-mouse-map'.
:htmlize-link - A function for the htmlize-link. Defaults
to (list :uri \"type:path\")
:activate-func - A function to run at the end of font-lock
activation. The function must accept (link-start link-end path bracketp)
as arguments."
:group 'org-link
:type '(alist :tag "Link display parameters"
:value-type plist))
(defun org-link-get-parameter (type key)
"Get TYPE link property for KEY.
TYPE is a string and KEY is a plist keyword."
(plist-get
(cdr (assoc type org-link-parameters))
key))
(defun org-link-set-parameters (type &rest parameters)
"Set link TYPE properties to PARAMETERS.
PARAMETERS should be :key val pairs."
(let ((data (assoc type org-link-parameters)))
(if data (setcdr data (org-combine-plists (cdr data) parameters))
(push (cons type parameters) org-link-parameters)
(org-make-link-regexps)
(org-element-update-syntax))))
(defun org-link-types ()
"Return a list of known link types."
(mapcar #'car org-link-parameters))
(defcustom org-link-abbrev-alist nil
"Alist of link abbreviations.
The car of each element is a string, to be replaced at the start of a link.
@ -5490,7 +5557,7 @@ The following commands are available:
org-display-table 4
(vconcat (mapcar
(lambda (c) (make-glyph-code c (and (not (stringp org-ellipsis))
org-ellipsis)))
org-ellipsis)))
(if (stringp org-ellipsis) org-ellipsis "..."))))
(setq buffer-display-table org-display-table))
(org-set-regexps-and-options)
@ -5658,9 +5725,6 @@ the rounding returns a past time."
(require 'font-lock)
(defconst org-non-link-chars "]\t\n\r<>")
(defvar org-link-types '("http" "https" "ftp" "mailto" "file" "file+emacs"
"file+sys" "news" "shell" "elisp" "doi" "message"
"help"))
(defvar org-link-types-re nil
"Matches a link that has a url-like prefix like \"http:\"")
(defvar org-link-re-with-space nil
@ -5727,8 +5791,8 @@ stacked delimiters is N. Escaping delimiters is not possible."
(defun org-make-link-regexps ()
"Update the link regular expressions.
This should be called after the variable `org-link-types' has changed."
(let ((types-re (regexp-opt org-link-types t)))
This should be called after the variable `org-link-parameters' has changed."
(let ((types-re (regexp-opt (org-link-types) t)))
(setq org-link-types-re
(concat "\\`" types-re ":")
org-link-re-with-space
@ -5766,7 +5830,7 @@ This should be called after the variable `org-link-types' has changed."
org-bracket-link-analytic-regexp++
(concat
"\\[\\["
"\\(" (regexp-opt (cons "coderef" org-link-types) t) ":\\)?"
"\\(" (regexp-opt (cons "coderef" (org-link-types)) t) ":\\)?"
"\\([^]]+\\)"
"\\]"
"\\(\\[" "\\([^]]+\\)" "\\]\\)?"
@ -7393,7 +7457,7 @@ a block. Return a non-nil value when toggling is successful."
;; Remove overlays when changing major mode
(add-hook 'org-mode-hook
(lambda () (add-hook 'change-major-mode-hook
'org-show-block-all 'append 'local)))
'org-show-block-all 'append 'local)))
;;; Org-goto
@ -9666,60 +9730,32 @@ The refresh happens only for the current tree (not subtree)."
(defvar org-store-link-plist nil
"Plist with info about the most recently link created with `org-store-link'.")
(defvar org-link-protocols nil
"Link protocols added to Org-mode using `org-add-link-type'.")
(defun org-store-link-functions ()
"Return a list of functions that are called to create and store a link.
The functions defined in the :store property of
`org-link-parameters'.
(defvar org-store-link-functions nil
"List of functions that are called to create and store a link.
Each function will be called in turn until one returns a non-nil
value. Each function should check if it is responsible for creating
this link (for example by looking at the major mode).
If not, it must exit and return nil.
If yes, it should return a non-nil value after a calling
`org-store-link-props' with a list of properties and values.
Special properties are:
value. Each function should check if it is responsible for
creating this link (for example by looking at the major mode).
If not, it must exit and return nil. If yes, it should return
a non-nil value after calling `org-store-link-props' with a list
of properties and values. Special properties are:
:type The link prefix, like \"http\". This must be given.
:link The link, like \"http://www.astro.uva.nl/~dominik\".
This is obligatory as well.
:description Optional default description for the second pair
of brackets in an Org-mode link. The user can still change
this when inserting this link into an Org-mode buffer.
of brackets in an Org mode link. The user can still change
this when inserting this link into an Org mode buffer.
In addition to these, any additional properties can be specified
and then used in capture templates.")
(defun org-add-link-type (type &optional follow export)
"Add TYPE to the list of `org-link-types'.
Re-compute all regular expressions depending on `org-link-types'
FOLLOW and EXPORT are two functions.
FOLLOW should take the link path as the single argument and do whatever
is necessary to follow the link, for example find a file or display
a mail message.
EXPORT should format the link path for export to one of the export formats.
It should be a function accepting three arguments:
path the path of the link, the text after the prefix (like \"http:\")
desc the description of the link, if any
format the export format, a symbol like `html' or `latex' or `ascii'.
The function may use the FORMAT information to return different values
depending on the format. The return value will be put literally into
the exported file. If the return value is nil, this means Org should
do what it normally does with links which do not have EXPORT defined.
Org mode has a built-in default for exporting links. If you are happy with
this default, there is no need to define an export function for the link
type. For a simple example of an export function, see `org-bbdb.el'."
(add-to-list 'org-link-types type t)
(org-make-link-regexps)
(org-element-update-syntax)
(if (assoc type org-link-protocols)
(setcdr (assoc type org-link-protocols) (list follow export))
(push (list type follow export) org-link-protocols)))
and then used in capture templates."
(cl-loop for link in org-link-parameters
with store-func
do (setq store-func (org-link-get-parameter (car link) :store))
if store-func
collect store-func))
(defvar org-agenda-buffer-name) ; Defined in org-agenda.el
(defvar org-id-link-to-org-use-id) ; Defined in org-id.el
@ -9764,7 +9800,7 @@ active region."
(delq
nil (mapcar (lambda (f)
(let (fs) (if (funcall f) (push f fs))))
org-store-link-functions))
(org-store-link-functions)))
sfunsn (mapcar (lambda (fu) (symbol-name (car fu))) sfuns))
(or (and (cdr sfuns)
(funcall (intern
@ -10325,7 +10361,7 @@ Use TAB to complete link prefixes, then RET for type-specific completion support
(and (window-live-p cw) (select-window cw)))
(setq all-prefixes (append (mapcar 'car abbrevs)
(mapcar 'car org-link-abbrev-alist)
org-link-types))
(org-link-types)))
(unwind-protect
;; Fake a link history, containing the stored links.
(let ((org--links-history
@ -10601,6 +10637,30 @@ they must return nil.")
(defvar org-link-search-inhibit-query nil) ;; dynamically scoped
(defvar clean-buffer-list-kill-buffer-names) ; Defined in midnight.el
(defun org--open-file-link (path app)
"Open PATH using APP.
PATH is from a file link, and can have the following syntax:
[[file:~/code/main.c::255]]
[[file:~/xx.org::My Target]]
[[file:~/xx.org::*My Target]]
[[file:~/xx.org::#my-custom-id]]
[[file:~/xx.org::/regexp/]]
If APP is non-nil, open PATH in Emacs. If it is `system', use
a system application instead."
(let* ((fields (split-string path "::"))
(option (and (cdr fields)
(mapconcat #'identity (cdr fields) ""))))
(apply #'org-open-file
(car fields)
app
(cond ((not option) nil)
((string-match-p "\\`[0-9]+\\'" option)
(list (string-to-number option)))
(t (list nil
(org-link-unescape option)))))))
(defun org-open-at-point (&optional arg reference-buffer)
"Open link, timestamp, footnote or tags at point.

View File

@ -4073,7 +4073,7 @@ meant to be translated with `org-export-data' or alike."
;;;; For Links
;;
;; `org-export-custom-protocol-maybe' handles custom protocol defined
;; with `org-add-link-type', which see.
;; in `org-link-parameters'.
;;
;; `org-export-get-coderef-format' returns an appropriate format
;; string for coderefs.

View File

@ -2571,8 +2571,8 @@ Para2"
(should
(string-match
"success"
(let ((org-link-types (copy-sequence org-link-types)))
(org-add-link-type "foo" nil (lambda (p d f) "success"))
(progn
(org-link-set-parameters "foo" :export (lambda (p d f) "success"))
(org-export-string-as
"[[foo:path]]"
(org-export-create-backend
@ -2586,9 +2586,9 @@ Para2"
(should-not
(string-match
"success"
(let ((org-link-types (copy-sequence org-link-types)))
(org-add-link-type
"foo" nil (lambda (p d f) (and (eq f 'test) "success")))
(progn
(org-link-set-parameters
"foo" :export (lambda (p d f) (and (eq f 'test) "success")))
(org-export-string-as
"[[foo:path]]"
(org-export-create-backend
@ -2603,9 +2603,9 @@ Para2"
(should-not
(string-match
"success"
(let ((org-link-types (copy-sequence org-link-types)))
(org-add-link-type
"foo" nil (lambda (p d f) (and (eq f 'test) "success")))
(progn
(org-link-set-parameters
"foo" :export (lambda (p d f) (and (eq f 'test) "success")))
(org-export-string-as
"[[foo:path]]"
(org-export-create-backend