-** addbibresource
-This is apparently used for biblatex.
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type "addbibresource"
- ;; this code is run on clicking. The addbibresource
- ;; may contain multiple files. this code finds the
- ;; one you clicked on and opens it.
- (lambda (link-string)
- ;; get link-string boundaries
- ;; we have to go to the beginning of the line, and then search forward
-
- (let* ((bibfile)
- ;; object is the link you clicked on
- (object (org-element-context))
-
- (link-string-beginning)
- (link-string-end))
-
- (save-excursion
- (goto-char (org-element-property :begin object))
- (search-forward link-string nil nil 1)
- (setq link-string-beginning (match-beginning 0))
- (setq link-string-end (match-end 0)))
-
- ;; We set the reftex-default-addbibresource
- ;; here. it should be a local variable only in
- ;; the current buffer. We need this for using
- ;; reftex to do citations.
- (set (make-local-variable 'reftex-default-addbibresource)
- (split-string (org-element-property :path object) ","))
-
- ;; now if we have comma separated bibliographies
- ;; we find the one clicked on. we want to
- ;; search forward to next comma from point
- (save-excursion
- (if (search-forward "," link-string-end 1 1)
- (setq key-end (- (match-end 0) 1)) ; we found a match
- (setq key-end (point)))) ; no comma found so take the point
- ;; and backward to previous comma from point
- (save-excursion
- (if (search-backward "," link-string-beginning 1 1)
- (setq key-beginning (+ (match-beginning 0) 1)) ; we found a match
- (setq key-beginning (point)))) ; no match found
- ;; save the key we clicked on.
- (setq bibfile (org-ref-strip-string (buffer-substring key-beginning key-end)))
- (find-file bibfile))) ; open file on click
-
- ;; formatting code
- (lambda (keyword desc format)
- (cond
- ((eq format 'html) (format "")); no output for html
- ((eq format 'latex)
- ;; write out the latex addbibresource command
- (format "\\addbibresource{%s}" keyword)))))
-#+END_SRC
-
-** List of Figures
-
-In long documents, a list of figures is not uncommon. Here we create a clickable link that generates a temporary buffer containing a list of figures in the document, and their captions. We make a function that can be called interactively, and define a link type that is rendered in LaTeX to create the list of figures.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-list-of-figures (&optional arg)
- "Generate buffer with list of figures in them"
- (interactive)
- (save-excursion (widen)
- (let* ((c-b (buffer-name))
- (counter 0)
- (list-of-figures
- (org-element-map (org-element-parse-buffer) 'link
- (lambda (link)
- "create a link for to the figure"
- (when
- (and (string= (org-element-property :type link) "file")
- (string-match-p
- "[^.]*\\.\\(png\\|jpg\\|eps\\|pdf\\)$"
- (org-element-property :path link)))
- (incf counter)
-
- (let* ((start (org-element-property :begin link))
- (parent (car (cdr (org-element-property :parent link))))
- (caption (caaar (plist-get parent :caption)))
- (name (plist-get parent :name)))
- (if caption
- (format
- "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]] %s\n"
- c-b start counter (or name "") caption)
- (format
- "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][figure %s: %s]]\n"
- c-b start counter (or name "")))))))))
- (switch-to-buffer "*List of Figures*")
- (setq buffer-read-only nil)
- (org-mode)
- (erase-buffer)
- (insert (mapconcat 'identity list-of-figures ""))
- (setq buffer-read-only t)
- (use-local-map (copy-keymap org-mode-map))
- (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
-
-(org-add-link-type
- "list-of-figures"
- 'org-ref-list-of-figures ; on click
- (lambda (keyword desc format)
- (cond
- ((eq format 'latex)
- (format "\\listoffigures")))))
-#+END_SRC
-
-** List of Tables
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-list-of-tables (&optional arg)
- "Generate a buffer with a list of tables"
- (interactive)
- (save-excursion
- (widen)
- (let* ((c-b (buffer-name))
- (counter 0)
- (list-of-tables
- (org-element-map (org-element-parse-buffer 'element) 'table
- (lambda (table)
- "create a link for to the table"
- (incf counter)
- (let ((start (org-element-property :begin table))
- (name (org-element-property :name table))
- (caption (caaar (org-element-property :caption table))))
- (if caption
- (format
- "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]] %s\n"
- c-b start counter (or name "") caption)
- (format
- "[[elisp:(progn (switch-to-buffer \"%s\")(widen)(goto-char %s))][table %s: %s]]\n"
- c-b start counter (or name ""))))))))
- (switch-to-buffer "*List of Tables*")
- (setq buffer-read-only nil)
- (org-mode)
- (erase-buffer)
- (insert (mapconcat 'identity list-of-tables ""))
- (setq buffer-read-only t)
- (use-local-map (copy-keymap org-mode-map))
- (local-set-key "q" #'(lambda () (interactive) (kill-buffer))))))
-
-(org-add-link-type
- "list-of-tables"
- 'org-ref-list-of-tables
- (lambda (keyword desc format)
- (cond
- ((eq format 'latex)
- (format "\\listoftables")))))
-#+END_SRC
-** label
-
-The label link provides a way to create labels in org-mode. We make it clickable because we want to make sure labels are unique. This code will tell you how many instances of a label are found. We search for label links, LaTeX labels, and the org-mode format for labels. We probably should search for tblnames too.
-*************** TODO search tblnames, custom_ids and check for case sensitivity
-*************** END
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type
- "label"
- (lambda (label)
- "on clicking count the number of label tags used in the buffer. A number greater than one means multiple labels!"
- (message (format "%s occurences"
- (+ (count-matches (format "label:%s\\b[^-:]" label) (point-min) (point-max) t)
- ;; for tblname, it is not enough to get word boundary
- ;; tab-little and tab-little-2 match then.
- (count-matches (format "^#\\+tblname:\\s-*%s\\b[^-:]" label) (point-min) (point-max) t)
- (count-matches (format "\\label{%s}\\b" label) (point-min) (point-max) t)
- ;; this is the org-format #+label:
- (count-matches (format "^#\\+label:\\s-*%s\\b[^-:]" label) (point-min) (point-max) t)))))
- (lambda (keyword desc format)
- (cond
- ((eq format 'html) (format "(<label>%s</label>)" path))
- ((eq format 'latex)
- (format "\\label{%s}" keyword)))))
-#+END_SRC
-
-We want to store links on labels, so you can put the cursor on the label, press C-c l, and later use C-c C-l to insert a link to the label. We also want to store links to tables with a table name, and for sections with CUSTOM_ID.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-label-store-link ()
- "store a link to a label. The output will be a ref to that label"
- ;; First we have to make sure we are on a label link.
- (let* ((object (org-element-context)))
- (when (and (equal (org-element-type object) 'link)
- (equal (org-element-property :type object) "label"))
- (org-store-link-props
- :type "ref"
- :link (concat "ref:" (org-element-property :path object))))
-
- ;; Store link on table
- (when (equal (org-element-type object) 'table)
- (org-store-link-props
- :type "ref"
- :link (concat "ref:" (org-element-property :name object))))
-
-;; it turns out this does not work. you can already store a link to a heading with a CUSTOM_ID
- ;; store link on heading with custom_id
-; (when (and (equal (org-element-type object) 'headline)
-; (org-entry-get (point) "CUSTOM_ID"))
-; (org-store-link-props
-; :type "ref"
-; :link (concat "ref:" (org-entry-get (point) "CUSTOM_ID"))))
-
- ;; and to #+label: lines
- (when (and (equal (org-element-type object) 'paragraph)
- (org-element-property :name object))
- (org-store-link-props
- :type "ref"
- :link (concat "ref:" (org-element-property :name object))))
-))
-
-(add-hook 'org-store-link-functions 'org-label-store-link)
-#+END_SRC
-** ref
-
-The ref link allows you make links to labels. Clicking on the link takes you to the label, and provides a mark to go back to.
-
-At the moment, ref links are not usable for section links. You need [[#CUSTOM_ID]] type links.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(org-add-link-type
- "ref"
- (lambda (label)
- "on clicking goto the label. Navigate back with C-c &"
- (org-mark-ring-push)
- ;; next search from beginning of the buffer
-
- ;; it is possible you would not find the label if narrowing is in effect
- (widen)
-
- (unless
- (or
- ;; our label links
- (progn
- (goto-char (point-min))
- (re-search-forward (format "label:%s\\b" label) nil t))
-
- ;; a latex label
- (progn
- (goto-char (point-min))
- (re-search-forward (format "\\label{%s}" label) nil t))
-
- ;; #+label: name org-definition
- (progn
- (goto-char (point-min))
- (re-search-forward (format "^#\\+label:\\s-*\\(%s\\)\\b" label) nil t))
-
- ;; org tblname
- (progn
- (goto-char (point-min))
- (re-search-forward (format "^#\\+tblname:\\s-*\\(%s\\)\\b" label) nil t))
-
-;; Commented out because these ref links do not actually translate correctly in LaTeX.
-;; you need [[#label]] links.
- ;; CUSTOM_ID
-; (progn
-; (goto-char (point-min))
-; (re-search-forward (format ":CUSTOM_ID:\s-*\\(%s\\)" label) nil t))
- )
- ;; we did not find anything, so go back to where we came
- (org-mark-ring-goto)
- (error "%s not found" label))
- (org-show-entry)
- (message "go back with (org-mark-ring-goto) `C-c &`"))
- ;formatting
- (lambda (keyword desc format)
- (cond
- ((eq format 'html) (format "(<ref>%s</ref>)" path))
- ((eq format 'latex)
- (format "\\ref{%s}" keyword)))))
-#+END_SRC
-
-It would be nice to use completion to enter a ref link, where a list of labels is provided. The following code searches the buffer for org and latex labels, custom_ids, and table names as potential items to make a ref link to.
-
-#+BEGIN_SRC emacs-lisp :tangle org-ref.el
-(defun org-ref-get-org-labels ()
- "find #+LABEL: labels"
- (save-excursion
- (goto-char (point-min))
- (let ((matches '()))
- (while (re-search-forward "^#\\+label:\\s-+\\(.*\\)\\b" (point-max) t)
- (add-to-list 'matches (match-string-no-properties 1) t))
-matches)))
-#+END_SRC