summaryrefslogtreecommitdiff
path: root/lisp/org-table.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/org-table.el')
-rw-r--r--lisp/org-table.el181
1 files changed, 102 insertions, 79 deletions
diff --git a/lisp/org-table.el b/lisp/org-table.el
index 62de402..ba79690 100644
--- a/lisp/org-table.el
+++ b/lisp/org-table.el
@@ -47,12 +47,18 @@
(declare-function org-element-map "org-element"
(data types fun
&optional info first-match no-recursion with-affiliated))
+(declare-function org-element-parse-buffer "org-element"
+ (&optional granularity visible-only))
(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
-(declare-function org-export-string-as "ox"
- (string backend &optional body-only ext-plist))
-(declare-function org-export-create-backend "ox")
-(declare-function org-export-get-backend "ox" (name))
+(declare-function org-export-create-backend "org-export" (&rest rest))
+(declare-function org-export-data-with-backend "org-export" (arg1 arg2 arg3))
+(declare-function org-export-first-sibling-p "org-export" (arg1 arg2))
+(declare-function org-export-get-backend "org-export" (arg1))
+(declare-function org-export-get-environment "org-export" (&optional arg1 arg2 arg3))
+(declare-function org-export-table-has-special-column-p "org-export" (arg1))
+(declare-function org-export-table-row-is-special-p "org-export" (arg1 arg2))
(declare-function calc-eval "calc" (str &optional separator &rest args))
@@ -278,9 +284,9 @@ relies on the variables to be present in the list."
(defcustom org-table-duration-custom-format 'hours
"Format for the output of calc computations like $1+$2;t.
-The default value is 'hours, and will output the results as a
-number of hours. Other allowed values are 'seconds, 'minutes and
-'days, and the output will be a fraction of seconds, minutes or
+The default value is `hours', and will output the results as a
+number of hours. Other allowed values are `seconds', `minutes' and
+`days', and the output will be a fraction of seconds, minutes or
days."
:group 'org-table-calculation
:version "24.1"
@@ -323,7 +329,7 @@ The car of each element is a name of a constant, without the `$' before it.
The cdr is the value as a string. For example, if you'd like to use the
speed of light in a formula, you would configure
- (setq org-table-formula-constants '((\"c\" . \"299792458.\")))
+ (setq org-table-formula-constants \\='((\"c\" . \"299792458.\")))
and then use it in an equation like `$1*$c'.
@@ -337,7 +343,9 @@ Constants can also be defined on a per-file basis using a line like
(defcustom org-table-allow-automatic-line-recalculation t
"Non-nil means lines marked with |#| or |*| will be recomputed automatically.
-Automatically means when TAB or RET or C-c C-c are pressed in the line."
+\\<org-mode-map>\
+Automatically means when TAB or RET or \\[org-ctrl-c-ctrl-c] \
+are pressed in the line."
:group 'org-table-calculation
:type 'boolean)
@@ -555,9 +563,9 @@ slightly, to make sure a beginning of line in the first line is included.
SEPARATOR specifies the field separator in the lines. It can have the
following values:
-'(4) Use the comma as a field separator
-'(16) Use a TAB as field separator
-'(64) Prompt for a regular expression as field separator
+(4) Use the comma as a field separator
+(16) Use a TAB as field separator
+(64) Prompt for a regular expression as field separator
integer When a number, use that many spaces as field separator
regexp When a regular expression, use it to match the separator
nil When nil, the command tries to be smart and figure out the
@@ -2560,14 +2568,14 @@ This function assumes the table is already analyzed (i.e., using
(cond
((cdr (assoc ref org-table-named-field-locations)))
((string-match "\\`@\\([1-9][0-9]*\\)\\$\\([1-9][0-9]*\\)\\'" ref)
- (cons (condition-case nil
+ (list (condition-case nil
(aref org-table-dlines
(string-to-number (match-string 1 ref)))
(error (user-error "Invalid row number in %s" ref)))
(string-to-number (match-string 2 ref))))
(t (user-error "Unknown field: %s" ref))))
(line (car coordinates))
- (column (cdr coordinates))
+ (column (nth 1 coordinates))
(create-new-column (if (functionp create-column-p)
(funcall create-column-p column)
create-column-p)))
@@ -3029,7 +3037,7 @@ search, as a string."
KEEP-EMPTY indicated to keep empty fields, default is to skip them.
NUMBERS indicates that everything should be converted to numbers.
LISPP non-nil means to return something appropriate for a Lisp
-list, 'literal is for the format specifier L."
+list, `literal' is for the format specifier L."
;; Calc nan (not a number) is used for the conversion of the empty
;; field to a reference for several reasons: (i) It is accepted in a
;; Calc formula (e. g. "" or "()" would result in a Calc error).
@@ -3384,7 +3392,7 @@ formulas that use a range of rows or columns, it may often be better
to anchor the formula with \"I\" row markers, or to offset from the
borders of the table using the @< @> $< $> makers."
(let (n nmax len char (start 0))
- (while (string-match "\\([@$]\\)\\(<+\\|>+\\)\\|\\(remote([^\)]+)\\)"
+ (while (string-match "\\([@$]\\)\\(<+\\|>+\\)\\|\\(remote([^)]+)\\)"
s start)
(if (match-end 3)
(setq start (match-end 3))
@@ -3549,8 +3557,10 @@ Parameters get priority."
(when (eq org-table-use-standard-references t)
(org-table-fedit-toggle-ref-type))
(org-goto-line startline)
- (message "Edit formulas, finish with `C-c C-c' or `C-c ' '. \
-See menu for more commands.")))
+ (message
+ (substitute-command-keys "\\<org-mode-map>\
+Edit formulas, finish with `\\[org-ctrl-c-ctrl-c]' or `\\[org-edit-special]'. \
+See menu for more commands."))))
(defun org-table-fedit-post-command ()
(when (not (memq this-command '(lisp-complete-symbol)))
@@ -4772,72 +4782,85 @@ This may be either a string or a function of two arguments:
example \"%s\\\\times10^{%s}\". This may also be a property
list with column numbers and format strings or functions.
:fmt will still be applied after :efmt."
- (let ((backend (plist-get params :backend))
- ;; Disable user-defined export filters and hooks.
- (org-export-filters-alist nil)
- (org-export-before-parsing-hook nil)
- (org-export-before-processing-hook nil))
- (when (and backend (symbolp backend) (not (org-export-get-backend backend)))
- (user-error "Unknown :backend value"))
- (when (or (not backend) (plist-get params :raw)) (require 'ox-org))
- ;; Remove final newline.
- (substring
- (org-export-string-as
- ;; Return TABLE as Org syntax. Tolerate non-string cells.
- (with-output-to-string
+ (let* ((backend (plist-get params :backend))
+ (custom-backend
+ ;; Build a custom back-end according to PARAMS. Before
+ ;; defining a translator, check if there is anything to do.
+ ;; When there isn't, let BACKEND handle the element.
+ (org-export-create-backend
+ :parent (or backend 'org)
+ :transcoders
+ `((table . ,(org-table--to-generic-table params))
+ (table-row . ,(org-table--to-generic-row params))
+ (table-cell . ,(org-table--to-generic-cell params))
+ ;; Macros are not going to be expanded. However, no
+ ;; regular back-end has a transcoder for them. We
+ ;; provide one so they are not ignored, but displayed
+ ;; as-is instead.
+ (macro . (lambda (m c i) (org-element-macro-interpreter m nil))))))
+ data info)
+ ;; Store TABLE as Org syntax in DATA. Tolerate non-string cells.
+ ;; Initialize communication channel in INFO.
+ (with-temp-buffer
+ (let ((org-inhibit-startup t)) (org-mode))
+ (let ((standard-output (current-buffer)))
(dolist (e table)
(cond ((eq e 'hline) (princ "|--\n"))
((consp e)
(princ "| ") (dolist (c e) (princ c) (princ " |"))
(princ "\n")))))
- ;; Build a custom back-end according to PARAMS. Before defining
- ;; a translator, check if there is anything to do. When there
- ;; isn't, let BACKEND handle the element.
- (org-export-create-backend
- :parent (or backend 'org)
- :filters
- '((:filter-parse-tree
- ;; Handle :skip parameter.
- (lambda (tree backend info)
- (let ((skip (plist-get info :skip)))
- (when skip
- (unless (wholenump skip) (user-error "Wrong :skip value"))
- (let ((n 0))
- (org-element-map tree 'table-row
- (lambda (row)
- (if (>= n skip) t
- (org-element-extract-element row)
- (incf n)
- nil))
- info t))
- tree)))
- ;; Handle :skipcols parameter.
- (lambda (tree backend info)
- (let ((skipcols (plist-get info :skipcols)))
- (when skipcols
- (unless (consp skipcols) (user-error "Wrong :skipcols value"))
- (org-element-map tree 'table
- (lambda (table)
- (let ((specialp
- (org-export-table-has-special-column-p table)))
- (dolist (row (org-element-contents table))
- (when (eq (org-element-property :type row) 'standard)
- (let ((c 1))
- (dolist (cell (nthcdr (if specialp 1 0)
- (org-element-contents row)))
- (when (memq c skipcols)
- (org-element-extract-element cell))
- (incf c)))))))
- info)
- tree)))))
- :transcoders
- `((table . ,(org-table--to-generic-table params))
- (table-row . ,(org-table--to-generic-row params))
- (table-cell . ,(org-table--to-generic-cell params))
- ;; Section. Return contents to avoid garbage around table.
- (section . (lambda (s c i) c))))
- 'body-only (org-combine-plists params '(:with-tables t)))
- 0 -1)))
+ (setq data
+ (org-element-map (org-element-parse-buffer) 'table
+ #'identity nil t))
+ (setq info (org-export-get-environment backend nil params)))
+ (when (and backend (symbolp backend) (not (org-export-get-backend backend)))
+ (user-error "Unknown :backend value"))
+ (when (or (not backend) (plist-get info :raw)) (require 'ox-org))
+ ;; Handle :skip parameter.
+ (let ((skip (plist-get info :skip)))
+ (when skip
+ (unless (wholenump skip) (user-error "Wrong :skip value"))
+ (let ((n 0))
+ (org-element-map data 'table-row
+ (lambda (row)
+ (if (>= n skip) t
+ (org-element-extract-element row)
+ (incf n)
+ nil))
+ nil t))))
+ ;; Handle :skipcols parameter.
+ (let ((skipcols (plist-get info :skipcols)))
+ (when skipcols
+ (unless (consp skipcols) (user-error "Wrong :skipcols value"))
+ (org-element-map data 'table
+ (lambda (table)
+ (let ((specialp (org-export-table-has-special-column-p table)))
+ (dolist (row (org-element-contents table))
+ (when (eq (org-element-property :type row) 'standard)
+ (let ((c 1))
+ (dolist (cell (nthcdr (if specialp 1 0)
+ (org-element-contents row)))
+ (when (memq c skipcols)
+ (org-element-extract-element cell))
+ (incf c))))))))))
+ ;; Since we are going to export using a low-level mechanism,
+ ;; ignore special column and special rows manually.
+ (let ((special? (org-export-table-has-special-column-p data))
+ ignore)
+ (org-element-map data (if special? '(table-cell table-row) 'table-row)
+ (lambda (datum)
+ (when (if (eq (org-element-type datum) 'table-row)
+ (org-export-table-row-is-special-p datum nil)
+ (org-export-first-sibling-p datum nil))
+ (push datum ignore))))
+ (setq info (plist-put info :ignore-list ignore)))
+ ;; We use a low-level mechanism to export DATA so as to skip all
+ ;; usual pre-processing and post-processing, i.e., hooks, filters,
+ ;; Babel code evaluation, include keywords and macro expansion,
+ ;; and filters.
+ (let ((output (org-export-data-with-backend data custom-backend info)))
+ ;; Remove final newline.
+ (if (org-string-nw-p output) (substring-no-properties output 0 -1) ""))))
(defun org-table--generic-apply (value name &optional with-cons &rest args)
(cond ((null value) nil)