litorgy-ref.el 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. ;;; litorgy-ref.el --- litorgical functions for referencing external data
  2. ;; Copyright (C) 2009 Eric Schulte, Dan Davison, Austin F. Frank
  3. ;; Author: Eric Schulte, Dan Davison, Austin F. Frank
  4. ;; Keywords: literate programming, reproducible research
  5. ;; Homepage: http://orgmode.org
  6. ;; Version: 0.01
  7. ;;; License:
  8. ;; This program is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 3, or (at your option)
  11. ;; any later version.
  12. ;;
  13. ;; This program is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;;
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  20. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. ;; Boston, MA 02110-1301, USA.
  22. ;;; Commentary:
  23. ;; Functions for referencing data from the header arguments of a
  24. ;; litorgical block. The syntax of such a reference should be
  25. ;;
  26. ;; #+VAR: variable-name=file:resource-id
  27. ;;
  28. ;; - variable-name :: the name of the variable to which the value
  29. ;; will be assigned
  30. ;;
  31. ;; - file :: path to the file containing the resource, or omitted if
  32. ;; resource is in the current file
  33. ;;
  34. ;; - resource-id :: the id or name of the resource, or 'previous' to
  35. ;; grab the previous table, or 'next' to grab the
  36. ;; next table
  37. ;;
  38. ;; So an example of a simple src block referencing table data in the
  39. ;; same file would be
  40. ;;
  41. ;; #+var: table previous
  42. ;; #+begin_src emacs-lisp
  43. ;; (message table)
  44. ;; #+end_src
  45. ;;
  46. ;;; Code:
  47. (require 'litorgy)
  48. (defun litorgy-read-cell (cell)
  49. "Convert the string value of CELL to a number if appropriate.
  50. Otherwise if cell looks like a list (meaning it starts with a
  51. '(') then read it as lisp, otherwise return it unmodified as a
  52. string.
  53. This is taken almost directly from `org-read-prop'."
  54. (if (and (stringp cell) (not (equal cell "")))
  55. (let ((out (string-to-number cell)))
  56. (if (equal out 0)
  57. (if (or (equal "(" (substring cell 0 1))
  58. (equal "'" (substring cell 0 1)))
  59. (read cell)
  60. (if (string-match "^\\(+0\\|-0\\|0\\)$" cell)
  61. 0
  62. (progn (set-text-properties 0 (length cell) nil cell)
  63. cell)))
  64. out))
  65. cell))
  66. (defun litorgy-ref-variables (params)
  67. "Takes a parameter alist, and return an alist of variable
  68. names, and the string representation of the related value."
  69. (mapcar #'litorgy-ref-parse
  70. (delq nil (mapcar (lambda (pair) (if (eq (car pair) :var) (cdr pair))) params))))
  71. (defun litorgy-ref-parse (reference)
  72. "Parse a reference to an external resource returning a list
  73. with two elements. The first element of the list will be the
  74. name of the variable, and the second will be an emacs-lisp
  75. representation of the value of the variable."
  76. (save-excursion
  77. (if (string-match "\\(.+\\)=\\(.+\\)" reference)
  78. (let ((var (match-string 1 reference))
  79. (ref (match-string 2 reference))
  80. direction type)
  81. (when (string-match "\\(.+\\):\\(.+\\)" reference)
  82. (find-file (match-string 1 reference))
  83. (setf ref (match-string 2 reference)))
  84. (cons (intern var)
  85. (progn
  86. (cond ;; follow the reference in the current file
  87. ((string= ref "previous") (setq direction -1))
  88. ((string= ref "next") (setq direction 1))
  89. (t
  90. (goto-char (point-min))
  91. (setq direction 1)
  92. (unless (let ((regexp (concat "^#\\+\\(TBL\\|SRC\\)NAME:[ \t]*"
  93. (regexp-quote ref) "[ \t]*$")))
  94. (or (re-search-forward regexp nil t)
  95. (re-search-backward regexp nil t)))
  96. ;; ;; TODO: allow searching for names in other buffers
  97. ;; (setq id-loc (org-id-find ref 'marker)
  98. ;; buffer (marker-buffer id-loc)
  99. ;; loc (marker-position id-loc))
  100. ;; (move-marker id-loc nil)
  101. (error (format "reference '%s' not found in this buffer" ref)))))
  102. (while (not (setq type (litorgy-ref-at-ref-p)))
  103. (forward-line direction)
  104. (beginning-of-line)
  105. (if (or (= (point) (point-min)) (= (point) (point-max)))
  106. (error "reference not found")))
  107. (case type
  108. ('table
  109. (mapcar (lambda (row)
  110. (mapcar #'litorgy-read-cell row))
  111. (org-table-to-lisp)))
  112. ('source-block
  113. (litorgy-execute-src-block t)))))))))
  114. (defun litorgy-ref-at-ref-p ()
  115. "Return the type of reference located at point or nil of none
  116. of the supported reference types are found. Supported reference
  117. types are tables and source blocks."
  118. (cond ((org-at-table-p) 'table)
  119. ((looking-at "^#\\+BEGIN_SRC") 'source-block)))
  120. (provide 'litorgy-ref)
  121. ;;; litorgy-ref.el ends here