emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
From: John Kitchin <jkitchin@andrew.cmu.edu>
To: "emacs-orgmode@gnu.org" <emacs-orgmode@gnu.org>
Subject: Draft of links-9.0
Date: Tue, 05 Jul 2016 10:50:20 -0400	[thread overview]
Message-ID: <m237nof8b7.fsf@Johns-MacBook-Air.local> (raw)

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

             reply	other threads:[~2016-07-05 14:50 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-05 14:50 John Kitchin [this message]
2016-07-05 19:12 ` Draft of links-9.0 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.orgmode.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=m237nof8b7.fsf@Johns-MacBook-Air.local \
    --to=jkitchin@andrew.cmu.edu \
    --cc=emacs-orgmode@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).