Skip to content

Instantly share code, notes, and snippets.

@bdarcus
Last active October 19, 2021 10:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bdarcus/1cebcff17fca762a363f89138214848d to your computer and use it in GitHub Desktop.
Save bdarcus/1cebcff17fca762a363f89138214848d to your computer and use it in GitHub Desktop.
maybe pieces of something like this for org?
;;; 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))))

Requirements:

  1. a function to collect targets by type (the completion candidates)
  2. an interactive function to insert cross-references by type
  3. either new typed cross-reference links, or way to add similar functionality to "internal links"
  4. maybe export enhancements
@bdarcus
Copy link
Author

bdarcus commented Oct 12, 2021

Default cross reference insert function here uses internal links, which has these limitations:

  1. no way to type them currently (though not clear how significant this is)
  2. probably because of that, no way AFAIK to do more advanced things like "follow" or custom "activate" functionality; this seems a bit more important

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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment