emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* Draft of links-9.0
@ 2016-07-05 14:50 John Kitchin
  2016-07-05 19:12 ` Nicolas Goaziou
  0 siblings, 1 reply; 6+ messages in thread
From: John Kitchin @ 2016-07-05 14:50 UTC (permalink / raw)
  To: emacs-orgmode@gnu.org

Hi all,

I have completed a draft of links-9.0
(https://github.com/jkitchin/org-mode/tree/link-9.0). This centralizes
almost all link properties into a variable `org-link-parameters' and
makes it possible to customize almost everything in the link.

This branch passes all the tests except these: 2 unexpected results:
FAILED ob-shell/bash-uses-assoc-arrays FAILED
test-ob/indented-cached-org-bracket-link

which also fail for me on master. There are about 27 commits from this
branch to master I think. I didn't make patches for all of them yet,
since that seemed like a bunch of them. This branch doesn't fix anything
in contrib yet (except the manual).

I am pretty sure all the previous link behavior has been preserved, and
a lot of new things are possible with this. Below are some example uses.
Let me know what you think!

* Example links 
** A basic link
Predefined links work the same as before.

A doi:10.1021 link and [[doi:10.1021][bracketed version]].  

This should look and act like it did before.
#+BEGIN_SRC emacs-lisp
  (org-add-link-type
   "test" nil nil)
#+END_SRC

#+RESULTS:
: Created test link.

A test:link and [[test:link][bracketed form]]     

** A colored link with a static tooltip.
#+BEGIN_SRC emacs-lisp
  (org-add-link-type
   "red"
   ;; follow
   (lambda (path) (message "You clicked me."))
   ;; export
   (lambda (path desc backend)
     (cond
      ((eq 'html backend)
       (format "<font color=\"red\">%s</font>"
	       (or desc path)))))
   :face '(:foreground "red")
   :help-echo "Click me for a message.")
#+END_SRC

#+RESULTS:
: Created red link.

A red:link that is colored red.  In bracketed form:  A [[red:link][link
with a description]].       

** A link with defface

#+BEGIN_SRC emacs-lisp
(defface org-link-green
  '((t (:inherit org-link :foreground "green")))
  "A green link.")

(org-add-link-type
   "green"
   ;; follow
   (lambda (path) (message "You clicked me."))
   ;; export
   (lambda (path desc backend)
     (cond
      ((eq 'html backend)
       (format "<font color=\"green\">%s</font>"
	       (or desc path)))))
   :face 'org-link-green
   :help-echo "Click me for a message.")
#+END_SRC

#+RESULTS:
: Created green link.

A green:link works. 

** A colored link with a static tooltip and no folding.
This link will be shown in full unfolded form even when other links are
folded in descriptive format. 

#+BEGIN_SRC emacs-lisp
  (org-add-link-type
   "red-full"
   ;; follow
   (lambda (path) (message "You clicked me."))
   ;; export
   (lambda (path desc backend)
     (cond
      ((eq 'html backend)
       (format "<font color=\"red\">%s</font>"
	       (or desc path)))))
   :face '(:foreground "red")
   :display 'full
   :help-echo "Click me for a message.")
#+END_SRC

#+RESULTS:
: Created red-full link.

A red-full:link that is colored red.  In bracketed form:  A
[[red-full:link][link with a description]].      [[doi:test][bracketed
doi]] 

** A dynamic tooltip
You can make tooltips dynamic. The function must take these arguments
(window object position), and construct the tooltip from that
information. Here is one way.

#+BEGIN_SRC emacs-lisp
  (defun redd-tip (window object position)
    (save-excursion
      (goto-char position)
      (goto-char (org-element-property :begin (org-element-context)))
      (cond ((looking-at org-plain-link-re)
	     (format "Looking at %s with mouse at %s" (match-string 0) position))
	    ((looking-at org-bracket-link-regexp)
	     (format "Looking at %s in a bracketed link with mouse at %s" (match-string 0) position))
	    (t
	     "No match"))))

  (org-add-link-type "redd" nil nil :face '(:underline t) :help-echo 'redd-tip)
#+END_SRC

#+RESULTS:
: Created redd link.


A link with a dynamic tooltip: redd:link or this one redd:another-link
[[redd:test][bracketed redd]]     

** A link with a modified keymap
This is not new behavior, you could always add new key bindings to the
org-mouse-map. You probably don't want to define characters here, since
it would lead to editing problems. Note this affects all links now,
however. 

#+BEGIN_SRC emacs-lisp
  (defun s-click ()
    (interactive)
    (message-box "You always wanted this right ;)"))

  (org-defkey org-mouse-map [s-mouse-1] 's-click)
  (org-defkey org-mouse-map [C-up] (lambda ()
				     (interactive)
				     (message-box "Got C-up")))

  (org-add-link-type "mouse-1" nil nil)
#+END_SRC

#+RESULTS:
: Created mouse-1 link.

mouse-1:test   

** a link with a new keymap.
To get a special keymap, we have to create a new keymap. We can make a
copy of org-mouse-map and add new keys to it that are specific to this
link. 

#+BEGIN_SRC emacs-lisp
  (defun prev-link ()
    (interactive)
    (re-search-backward "keym:" nil t))

  (defun next-link ()
    (interactive)
    (re-search-forward "keym:" nil t))

  (org-add-link-type "keym"
		     (lambda (path)
		       (interactive)
		       (message "You followed me."))
		     nil
		     :keymap (let ((map (copy-keymap org-mouse-map)))
			       (define-key map (kbd "C-<left>") 'prev-link)
			       (define-key map (kbd "C-<right>") 'next-link)
			       (define-key map (kbd "C-<up>") (lambda ()(interactive)(message-box "special C-up")))
			       (define-key map [s-mouse-1] (lambda ()
							     (interactive)
							     (message-box "s-Followed")))
			       map))
#+END_SRC

#+RESULTS:
: Created keym link.

 keym:one  then keym:two and finally keym:three            

** a completion example with a dynamic face for validation
This example shows how to add a completion function, and use a dynamic
face to show when a bad link has been made (in this case there are 4
allowed fruits, and anything else should be red. 

#+BEGIN_SRC emacs-lisp
  (defun my-comp (&optional arg)
   (format "fruit:%s"
	   (completing-read "Choose a fruit: " '("apple" "orange" "grapes" "kiwi"))))


  (defun fruit-link-face (path)
    (if (member path '("apple" "orange" "grapes" "kiwi"))
	'org-link
      '(:foreground "red")))

  (defun fruit-tooltip (_win _obj position)
    (save-match-data
      (save-excursion
	(goto-char position)
	(let ((path (org-element-property :path (org-element-context))))
	  (if (member path '("apple" "orange" "grapes" "kiwi"))
	      "A fruit"
	    (format "%s: Illegal value. Must be one of apple, orange, grapes or kiwi."
		    path))))))

  (org-add-link-type "fruit" nil nil

		     :help-echo 'fruit-tooltip
		     :face 'fruit-link-face
		     :complete 'my-comp)
#+END_SRC

#+RESULTS:
: Created fruit link.

[[fruit:apple]]         [[fruit:orange][an orange in brackets]]            
    
      a bad fruit:grapefruit.   
      
[[fruit:kiwi]]

** a store link example

[[head:*a%20store%20link%20example][a store link example]]

#+BEGIN_SRC emacs-lisp
  (defun store-my-headline ()
    (when (and (eq major-mode 'org-mode)
	       (org-at-heading-p))
      (org-store-link-props
       :type "head"
       :link (format "head:*%s" (nth 4 (org-heading-components)))
       :description (nth 4 (org-heading-components)))))

  (defun follow-head (path)
    (org-open-link-from-string (format "[[%s]]" path)))

  (org-add-link-type "head" 'follow-head nil :store 'store-my-headline)
#+END_SRC

#+RESULTS:
: Created head link.

** an activate-func example
You may want to do some additional things when a link is activated. For
example, maybe it makes sense for different parts of the link to have
different actions,  or colors. Here is an example where we make an rgb
link of three numbers, and color each number, and make the link color
dynamic. 

This is an rgb link with three comma separated numbers. We color each
number accordingly, and set the rgb link to the color represented by the
RGB pair. 

rgb:238,130,238  This is a violet color.               

rgb:225,225,225  This is a light gray.     

A subtle point in this example is the need to save-match-data. Some
functions modify the match-data, and this will mess up the whole
font-lock system. 

#+BEGIN_SRC emacs-lisp
  (require 'color)

  (defun rgb-face (path)
    (let* ((f (split-string path ","))
	     (red (/ (string-to-number (nth 0 f)) 255.0))
	     (green (/ (string-to-number (nth 1 f)) 255.0))
	     (blue (/ (string-to-number (nth 2 f)) 255.0))
	     (hex (color-rgb-to-hex red green blue)))
      (list :foreground hex)))

  (defun rgb-func (start end path bracketp) 
    (save-excursion
      (goto-char start)
      (save-match-data
	(cl-loop for num in (split-string path ",")
		 for face in (list '(:foreground "red")
				   '(:foreground "green")
				   '(:foreground "blue"))
		 do
		 (progn
		   (re-search-forward num end t)
		   (add-text-properties
		    (match-beginning 0)
		    (match-end 0)
		    (list 'face face)))))))

  (org-add-link-type "rgb" nil nil :face 'rgb-face :activate-func 'rgb-func)
#+END_SRC

#+RESULTS:
: Created rgb link.
 

 

-- 
Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
@johnkitchin
http://kitchingroup.cheme.cmu.edu

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Draft of links-9.0
  2016-07-05 14:50 Draft of links-9.0 John Kitchin
@ 2016-07-05 19:12 ` Nicolas Goaziou
  2016-07-05 19:42   ` Nicolas Goaziou
  2016-07-05 20:30   ` John Kitchin
  0 siblings, 2 replies; 6+ messages in thread
From: Nicolas Goaziou @ 2016-07-05 19:12 UTC (permalink / raw)
  To: John Kitchin; +Cc: emacs-orgmode@gnu.org

Hello,

John Kitchin <jkitchin@andrew.cmu.edu> writes:

> I have completed a draft of links-9.0
> (https://github.com/jkitchin/org-mode/tree/link-9.0). This centralizes
> almost all link properties into a variable `org-link-parameters' and
> makes it possible to customize almost everything in the link.

Thank you.

> which also fail for me on master. There are about 27 commits from this
> branch to master I think. I didn't make patches for all of them yet,
> since that seemed like a bunch of them. This branch doesn't fix anything
> in contrib yet (except the manual).

I'm surprised there are so many of them. Anyway, it would be nice to
display them here, for review.

> I am pretty sure all the previous link behavior has been preserved, and
> a lot of new things are possible with this. Below are some example uses.
> Let me know what you think!
>
> * Example links 
> ** A basic link
> Predefined links work the same as before.
>
> A doi:10.1021 link and [[doi:10.1021][bracketed version]].  
>
> This should look and act like it did before.
> #+BEGIN_SRC emacs-lisp
>   (org-add-link-type
>    "test" nil nil)
> #+END_SRC
>
> #+RESULTS:
> : Created test link.
>
> A test:link and [[test:link][bracketed form]]     
>
> ** A colored link with a static tooltip.
> #+BEGIN_SRC emacs-lisp
>   (org-add-link-type
>    "red"
>    ;; follow
>    (lambda (path) (message "You clicked me."))
>    ;; export
>    (lambda (path desc backend)
>      (cond
>       ((eq 'html backend)
>        (format "<font color=\"red\">%s</font>"
> 	       (or desc path)))))
>    :face '(:foreground "red")
>    :help-echo "Click me for a message.")
> #+END_SRC

Please do not extend `org-add-link-type': you are conflating two ways to
set the same thing. 

It is better to create a new function, e.g., `org-link-add' with the
following signature

  (defun org-link-add (type &rest properties)
   ...)

used like

  (org-link-add "red" :follow (lambda (path desc backend) ...) :export ....)

and keep `org-add-link-type' as a _deprecated_ function basically
calling the previous one:

  (defun org-add-link-type (type &optional follow export)
   (org-link-add type :follow follow :export export))

Otherwise, it looks good.


Regards,

-- 
Nicolas Goaziou

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Draft of links-9.0
  2016-07-05 19:12 ` Nicolas Goaziou
@ 2016-07-05 19:42   ` Nicolas Goaziou
  2016-07-05 20:30   ` John Kitchin
  1 sibling, 0 replies; 6+ messages in thread
From: Nicolas Goaziou @ 2016-07-05 19:42 UTC (permalink / raw)
  To: John Kitchin; +Cc: emacs-orgmode@gnu.org

Completing myself,

Nicolas Goaziou <mail@nicolasgoaziou.fr> writes:

> It is better to create a new function, e.g., `org-link-add' with the
> following signature
>
>   (defun org-link-add (type &rest properties)
>    ...)
>
> used like
>
>   (org-link-add "red" :follow (lambda (path desc backend) ...) :export ....)

Basically, `org-link-add' is `org-link-set-parameters', so it two
different functions may not even be needed in this case.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Draft of links-9.0
  2016-07-05 19:12 ` Nicolas Goaziou
  2016-07-05 19:42   ` Nicolas Goaziou
@ 2016-07-05 20:30   ` John Kitchin
  2016-07-05 21:56     ` Nicolas Goaziou
  1 sibling, 1 reply; 6+ messages in thread
From: John Kitchin @ 2016-07-05 20:30 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode@gnu.org


Nicolas Goaziou writes:

> Hello,
>
> John Kitchin <jkitchin@andrew.cmu.edu> writes:
>
>> I have completed a draft of links-9.0
>> (https://github.com/jkitchin/org-mode/tree/link-9.0). This centralizes
>> almost all link properties into a variable `org-link-parameters' and
>> makes it possible to customize almost everything in the link.
>
> Thank you.
No problem.

>
>> which also fail for me on master. There are about 27 commits from this
>> branch to master I think. I didn't make patches for all of them yet,
>> since that seemed like a bunch of them. This branch doesn't fix anything
>> in contrib yet (except the manual).
>
> I'm surprised there are so many of them. Anyway, it would be nice to
> display them here, for review.

I pasted the diffs at the end. There are a lot because it touched a lot of
files, and I committed each one separately, and forgot a few commits
that ended up as extras. Probably some could be combined and squashed if
that is desirable. I am not sure how to do it yet though.


> Please do not extend `org-add-link-type': you are conflating two ways to
> set the same thing. 
>
> It is better to create a new function, e.g., `org-link-add' with the
> following signature
>
>   (defun org-link-add (type &rest properties)
>    ...)
>
> used like
>
>   (org-link-add "red" :follow (lambda (path desc backend) ...) :export ....)
>
> and keep `org-add-link-type' as a _deprecated_ function basically
> calling the previous one:
>
>   (defun org-add-link-type (type &optional follow export)
>    (org-link-add type :follow follow :export export))

I did all of this in the commits that are listed below. There is no formal
deprecation on org-add-link-type, other than a note in the docstring.

I still haven't touched anything in contrib.


>
> Otherwise, it looks good.
>
>
> Regards,

commit 546031bb7b59a9deb6bce976f7f7496ea7b2ffc4
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:16:29 2016 -0400

    add link-start and link-end variables

diff --git a/lisp/org.el b/lisp/org.el
index 872f861..684eae0 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5927,6 +5927,8 @@ prompted for."
 	   (link (match-string-no-properties 0))
 	   (type (match-string-no-properties 1))
 	   (path (match-string-no-properties 2))
+	   (link-start (match-beginning 0))
+	   (link-end (match-end 0))
 	   (link-face (org-link-get-parameter type :face))
 	   (help-echo (org-link-get-parameter type :help-echo))	   
 	   (htmlize-link (org-link-get-parameter type :htmlize-link))

commit d1799252a7e4bd255a5507d742e0b0a7c19983b1
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:16:02 2016 -0400

    deprecate org-add-link-type
    
    It now calls org-link-add.

diff --git a/lisp/org.el b/lisp/org.el
index 4fb1cfb..872f861 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9852,10 +9852,10 @@ Special properties are:
 In addition to these, any additional properties can be specified
 and then used in capture templates.")
 
-(cl-defun org-add-link-type (type &optional follow export
-				  &key store complete face mouse-face display
-				  help-echo keymap htmlize-link activate-func)
+(defun org-add-link-type (type &optional follow export)
   "Add a new TYPE link.
+Deprecated. Use `org-link-add' instead.
+
 FOLLOW and EXPORT are two functions.
 
 FOLLOW should take the link path as the single argument and do whatever
@@ -9880,20 +9880,7 @@ 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."
-  (if (assoc type org-link-parameters)
-      (org-link-set-parameters
-       type :follow follow :export export :store store
-       :complete complete :face face :mouse-face mouse-face
-       :display display :help-echo help-echo :keymap keymap
-       :htmlize-link htmlize-link :activate-func activate-func)
-    ;; Add new link
-    (push (list type :follow follow :export export :store store
-		:complete complete :face face :mouse-face mouse-face
-		:display display :help-echo help-echo :keymap keymap
-		:htmlize-link htmlize-link :activate-func activate-func)
-	  org-link-parameters))
-  (org-make-link-regexps)
-  (org-element-update-syntax)
+  (org-link-add type :follow follow :export export) 
   (message "Created %s link." type))
 
   (defun org-store-link-functions ()

commit 4b2cc306d43c7b641690a2feb7f78881025bf3e8
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:15:11 2016 -0400

    make set-parameters only set existing parameters.
    
    Create a new org-link-add function for making links.

diff --git a/lisp/org.el b/lisp/org.el
index 3e80243..4fb1cfb 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -1796,20 +1796,24 @@ Subsequent optional elements make up a p-list of link properties.
 (defun org-link-set-parameters (type &rest parameters)
   "Set link TYPE properties to PARAMETERS.
 PARAMETERS should be :key val pairs."
-  (if (cdr (assoc type org-link-parameters))
-      ;; update old link
-      (cl-loop for (key val) on parameters by #'cddr
-	       do
-	       (setf (cl-getf
-		      (cdr (assoc type org-link-parameters))
-		      key)
-		     val))
-    ;; add new one.
-    (push `(,type ,@parameters) org-link-parameters)
-    (org-make-link-regexps)
-    (org-element-update-syntax))
+  (unless (cdr (assoc type org-link-parameters))
+    (error "No link of type %s defined." type))
+  (cl-loop for (key val) on parameters by #'cddr
+	   do
+	   (setf (cl-getf
+		  (cdr (assoc type org-link-parameters))
+		  key)
+		 val))
   org-link-parameters)
 
+(defun org-link-add (type &rest properties)
+  "Add a TYPE link with PROPERTIES defined as a plist.
+See `org-link-parameters' for details on the PROPERTIES." 
+  (push (append (list type) properties)
+	org-link-parameters)
+  (org-make-link-regexps)
+  (org-element-update-syntax))
+
 (defun org-link-types ()
   "Returns a list of known link types."
   (mapcar 'car org-link-parameters))

commit 1069d9bac0974f27abda2736fef883eb8334c761
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:14:02 2016 -0400

    update comment for new variable.

diff --git a/lisp/ox.el b/lisp/ox.el
index 0b749e8..8472e9d 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.

commit 70ccc670145312907fa3a0c62a3a9dd9dc3ef38e
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:12:36 2016 -0400

    change to org-link-add

diff --git a/lisp/org-rmail.el b/lisp/org-rmail.el
index 9eff516..a3a17df 100644
--- a/lisp/org-rmail.el
+++ b/lisp/org-rmail.el
@@ -43,7 +43,7 @@
 (defvar rmail-file-name)        ; From rmail.el
 
 ;; Install the link type
-(org-add-link-type "rmail" 'org-rmail-open nil :store 'org-rmail-store-link)
+(org-link-add "rmail" :follow 'org-rmail-open :store 'org-rmail-store-link)
 
 ;; Implementation
 (defun org-rmail-store-link ()

commit 7890d9b5dc5d08d8d8d9069d3caa72873d0eee14
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:12:13 2016 -0400

    change to org-link-add

diff --git a/lisp/org-mhe.el b/lisp/org-mhe.el
index ca8b68d..3fb9e4b 100644
--- a/lisp/org-mhe.el
+++ b/lisp/org-mhe.el
@@ -74,7 +74,7 @@ supported by MH-E."
 (defvar mh-search-regexp-builder)
 
 ;; Install the link type
-(org-add-link-type "mhe" 'org-mhe-open nil :store 'org-mhe-store-link)
+(org-link-add "mhe" :follow 'org-mhe-open :store 'org-mhe-store-link)
 
 ;; Implementation
 (defun org-mhe-store-link ()

commit 3a9bfa47a89bcaef41aecedcaa4a044421a3b755
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:11:44 2016 -0400

    add properties

diff --git a/lisp/org-irc.el b/lisp/org-irc.el
index 4996d60..3e97a5f 100644
--- a/lisp/org-irc.el
+++ b/lisp/org-irc.el
@@ -71,7 +71,7 @@
 
 ;; Generic functions/config (extend these for other clients)
 
-(org-add-link-type "irc" 'org-irc-visit nil :store 'org-irc-store-link)
+(org-link-add "irc" :follow 'org-irc-visit :store 'org-irc-store-link)
 
 (defun org-irc-visit (link)
   "Parse LINK and dispatch to the correct function based on the client found."

commit 87b51146f1496c746aed87b4b16a0c085dbb803d
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:11:26 2016 -0400

    add properties

diff --git a/lisp/org-info.el b/lisp/org-info.el
index 156de34..45e63ac 100644
--- a/lisp/org-info.el
+++ b/lisp/org-info.el
@@ -40,7 +40,7 @@
 (defvar Info-current-node)
 
 ;; Install the link type
-(org-link-add "info" 'org-info-open 'org-info-export :store 'org-info-store-link)
+(org-link-add "info" :follow 'org-info-open :export 'org-info-export :store 'org-info-store-link)
 
 ;; Implementation
 (defun org-info-store-link ()

commit d7f9c45e39bc17850f7efd32208ce2fd57290cba
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:11:08 2016 -0400

    change to org-link-add

diff --git a/lisp/org-id.el b/lisp/org-id.el
index 2646c80..30b3558 100644
--- a/lisp/org-id.el
+++ b/lisp/org-id.el
@@ -675,7 +675,7 @@ optional argument MARKERP, return the position as a new marker."
     (move-marker m nil)
     (org-show-context)))
 
-(org-add-link-type "id" 'org-id-open)
+(org-link-add "id" :follow 'org-id-open)
 
 (provide 'org-id)
 

commit 6c0db58062879bad1b0f6bf39e3f378eb65bbb4f
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:10:42 2016 -0400

    add property

diff --git a/lisp/org-gnus.el b/lisp/org-gnus.el
index 47f5250..f1a557c 100644
--- a/lisp/org-gnus.el
+++ b/lisp/org-gnus.el
@@ -74,7 +74,7 @@ this variable to t."
   :type 'boolean)
 
 ;; Install the link type
-(org-link-add "gnus" 'org-gnus-open nil :store 'org-gnus-store-link)
+(org-link-add "gnus" :follow 'org-gnus-open :store 'org-gnus-store-link)
 
 ;; Implementation
 

commit 73f7803d8ee752fd22e3621a1197c114e4e7f635
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:10:26 2016 -0400

    add property

diff --git a/lisp/org-eshell.el b/lisp/org-eshell.el
index 04cc600..358bf67 100644
--- a/lisp/org-eshell.el
+++ b/lisp/org-eshell.el
@@ -27,7 +27,8 @@
 (require 'eshell)
 (require 'esh-mode)
 
-(org-link-add "eshell" 'org-eshell-open nil
+(org-link-add "eshell"
+	      :follow 'org-eshell-open
 	      :store 'org-eshell-store-link)
 
 (defun org-eshell-open (link)

commit d5c31edc8a29829645a67657100997265a821708
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:10:07 2016 -0400

    add properties

diff --git a/lisp/org-docview.el b/lisp/org-docview.el
index 6f3dcdd..04f7ec2 100644
--- a/lisp/org-docview.el
+++ b/lisp/org-docview.el
@@ -49,7 +49,10 @@
 (declare-function doc-view-goto-page "doc-view" (page))
 (declare-function image-mode-window-get "image-mode" (prop &optional winprops))
 
-(org-link-add "docview" 'org-docview-open 'org-docview-export :store 'org-docview-store-link)
+(org-link-add "docview"
+	      :follow 'org-docview-open
+	      :export 'org-docview-export
+	      :store 'org-docview-store-link)
 
 (defun org-docview-export (link description format)
   "Export a docview link from Org files."

commit b47d402b475ce89fcd765c579ee4f9320ba18723
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:09:44 2016 -0400

    add property

diff --git a/lisp/org-bibtex.el b/lisp/org-bibtex.el
index 8fcbbca..900d570 100644
--- a/lisp/org-bibtex.el
+++ b/lisp/org-bibtex.el
@@ -452,7 +452,7 @@ With optional argument OPTIONAL, also prompt for optional fields."
 
 \f
 ;;; Bibtex link functions
-(org-link-add "bibtex" 'org-bibtex-open nil :store 'org-bibtex-store-link)
+(org-link-add "bibtex" :follow 'org-bibtex-open nil :store 'org-bibtex-store-link)
 
 (defun org-bibtex-open (path)
   "Visit the bibliography entry on PATH."

commit 349604076b8609f4e7fa612824a384fbe8bf7774
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:09:28 2016 -0400

    add properties

diff --git a/lisp/org-bbdb.el b/lisp/org-bbdb.el
index 2241b15..748aa4b 100644
--- a/lisp/org-bbdb.el
+++ b/lisp/org-bbdb.el
@@ -196,7 +196,7 @@ date year)."
 
 
 ;; Install the link type
-(org-link-add "bbdb" 'org-bbdb-open 'org-bbdb-export
+(org-link-add "bbdb" :follow 'org-bbdb-open :export 'org-bbdb-export
 	      :complete 'org-bbdb-complete-link
 	      :store 'org-bbdb-store-link)
 

commit a9dcab24cce7826ff80c83ba278304badbc0bc8c
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:08:23 2016 -0400

    change doc string to point to new variable.

diff --git a/lisp/org-info.el b/lisp/org-info.el
index 627caf7..156de34 100644
--- a/lisp/org-info.el
+++ b/lisp/org-info.el
@@ -112,7 +112,7 @@ emacs related documents. See `org-info-official-gnu-document' and
 
 (defun org-info-export (path desc format)
   "Export an info link.
-See `org-add-link-type' for details about PATH, DESC and FORMAT."
+See `org-link-parameters' for details about PATH, DESC and FORMAT."
   (when (eq format 'html)
     (or (string-match "\\(.*\\)[#:]:?\\(.*\\)" path)
 	(string-match "\\(.*\\)" path))

commit 73af2a5192d85752517505e34d297de9f7de8d2b
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:07:40 2016 -0400

    change to org-link-add

diff --git a/lisp/org-info.el b/lisp/org-info.el
index d9e9b07..627caf7 100644
--- a/lisp/org-info.el
+++ b/lisp/org-info.el
@@ -40,7 +40,7 @@
 (defvar Info-current-node)
 
 ;; Install the link type
-(org-add-link-type "info" 'org-info-open 'org-info-export :store 'org-info-store-link)
+(org-link-add "info" 'org-info-open 'org-info-export :store 'org-info-store-link)
 
 ;; Implementation
 (defun org-info-store-link ()

commit 9010641c4b7736c1d194d4dc4d6fded2896520ff
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:07:07 2016 -0400

    change to org-link-add

diff --git a/lisp/org-gnus.el b/lisp/org-gnus.el
index 271f480..47f5250 100644
--- a/lisp/org-gnus.el
+++ b/lisp/org-gnus.el
@@ -74,7 +74,7 @@ this variable to t."
   :type 'boolean)
 
 ;; Install the link type
-(org-add-link-type "gnus" 'org-gnus-open nil :store 'org-gnus-store-link)
+(org-link-add "gnus" 'org-gnus-open nil :store 'org-gnus-store-link)
 
 ;; Implementation
 

commit 2255bb886e2aa0026ad72a20a658ea682db47f8f
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:06:48 2016 -0400

    change to org-link-add

diff --git a/lisp/org-eshell.el b/lisp/org-eshell.el
index 4782d94..04cc600 100644
--- a/lisp/org-eshell.el
+++ b/lisp/org-eshell.el
@@ -27,8 +27,8 @@
 (require 'eshell)
 (require 'esh-mode)
 
-(org-add-link-type "eshell" 'org-eshell-open nil
-		   :store 'org-eshell-store-link)
+(org-link-add "eshell" 'org-eshell-open nil
+	      :store 'org-eshell-store-link)
 
 (defun org-eshell-open (link)
   "Switch to am eshell buffer and execute a command line.

commit 376737075c6bbcbd3ba70bd93e83882d30e5da80
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:06:27 2016 -0400

    change to org-link-add

diff --git a/lisp/org-docview.el b/lisp/org-docview.el
index 3e8f659..6f3dcdd 100644
--- a/lisp/org-docview.el
+++ b/lisp/org-docview.el
@@ -49,7 +49,7 @@
 (declare-function doc-view-goto-page "doc-view" (page))
 (declare-function image-mode-window-get "image-mode" (prop &optional winprops))
 
-(org-add-link-type "docview" 'org-docview-open 'org-docview-export :store 'org-docview-store-link)
+(org-link-add "docview" 'org-docview-open 'org-docview-export :store 'org-docview-store-link)
 
 (defun org-docview-export (link description format)
   "Export a docview link from Org files."

commit 3ad9203d9d944633b0779840057051b017b907c8
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:06:04 2016 -0400

    change to org-link-add

diff --git a/lisp/org-bibtex.el b/lisp/org-bibtex.el
index db30510..8fcbbca 100644
--- a/lisp/org-bibtex.el
+++ b/lisp/org-bibtex.el
@@ -452,7 +452,7 @@ With optional argument OPTIONAL, also prompt for optional fields."
 
 \f
 ;;; Bibtex link functions
-(org-add-link-type "bibtex" 'org-bibtex-open nil :store 'org-bibtex-store-link)
+(org-link-add "bibtex" 'org-bibtex-open nil :store 'org-bibtex-store-link)
 
 (defun org-bibtex-open (path)
   "Visit the bibliography entry on PATH."

commit e929c0537fa2862aacc4012957133584bb24f5c7
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:05:42 2016 -0400

    change to org-link-add

diff --git a/lisp/org-bbdb.el b/lisp/org-bbdb.el
index 0f90e1e..2241b15 100644
--- a/lisp/org-bbdb.el
+++ b/lisp/org-bbdb.el
@@ -196,9 +196,9 @@ date year)."
 
 
 ;; Install the link type
-(org-add-link-type "bbdb" 'org-bbdb-open 'org-bbdb-export
-		   :complete 'org-bbdb-complete-link
-		   :store 'org-bbdb-store-link)
+(org-link-add "bbdb" 'org-bbdb-open 'org-bbdb-export
+	      :complete 'org-bbdb-complete-link
+	      :store 'org-bbdb-store-link)
 
 ;; Implementation
 (defun org-bbdb-store-link ()

commit a883c04c1c9cd9ae7eeaac485eebebc49204f5d3
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:42:49 2016 -0400

    remove copy-sequence
    
    Actually it seems like the let statement is no longer needed. I guess it
    was around to protect the list from extra links getting defined.

diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 8b07cca..f1acc54 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -2571,7 +2571,7 @@ Para2"
   (should
    (string-match
     "success"
-    (let ((org-link-types (copy-sequence org-link-types)))
+    (let ((org-link-types (org-link-types)))
       (org-add-link-type "foo" nil (lambda (p d f) "success"))
       (org-export-string-as
        "[[foo:path]]"
@@ -2586,7 +2586,7 @@ Para2"
   (should-not
    (string-match
     "success"
-    (let ((org-link-types (copy-sequence org-link-types)))
+    (let ((org-link-types (org-link-types)))
       (org-add-link-type
        "foo" nil (lambda (p d f) (and (eq f 'test) "success")))
       (org-export-string-as
@@ -2603,7 +2603,7 @@ Para2"
   (should-not
    (string-match
     "success"
-    (let ((org-link-types (copy-sequence org-link-types)))
+    (let ((org-link-types (org-link-types)))
       (org-add-link-type
        "foo" nil (lambda (p d f) (and (eq f 'test) "success")))
       (org-export-string-as

commit a863a4b00d72c17c8134eb3670bfea41abb9e21e
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:38:42 2016 -0400

    update the contrib manual

diff --git a/contrib/orgmanual.org b/contrib/orgmanual.org
index e48ae97..4346083 100644
--- a/contrib/orgmanual.org
+++ b/contrib/orgmanual.org
@@ -3300,12 +3300,16 @@ can define them in the file with
   ,#+LINK: google    http://www.google.com/search?q=%s
 #+end_src
 
-{{{noindent}}} In-buffer completion (see [[Completion]]) can be used after
-{{{samp([)}}} to complete link abbreviations.  You may also define a
-function ~org-PREFIX-complete-link~ that implements special (e.g.,
-completion) support for inserting such a link with {{{kbd(C-c C-l)}}}.
-Such a function should not accept any arguments, and return the full
-link with prefix.
+{{{noindent}}} In-buffer completion (see [[Completion]]) can be used
+after {{{samp([)}}} to complete link abbreviations.  You may also
+define a function that implements special (e.g., completion) support
+for inserting such a link with {{{kbd(C-c C-l)}}}.  Such a function
+should not accept any arguments, and return the full link with
+prefix. You can set the link completion function like this:
+
+#+BEGIN_SRC emacs-lisp
+(org-link-set-parameter "type" :complete 'some-completion-function)
+#+END_SRC
 
 ** Search options
    :PROPERTIES:
@@ -16998,10 +17002,9 @@ description when the link is later inserted into an Org buffer with
 {{{kbd(C-c C-l)}}}.
 
 When it makes sense for your new link type, you may also define a
-function ~org-PREFIX-complete-link~ that implements special (e.g.,
-completion) support for inserting such a link with {{{kbd(C-c C-l)}}}.
-Such a function should not accept any arguments, and return the full
-link with prefix.
+function that implements special (e.g., completion) support for
+inserting such a link with {{{kbd(C-c C-l)}}}.  Such a function should
+not accept any arguments, and return the full link with prefix.
 
 ** Context-sensitive commands
    :PROPERTIES:
@@ -19181,8 +19184,8 @@ from the list of stored links.  To keep it in the list later use, use a
 triple {{{kbd(C-u)}}} prefix argument to {{{kbd(C-c C-l)}}}, or
 configure the option ~org-keep-stored-link-after-insertion~.
 
-[fn:37] This works by calling a special function
-~org-PREFIX-complete-link~.
+[fn:37] This works if a function has been defined in the :complete
+property of a link in org-link-parameters.
 
 [fn:38] See the variable ~org-display-internal-link-with-indirect-buffer~.
 

commit 160c24daf99ef33b71cc0ef22604d1063f3617e0
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:31:30 2016 -0400

    update NEWS with link announcement

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 9909910..6ff7442 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -353,6 +353,8 @@ first footnote.
 *** The ~org-block~ face is inherited by ~src-blocks~
 This works also when =org-src-fontify-natively= is non-nil.  It is also
 possible to specify per-languages faces.  See the manual for details.
+*** Links are now customizable
+Links can now have custom colors, tooltips, keymaps, display behavior, etc... Links are now centralized in ~org-link-parameters~.
 ** New functions
 *** ~org-next-line-empty-p~
 It replaces the deprecated ~next~ argument to ~org-previous-line-empty-p~.

commit c922ab8b2d19d265f8183a5b0d36adb9b61087ce
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:30:48 2016 -0400

    replace an org-link-types variable with function

diff --git a/lisp/org-element.el b/lisp/org-element.el
index 21a7e86..9452641 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:]]\\)"

commit 34eece2527c5fa3e5864d037a3f5df07a44b0f33
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:29:07 2016 -0400

    update the texinfo for link parameters documentation.

diff --git a/doc/org.texi b/doc/org.texi
index e92788f..aa552fc 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -3711,11 +3711,11 @@ them with @key{up} and @key{down} (or @kbd{M-p/n}).
 valid link prefixes like @samp{http:} or @samp{ftp:}, including the prefixes
 defined through link abbreviations (@pxref{Link abbreviations}).  If you
 press @key{RET} after inserting only the @var{prefix}, Org will offer
-specific completion support for some link types@footnote{This works by
-calling a special function @code{org-PREFIX-complete-link}.}  For
-example, if you type @kbd{file @key{RET}}, file name completion (alternative
-access: @kbd{C-u C-c C-l}, see below) will be offered, and after @kbd{bbdb
-@key{RET}} you can complete contact names.
+specific completion support for some link types@footnote{This works if a
+completion function is defined in the :complete property of a link in
+@var{org-link-parameters}.}  For example, if you type @kbd{file @key{RET}},
+file name completion (alternative access: @kbd{C-u C-c C-l}, see below) will
+be offered, and after @kbd{bbdb @key{RET}} you can complete contact names.
 @orgkey C-u C-c C-l
 @cindex file name completion
 @cindex completion, of file names
@@ -3887,10 +3887,13 @@ can define them in the file with
 
 @noindent
 In-buffer completion (@pxref{Completion}) can be used after @samp{[} to
-complete link abbreviations.  You may also define a function
-@code{org-PREFIX-complete-link} that implements special (e.g., completion)
-support for inserting such a link with @kbd{C-c C-l}.  Such a function should
-not accept any arguments, and return the full link with prefix.
+complete link abbreviations.  You may also define a function that implements
+special (e.g., completion) support for inserting such a link with @kbd{C-c
+C-l}.  Such a function should not accept any arguments, and return the full
+link with prefix. You can add a completion function to a link like this:
+
+@code{(org-link-set-parameters ``type'' :complete 'some-function)}
+
 
 @node Search options
 @section Search options in file links
@@ -18005,9 +18008,9 @@ the link description when the link is later inserted into an Org
 buffer with @kbd{C-c C-l}.
 
 When it makes sense for your new link type, you may also define a function
-@code{org-PREFIX-complete-link} that implements special (e.g., completion)
-support for inserting such a link with @kbd{C-c C-l}.  Such a function should
-not accept any arguments, and return the full link with prefix.
+that implements special (e.g., completion) support for inserting such a link
+with @kbd{C-c C-l}.  Such a function should not accept any arguments, and
+return the full link with prefix.
 
 @node Adding export back-ends
 @section Adding export back-ends

commit 75fa053296d8b4bbb8e7edeb9b7e077eb8ed37f1
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:28:38 2016 -0400

    update w3m link

diff --git a/lisp/org-w3m.el b/lisp/org-w3m.el
index 57ecafe..97b9841 100644
--- a/lisp/org-w3m.el
+++ b/lisp/org-w3m.el
@@ -46,7 +46,7 @@
 (defvar w3m-current-url)
 (defvar w3m-current-title)
 
-(add-hook 'org-store-link-functions 'org-w3m-store-link)
+(org-link-set-parameters "w3m" :store 'org-w3m-store-link)
 (defun org-w3m-store-link ()
   "Store a link to a w3m buffer."
   (when (eq major-mode 'w3m-mode)

commit c41dcddfa8ba848d4e911282bc5760a4e4b953ff
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:28:09 2016 -0400

    update rmail link definition

diff --git a/lisp/org-rmail.el b/lisp/org-rmail.el
index 0bf44b8..9eff516 100644
--- a/lisp/org-rmail.el
+++ b/lisp/org-rmail.el
@@ -43,8 +43,7 @@
 (defvar rmail-file-name)        ; From rmail.el
 
 ;; Install the link type
-(org-add-link-type "rmail" 'org-rmail-open)
-(add-hook 'org-store-link-functions 'org-rmail-store-link)
+(org-add-link-type "rmail" 'org-rmail-open nil :store 'org-rmail-store-link)
 
 ;; Implementation
 (defun org-rmail-store-link ()

commit 86221a71daa897d94cb8ca7aa4f63f0b4e897477
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:55 2016 -0400

    update mhe link definition.

diff --git a/lisp/org-mhe.el b/lisp/org-mhe.el
index 2ee21de..ca8b68d 100644
--- a/lisp/org-mhe.el
+++ b/lisp/org-mhe.el
@@ -74,8 +74,7 @@ supported by MH-E."
 (defvar mh-search-regexp-builder)
 
 ;; Install the link type
-(org-add-link-type "mhe" 'org-mhe-open)
-(add-hook 'org-store-link-functions 'org-mhe-store-link)
+(org-add-link-type "mhe" 'org-mhe-open nil :store 'org-mhe-store-link)
 
 ;; Implementation
 (defun org-mhe-store-link ()

commit fc6accee74dd61dc58cab3e5d70fbf411faedb74
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:45 2016 -0400

    update irc link definition

diff --git a/lisp/org-irc.el b/lisp/org-irc.el
index 81d0296..4996d60 100644
--- a/lisp/org-irc.el
+++ b/lisp/org-irc.el
@@ -71,9 +71,7 @@
 
 ;; Generic functions/config (extend these for other clients)
 
-(add-to-list 'org-store-link-functions 'org-irc-store-link)
-
-(org-add-link-type "irc" 'org-irc-visit nil)
+(org-add-link-type "irc" 'org-irc-visit nil :store 'org-irc-store-link)
 
 (defun org-irc-visit (link)
   "Parse LINK and dispatch to the correct function based on the client found."

commit 6e7d024b316fb8c9f1ebf37421a50917ac69aa15
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:32 2016 -0400

    update info link definition

diff --git a/lisp/org-info.el b/lisp/org-info.el
index 9e8fde0..d9e9b07 100644
--- a/lisp/org-info.el
+++ b/lisp/org-info.el
@@ -40,8 +40,7 @@
 (defvar Info-current-node)
 
 ;; Install the link type
-(org-add-link-type "info" 'org-info-open 'org-info-export)
-(add-hook 'org-store-link-functions 'org-info-store-link)
+(org-add-link-type "info" 'org-info-open 'org-info-export :store 'org-info-store-link)
 
 ;; Implementation
 (defun org-info-store-link ()

commit 898abadf1decbf730a679ba34f5b26a37f52bcf5
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:14 2016 -0400

    update gnus link definition

diff --git a/lisp/org-gnus.el b/lisp/org-gnus.el
index 386d6dc..271f480 100644
--- a/lisp/org-gnus.el
+++ b/lisp/org-gnus.el
@@ -74,8 +74,7 @@ this variable to t."
   :type 'boolean)
 
 ;; Install the link type
-(org-add-link-type "gnus" 'org-gnus-open)
-(add-hook 'org-store-link-functions 'org-gnus-store-link)
+(org-add-link-type "gnus" 'org-gnus-open nil :store 'org-gnus-store-link)
 
 ;; Implementation
 

commit 917114bd4968f7ff8e653950af194a70d625c849
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:03 2016 -0400

    update eshell link definition

diff --git a/lisp/org-eshell.el b/lisp/org-eshell.el
index 1919f6d..4782d94 100644
--- a/lisp/org-eshell.el
+++ b/lisp/org-eshell.el
@@ -27,8 +27,8 @@
 (require 'eshell)
 (require 'esh-mode)
 
-(org-add-link-type "eshell" 'org-eshell-open)
-(add-hook 'org-store-link-functions 'org-eshell-store-link)
+(org-add-link-type "eshell" 'org-eshell-open nil
+		   :store 'org-eshell-store-link)
 
 (defun org-eshell-open (link)
   "Switch to am eshell buffer and execute a command line.

commit 626682724311ca54292a34f2b9a4b8aa519c6fe8
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:26:28 2016 -0400

    Update docview link definition

diff --git a/lisp/org-docview.el b/lisp/org-docview.el
index fbc5551..3e8f659 100644
--- a/lisp/org-docview.el
+++ b/lisp/org-docview.el
@@ -49,8 +49,7 @@
 (declare-function doc-view-goto-page "doc-view" (page))
 (declare-function image-mode-window-get "image-mode" (prop &optional winprops))
 
-(org-add-link-type "docview" 'org-docview-open 'org-docview-export)
-(add-hook 'org-store-link-functions 'org-docview-store-link)
+(org-add-link-type "docview" 'org-docview-open 'org-docview-export :store 'org-docview-store-link)
 
 (defun org-docview-export (link description format)
   "Export a docview link from Org files."

commit 2f32ebf222c6d1e391358d6146ebc6f21a4bf095
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:26:04 2016 -0400

    update bibtex link definition.
    
    * lisp/org-bibtex.el ("bibtex"):

diff --git a/lisp/org-bibtex.el b/lisp/org-bibtex.el
index 74e32f7..db30510 100644
--- a/lisp/org-bibtex.el
+++ b/lisp/org-bibtex.el
@@ -452,8 +452,7 @@ With optional argument OPTIONAL, also prompt for optional fields."
 
 \f
 ;;; Bibtex link functions
-(org-add-link-type "bibtex" 'org-bibtex-open)
-(add-hook 'org-store-link-functions 'org-bibtex-store-link)
+(org-add-link-type "bibtex" 'org-bibtex-open nil :store 'org-bibtex-store-link)
 
 (defun org-bibtex-open (path)
   "Visit the bibliography entry on PATH."

commit 776f20bfc5afd744c6318f9d66ced055c02a88c5
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:25:39 2016 -0400

    update bbdb link definition.
    
    * lisp/org-bbdb.el ("bbdb"):

diff --git a/lisp/org-bbdb.el b/lisp/org-bbdb.el
index 8d886cd..0f90e1e 100644
--- a/lisp/org-bbdb.el
+++ b/lisp/org-bbdb.el
@@ -196,8 +196,9 @@ date year)."
 
 
 ;; Install the link type
-(org-add-link-type "bbdb" 'org-bbdb-open 'org-bbdb-export)
-(add-hook 'org-store-link-functions 'org-bbdb-store-link)
+(org-add-link-type "bbdb" 'org-bbdb-open 'org-bbdb-export
+		   :complete 'org-bbdb-complete-link
+		   :store 'org-bbdb-store-link)
 
 ;; Implementation
 (defun org-bbdb-store-link ()

commit 5a296333a30e3880e5f551eb82c8b0219447e793
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:24:01 2016 -0400

    add activate-func
    
    * lisp/org.el (org-activate-bracket-links):
    This should have been in the previous commit on this function.

diff --git a/lisp/org.el b/lisp/org.el
index 0f345a8..3e80243 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -6251,6 +6251,8 @@ by a #."
 	(org-rear-nonsticky-at (match-end 1))
 	(add-text-properties (match-end 1) (match-end 0) ip)
 	(org-rear-nonsticky-at (match-end 0)))
+      (when activate-func
+	(funcall activate-func link-start link-end path bracketp))
       t)))
 
 (defun org-activate-dates (limit)

commit c306e89aa41b8f84107dc60957540e3eaa85d009
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:23:27 2016 -0400

    replace org-link-protocols with the link export parameter.

diff --git a/lisp/ox.el b/lisp/ox.el
index da985f3..0b749e8 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -4116,7 +4116,7 @@ The function ignores links with an implicit type (e.g.,
   (let ((type (org-element-property :type link)))
     (unless (or (member type '("coderef" "custom-id" "fuzzy" "radio"))
 		(not backend))
-      (let ((protocol (nth 2 (assoc type org-link-protocols))))
+      (let ((protocol (org-link-get-parameter type :export)))
 	(and (functionp protocol)
 	     (funcall protocol
 		      (org-link-unescape (org-element-property :path link))

commit 50d93f950f68587bad239b8fa26741f8b44675d8
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:22:24 2016 -0400

    Make plain and bracketed link properties stick
    
    * lisp/org.el (org-set-font-lock-defaults): If t is after the face, than
      org-link clobbers everything from the activation functions.

diff --git a/lisp/org.el b/lisp/org.el
index d6699ff..0f345a8 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -6522,8 +6522,8 @@ needs to be inserted at a specific position in the font-lock sequence.")
 	   ;; Links
 	   (when (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
 	   (when (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
-	   (when (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
-	   (when (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
+	   (when (memq 'plain lk) '(org-activate-plain-links (0 'org-link)))
+	   (when (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link)))
 	   (when (memq 'radio lk) '(org-activate-target-links (1 'org-link t)))
 	   (when (memq 'date lk) '(org-activate-dates (0 'org-date t)))
 	   (when (memq 'footnote lk) '(org-activate-footnote-links))

commit 70cd41305abdce2f5deb458cea6b493d6c850e3c
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:21:50 2016 -0400

    Update org-activate-bracket-links
    
    * lisp/org.el (org-activate-bracket-links): Use org-link-parameters to
      build link properties.

diff --git a/lisp/org.el b/lisp/org.el
index 21122b7..d6699ff 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -6155,14 +6155,83 @@ by a #."
   (when (and (re-search-forward org-bracket-link-regexp limit t)
 	     (not (org-in-src-block-p)))
     (let* ((hl (match-string-no-properties 1))
-	   (help (concat "LINK: " (save-match-data (org-link-unescape hl))))
-	   (ip (list 'invisible 'org-link
-		     'keymap org-mouse-map 'mouse-face 'highlight
-		     'font-lock-multiline t 'help-echo help
-		     'htmlize-link `(:uri ,hl)))
-	   (vp (list 'keymap org-mouse-map 'mouse-face 'highlight
-		     'font-lock-multiline t 'help-echo help
-		     'htmlize-link `(:uri ,hl))))
+	   (type (save-match-data
+		   (if (string-match org-plain-link-re hl)
+		       (match-string-no-properties 1 hl)
+		     nil)))
+	   (path (save-match-data
+		   (if (string-match org-plain-link-re hl)
+		       (match-string-no-properties 2 hl)
+		     nil)))
+	   (link-start (match-beginning 0))
+	   (link-end (match-end 0))
+	   (bracketp t)
+	   (help-echo (org-link-get-parameter type :help-echo))
+	   (help (cond
+		  ((stringp help-echo)
+		   help-echo)
+		  ((functionp help-echo)
+		   help-echo)
+		  (t
+		   (concat "LINK: "
+			   (save-match-data
+			     (org-link-unescape hl))))))
+	   (link-face (org-link-get-parameter type :face))
+	   (htmlize-link (org-link-get-parameter type :htmlize-link))
+	   (activate-func (org-link-get-parameter type :activate-func))
+	   ;; invisible part
+	   (ip (list 'invisible (or
+				 (org-link-get-parameter type :display)
+				 'org-link)
+		     'face (cond
+			    ;; A function that returns a face
+			    ((functionp link-face)
+			     (funcall link-face path))
+			    ;; a face
+			    ((facep link-face)
+			     link-face)
+			    ;; An anonymous face
+			    ((listp link-face)
+			     link-face)
+			    ;; default
+			    (t
+			     'org-link))
+		     'keymap (or (org-link-get-parameter type :keymap)
+				 org-mouse-map)
+		     'mouse-face (or (org-link-get-parameter type :mouse-face)
+				     'highlight)
+		     'font-lock-multiline t
+		     'help-echo help
+		     'htmlize-link (cond
+				    ((functionp htmlize-link)
+				     (funcall htmlize-link))
+				    (t
+				     `(:uri ,(format "%s:%s" type path))))))
+	   ;; visible part
+	   (vp (list 'keymap (or (org-link-get-parameter type :keymap)
+				 org-mouse-map)
+		     'face (cond
+			    ;; A function that returns a face
+			    ((functionp link-face)
+			     (funcall link-face path))
+			    ;; a face
+			    ((facep link-face)
+			     link-face)
+			    ;; An anonymous face
+			    ((listp link-face)
+			     link-face)
+			    ;; default
+			    (t
+			     'org-link))
+		     'mouse-face (or (org-link-get-parameter type :mouse-face)
+				     'highlight)
+		     'font-lock-multiline t
+		     'help-echo help
+		     'htmlize-link (cond
+				    ((functionp htmlize-link)
+				     (funcall htmlize-link))
+				    (t
+				     `(:uri ,(format "%s:%s" type path)))))))
       ;; We need to remove the invisible property here.  Table narrowing
       ;; may have made some of this invisible.
       (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))

commit d2d39fc4ea24e17dd24c0bc78b4ef1cc14ef8258
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:21:08 2016 -0400

    update org-activate-plain-links
    
    * lisp/org.el (org-activate-plain-links): Use org-link-parameters to
      create the link properties.

diff --git a/lisp/org.el b/lisp/org.el
index 6dfd089..21122b7 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5917,17 +5917,55 @@ prompted for."
   "Add link properties for plain links."
   (when (and (re-search-forward org-plain-link-re limit t)
 	     (not (org-in-src-block-p)))
-    (let ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
-				   'face))
-	  (link (match-string-no-properties 0)))
+
+    (let* ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
+				    'face))
+	   (link (match-string-no-properties 0))
+	   (type (match-string-no-properties 1))
+	   (path (match-string-no-properties 2))
+	   (link-face (org-link-get-parameter type :face))
+	   (help-echo (org-link-get-parameter type :help-echo))	   
+	   (htmlize-link (org-link-get-parameter type :htmlize-link))
+	   (activate-func (org-link-get-parameter type :activate-func)))
       (unless (if (consp face) (memq 'org-tag face) (eq 'org-tag face))
 	(org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
 	(add-text-properties (match-beginning 0) (match-end 0)
-			     (list 'mouse-face 'highlight
-				   'face 'org-link
-				   'htmlize-link `(:uri ,link)
-				   'keymap org-mouse-map))
+			     (list
+			      'mouse-face (or (org-link-get-parameter type :mouse-face)
+					      'highlight)
+			      'face (cond
+				     ;; A function that returns a face
+				     ((functionp link-face)
+				      (funcall link-face path))
+				     ;; a face
+				     ((facep link-face)
+				      link-face)
+				     ;; An anonymous face
+				     ((listp link-face)
+				      link-face)
+				     ;; default
+				     (t
+				      'org-link))
+			      'help-echo (cond
+					  ((stringp help-echo)
+					   help-echo)
+					  ((functionp help-echo)
+					   help-echo)
+					  (t
+					   (concat "LINK: "
+						   (save-match-data
+						     (org-link-unescape link)))))
+			      'htmlize-link (cond
+					     ((functionp htmlize-link)
+					      (funcall htmlize-link path))
+					     (t
+					      `(:uri ,link)))
+			      'keymap (or (org-link-get-parameter type :keymap)
+					  org-mouse-map)
+			      'org-link-start (match-beginning 0)))
 	(org-rear-nonsticky-at (match-end 0))
+	(when activate-func
+	  (funcall activate-func link-start link-end path nil))
 	t))))
 
 (defun org-activate-code (limit)

commit 66ad0a6d2c79ac0424f8424b875d707e36fe11d2
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:20:23 2016 -0400

    get complete function from org-link-parameters.

diff --git a/lisp/org.el b/lisp/org.el
index f9e5487..6dfd089 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -10522,7 +10522,12 @@ Use TAB to complete link prefixes, then RET for type-specific completion support
 
 (defun org-link-try-special-completion (type)
   "If there is completion support for link type TYPE, offer it."
-  (let ((fun (intern (concat "org-" type "-complete-link"))))
+  (let ((fun (or (org-link-get-parameter type :complete)
+		 ;; We still honor the "org-type-complete-link
+		 ;; form. There are some built in links like
+		 ;; org-file-complete-link that don't fit nicely into
+		 ;; org-link-parameters.
+		 (intern (concat "org-" type "-complete-link")))))
     (if (functionp fun)
 	(funcall fun)
       (read-string "Link (no completion support): " (concat type ":")))))

commit 251b574b8669d3ed685542eec03c89336c0c91c5
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:19:52 2016 -0400

    Replace org-store-link-functions variable with function

diff --git a/lisp/org.el b/lisp/org.el
index 59d6c63..f9e5487 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9857,7 +9857,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

commit c8580dd27d0f71649a938c56357b471f58b2aa97
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:18:57 2016 -0400

    Update org-add-link-type
    
    * lisp/org.el org-add-link-type: Now accepts keyword arguments for link parameters.

diff --git a/lisp/org.el b/lisp/org.el
index 0aa29d2..59d6c63 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9739,10 +9739,10 @@ Special properties are:
 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'
-
+(cl-defun org-add-link-type (type &optional follow export
+				  &key store complete face mouse-face display
+				  help-echo keymap htmlize-link activate-func)
+  "Add a new TYPE link.
 FOLLOW and EXPORT are two functions.
 
 FOLLOW should take the link path as the single argument and do whatever
@@ -9763,13 +9763,56 @@ 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)
+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."
+  (if (assoc type org-link-parameters)
+      (org-link-set-parameters
+       type :follow follow :export export :store store
+       :complete complete :face face :mouse-face mouse-face
+       :display display :help-echo help-echo :keymap keymap
+       :htmlize-link htmlize-link :activate-func activate-func)
+    ;; Add new link
+    (push (list type :follow follow :export export :store store
+		:complete complete :face face :mouse-face mouse-face
+		:display display :help-echo help-echo :keymap keymap
+		:htmlize-link htmlize-link :activate-func activate-func)
+	  org-link-parameters))
   (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)))
+  (message "Created %s link." type))
+
+  (defun org-store-link-functions ()
+    "Returns a list of functions that are called to create and store a link.
+The functions in the variable `org-store-link-functions' come
+first. These may be user-defined for different contexts. Then
+comes the functions defined in the :store property of
+org-link-parameters.
+
+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:
+
+: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.
+
+In addition to these, any additional properties can be specified
+and then used in capture templates."
+    (append
+     org-store-link-functions
+     (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

commit 763a0a8cb636bccf6a0211447d287296cd624ccb
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:16:38 2016 -0400

    Remove org-link-protocols
    
    The data in this variable is now retrieved with org-link-get-parameter.

diff --git a/lisp/org.el b/lisp/org.el
index 55c9b01..0aa29d2 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9719,9 +9719,6 @@ 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'.")
-
 (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
@@ -10760,7 +10757,7 @@ link in a property drawer line."
 	       ((equal type "file")
 		(if (string-match "[*?{]" (file-name-nondirectory path))
 		    (dired path)
-		  ;; Look into `org-link-protocols' in order to find
+		  ;; Look into `org-link-parameters' in order to find
 		  ;; a DEDICATED-FUNCTION to open file.  The function
 		  ;; will be applied on raw link instead of parsed
 		  ;; link due to the limitation in `org-add-link-type'
@@ -10774,7 +10771,7 @@ link in a property drawer line."
 		  (let* ((option (org-element-property :search-option link))
 			 (app (org-element-property :application link))
 			 (dedicated-function
-			  (nth 1 (assoc app org-link-protocols))))
+			  (org-link-get-parameter type :follow)))
 		    (if dedicated-function
 			(funcall dedicated-function
 				 (concat path
@@ -10789,8 +10786,8 @@ link in a property drawer line."
 				    (list (string-to-number option)))
 				   (t (list nil
 					    (org-link-unescape option)))))))))
-	       ((assoc type org-link-protocols)
-		(funcall (nth 1 (assoc type org-link-protocols)) path))
+	       ((assoc type org-link-parameters)
+		(funcall (org-link-get-parameter type :follow) path))
 	       ((equal type "help")
 		(let ((f-or-v (intern path)))
 		  (cond ((fboundp f-or-v) (describe-function f-or-v))
@@ -10839,7 +10836,7 @@ link in a property drawer line."
 		    (user-error "Abort"))))
 	       ((equal type "id")
 		(require 'org-id)
-		(funcall (nth 1 (assoc "id" org-link-protocols)) path))
+		(funcall (org-link-get-parameter type :follow) path))
 	       ((member type '("coderef" "custom-id" "fuzzy" "radio"))
 		(unless (run-hook-with-args-until-success
 			 'org-open-link-functions path)

commit 91d90b6bef8fac0a94efdf915561a03e75526b11
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:13:17 2016 -0400

    Replace org-link-types with function
    
    * lisp/org.el: The variable was replaced with the function everywhere.

diff --git a/lisp/org-element.el b/lisp/org-element.el
index 269bc7d..21a7e86 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -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 8300f8f..55c9b01 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5780,8 +5780,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
@@ -5819,7 +5819,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) ":\\)?"
 	   "\\([^]]+\\)"
 	   "\\]"
 	   "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
@@ -10378,7 +10378,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

commit 31f6309dd86344b03f3e58263d05ee2ec688c995
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:08:14 2016 -0400

    Add org-link-parameters
    
    * lisp/org.el (org-link-parameters): Add new centralized link variable.
    
    (org-link-get-parameter): A getter function to get link parameters
    
    (org-link-set-parameters): A setter function to set link parameters
    
    (org-link-types): A function to return a list of link types.

diff --git a/lisp/org.el b/lisp/org.el
index 6dd7f91..8300f8f 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -1758,6 +1758,62 @@ 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
+  '(("http") ("https") ("ftp") ("mailto")
+    ("file") ("file+emacs") ("file+sys")
+    ("news") ("shell") ("elisp")
+    ("doi") ("message") ("help"))
+  "An alist of properties that defines all the links in org-mode.
+The first key in each list 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 variable `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 args 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 paramters"
+		:type string
+		:follow :export :store :completion :face :mouse-face
+		:display :help-echo :keymap :htmlize-link :activate-func))
+
+(defun org-link-get-parameter (type key)
+  "Get TYPE link property for KEY."
+  (cl-getf
+   (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."
+  (if (cdr (assoc type org-link-parameters))
+      ;; update old link
+      (cl-loop for (key val) on parameters by #'cddr
+	       do
+	       (setf (cl-getf
+		      (cdr (assoc type org-link-parameters))
+		      key)
+		     val))
+    ;; add new one.
+    (push `(,type ,@parameters) org-link-parameters)
+    (org-make-link-regexps)
+    (org-element-update-syntax))
+  org-link-parameters)
+
+(defun org-link-types ()
+  "Returns 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.

commit 8b8f65f4314fa9eb08bc5bd7c23dcf32f456f57d
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:07:10 2016 -0400

    Remove org-link-types
    
    * lisp/org.el (org-link-types): Remove this variable.

diff --git a/lisp/org.el b/lisp/org.el
index 2202d41..6dd7f91 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5658,9 +5658,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


-- 
Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
@johnkitchin
http://kitchingroup.cheme.cmu.edu

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: Draft of links-9.0
  2016-07-05 20:30   ` John Kitchin
@ 2016-07-05 21:56     ` Nicolas Goaziou
  2016-07-06  1:49       ` John Kitchin
  0 siblings, 1 reply; 6+ messages in thread
From: Nicolas Goaziou @ 2016-07-05 21:56 UTC (permalink / raw)
  To: John Kitchin; +Cc: emacs-orgmode@gnu.org

John Kitchin <jkitchin@andrew.cmu.edu> writes:

> I pasted the diffs at the end. There are a lot because it touched a lot of
> files, and I committed each one separately, and forgot a few commits
> that ended up as extras. Probably some could be combined and squashed if
> that is desirable. I am not sure how to do it yet though.

Clearly some of them could be merged. From magit, this is "r i" from the
first commit (aka interactive rebase) then, you can squash or fixup
commits, reorder them...

Comments follow, in reverse order.

> commit 546031bb7b59a9deb6bce976f7f7496ea7b2ffc4
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 16:16:29 2016 -0400
>
>     add link-start and link-end variables

This can probably be merged with another commit.

> commit d1799252a7e4bd255a5507d742e0b0a7c19983b1
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 16:16:02 2016 -0400
>
>     deprecate org-add-link-type
>     
>     It now calls org-link-add.
>
> diff --git a/lisp/org.el b/lisp/org.el
> index 4fb1cfb..872f861 100644
> --- a/lisp/org.el
> +++ b/lisp/org.el
> @@ -9852,10 +9852,10 @@ Special properties are:
>  In addition to these, any additional properties can be specified
>  and then used in capture templates.")
>  
> -(cl-defun org-add-link-type (type &optional follow export
> -				  &key store complete face mouse-face display
> -				  help-echo keymap htmlize-link activate-func)
> +(defun org-add-link-type (type &optional follow export)
>    "Add a new TYPE link.
> +Deprecated. Use `org-link-add' instead.

No need to add this in the docstring. Use `make-obsolete'. Also,
obsolete definitions should be moved to "org-compat.el".

> +  (unless (cdr (assoc type org-link-parameters))
> +    (error "No link of type %s defined." type))
> +  (cl-loop for (key val) on parameters by #'cddr
> +	   do
> +	   (setf (cl-getf
> +		  (cdr (assoc type org-link-parameters))
> +		  key)
> +		 val))
>    org-link-parameters)

See below for a suggested implementation of the function.

> +(defun org-link-add (type &rest properties)
> +  "Add a TYPE link with PROPERTIES defined as a plist.
> +See `org-link-parameters' for details on the PROPERTIES." 
> +  (push (append (list type) properties)
> +	org-link-parameters)
> +  (org-make-link-regexps)
> +  (org-element-update-syntax))

This function is not needed since it is the same as
`org-link-set-parameters'.

>  (defun org-link-types ()
>    "Returns a list of known link types."
>    (mapcar 'car org-link-parameters))
>
> commit 1069d9bac0974f27abda2736fef883eb8334c761
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 16:14:02 2016 -0400
>
>     update comment for new variable.

"Update ..."

This can probably be merged with another commit.

I skipped intermediary commits. You can merge them.

> commit a883c04c1c9cd9ae7eeaac485eebebc49204f5d3
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:42:49 2016 -0400
>
>     remove copy-sequence
>     
>     Actually it seems like the let statement is no longer needed. I guess it
>     was around to protect the list from extra links getting defined.

You can merge this commit with another one below.

> commit c922ab8b2d19d265f8183a5b0d36adb9b61087ce
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:30:48 2016 -0400
>
>     replace an org-link-types variable with function

You can merge it with a commit below.

> commit 75fa053296d8b4bbb8e7edeb9b7e077eb8ed37f1
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:28:38 2016 -0400
>
>     update w3m link
>
> commit c41dcddfa8ba848d4e911282bc5760a4e4b953ff
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:28:09 2016 -0400
>
>     update rmail link definition
>
> commit 86221a71daa897d94cb8ca7aa4f63f0b4e897477
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:27:55 2016 -0400
>
>     update mhe link definition.
>
> commit fc6accee74dd61dc58cab3e5d70fbf411faedb74
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:27:45 2016 -0400
>
>     update irc link definition
>
> commit 6e7d024b316fb8c9f1ebf37421a50917ac69aa15
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:27:32 2016 -0400
>
>     update info link definition
>
> commit 898abadf1decbf730a679ba34f5b26a37f52bcf5
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:27:14 2016 -0400
>
>     update gnus link definition
>
> commit 917114bd4968f7ff8e653950af194a70d625c849
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:27:03 2016 -0400
>
>     update eshell link definition
>
> commit 626682724311ca54292a34f2b9a4b8aa519c6fe8
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:26:28 2016 -0400
>
>     Update docview link definition
>
> commit 2f32ebf222c6d1e391358d6146ebc6f21a4bf095
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:26:04 2016 -0400
>
>     update bibtex link definition.
>     
>     * lisp/org-bibtex.el ("bibtex"):
>
> commit 776f20bfc5afd744c6318f9d66ced055c02a88c5
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:25:39 2016 -0400
>
>     update bbdb link definition.
>     
>     * lisp/org-bbdb.el ("bbdb"):

Skipped type specific patches. Please mind the commit messages, though.

> commit 5a296333a30e3880e5f551eb82c8b0219447e793
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:24:01 2016 -0400
>
>     add activate-func

"Add activate-func"

>     * lisp/org.el (org-activate-bracket-links):
>     This should have been in the previous commit on this function.

You can merge commits easily.

> commit c306e89aa41b8f84107dc60957540e3eaa85d009
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:23:27 2016 -0400
>
>     replace org-link-protocols with the link export parameter.

Commit message is incomplete. Otherwise, OK.

> commit 50d93f950f68587bad239b8fa26741f8b44675d8
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:22:24 2016 -0400
>
>     Make plain and bracketed link properties stick
>     
>     * lisp/org.el (org-set-font-lock-defaults): If t is after the face, than
>       org-link clobbers everything from the activation functions.

Ok.

> commit 70cd41305abdce2f5deb458cea6b493d6c850e3c
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:21:50 2016 -0400
>
>     Update org-activate-bracket-links

`org-activate-bracket-links'

>     * lisp/org.el (org-activate-bracket-links): Use org-link-parameters to
>       build link properties.

`org-link-parameters'

> +			    ;; An anonymous face
> +			    ((listp link-face)
> +			     link-face)

See below.

> +			    ;; default
> +			    (t
> +			     'org-link))
> +		     'keymap (or (org-link-get-parameter type :keymap)
> +				 org-mouse-map)
> +		     'mouse-face (or (org-link-get-parameter type :mouse-face)
> +				     'highlight)
> +		     'font-lock-multiline t
> +		     'help-echo help
> +		     'htmlize-link (cond
> +				    ((functionp htmlize-link)
> +				     (funcall htmlize-link))
> +				    (t
> +				     `(:uri ,(format "%s:%s" type path))))))
> +	   ;; visible part
> +	   (vp (list 'keymap (or (org-link-get-parameter type :keymap)
> +				 org-mouse-map)
> +		     'face (cond
> +			    ;; A function that returns a face
> +			    ((functionp link-face)
> +			     (funcall link-face path))
> +			    ;; a face
> +			    ((facep link-face)
> +			     link-face)
> +			    ;; An anonymous face
> +			    ((listp link-face)
> +			     link-face)
> +			    ;; default
> +			    (t
> +			     'org-link))
> +		     'mouse-face (or (org-link-get-parameter type :mouse-face)
> +				     'highlight)
> +		     'font-lock-multiline t
> +		     'help-echo help
> +		     'htmlize-link (cond
> +				    ((functionp htmlize-link)
> +				     (funcall htmlize-link))
> +				    (t
> +				     `(:uri ,(format "%s:%s" type path)))))))

There is some code duplication going on here. It doesn't matter much for
now.

> commit d2d39fc4ea24e17dd24c0bc78b4ef1cc14ef8258
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:21:08 2016 -0400
>
>     update org-activate-plain-links

`org-activate-plain-links'
>     
>     * lisp/org.el (org-activate-plain-links): Use org-link-parameters to
>       create the link properties.

`org-link-parameters'

>
> diff --git a/lisp/org.el b/lisp/org.el
> index 6dfd089..21122b7 100644
> --- a/lisp/org.el
> +++ b/lisp/org.el
> @@ -5917,17 +5917,55 @@ prompted for."
>    "Add link properties for plain links."
>    (when (and (re-search-forward org-plain-link-re limit t)
>  	     (not (org-in-src-block-p)))
> -    (let ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
> -				   'face))
> -	  (link (match-string-no-properties 0)))
> +
> +    (let* ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
> +				    'face))
> +	   (link (match-string-no-properties 0))
> +	   (type (match-string-no-properties 1))
> +	   (path (match-string-no-properties 2))
> +	   (link-face (org-link-get-parameter type :face))
> +	   (help-echo (org-link-get-parameter type :help-echo))	   
> +	   (htmlize-link (org-link-get-parameter type :htmlize-link))
> +	   (activate-func (org-link-get-parameter type :activate-func)))
>        (unless (if (consp face) (memq 'org-tag face) (eq 'org-tag face))
>  	(org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
>  	(add-text-properties (match-beginning 0) (match-end 0)
> -			     (list 'mouse-face 'highlight
> -				   'face 'org-link
> -				   'htmlize-link `(:uri ,link)
> -				   'keymap org-mouse-map))
> +			     (list

I suggest to move `list' under `add-text-properties'

> +			      'mouse-face (or (org-link-get-parameter type :mouse-face)
> +					      'highlight)
> +			      'face (cond
> +				     ;; A function that returns a face
> +				     ((functionp link-face)
> +				      (funcall link-face path))
> +				     ;; a face
> +				     ((facep link-face)
> +				      link-face)
> +				     ;; An anonymous face
> +				     ((listp link-face)
> +				      link-face)

This should be (consp link-face) so as to avoid nil face, shouldn't it?

> commit 66ad0a6d2c79ac0424f8424b875d707e36fe11d2
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:20:23 2016 -0400
>
>     get complete function from org-link-parameters.

Commit message is incomplete.

>  (defun org-link-try-special-completion (type)
>    "If there is completion support for link type TYPE, offer it."
> -  (let ((fun (intern (concat "org-" type "-complete-link"))))
> +  (let ((fun (or (org-link-get-parameter type :complete)
> +		 ;; We still honor the "org-type-complete-link
> +		 ;; form. There are some built in links like
> +		 ;; org-file-complete-link that don't fit nicely into
> +		 ;; org-link-parameters.
> +		 (intern (concat "org-" type "-complete-link")))))

Eww. How so? Why couldn't `org-file-complete-link' the value
of :complete property of "file" type in `org-link-parameters'?

> commit 251b574b8669d3ed685542eec03c89336c0c91c5
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:19:52 2016 -0400
>
>     Replace org-store-link-functions variable with function

You need to specify what function is modified in the commit message.

> diff --git a/lisp/org.el b/lisp/org.el
> index 59d6c63..f9e5487 100644
> --- a/lisp/org.el
> +++ b/lisp/org.el
> @@ -9857,7 +9857,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
>
> commit c8580dd27d0f71649a938c56357b471f58b2aa97
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:18:57 2016 -0400
>
>     Update org-add-link-type
>     
>     * lisp/org.el org-add-link-type: Now accepts keyword arguments for link parameters.

This one can be removed.

> commit 763a0a8cb636bccf6a0211447d287296cd624ccb
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:16:38 2016 -0400
>
>     Remove org-link-protocols

Missing:

  lisp/org.el (org-link-protocols): Remove variable.

Looks good otherwise.

> commit 91d90b6bef8fac0a94efdf915561a03e75526b11
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:13:17 2016 -0400
>
>     Replace org-link-types with function
>     
>     * lisp/org.el: The variable was replaced with the function
>     everywhere.

Looks good, but it could be merged with the commit actually defining the function.

> commit 31f6309dd86344b03f3e58263d05ee2ec688c995
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:08:14 2016 -0400
>
>     Add org-link-parameters
>     
>     * lisp/org.el (org-link-parameters): Add new centralized link variable.
>     
>     (org-link-get-parameter): A getter function to get link parameters
>     
>     (org-link-set-parameters): A setter function to set link parameters
>     
>     (org-link-types): A function to return a list of link types.
>
> diff --git a/lisp/org.el b/lisp/org.el
> index 6dd7f91..8300f8f 100644
> --- a/lisp/org.el
> +++ b/lisp/org.el
> @@ -1758,6 +1758,62 @@ 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
> +  '(("http") ("https") ("ftp") ("mailto")
> +    ("file") ("file+emacs") ("file+sys")
> +    ("news") ("shell") ("elisp")
> +    ("doi") ("message") ("help"))

I think follow function could be extracted from `org-open-at-point' for,
at least, "help", "doi", "message", "shell" and "elisp".  This is not
blocking anyway.

> +  "An alist of properties that defines all the links in org-mode.

org-mode -> Org mode.

> +The first key in each list is a string of the link type.

The key in each association is ...

> +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 variable `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 args 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."

You need to separate sentences with two spaces.  Also, lines should be
shorter.

> +  :group 'org-link
> +  :type '(alist :tag "Link display paramters"
> +		:type string
> +		:follow :export :store :completion :face :mouse-face
> +		:display :help-echo :keymap :htmlize-link :activate-func))

I think this :type is invalid.

  :type '(alist :tag "Link display parameters"
		:value-type (plist))

is a good start, but ultimately, it should be more subtle.

> +(defun org-link-get-parameter (type key)
> +  "Get TYPE link property for KEY."
> +  (cl-getf
> +   (cdr (assoc type org-link-parameters))
> +   key))

Nitpick: `cl-getf' -> `plist-get'

> +(defun org-link-set-parameters (type &rest parameters)
> +  "Set link TYPE properties to PARAMETERS.
> +PARAMETERS should be :key val pairs."
> +  (if (cdr (assoc type org-link-parameters))
> +      ;; update old link
> +      (cl-loop for (key val) on parameters by #'cddr
> +	       do
> +	       (setf (cl-getf
> +		      (cdr (assoc type org-link-parameters))
> +		      key)
> +		     val))
> +    ;; add new one.
> +    (push `(,type ,@parameters) org-link-parameters)
> +    (org-make-link-regexps)
> +    (org-element-update-syntax))
> +  org-link-parameters)

There's already `org-combine-plists'. Also I don't think returning
`org-link-parameters' is needed. If you think it is, it should be
notified in the docstring.

  (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 (cdr 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 ()
> +  "Returns a list of known link types."
> +  (mapcar 'car org-link-parameters))

Nitpick (mapcar #'car ...)

> commit 8b8f65f4314fa9eb08bc5bd7c23dcf32f456f57d
> Author: John Kitchin <jkitchin@andrew.cmu.edu>
> Date:   Tue Jul 5 10:07:10 2016 -0400
>
>     Remove org-link-types
>     
>     * lisp/org.el (org-link-types): Remove this variable.

This one can be merged above.


Regards,

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Draft of links-9.0
  2016-07-05 21:56     ` Nicolas Goaziou
@ 2016-07-06  1:49       ` John Kitchin
  0 siblings, 0 replies; 6+ messages in thread
From: John Kitchin @ 2016-07-06  1:49 UTC (permalink / raw)
  To: Nicolas Goaziou; +Cc: emacs-orgmode@gnu.org

Thanks for the feedback. Here is a second round of revised commits. I
addressed the comments you made. I have not pushed these to the branch
yet. Let me know what you think about these. Thanks for the help!


commit f5bcdaac6e3d4507c934b8872c4a53c4d90e9143
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:38:42 2016 -0400

    Update the contrib manual

diff --git a/contrib/orgmanual.org b/contrib/orgmanual.org
index e48ae97..4346083 100644
--- a/contrib/orgmanual.org
+++ b/contrib/orgmanual.org
@@ -3300,12 +3300,16 @@ can define them in the file with
   ,#+LINK: google    http://www.google.com/search?q=%s
 #+end_src
 
-{{{noindent}}} In-buffer completion (see [[Completion]]) can be used after
-{{{samp([)}}} to complete link abbreviations.  You may also define a
-function ~org-PREFIX-complete-link~ that implements special (e.g.,
-completion) support for inserting such a link with {{{kbd(C-c C-l)}}}.
-Such a function should not accept any arguments, and return the full
-link with prefix.
+{{{noindent}}} In-buffer completion (see [[Completion]]) can be used
+after {{{samp([)}}} to complete link abbreviations.  You may also
+define a function that implements special (e.g., completion) support
+for inserting such a link with {{{kbd(C-c C-l)}}}.  Such a function
+should not accept any arguments, and return the full link with
+prefix. You can set the link completion function like this:
+
+#+BEGIN_SRC emacs-lisp
+(org-link-set-parameter "type" :complete 'some-completion-function)
+#+END_SRC
 
 ** Search options
    :PROPERTIES:
@@ -16998,10 +17002,9 @@ description when the link is later inserted into an Org buffer with
 {{{kbd(C-c C-l)}}}.
 
 When it makes sense for your new link type, you may also define a
-function ~org-PREFIX-complete-link~ that implements special (e.g.,
-completion) support for inserting such a link with {{{kbd(C-c C-l)}}}.
-Such a function should not accept any arguments, and return the full
-link with prefix.
+function that implements special (e.g., completion) support for
+inserting such a link with {{{kbd(C-c C-l)}}}.  Such a function should
+not accept any arguments, and return the full link with prefix.
 
 ** Context-sensitive commands
    :PROPERTIES:
@@ -19181,8 +19184,8 @@ from the list of stored links.  To keep it in the list later use, use a
 triple {{{kbd(C-u)}}} prefix argument to {{{kbd(C-c C-l)}}}, or
 configure the option ~org-keep-stored-link-after-insertion~.
 
-[fn:37] This works by calling a special function
-~org-PREFIX-complete-link~.
+[fn:37] This works if a function has been defined in the :complete
+property of a link in org-link-parameters.
 
 [fn:38] See the variable ~org-display-internal-link-with-indirect-buffer~.
 

commit 20266af390615d89e23784f04e5a29315394d263
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:31:30 2016 -0400

    Update NEWS with link announcement

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 9909910..6ff7442 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -353,6 +353,8 @@ first footnote.
 *** The ~org-block~ face is inherited by ~src-blocks~
 This works also when =org-src-fontify-natively= is non-nil.  It is also
 possible to specify per-languages faces.  See the manual for details.
+*** Links are now customizable
+Links can now have custom colors, tooltips, keymaps, display behavior, etc... Links are now centralized in ~org-link-parameters~.
 ** New functions
 *** ~org-next-line-empty-p~
 It replaces the deprecated ~next~ argument to ~org-previous-line-empty-p~.

commit 22f9143cda8619fb04d03e33d687a7502ae1cdf4
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:29:07 2016 -0400

    Update the texinfo for link parameters documentation

diff --git a/doc/org.texi b/doc/org.texi
index e92788f..aa552fc 100644
--- a/doc/org.texi
+++ b/doc/org.texi
@@ -3711,11 +3711,11 @@ them with @key{up} and @key{down} (or @kbd{M-p/n}).
 valid link prefixes like @samp{http:} or @samp{ftp:}, including the prefixes
 defined through link abbreviations (@pxref{Link abbreviations}).  If you
 press @key{RET} after inserting only the @var{prefix}, Org will offer
-specific completion support for some link types@footnote{This works by
-calling a special function @code{org-PREFIX-complete-link}.}  For
-example, if you type @kbd{file @key{RET}}, file name completion (alternative
-access: @kbd{C-u C-c C-l}, see below) will be offered, and after @kbd{bbdb
-@key{RET}} you can complete contact names.
+specific completion support for some link types@footnote{This works if a
+completion function is defined in the :complete property of a link in
+@var{org-link-parameters}.}  For example, if you type @kbd{file @key{RET}},
+file name completion (alternative access: @kbd{C-u C-c C-l}, see below) will
+be offered, and after @kbd{bbdb @key{RET}} you can complete contact names.
 @orgkey C-u C-c C-l
 @cindex file name completion
 @cindex completion, of file names
@@ -3887,10 +3887,13 @@ can define them in the file with
 
 @noindent
 In-buffer completion (@pxref{Completion}) can be used after @samp{[} to
-complete link abbreviations.  You may also define a function
-@code{org-PREFIX-complete-link} that implements special (e.g., completion)
-support for inserting such a link with @kbd{C-c C-l}.  Such a function should
-not accept any arguments, and return the full link with prefix.
+complete link abbreviations.  You may also define a function that implements
+special (e.g., completion) support for inserting such a link with @kbd{C-c
+C-l}.  Such a function should not accept any arguments, and return the full
+link with prefix. You can add a completion function to a link like this:
+
+@code{(org-link-set-parameters ``type'' :complete 'some-function)}
+
 
 @node Search options
 @section Search options in file links
@@ -18005,9 +18008,9 @@ the link description when the link is later inserted into an Org
 buffer with @kbd{C-c C-l}.
 
 When it makes sense for your new link type, you may also define a function
-@code{org-PREFIX-complete-link} that implements special (e.g., completion)
-support for inserting such a link with @kbd{C-c C-l}.  Such a function should
-not accept any arguments, and return the full link with prefix.
+that implements special (e.g., completion) support for inserting such a link
+with @kbd{C-c C-l}.  Such a function should not accept any arguments, and
+return the full link with prefix.
 
 @node Adding export back-ends
 @section Adding export back-ends

commit 125d6b4ac3468ce302714ab3437f42a4448a55b5
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 16:11:08 2016 -0400

    Update the "id" link with org-link-set-parameters
    
    * lisp/org-id.el:

diff --git a/lisp/org-id.el b/lisp/org-id.el
index 2646c80..c517034 100644
--- a/lisp/org-id.el
+++ b/lisp/org-id.el
@@ -675,7 +675,7 @@ optional argument MARKERP, return the position as a new marker."
     (move-marker m nil)
     (org-show-context)))
 
-(org-add-link-type "id" 'org-id-open)
+(org-link-set-parameters "id" :follow 'org-id-open)
 
 (provide 'org-id)
 

commit 7bfdf1cad335d7dcaffe5ce75feabef210a147ed
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:28:38 2016 -0400

    Update w3m link definition
    
    * lisp/org-w3m.el ("w3m"):

diff --git a/lisp/org-w3m.el b/lisp/org-w3m.el
index 57ecafe..97b9841 100644
--- a/lisp/org-w3m.el
+++ b/lisp/org-w3m.el
@@ -46,7 +46,7 @@
 (defvar w3m-current-url)
 (defvar w3m-current-title)
 
-(add-hook 'org-store-link-functions 'org-w3m-store-link)
+(org-link-set-parameters "w3m" :store 'org-w3m-store-link)
 (defun org-w3m-store-link ()
   "Store a link to a w3m buffer."
   (when (eq major-mode 'w3m-mode)

commit f28838515b438d992d0b0f477a03e9cd1c1604f2
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:28:09 2016 -0400

    Update rmail link definition
    
    * lisp/org-rmail.el ("rmail"):
    Use org-link-set-parameters to define link.

diff --git a/lisp/org-rmail.el b/lisp/org-rmail.el
index 0bf44b8..7ceb972 100644
--- a/lisp/org-rmail.el
+++ b/lisp/org-rmail.el
@@ -43,8 +43,7 @@
 (defvar rmail-file-name)        ; From rmail.el
 
 ;; Install the link type
-(org-add-link-type "rmail" 'org-rmail-open)
-(add-hook 'org-store-link-functions 'org-rmail-store-link)
+(org-link-set-parameters "rmail" :follow 'org-rmail-open :store 'org-rmail-store-link)
 
 ;; Implementation
 (defun org-rmail-store-link ()

commit 43b801f3dc71d653705ccdd329ed3db4a6e363ba
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:55 2016 -0400

    Update mhe link definition.
    
    * lisp/org-mhe.el ("mhe"):
    Define link with org-link-set-parameters.

diff --git a/lisp/org-mhe.el b/lisp/org-mhe.el
index 2ee21de..773bcfd 100644
--- a/lisp/org-mhe.el
+++ b/lisp/org-mhe.el
@@ -74,8 +74,7 @@ supported by MH-E."
 (defvar mh-search-regexp-builder)
 
 ;; Install the link type
-(org-add-link-type "mhe" 'org-mhe-open)
-(add-hook 'org-store-link-functions 'org-mhe-store-link)
+(org-link-set-parameters "mhe" :follow 'org-mhe-open :store 'org-mhe-store-link)
 
 ;; Implementation
 (defun org-mhe-store-link ()

commit d64f1cf33805c396f511bbbecf66a965f9564553
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:45 2016 -0400

    Update irc link definition
    
    * lisp/org-irc.el ("irc"):
    Define link with org-link-set-parameters.

diff --git a/lisp/org-irc.el b/lisp/org-irc.el
index 81d0296..afb24c1 100644
--- a/lisp/org-irc.el
+++ b/lisp/org-irc.el
@@ -71,9 +71,7 @@
 
 ;; Generic functions/config (extend these for other clients)
 
-(add-to-list 'org-store-link-functions 'org-irc-store-link)
-
-(org-add-link-type "irc" 'org-irc-visit nil)
+(org-link-set-parameters "irc" :follow 'org-irc-visit :store 'org-irc-store-link)
 
 (defun org-irc-visit (link)
   "Parse LINK and dispatch to the correct function based on the client found."

commit d383c75f4e9e5aecdea82714b84d51494d444d8b
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:32 2016 -0400

    Update info link definition
    
    * lisp/org-info.el ("info"):
    Update link definition with org-link-set-parameters and change a doc string to
    point to org-link-parameters.

diff --git a/lisp/org-info.el b/lisp/org-info.el
index 9e8fde0..0e9c43e 100644
--- a/lisp/org-info.el
+++ b/lisp/org-info.el
@@ -40,8 +40,8 @@
 (defvar Info-current-node)
 
 ;; Install the link type
-(org-add-link-type "info" 'org-info-open 'org-info-export)
-(add-hook 'org-store-link-functions 'org-info-store-link)
+(org-link-set-parameters "info" :follow 'org-info-open
+			 :export 'org-info-export :store 'org-info-store-link)
 
 ;; Implementation
 (defun org-info-store-link ()
@@ -113,7 +113,7 @@ emacs related documents. See `org-info-official-gnu-document' and
 
 (defun org-info-export (path desc format)
   "Export an info link.
-See `org-add-link-type' for details about PATH, DESC and FORMAT."
+See `org-link-parameters' for details about PATH, DESC and FORMAT."
   (when (eq format 'html)
     (or (string-match "\\(.*\\)[#:]:?\\(.*\\)" path)
 	(string-match "\\(.*\\)" path))

commit 32835426cfab9666c08f37a68c1fc93a34c5e581
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:14 2016 -0400

    Update gnus link definition
    
    * lisp/org-gnus.el ("gnus"):
    Update link definition with org-link-set-parameters.

diff --git a/lisp/org-gnus.el b/lisp/org-gnus.el
index 386d6dc..8544f75 100644
--- a/lisp/org-gnus.el
+++ b/lisp/org-gnus.el
@@ -74,8 +74,7 @@ this variable to t."
   :type 'boolean)
 
 ;; Install the link type
-(org-add-link-type "gnus" 'org-gnus-open)
-(add-hook 'org-store-link-functions 'org-gnus-store-link)
+(org-link-set-parameters "gnus" :follow 'org-gnus-open :store 'org-gnus-store-link)
 
 ;; Implementation
 

commit 29ae3ba2eb3ece1f57328822a403430467b7dbe4
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:27:03 2016 -0400

    Update eshell link definition
    
    * lisp/org-eshell.el ("eshell"):
    
    Update to use org-link-set-parameters.

diff --git a/lisp/org-eshell.el b/lisp/org-eshell.el
index 1919f6d..76b315e 100644
--- a/lisp/org-eshell.el
+++ b/lisp/org-eshell.el
@@ -27,8 +27,9 @@
 (require 'eshell)
 (require 'esh-mode)
 
-(org-add-link-type "eshell" 'org-eshell-open)
-(add-hook 'org-store-link-functions 'org-eshell-store-link)
+(org-link-set-parameters "eshell"
+			 :follow 'org-eshell-open
+			 :store 'org-eshell-store-link)
 
 (defun org-eshell-open (link)
   "Switch to am eshell buffer and execute a command line.

commit e8eecbb66061e7a1ce3d20497758c55aa4a02d5b
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:26:28 2016 -0400

    Update docview link definition
    
    * lisp/org-docview.el ("docview"):
    
    Update link definition with org-link-set-parameters.

diff --git a/lisp/org-docview.el b/lisp/org-docview.el
index fbc5551..e6404aa 100644
--- a/lisp/org-docview.el
+++ b/lisp/org-docview.el
@@ -49,8 +49,10 @@
 (declare-function doc-view-goto-page "doc-view" (page))
 (declare-function image-mode-window-get "image-mode" (prop &optional winprops))
 
-(org-add-link-type "docview" 'org-docview-open 'org-docview-export)
-(add-hook 'org-store-link-functions 'org-docview-store-link)
+(org-link-set-parameters "docview"
+			 :follow 'org-docview-open
+			 :export 'org-docview-export
+			 :store 'org-docview-store-link)
 
 (defun org-docview-export (link description format)
   "Export a docview link from Org files."

commit 5f0a3e9d7c72938aff9eb38621c4e3e1d7bd4975
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:26:04 2016 -0400

    Update bibtex link definition
    
    * lisp/org-bibtex.el ("bibtex"):
    
    Change link definition to use org-link-set-parameters

diff --git a/lisp/org-bibtex.el b/lisp/org-bibtex.el
index 74e32f7..479422b 100644
--- a/lisp/org-bibtex.el
+++ b/lisp/org-bibtex.el
@@ -452,8 +452,7 @@ With optional argument OPTIONAL, also prompt for optional fields."
 
 \f
 ;;; Bibtex link functions
-(org-add-link-type "bibtex" 'org-bibtex-open)
-(add-hook 'org-store-link-functions 'org-bibtex-store-link)
+(org-link-set-parameters "bibtex" :follow 'org-bibtex-open nil :store 'org-bibtex-store-link)
 
 (defun org-bibtex-open (path)
   "Visit the bibliography entry on PATH."

commit ff3b14496d87111f03110ba7a825fa7241599cee
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:25:39 2016 -0400

    Update bbdb link definition
    
    * lisp/org-bbdb.el ("bbdb"):
    
    Change link definition to org-link-set-parameters

diff --git a/lisp/org-bbdb.el b/lisp/org-bbdb.el
index 8d886cd..4af71fb 100644
--- a/lisp/org-bbdb.el
+++ b/lisp/org-bbdb.el
@@ -194,10 +194,10 @@ date year)."
   :group 'org-bbdb-anniversaries
   :require 'bbdb)
 
-
 ;; Install the link type
-(org-add-link-type "bbdb" 'org-bbdb-open 'org-bbdb-export)
-(add-hook 'org-store-link-functions 'org-bbdb-store-link)
+(org-link-set-parameters "bbdb" :follow 'org-bbdb-open :export 'org-bbdb-export
+			 :complete 'org-bbdb-complete-link
+			 :store 'org-bbdb-store-link)
 
 ;; Implementation
 (defun org-bbdb-store-link ()

commit 61c530c96c565aca11e07e55b9992811b3a3d149
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:22:24 2016 -0400

    Make plain and bracketed link properties stick
    
    * lisp/org.el (org-set-font-lock-defaults): If t is after the face, than
      org-link clobbers everything from the activation functions.

diff --git a/lisp/org.el b/lisp/org.el
index 7b3731f..ec45e6c 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -6521,8 +6521,8 @@ needs to be inserted at a specific position in the font-lock sequence.")
 	   ;; Links
 	   (when (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
 	   (when (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
-	   (when (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
-	   (when (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
+	   (when (memq 'plain lk) '(org-activate-plain-links (0 'org-link)))
+	   (when (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link)))
 	   (when (memq 'radio lk) '(org-activate-target-links (1 'org-link t)))
 	   (when (memq 'date lk) '(org-activate-dates (0 'org-date t)))
 	   (when (memq 'footnote lk) '(org-activate-footnote-links))

commit 2c8cef397f55f7e59000cd91b8095adcea81b875
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:21:50 2016 -0400

    Update `org-activate-bracket-links'
    
    * lisp/org.el (org-activate-bracket-links): Use `org-link-parameters' to
      build link properties.

diff --git a/lisp/org.el b/lisp/org.el
index a5d809d..7b3731f 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -6166,14 +6166,69 @@ by a #."
   (when (and (re-search-forward org-bracket-link-regexp limit t)
 	     (not (org-in-src-block-p)))
     (let* ((hl (match-string-no-properties 1))
-	   (help (concat "LINK: " (save-match-data (org-link-unescape hl))))
-	   (ip (list 'invisible 'org-link
-		     'keymap org-mouse-map 'mouse-face 'highlight
-		     'font-lock-multiline t 'help-echo help
-		     'htmlize-link `(:uri ,hl)))
-	   (vp (list 'keymap org-mouse-map 'mouse-face 'highlight
-		     'font-lock-multiline t 'help-echo help
-		     'htmlize-link `(:uri ,hl))))
+	   (type (save-match-data
+		   (if (string-match org-plain-link-re hl)
+		       (match-string-no-properties 1 hl)
+		     nil)))
+	   (path (save-match-data
+		   (if (string-match org-plain-link-re hl)
+		       (match-string-no-properties 2 hl)
+		     nil)))
+	   (link-start (match-beginning 0))
+	   (link-end (match-end 0))
+	   (bracketp t)
+	   (help-echo (org-link-get-parameter type :help-echo))
+	   (help (cond
+		  ((stringp help-echo)
+		   help-echo)
+		  ((functionp help-echo)
+		   help-echo)
+		  (t
+		   (concat "LINK: "
+			   (save-match-data
+			     (org-link-unescape hl))))))
+	   (link-face (org-link-get-parameter type :face))
+	   (face (cond
+		  ;; A function that returns a face
+		  ((functionp link-face)
+		   (funcall link-face path))
+		  ;; a face
+		  ((facep link-face)
+		   link-face)
+		  ;; An anonymous face
+		  ((consp link-face)
+		   link-face)
+		  ;; default
+		  (t
+		   'org-link)))
+	   (keymap (or (org-link-get-parameter type :keymap)
+		       org-mouse-map))
+	   (mouse-face (or (org-link-get-parameter type :mouse-face)
+			   'highlight))
+	   (htmlize (org-link-get-parameter type :htmlize-link))
+	   (htmlize-link (cond
+			  ((functionp htmlize)
+			   (funcall htmlize))
+			  (t
+			   `(:uri ,(format "%s:%s" type path)))))
+	   (activate-func (org-link-get-parameter type :activate-func))
+	   ;; invisible part
+	   (ip (list 'invisible (or
+				 (org-link-get-parameter type :display)
+				 'org-link)
+		     'face face
+		     'keymap keymap
+		     'mouse-face mouse-face
+		     'font-lock-multiline t
+		     'help-echo help
+		     'htmlize-link htmlize-link))
+	   ;; visible part
+	   (vp (list 'keymap keymap
+		     'face face
+		     'mouse-face mouse-face
+		     'font-lock-multiline t
+		     'help-echo help
+		     'htmlize-link htmlize-link)))
       ;; We need to remove the invisible property here.  Table narrowing
       ;; may have made some of this invisible.
       (org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
@@ -6193,6 +6248,8 @@ by a #."
 	(org-rear-nonsticky-at (match-end 1))
 	(add-text-properties (match-end 1) (match-end 0) ip)
 	(org-rear-nonsticky-at (match-end 0)))
+      (when activate-func
+	(funcall activate-func link-start link-end path bracketp))
       t)))
 
 (defun org-activate-dates (limit)

commit a6bf839e14bf35dd2f068ef006564d82d61ff794
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:21:08 2016 -0400

    Update `org-activate-plain-links'
    
    * lisp/org.el (org-activate-plain-links): Use `org-link-parameters' to
      create the link properties.

diff --git a/lisp/org.el b/lisp/org.el
index 87788dc..a5d809d 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5926,17 +5926,57 @@ prompted for."
   "Add link properties for plain links."
   (when (and (re-search-forward org-plain-link-re limit t)
 	     (not (org-in-src-block-p)))
-    (let ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
-				   'face))
-	  (link (match-string-no-properties 0)))
+
+    (let* ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
+				    'face))
+	   (link (match-string-no-properties 0))
+	   (type (match-string-no-properties 1))
+	   (path (match-string-no-properties 2))
+	   (link-start (match-beginning 0))
+	   (link-end (match-end 0))
+	   (link-face (org-link-get-parameter type :face))
+	   (help-echo (org-link-get-parameter type :help-echo))	   
+	   (htmlize-link (org-link-get-parameter type :htmlize-link))
+	   (activate-func (org-link-get-parameter type :activate-func)))
       (unless (if (consp face) (memq 'org-tag face) (eq 'org-tag face))
 	(org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
 	(add-text-properties (match-beginning 0) (match-end 0)
-			     (list 'mouse-face 'highlight
-				   'face 'org-link
-				   'htmlize-link `(:uri ,link)
-				   'keymap org-mouse-map))
+			     (list
+			      'mouse-face (or (org-link-get-parameter type :mouse-face)
+					      'highlight)
+			      'face (cond
+				     ;; A function that returns a face
+				     ((functionp link-face)
+				      (funcall link-face path))
+				     ;; a face
+				     ((facep link-face)
+				      link-face)
+				     ;; An anonymous face
+				     ((consp link-face)
+				      link-face)
+				     ;; default
+				     (t
+				      'org-link))
+			      'help-echo (cond
+					  ((stringp help-echo)
+					   help-echo)
+					  ((functionp help-echo)
+					   help-echo)
+					  (t
+					   (concat "LINK: "
+						   (save-match-data
+						     (org-link-unescape link)))))
+			      'htmlize-link (cond
+					     ((functionp htmlize-link)
+					      (funcall htmlize-link path))
+					     (t
+					      `(:uri ,link)))
+			      'keymap (or (org-link-get-parameter type :keymap)
+					  org-mouse-map)
+			      'org-link-start (match-beginning 0)))
 	(org-rear-nonsticky-at (match-end 0))
+	(when activate-func
+	  (funcall activate-func link-start link-end path nil))
 	t))))
 
 (defun org-activate-code (limit)

commit 03c28269f1647c73778e05049371e3c229baa9ea
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:20:23 2016 -0400

    Get the complete function from org-link-parameters
    
    * lisp/org.el (org-link-try-special-completion):

diff --git a/lisp/org.el b/lisp/org.el
index c21b3f4..87788dc 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -10488,7 +10488,7 @@ Use TAB to complete link prefixes, then RET for type-specific completion support
 
 (defun org-link-try-special-completion (type)
   "If there is completion support for link type TYPE, offer it."
-  (let ((fun (intern (concat "org-" type "-complete-link"))))
+  (let ((fun (org-link-get-parameter type :complete)))
     (if (functionp fun)
 	(funcall fun)
       (read-string "Link (no completion support): " (concat type ":")))))

commit c6a9e7f6f3a0633a6601ad539a97f782201b09c9
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:19:52 2016 -0400

    Replace org-store-link-functions variable with function
    
    * lisp/org.el: Replace the variable `org-store-link-functions' with a
      function by the same name.

diff --git a/lisp/org.el b/lisp/org.el
index 9ace135..c21b3f4 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9823,7 +9823,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

commit 16338bacc292659bcf486cc507bc0ecb1b0695d9
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:18:57 2016 -0400

    Update org-add-link-type
    
    * lisp/org.el org-add-link-type: deprecated and now calls
      `org-link-add'.
    
    Create a new `org-link-add' function for making links.

diff --git a/lisp/org-compat.el b/lisp/org-compat.el
index 92fdb1c..a856ff7 100644
--- a/lisp/org-compat.el
+++ b/lisp/org-compat.el
@@ -374,6 +374,37 @@ Implements `define-error' for older emacsen."
     (put name 'error-conditions
 	 (copy-sequence (cons name (get 'error 'error-conditions))))))
 
+(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-add type :follow follow :export export) 
+  (message "Created %s link." type))
+
+(make-obsolete 'org-add-link-type "org-link-add." "Org 9.0")
+
 (provide 'org-compat)
 
 ;;; org-compat.el ends here
diff --git a/lisp/org.el b/lisp/org.el
index e833ec2..9ace135 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9748,37 +9748,37 @@ Special properties are:
 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)))
+
+(defun org-store-link-functions ()
+  "Returns a list of functions that are called to create and store a link.
+The functions in the variable `org-store-link-functions' come
+first. These may be user-defined for different contexts. Then
+comes the functions defined in the :store property of
+org-link-parameters.
+
+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:
+
+: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.
+
+In addition to these, any additional properties can be specified
+and then used in capture templates."
+  (append
+   org-store-link-functions
+   (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

commit d0914669c7668b1e689604d5ac68e214dc6be361
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:16:38 2016 -0400

    Remove `org-link-protocols'
    
    * lisp/org.el (org-link-protocols): Remove variable.
    The data in this variable is now retrieved with org-link-get-parameter.

diff --git a/lisp/org.el b/lisp/org.el
index 954ed58..e833ec2 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -9728,9 +9728,6 @@ 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'.")
-
 (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
@@ -10769,7 +10766,7 @@ link in a property drawer line."
 	       ((equal type "file")
 		(if (string-match "[*?{]" (file-name-nondirectory path))
 		    (dired path)
-		  ;; Look into `org-link-protocols' in order to find
+		  ;; Look into `org-link-parameters' in order to find
 		  ;; a DEDICATED-FUNCTION to open file.  The function
 		  ;; will be applied on raw link instead of parsed
 		  ;; link due to the limitation in `org-add-link-type'
@@ -10783,7 +10780,7 @@ link in a property drawer line."
 		  (let* ((option (org-element-property :search-option link))
 			 (app (org-element-property :application link))
 			 (dedicated-function
-			  (nth 1 (assoc app org-link-protocols))))
+			  (org-link-get-parameter type :follow)))
 		    (if dedicated-function
 			(funcall dedicated-function
 				 (concat path
@@ -10798,8 +10795,8 @@ link in a property drawer line."
 				    (list (string-to-number option)))
 				   (t (list nil
 					    (org-link-unescape option)))))))))
-	       ((assoc type org-link-protocols)
-		(funcall (nth 1 (assoc type org-link-protocols)) path))
+	       ((assoc type org-link-parameters)
+		(funcall (org-link-get-parameter type :follow) path))
 	       ((equal type "help")
 		(let ((f-or-v (intern path)))
 		  (cond ((fboundp f-or-v) (describe-function f-or-v))
@@ -10848,7 +10845,7 @@ link in a property drawer line."
 		    (user-error "Abort"))))
 	       ((equal type "id")
 		(require 'org-id)
-		(funcall (nth 1 (assoc "id" org-link-protocols)) path))
+		(funcall (org-link-get-parameter type :follow) path))
 	       ((member type '("coderef" "custom-id" "fuzzy" "radio"))
 		(unless (run-hook-with-args-until-success
 			 'org-open-link-functions path)
diff --git a/lisp/ox.el b/lisp/ox.el
index 3986ec3..8472e9d 100644
--- a/lisp/ox.el
+++ b/lisp/ox.el
@@ -4116,7 +4116,7 @@ The function ignores links with an implicit type (e.g.,
   (let ((type (org-element-property :type link)))
     (unless (or (member type '("coderef" "custom-id" "fuzzy" "radio"))
 		(not backend))
-      (let ((protocol (nth 2 (assoc type org-link-protocols))))
+      (let ((protocol (org-link-get-parameter type :export)))
 	(and (functionp protocol)
 	     (funcall protocol
 		      (org-link-unescape (org-element-property :path link))

commit a8a86523c22b663c176f3a5be3ecc328a694e6b8
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:08:14 2016 -0400

    Add org-link-parameters
    
    * lisp/org.el (org-link-parameters): Add new centralized link variable.
    
    (org-link-get-parameter): A getter function to get link parameters
    
    (org-link-set-parameters): A setter function to set link parameters
    
    (org-link-types): A function to return a list of link types.
    
    * lisp/ox.el: update comment for this new variable.
    
    add # to func in link-types
    
    org-lik-parameters redef
    
    change cl-getf to plist-get
    
    rm return value in org-link-set-parameters
    
    replace org-link-set-parameters
    
    * testing/lisp/test-ox.el
    update tests to take out org-link-types and use org-link-set-parameters.

diff --git a/lisp/org.el b/lisp/org.el
index c875d03..954ed58 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -1758,6 +1758,71 @@ 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
+  '(("http") ("https") ("ftp") ("mailto")
+    ("file" :complete 'org-file-complete-link)
+    ("file+emacs") ("file+sys")
+    ("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
+variable `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 args 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 paramters"
+		:value-type (plist)))
+
+(defun org-link-get-parameter (type key)
+  "Get TYPE link property for KEY."
+  (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 (cdr 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 ()
+  "Returns 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 +5555,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)
@@ -7390,7 +7455,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
 
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 f1acc54..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 (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 (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 (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

commit a4b9ed7783437838f909f3516fb53f32598e803e
Author: John Kitchin <jkitchin@andrew.cmu.edu>
Date:   Tue Jul 5 10:07:10 2016 -0400

    Remove org-link-types
    
    * lisp/org.el (org-link-types): Remove this variable.
    
    * testing/lisp/test-ox.el (test-org-export/custom-protocol-maybe):
    
    Remove copy-sequence in the tests. Actually it seems like the let
    statement is no longer needed. I guess it was around to protect the list
    from extra links getting defined. A downside of this is the links may
    get added during tests. That does not seem like a big deal if those are
    run in batch mode.
    
    * lisp/org.el: The `org-link-types' variable was replaced with the
      `org-link-types' function everywhere.

diff --git a/lisp/org-element.el b/lisp/org-element.el
index 269bc7d..9452641 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 2202d41..c875d03 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -5658,9 +5658,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 +5724,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 +5763,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) ":\\)?"
 	   "\\([^]]+\\)"
 	   "\\]"
 	   "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
@@ -10325,7 +10322,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
diff --git a/testing/lisp/test-ox.el b/testing/lisp/test-ox.el
index 8b07cca..f1acc54 100644
--- a/testing/lisp/test-ox.el
+++ b/testing/lisp/test-ox.el
@@ -2571,7 +2571,7 @@ Para2"
   (should
    (string-match
     "success"
-    (let ((org-link-types (copy-sequence org-link-types)))
+    (let ((org-link-types (org-link-types)))
       (org-add-link-type "foo" nil (lambda (p d f) "success"))
       (org-export-string-as
        "[[foo:path]]"
@@ -2586,7 +2586,7 @@ Para2"
   (should-not
    (string-match
     "success"
-    (let ((org-link-types (copy-sequence org-link-types)))
+    (let ((org-link-types (org-link-types)))
       (org-add-link-type
        "foo" nil (lambda (p d f) (and (eq f 'test) "success")))
       (org-export-string-as
@@ -2603,7 +2603,7 @@ Para2"
   (should-not
    (string-match
     "success"
-    (let ((org-link-types (copy-sequence org-link-types)))
+    (let ((org-link-types (org-link-types)))
       (org-add-link-type
        "foo" nil (lambda (p d f) (and (eq f 'test) "success")))
       (org-export-string-as



Nicolas Goaziou writes:

> John Kitchin <jkitchin@andrew.cmu.edu> writes:
>
>> I pasted the diffs at the end. There are a lot because it touched a lot of
>> files, and I committed each one separately, and forgot a few commits
>> that ended up as extras. Probably some could be combined and squashed if
>> that is desirable. I am not sure how to do it yet though.
>
> Clearly some of them could be merged. From magit, this is "r i" from the
> first commit (aka interactive rebase) then, you can squash or fixup
> commits, reorder them...
>
> Comments follow, in reverse order.
>
>> commit 546031bb7b59a9deb6bce976f7f7496ea7b2ffc4
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 16:16:29 2016 -0400
>>
>>     add link-start and link-end variables
>
> This can probably be merged with another commit.
>
>> commit d1799252a7e4bd255a5507d742e0b0a7c19983b1
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 16:16:02 2016 -0400
>>
>>     deprecate org-add-link-type
>>     
>>     It now calls org-link-add.
>>
>> diff --git a/lisp/org.el b/lisp/org.el
>> index 4fb1cfb..872f861 100644
>> --- a/lisp/org.el
>> +++ b/lisp/org.el
>> @@ -9852,10 +9852,10 @@ Special properties are:
>>  In addition to these, any additional properties can be specified
>>  and then used in capture templates.")
>>  
>> -(cl-defun org-add-link-type (type &optional follow export
>> -				  &key store complete face mouse-face display
>> -				  help-echo keymap htmlize-link activate-func)
>> +(defun org-add-link-type (type &optional follow export)
>>    "Add a new TYPE link.
>> +Deprecated. Use `org-link-add' instead.
>
> No need to add this in the docstring. Use `make-obsolete'. Also,
> obsolete definitions should be moved to "org-compat.el".
>
>> +  (unless (cdr (assoc type org-link-parameters))
>> +    (error "No link of type %s defined." type))
>> +  (cl-loop for (key val) on parameters by #'cddr
>> +	   do
>> +	   (setf (cl-getf
>> +		  (cdr (assoc type org-link-parameters))
>> +		  key)
>> +		 val))
>>    org-link-parameters)
>
> See below for a suggested implementation of the function.
>
>> +(defun org-link-add (type &rest properties)
>> +  "Add a TYPE link with PROPERTIES defined as a plist.
>> +See `org-link-parameters' for details on the PROPERTIES." 
>> +  (push (append (list type) properties)
>> +	org-link-parameters)
>> +  (org-make-link-regexps)
>> +  (org-element-update-syntax))
>
> This function is not needed since it is the same as
> `org-link-set-parameters'.
>
>>  (defun org-link-types ()
>>    "Returns a list of known link types."
>>    (mapcar 'car org-link-parameters))
>>
>> commit 1069d9bac0974f27abda2736fef883eb8334c761
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 16:14:02 2016 -0400
>>
>>     update comment for new variable.
>
> "Update ..."
>
> This can probably be merged with another commit.
>
> I skipped intermediary commits. You can merge them.
>
>> commit a883c04c1c9cd9ae7eeaac485eebebc49204f5d3
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:42:49 2016 -0400
>>
>>     remove copy-sequence
>>     
>>     Actually it seems like the let statement is no longer needed. I guess it
>>     was around to protect the list from extra links getting defined.
>
> You can merge this commit with another one below.
>
>> commit c922ab8b2d19d265f8183a5b0d36adb9b61087ce
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:30:48 2016 -0400
>>
>>     replace an org-link-types variable with function
>
> You can merge it with a commit below.
>
>> commit 75fa053296d8b4bbb8e7edeb9b7e077eb8ed37f1
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:28:38 2016 -0400
>>
>>     update w3m link
>>
>> commit c41dcddfa8ba848d4e911282bc5760a4e4b953ff
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:28:09 2016 -0400
>>
>>     update rmail link definition
>>
>> commit 86221a71daa897d94cb8ca7aa4f63f0b4e897477
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:27:55 2016 -0400
>>
>>     update mhe link definition.
>>
>> commit fc6accee74dd61dc58cab3e5d70fbf411faedb74
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:27:45 2016 -0400
>>
>>     update irc link definition
>>
>> commit 6e7d024b316fb8c9f1ebf37421a50917ac69aa15
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:27:32 2016 -0400
>>
>>     update info link definition
>>
>> commit 898abadf1decbf730a679ba34f5b26a37f52bcf5
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:27:14 2016 -0400
>>
>>     update gnus link definition
>>
>> commit 917114bd4968f7ff8e653950af194a70d625c849
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:27:03 2016 -0400
>>
>>     update eshell link definition
>>
>> commit 626682724311ca54292a34f2b9a4b8aa519c6fe8
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:26:28 2016 -0400
>>
>>     Update docview link definition
>>
>> commit 2f32ebf222c6d1e391358d6146ebc6f21a4bf095
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:26:04 2016 -0400
>>
>>     update bibtex link definition.
>>     
>>     * lisp/org-bibtex.el ("bibtex"):
>>
>> commit 776f20bfc5afd744c6318f9d66ced055c02a88c5
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:25:39 2016 -0400
>>
>>     update bbdb link definition.
>>     
>>     * lisp/org-bbdb.el ("bbdb"):
>
> Skipped type specific patches. Please mind the commit messages, though.
>
>> commit 5a296333a30e3880e5f551eb82c8b0219447e793
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:24:01 2016 -0400
>>
>>     add activate-func
>
> "Add activate-func"
>
>>     * lisp/org.el (org-activate-bracket-links):
>>     This should have been in the previous commit on this function.
>
> You can merge commits easily.
>
>> commit c306e89aa41b8f84107dc60957540e3eaa85d009
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:23:27 2016 -0400
>>
>>     replace org-link-protocols with the link export parameter.
>
> Commit message is incomplete. Otherwise, OK.
>
>> commit 50d93f950f68587bad239b8fa26741f8b44675d8
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:22:24 2016 -0400
>>
>>     Make plain and bracketed link properties stick
>>     
>>     * lisp/org.el (org-set-font-lock-defaults): If t is after the face, than
>>       org-link clobbers everything from the activation functions.
>
> Ok.
>
>> commit 70cd41305abdce2f5deb458cea6b493d6c850e3c
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:21:50 2016 -0400
>>
>>     Update org-activate-bracket-links
>
> `org-activate-bracket-links'
>
>>     * lisp/org.el (org-activate-bracket-links): Use org-link-parameters to
>>       build link properties.
>
> `org-link-parameters'
>
>> +			    ;; An anonymous face
>> +			    ((listp link-face)
>> +			     link-face)
>
> See below.
>
>> +			    ;; default
>> +			    (t
>> +			     'org-link))
>> +		     'keymap (or (org-link-get-parameter type :keymap)
>> +				 org-mouse-map)
>> +		     'mouse-face (or (org-link-get-parameter type :mouse-face)
>> +				     'highlight)
>> +		     'font-lock-multiline t
>> +		     'help-echo help
>> +		     'htmlize-link (cond
>> +				    ((functionp htmlize-link)
>> +				     (funcall htmlize-link))
>> +				    (t
>> +				     `(:uri ,(format "%s:%s" type path))))))
>> +	   ;; visible part
>> +	   (vp (list 'keymap (or (org-link-get-parameter type :keymap)
>> +				 org-mouse-map)
>> +		     'face (cond
>> +			    ;; A function that returns a face
>> +			    ((functionp link-face)
>> +			     (funcall link-face path))
>> +			    ;; a face
>> +			    ((facep link-face)
>> +			     link-face)
>> +			    ;; An anonymous face
>> +			    ((listp link-face)
>> +			     link-face)
>> +			    ;; default
>> +			    (t
>> +			     'org-link))
>> +		     'mouse-face (or (org-link-get-parameter type :mouse-face)
>> +				     'highlight)
>> +		     'font-lock-multiline t
>> +		     'help-echo help
>> +		     'htmlize-link (cond
>> +				    ((functionp htmlize-link)
>> +				     (funcall htmlize-link))
>> +				    (t
>> +				     `(:uri ,(format "%s:%s" type path)))))))
>
> There is some code duplication going on here. It doesn't matter much for
> now.
>
>> commit d2d39fc4ea24e17dd24c0bc78b4ef1cc14ef8258
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:21:08 2016 -0400
>>
>>     update org-activate-plain-links
>
> `org-activate-plain-links'
>>     
>>     * lisp/org.el (org-activate-plain-links): Use org-link-parameters to
>>       create the link properties.
>
> `org-link-parameters'
>
>>
>> diff --git a/lisp/org.el b/lisp/org.el
>> index 6dfd089..21122b7 100644
>> --- a/lisp/org.el
>> +++ b/lisp/org.el
>> @@ -5917,17 +5917,55 @@ prompted for."
>>    "Add link properties for plain links."
>>    (when (and (re-search-forward org-plain-link-re limit t)
>>  	     (not (org-in-src-block-p)))
>> -    (let ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
>> -				   'face))
>> -	  (link (match-string-no-properties 0)))
>> +
>> +    (let* ((face (get-text-property (max (1- (match-beginning 0)) (point-min))
>> +				    'face))
>> +	   (link (match-string-no-properties 0))
>> +	   (type (match-string-no-properties 1))
>> +	   (path (match-string-no-properties 2))
>> +	   (link-face (org-link-get-parameter type :face))
>> +	   (help-echo (org-link-get-parameter type :help-echo))	   
>> +	   (htmlize-link (org-link-get-parameter type :htmlize-link))
>> +	   (activate-func (org-link-get-parameter type :activate-func)))
>>        (unless (if (consp face) (memq 'org-tag face) (eq 'org-tag face))
>>  	(org-remove-flyspell-overlays-in (match-beginning 0) (match-end 0))
>>  	(add-text-properties (match-beginning 0) (match-end 0)
>> -			     (list 'mouse-face 'highlight
>> -				   'face 'org-link
>> -				   'htmlize-link `(:uri ,link)
>> -				   'keymap org-mouse-map))
>> +			     (list
>
> I suggest to move `list' under `add-text-properties'
>
>> +			      'mouse-face (or (org-link-get-parameter type :mouse-face)
>> +					      'highlight)
>> +			      'face (cond
>> +				     ;; A function that returns a face
>> +				     ((functionp link-face)
>> +				      (funcall link-face path))
>> +				     ;; a face
>> +				     ((facep link-face)
>> +				      link-face)
>> +				     ;; An anonymous face
>> +				     ((listp link-face)
>> +				      link-face)
>
> This should be (consp link-face) so as to avoid nil face, shouldn't it?
>
>> commit 66ad0a6d2c79ac0424f8424b875d707e36fe11d2
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:20:23 2016 -0400
>>
>>     get complete function from org-link-parameters.
>
> Commit message is incomplete.
>
>>  (defun org-link-try-special-completion (type)
>>    "If there is completion support for link type TYPE, offer it."
>> -  (let ((fun (intern (concat "org-" type "-complete-link"))))
>> +  (let ((fun (or (org-link-get-parameter type :complete)
>> +		 ;; We still honor the "org-type-complete-link
>> +		 ;; form. There are some built in links like
>> +		 ;; org-file-complete-link that don't fit nicely into
>> +		 ;; org-link-parameters.
>> +		 (intern (concat "org-" type "-complete-link")))))
>
> Eww. How so? Why couldn't `org-file-complete-link' the value
> of :complete property of "file" type in `org-link-parameters'?
>
>> commit 251b574b8669d3ed685542eec03c89336c0c91c5
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:19:52 2016 -0400
>>
>>     Replace org-store-link-functions variable with function
>
> You need to specify what function is modified in the commit message.
>
>> diff --git a/lisp/org.el b/lisp/org.el
>> index 59d6c63..f9e5487 100644
>> --- a/lisp/org.el
>> +++ b/lisp/org.el
>> @@ -9857,7 +9857,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
>>
>> commit c8580dd27d0f71649a938c56357b471f58b2aa97
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:18:57 2016 -0400
>>
>>     Update org-add-link-type
>>     
>>     * lisp/org.el org-add-link-type: Now accepts keyword arguments for link parameters.
>
> This one can be removed.
>
>> commit 763a0a8cb636bccf6a0211447d287296cd624ccb
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:16:38 2016 -0400
>>
>>     Remove org-link-protocols
>
> Missing:
>
>   lisp/org.el (org-link-protocols): Remove variable.
>
> Looks good otherwise.
>
>> commit 91d90b6bef8fac0a94efdf915561a03e75526b11
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:13:17 2016 -0400
>>
>>     Replace org-link-types with function
>>     
>>     * lisp/org.el: The variable was replaced with the function
>>     everywhere.
>
> Looks good, but it could be merged with the commit actually defining the function.
>
>> commit 31f6309dd86344b03f3e58263d05ee2ec688c995
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:08:14 2016 -0400
>>
>>     Add org-link-parameters
>>     
>>     * lisp/org.el (org-link-parameters): Add new centralized link variable.
>>     
>>     (org-link-get-parameter): A getter function to get link parameters
>>     
>>     (org-link-set-parameters): A setter function to set link parameters
>>     
>>     (org-link-types): A function to return a list of link types.
>>
>> diff --git a/lisp/org.el b/lisp/org.el
>> index 6dd7f91..8300f8f 100644
>> --- a/lisp/org.el
>> +++ b/lisp/org.el
>> @@ -1758,6 +1758,62 @@ 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
>> +  '(("http") ("https") ("ftp") ("mailto")
>> +    ("file") ("file+emacs") ("file+sys")
>> +    ("news") ("shell") ("elisp")
>> +    ("doi") ("message") ("help"))
>
> I think follow function could be extracted from `org-open-at-point' for,
> at least, "help", "doi", "message", "shell" and "elisp".  This is not
> blocking anyway.
>
>> +  "An alist of properties that defines all the links in org-mode.
>
> org-mode -> Org mode.
>
>> +The first key in each list is a string of the link type.
>
> The key in each association is ...
>
>> +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 variable `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 args 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."
>
> You need to separate sentences with two spaces.  Also, lines should be
> shorter.
>
>> +  :group 'org-link
>> +  :type '(alist :tag "Link display paramters"
>> +		:type string
>> +		:follow :export :store :completion :face :mouse-face
>> +		:display :help-echo :keymap :htmlize-link :activate-func))
>
> I think this :type is invalid.
>
>   :type '(alist :tag "Link display parameters"
> 		:value-type (plist))
>
> is a good start, but ultimately, it should be more subtle.
>
>> +(defun org-link-get-parameter (type key)
>> +  "Get TYPE link property for KEY."
>> +  (cl-getf
>> +   (cdr (assoc type org-link-parameters))
>> +   key))
>
> Nitpick: `cl-getf' -> `plist-get'
>
>> +(defun org-link-set-parameters (type &rest parameters)
>> +  "Set link TYPE properties to PARAMETERS.
>> +PARAMETERS should be :key val pairs."
>> +  (if (cdr (assoc type org-link-parameters))
>> +      ;; update old link
>> +      (cl-loop for (key val) on parameters by #'cddr
>> +	       do
>> +	       (setf (cl-getf
>> +		      (cdr (assoc type org-link-parameters))
>> +		      key)
>> +		     val))
>> +    ;; add new one.
>> +    (push `(,type ,@parameters) org-link-parameters)
>> +    (org-make-link-regexps)
>> +    (org-element-update-syntax))
>> +  org-link-parameters)
>
> There's already `org-combine-plists'. Also I don't think returning
> `org-link-parameters' is needed. If you think it is, it should be
> notified in the docstring.
>
>   (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 (cdr 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 ()
>> +  "Returns a list of known link types."
>> +  (mapcar 'car org-link-parameters))
>
> Nitpick (mapcar #'car ...)
>
>> commit 8b8f65f4314fa9eb08bc5bd7c23dcf32f456f57d
>> Author: John Kitchin <jkitchin@andrew.cmu.edu>
>> Date:   Tue Jul 5 10:07:10 2016 -0400
>>
>>     Remove org-link-types
>>     
>>     * lisp/org.el (org-link-types): Remove this variable.
>
> This one can be merged above.
>
>
> Regards,


-- 
Professor John Kitchin
Doherty Hall A207F
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
@johnkitchin
http://kitchingroup.cheme.cmu.edu

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2016-07-06  1:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-07-05 14:50 Draft of links-9.0 John Kitchin
2016-07-05 19:12 ` Nicolas Goaziou
2016-07-05 19:42   ` Nicolas Goaziou
2016-07-05 20:30   ` John Kitchin
2016-07-05 21:56     ` Nicolas Goaziou
2016-07-06  1:49       ` John Kitchin

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).