emacs-orgmode
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[O] Draft of links-9.0


From: John Kitchin
Subject: [O] Draft of links-9.0
Date: Tue, 05 Jul 2016 10:50:20 -0400
User-agent: mu4e 0.9.16; emacs 25.1.50.1

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 via email to

[Prev in Thread] Current Thread [Next in Thread]