summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Kitchin <jkitchin@andrew.cmu.edu>2016-07-07 09:58:29 -0400
committerNicolas Goaziou <mail@nicolasgoaziou.fr>2016-07-18 22:47:42 +0200
commit9bc294003417a17c58b1c25156a885b5ac109309 (patch)
tree550191e429f9f9dcb0b3137756b4f4b8c98b70f2
parent481709e11bef2e437d9ec25333da2208af34f184 (diff)
downloadorg-mode-9bc294003417a17c58b1c25156a885b5ac109309.tar.gz
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.
-rw-r--r--lisp/org-compat.el31
-rw-r--r--lisp/org-element.el4
-rw-r--r--lisp/org.el170
-rw-r--r--lisp/ox.el2
-rw-r--r--testing/lisp/test-ox.el16
5 files changed, 157 insertions, 66 deletions
diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 92fdb1c..5dd3d40 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -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
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 269bc7d..4079a5f 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -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))))
diff --git a/lisp/org.el b/lisp/org.el
index 0c8a42b..bd278c0 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -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.
diff --git a/lisp/ox.el b/lisp/ox.el
index da985f3..3986ec3 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -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.
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 8b07cca..09d2e2a 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -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