|
|
|
;;; Code: |
|
|
|
(require 'org-element) |
|
|
|
(declare-function 'org-element-property "ex:org") |
|
|
|
;; As this is just experimental, and I don't care about math, this currently |
|
;; only supports figures and tables. |
|
;; |
|
;; Should be easy enough to extend the list of types though. |
|
(defvar org-crossref-types '((figure . "fig") |
|
(table . "tab"))) |
|
(defvar org-crossref-create-table-function 'org-table-create) |
|
(defvar org-crossref-insert-function 'org-crossref--insert-internal) |
|
|
|
;;; Cross-reference insert functions |
|
|
|
(defun org-crossref-insert () |
|
"Insert cross-reference link in buffer." |
|
(interactive) |
|
(funcall org-crossref-insert-function)) |
|
|
|
(defun org-crossref--insert-internal () |
|
"Insert cross-reference in buffer as internal link." |
|
;; Add annotation function with caption. |
|
(let ((type (completing-read "Cross-reference type: " org-crossref-types))) |
|
(let ((target (org-crossref--select-targets type))) |
|
(org-insert-link 'internal target)))) |
|
|
|
(defun org-crossref--insert-typed () |
|
"Insert cross-reference in buffer as org-ref compatible typed link." |
|
;; Add annotation function with caption. |
|
(let ((type (completing-read "Cross-reference type: " org-crossref-types))) |
|
(let* ((target (org-crossref--select-targets type)) |
|
(link-type (pcase type |
|
("table" "tab") |
|
("figure" "fig") |
|
("section" "sec"))) |
|
(typed-target (concat link-type ":" target))) |
|
(org-insert-link 'typed typed-target typed-target)))) |
|
|
|
(defun org-crossref--insert-annotate (target) |
|
"Annotate the cross-reference TARGET with type and caption." |
|
;; TODO: hook this up, format correctly. |
|
(cdr target)) |
|
|
|
(defun org-crossref--select-targets (type) |
|
"Select cross-reference target for TYPE." |
|
;; TODO add annotation function with caption. |
|
(completing-read "Cross-reference target: " |
|
(org-crossref--parse-targets type))) |
|
|
|
(defun org-crossref--parse-targets (type) |
|
"Parse cross-reference targets from org buffer by TYPE." |
|
(let* ((result (list)) |
|
;; org-element doesn't have types for many of these, so have to interpret |
|
(parse-type (pcase type |
|
("table" 'table) |
|
(_ 'link)))) |
|
(org-element-map (org-element-parse-buffer) parse-type |
|
(lambda (target) |
|
(let* ((el-type (org-element-type target)) |
|
(parent (car (cdr (org-element-property :parent target)))) |
|
(name (pcase el-type |
|
('table (org-element-property :name target)) |
|
(_ (plist-get parent :name)))) |
|
(caption (or (caaar (org-element-property :caption target)) |
|
(caaar (plist-get parent :caption))))) |
|
(when name (push (list name caption type) result))))) |
|
(nreverse result))) |
|
|
|
;;; Convenience functions for inserting new cross-reference targets (tables and figures) |
|
|
|
(defun org-table-insert () |
|
"Insert a new table, with name and caption." |
|
(let* ((name (read-from-minibuffer "Name: ")) |
|
(caption (read-from-minibuffer "Caption: "))) |
|
(insert (concat "#+CAPTION: " caption "\n")) |
|
(insert (concat "#+NAME: tab-" name "\n")) |
|
(funcall org-crossref-create-table-function))) |
|
|
|
(defun org-figure-insert () |
|
"Insert a new figure, with name and caption." |
|
(interactive) |
|
(let* ((image_file (read-file-name "Image file: " "~/Pictures/")) |
|
(name (read-from-minibuffer "Name: ")) |
|
(caption (read-from-minibuffer "Caption: "))) |
|
(insert (concat "#+CAPTION: " caption "\n")) |
|
(insert (concat "#+NAME: fig-" name "\n")) |
|
(org-insert-link 'file image_file))) |
|
|
|
(defun org-crossref-name-insert () |
|
"Insert name for cross-referencing." |
|
(interactive) |
|
(let* ((object-type |
|
(completing-read "Object type: " org-crossref-types)) |
|
(name (read-from-minibuffer "Description: "))) |
|
(insert (concat (cdr (assoc object-type org-crossref-types)) "-" name)))) |
Default cross reference insert function here uses internal links, which has these limitations:
Is this better implemented as standard typed links, as in org-ref, like
[[crossref:test1][the test]]
? Should org add such link types? Or modify internal links to support the same functionality?